forked from Minki/linux
media updates for v5.15-rc1
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmEvK4gACgkQCF8+vY7k 4RUn3Q//YocYb+1s6K+nX2LFFGv5wKgMuqcjJbnuex43/z1dQ+B3T5/RiMmndOvw xZwcCQJFI0c42kfDapdCunfICgYDzqncnUZ5V7pO3efeeuN3j6t3EAMxQKD0gR5A RmFHe/aJpkRANoEWiA4vFKDNWy1cmi6zQDQ8njK1LUb4euwqxrH5mMJSSpObZU/p 4/mV5no2CjhvE3k/JPGqh6zJ8WZtptbcf8E6e9fwTsS91nIfbO1/FqudeOleS3fU 4BYv7zjx/fQsNHpkJZoNNTlZcZGzA1QcWHne4cem+5yudJO2AgRHKC0LnEyhfn19 Q8xw23yB9TP2/mq0QAjc4r6XfJJd18UGp/rI9LP2K6+YjAqX067+TVIfQXswpcui oLDWwGXKtOT7tA5Mrk9XeocpQ6yMUJlCg/JUfpTwJDSaJdEFgAfxVSCsJLLoBT3/ I8AkfcvBeybwUXgZDaYpDdeE2CBWXvYzdXGzWkiQlZ/jIC35cjRcfWjoUvXIAw8K QRDT71VAR67HwufmjkayyDCB0szx+u3xskPdoIAsbtoZCfzgzF+14Z+dAPGQ5YF1 /+UdiNF5lTRMlTR6Xlz5Zckfix0NV002FeHorSoHD/E9jlLwvd3s+sv/1XSzFBQN 9Be5hsEJZpE7uuygLzZ09yj4g0wHlWPTkcOuOTyrH+y0IFU5PI4= =PQpb -----END PGP SIGNATURE----- Merge tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - new sensor drivers: imx335, imx412, ov9282 - new IR transmitter driver: meson-ir-tx - handro driver gained support for H.264 for Rockchip VDPU2 - imx gained support for i.MX8MQ - ti-vpe has gained support for other SoC variants - lots of cleanups, fixes, board additions and doc improvements * tag 'media/v5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (195 commits) media: venus: venc: add support for V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM control media: venus: venc: Add support for intra-refresh period media: v4l2-ctrls: Add intra-refresh period control media: docs: ext-ctrls-codec: Document cyclic intra-refresh zero control value media: venus: helper: do not set constrained parameters for UBWC media: venus: venc: Fix potential null pointer dereference on pointer fmt media: venus: hfi: fix return value check in sys_get_prop_image_version() media: tegra-cec: Handle errors of clk_prepare_enable() media: cec-pin: rename timer overrun variables media: TDA1997x: report -ENOLINK after disconnecting HDMI source media: TDA1997x: fix tda1997x_query_dv_timings() return value media: Fix cosmetic error in TDA1997x driver media: v4l2-dv-timings.c: fix wrong condition in two for-loops media: imx: add a driver for i.MX8MQ mipi csi rx phy and controller media: dt-bindings: media: document the nxp,imx8mq-mipi-csi2 receiver phy and controller media: imx: imx7_mipi_csis: convert some switch cases to the default media: imx: imx7-media-csi: Fix buffer return upon stream start failure media: imx: imx7-media-csi: Don't set PIXEL_BIT in CSICR1 media: imx: imx7-media-csi: Set TWO_8BIT_SENSOR for >= 10-bit formats media: dt-bindings: media: nxp,imx7-csi: Add i.MX8MM support ...
This commit is contained in:
commit
835d31d319
@ -0,0 +1,60 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: "http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#"
|
||||
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
|
||||
|
||||
title: Amlogic Meson IR transmitter
|
||||
|
||||
maintainers:
|
||||
- Viktor Prutyanov <viktor.prutyanov@phystech.edu>
|
||||
|
||||
description: |
|
||||
Some Amlogic SoCs such as A311D and T950D4 have IR transmitter
|
||||
(also called blaster) controller onboard. It is capable of
|
||||
sending IR signals with arbitrary carrier frequency and duty cycle.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: amlogic,meson-ir-tx
|
||||
- items:
|
||||
- const: amlogic,meson-g12a-ir-tx
|
||||
- const: amlogic,meson-ir-tx
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: sysclk
|
||||
- const: xtal
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/clock/g12a-clkc.h>
|
||||
|
||||
ir@ff80014c {
|
||||
compatible = "amlogic,meson-g12a-ir-tx", "amlogic,meson-ir-tx";
|
||||
reg = <0xff80014c 0x10>;
|
||||
interrupts = <0 198 IRQ_TYPE_EDGE_RISING>;
|
||||
clocks = <&clkc CLKID_CLK81>, <&xtal>;
|
||||
clock-names = "sysclk", "xtal";
|
||||
};
|
@ -35,6 +35,14 @@ properties:
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
adv,force-bt656-4:
|
||||
description:
|
||||
Indicates that the output is a BT.656-4 compatible stream.
|
||||
type: boolean
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
|
91
Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
Normal file
91
Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/ovti,ov9282.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: OmniVision OV9282 Sensor
|
||||
|
||||
maintainers:
|
||||
- Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
|
||||
description:
|
||||
OV9282 sensor is an OmniVision black & white CMOS active pixel digital image
|
||||
sensor with an active array size of 1296H x 816V. It is programmable through
|
||||
I2C interface. The I2C client address is fixed to 0x60/0x70 as per sensor data
|
||||
sheet. Image data is sent through MIPI CSI-2.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ovti,ov9282
|
||||
reg:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27MHz
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reference to the GPIO connected to the XCLR pin, if any.
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes: true
|
||||
link-frequencies: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
camera@60 {
|
||||
compatible = "ovti,ov9282";
|
||||
reg = <0x60>;
|
||||
clocks = <&ov9282_clk>;
|
||||
|
||||
assigned-clocks = <&ov9282_clk>;
|
||||
assigned-clock-parents = <&ov9282_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
ov9282: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
data-lanes = <1 2>;
|
||||
link-frequencies = /bits/ 64 <800000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
91
Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
Normal file
91
Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/sony,imx335.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony IMX335 Sensor
|
||||
|
||||
maintainers:
|
||||
- Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
|
||||
description:
|
||||
IMX335 sensor is a Sony CMOS active pixel digital image sensor with an active
|
||||
array size of 2592H x 1944V. It is programmable through I2C interface. The
|
||||
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
|
||||
sent through MIPI CSI-2.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx335
|
||||
reg:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reference to the GPIO connected to the XCLR pin, if any.
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes: true
|
||||
link-frequencies: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
camera@1a {
|
||||
compatible = "sony,imx335";
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx335_clk>;
|
||||
|
||||
assigned-clocks = <&imx335_clk>;
|
||||
assigned-clock-parents = <&imx335_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
imx335: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <594000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
91
Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
Normal file
91
Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/sony,imx412.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony IMX412 Sensor
|
||||
|
||||
maintainers:
|
||||
- Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
|
||||
description:
|
||||
IMX412 sensor is a Sony CMOS active pixel digital image sensor with an active
|
||||
array size of 4072H x 3176V. It is programmable through I2C interface. The
|
||||
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
|
||||
sent through MIPI CSI-2.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx412
|
||||
reg:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency 6MHz, 12MHz, 18MHz, 24MHz or 27MHz
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reference to the GPIO connected to the XCLR pin, if any.
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes: true
|
||||
link-frequencies: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
camera@1a {
|
||||
compatible = "sony,imx412";
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx412_clk>;
|
||||
|
||||
assigned-clocks = <&imx412_clk>;
|
||||
assigned-clock-parents = <&imx412_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
imx412: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <600000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -4,7 +4,7 @@
|
||||
$id: http://devicetree.org/schemas/media/nxp,imx7-csi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: i.MX7 CMOS Sensor Interface
|
||||
title: i.MX7 and i.MX8 CSI bridge (CMOS Sensor Interface)
|
||||
|
||||
maintainers:
|
||||
- Rui Miguel Silva <rmfrfs@gmail.com>
|
||||
@ -15,9 +15,13 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx7-csi
|
||||
- fsl,imx6ul-csi
|
||||
oneOf:
|
||||
- enum:
|
||||
- fsl,imx7-csi
|
||||
- fsl,imx6ul-csi
|
||||
- items:
|
||||
- const: fsl,imx8mm-csi
|
||||
- const: fsl,imx7-csi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -0,0 +1,174 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/nxp,imx8mq-mipi-csi2.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP i.MX8MQ MIPI CSI-2 receiver
|
||||
|
||||
maintainers:
|
||||
- Martin Kepplinger <martin.kepplinger@puri.sm>
|
||||
|
||||
description: |-
|
||||
This binding covers the CSI-2 RX PHY and host controller included in the
|
||||
NXP i.MX8MQ SoC. It handles the sensor/image input and process for all the
|
||||
input imaging devices.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- fsl,imx8mq-mipi-csi2
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: core is the RX Controller Core Clock input. This clock
|
||||
must be exactly equal to or faster than the receive
|
||||
byteclock from the RX DPHY.
|
||||
- description: esc is the Rx Escape Clock. This must be the same escape
|
||||
clock that the RX DPHY receives.
|
||||
- description: ui is the pixel clock (phy_ref up to 333Mhz).
|
||||
See the reference manual for details.
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: esc
|
||||
- const: ui
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
items:
|
||||
- description: CORE_RESET reset register bit definition
|
||||
- description: PHY_REF_RESET reset register bit definition
|
||||
- description: ESC_RESET reset register bit definition
|
||||
|
||||
fsl,mipi-phy-gpr:
|
||||
description: |
|
||||
The phandle to the imx8mq syscon iomux-gpr with the register
|
||||
for setting RX_ENABLE for the mipi receiver.
|
||||
|
||||
The format should be as follows:
|
||||
<gpr req_gpr>
|
||||
gpr is the phandle to general purpose register node.
|
||||
req_gpr is the gpr register offset of RX_ENABLE for the mipi phy.
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
items:
|
||||
items:
|
||||
- description: The 'gpr' is the phandle to general purpose register node.
|
||||
- description: The 'req_gpr' is the gpr register offset containing
|
||||
CSI2_1_RX_ENABLE or CSI2_2_RX_ENABLE respectively.
|
||||
maximum: 0xff
|
||||
|
||||
interconnects:
|
||||
maxItems: 1
|
||||
|
||||
interconnect-names:
|
||||
const: dram
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Input port node, single endpoint describing the CSI-2 transmitter.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
items:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
- const: 1
|
||||
- const: 2
|
||||
- const: 3
|
||||
- const: 4
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output port node
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- power-domains
|
||||
- resets
|
||||
- fsl,mipi-phy-gpr
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/imx8mq-clock.h>
|
||||
#include <dt-bindings/interconnect/imx8mq.h>
|
||||
#include <dt-bindings/reset/imx8mq-reset.h>
|
||||
|
||||
csi@30a70000 {
|
||||
compatible = "fsl,imx8mq-mipi-csi2";
|
||||
reg = <0x30a70000 0x1000>;
|
||||
clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
|
||||
<&clk IMX8MQ_CLK_CSI1_ESC>,
|
||||
<&clk IMX8MQ_CLK_CSI1_PHY_REF>;
|
||||
clock-names = "core", "esc", "ui";
|
||||
assigned-clocks = <&clk IMX8MQ_CLK_CSI1_CORE>,
|
||||
<&clk IMX8MQ_CLK_CSI1_PHY_REF>,
|
||||
<&clk IMX8MQ_CLK_CSI1_ESC>;
|
||||
assigned-clock-rates = <266000000>, <200000000>, <66000000>;
|
||||
assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_266M>,
|
||||
<&clk IMX8MQ_SYS2_PLL_1000M>,
|
||||
<&clk IMX8MQ_SYS1_PLL_800M>;
|
||||
power-domains = <&pgc_mipi_csi1>;
|
||||
resets = <&src IMX8MQ_RESET_MIPI_CSI1_CORE_RESET>,
|
||||
<&src IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET>,
|
||||
<&src IMX8MQ_RESET_MIPI_CSI1_ESC_RESET>;
|
||||
fsl,mipi-phy-gpr = <&iomuxc_gpr 0x88>;
|
||||
interconnects = <&noc IMX8MQ_ICM_CSI1 &noc IMX8MQ_ICS_DRAM>;
|
||||
interconnect-names = "dram";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
imx8mm_mipi_csi_in: endpoint {
|
||||
remote-endpoint = <&imx477_out>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
imx8mm_mipi_csi_out: endpoint {
|
||||
remote-endpoint = <&csi_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -22,6 +22,7 @@ properties:
|
||||
- rockchip,rk3288-vpu
|
||||
- rockchip,rk3328-vpu
|
||||
- rockchip,rk3399-vpu
|
||||
- rockchip,px30-vpu
|
||||
- items:
|
||||
- const: rockchip,rk3188-vpu
|
||||
- const: rockchip,rk3066-vpu
|
||||
|
@ -3,10 +3,10 @@
|
||||
Writing camera sensor drivers
|
||||
=============================
|
||||
|
||||
CSI-2
|
||||
-----
|
||||
CSI-2 and parallel (BT.601 and BT.656) busses
|
||||
---------------------------------------------
|
||||
|
||||
Please see what is written on :ref:`MIPI_CSI_2`.
|
||||
Please see :ref:`transmitter-receiver`.
|
||||
|
||||
Handling clocks
|
||||
---------------
|
||||
@ -26,15 +26,16 @@ user.
|
||||
ACPI
|
||||
~~~~
|
||||
|
||||
Read the "clock-frequency" _DSD property to denote the frequency. The driver can
|
||||
rely on this frequency being used.
|
||||
Read the ``clock-frequency`` _DSD property to denote the frequency. The driver
|
||||
can rely on this frequency being used.
|
||||
|
||||
Devicetree
|
||||
~~~~~~~~~~
|
||||
|
||||
The currently preferred way to achieve this is using "assigned-clock-rates"
|
||||
property. See Documentation/devicetree/bindings/clock/clock-bindings.txt for
|
||||
more information. The driver then gets the frequency using clk_get_rate().
|
||||
The currently preferred way to achieve this is using ``assigned-clocks``,
|
||||
``assigned-clock-parents`` and ``assigned-clock-rates`` properties. See
|
||||
``Documentation/devicetree/bindings/clock/clock-bindings.txt`` for more
|
||||
information. The driver then gets the frequency using ``clk_get_rate()``.
|
||||
|
||||
This approach has the drawback that there's no guarantee that the frequency
|
||||
hasn't been modified directly or indirectly by another driver, or supported by
|
||||
@ -55,7 +56,7 @@ processing pipeline as one or more sub-devices with different cropping and
|
||||
scaling configurations. The output size of the device is the result of a series
|
||||
of cropping and scaling operations from the device's pixel array's size.
|
||||
|
||||
An example of such a driver is the smiapp driver (see drivers/media/i2c/smiapp).
|
||||
An example of such a driver is the CCS driver (see ``drivers/media/i2c/ccs``).
|
||||
|
||||
Register list based drivers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -67,7 +68,7 @@ level are independent. How a driver picks such configuration is based on the
|
||||
format set on a source pad at the end of the device's internal pipeline.
|
||||
|
||||
Most sensor drivers are implemented this way, see e.g.
|
||||
drivers/media/i2c/imx319.c for an example.
|
||||
``drivers/media/i2c/imx319.c`` for an example.
|
||||
|
||||
Frame interval configuration
|
||||
----------------------------
|
||||
@ -94,9 +95,10 @@ large variety of devices beyond camera sensors. Devices that have no analogue
|
||||
crop, use the full source image size, i.e. pixel array size.
|
||||
|
||||
Horizontal and vertical blanking are specified by ``V4L2_CID_HBLANK`` and
|
||||
``V4L2_CID_VBLANK``, respectively. The unit of these controls are lines. The
|
||||
pixel rate is specified by ``V4L2_CID_PIXEL_RATE`` in the same sub-device. The
|
||||
unit of that control is Hz.
|
||||
``V4L2_CID_VBLANK``, respectively. The unit of the ``V4L2_CID_HBLANK`` control
|
||||
is pixels and the unit of the ``V4L2_CID_VBLANK`` is lines. The pixel rate in
|
||||
the sensor's **pixel array** is specified by ``V4L2_CID_PIXEL_RATE`` in the same
|
||||
sub-device. The unit of that control is pixels per second.
|
||||
|
||||
Register list based drivers need to implement read-only sub-device nodes for the
|
||||
purpose. Devices that are not register list based need these to configure the
|
||||
@ -125,14 +127,14 @@ general, the device must be powered on at least when its registers are being
|
||||
accessed and when it is streaming.
|
||||
|
||||
Existing camera sensor drivers may rely on the old
|
||||
:c:type:`v4l2_subdev_core_ops`->s_power() callback for bridge or ISP drivers to
|
||||
struct v4l2_subdev_core_ops->s_power() callback for bridge or ISP drivers to
|
||||
manage their power state. This is however **deprecated**. If you feel you need
|
||||
to begin calling an s_power from an ISP or a bridge driver, instead please add
|
||||
runtime PM support to the sensor driver you are using. Likewise, new drivers
|
||||
should not use s_power.
|
||||
|
||||
Please see examples in e.g. ``drivers/media/i2c/ov8856.c`` and
|
||||
``drivers/media/i2c/smiapp/smiapp-core.c``. The two drivers work in both ACPI
|
||||
``drivers/media/i2c/ccs/ccs-core.c``. The two drivers work in both ACPI
|
||||
and DT based systems.
|
||||
|
||||
Control framework
|
||||
@ -149,16 +151,3 @@ used to obtain device's power state after the power state transition:
|
||||
The function returns a non-zero value if it succeeded getting the power count or
|
||||
runtime PM was disabled, in either of which cases the driver may proceed to
|
||||
access the device.
|
||||
|
||||
Controls
|
||||
--------
|
||||
|
||||
For camera sensors that are connected to a bus where transmitter and receiver
|
||||
require common configuration set by drivers, such as CSI-2 or parallel (BT.601
|
||||
or BT.656) bus, the ``V4L2_CID_LINK_FREQ`` control is mandatory on transmitter
|
||||
drivers. Receiver drivers can use the ``V4L2_CID_LINK_FREQ`` to query the
|
||||
frequency used on the bus.
|
||||
|
||||
The transmitter drivers should also implement ``V4L2_CID_PIXEL_RATE`` control in
|
||||
order to tell the maximum pixel rate to the receiver. This is required on raw
|
||||
camera sensors.
|
||||
|
@ -130,9 +130,12 @@ To enable/disable the hardware::
|
||||
int (*adap_enable)(struct cec_adapter *adap, bool enable);
|
||||
|
||||
This callback enables or disables the CEC hardware. Enabling the CEC hardware
|
||||
means powering it up in a state where no logical addresses are claimed. This
|
||||
op assumes that the physical address (adap->phys_addr) is valid when enable is
|
||||
true and will not change while the CEC adapter remains enabled. The initial
|
||||
means powering it up in a state where no logical addresses are claimed. The
|
||||
physical address will always be valid if CEC_CAP_NEEDS_HPD is set. If that
|
||||
capability is not set, then the physical address can change while the CEC
|
||||
hardware is enabled. CEC drivers should not set CEC_CAP_NEEDS_HPD unless
|
||||
the hardware design requires that as this will make it impossible to wake
|
||||
up displays that pull the HPD low when in standby mode. The initial
|
||||
state of the CEC adapter after calling cec_allocate_adapter() is disabled.
|
||||
|
||||
Note that adap_enable must return 0 if enable is false.
|
||||
|
@ -1,94 +0,0 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. _MIPI_CSI_2:
|
||||
|
||||
MIPI CSI-2
|
||||
==========
|
||||
|
||||
CSI-2 is a data bus intended for transferring images from cameras to
|
||||
the host SoC. It is defined by the `MIPI alliance`_.
|
||||
|
||||
.. _`MIPI alliance`: http://www.mipi.org/
|
||||
|
||||
Media bus formats
|
||||
-----------------
|
||||
|
||||
See :ref:`v4l2-mbus-pixelcode` for details on which media bus formats should
|
||||
be used for CSI-2 interfaces.
|
||||
|
||||
Transmitter drivers
|
||||
-------------------
|
||||
|
||||
CSI-2 transmitter, such as a sensor or a TV tuner, drivers need to
|
||||
provide the CSI-2 receiver with information on the CSI-2 bus
|
||||
configuration. These include the V4L2_CID_LINK_FREQ and
|
||||
V4L2_CID_PIXEL_RATE controls and
|
||||
(:c:type:`v4l2_subdev_video_ops`->s_stream() callback). These
|
||||
interface elements must be present on the sub-device represents the
|
||||
CSI-2 transmitter.
|
||||
|
||||
The V4L2_CID_LINK_FREQ control is used to tell the receiver driver the
|
||||
frequency (and not the symbol rate) of the link. The V4L2_CID_PIXEL_RATE
|
||||
control may be used by the receiver to obtain the pixel rate the transmitter
|
||||
uses. The :c:type:`v4l2_subdev_video_ops`->s_stream() callback provides an
|
||||
ability to start and stop the stream.
|
||||
|
||||
The value of the V4L2_CID_PIXEL_RATE is calculated as follows::
|
||||
|
||||
pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
|
||||
|
||||
where
|
||||
|
||||
.. list-table:: variables in pixel rate calculation
|
||||
:header-rows: 1
|
||||
|
||||
* - variable or constant
|
||||
- description
|
||||
* - link_freq
|
||||
- The value of the V4L2_CID_LINK_FREQ integer64 menu item.
|
||||
* - nr_of_lanes
|
||||
- Number of data lanes used on the CSI-2 link. This can
|
||||
be obtained from the OF endpoint configuration.
|
||||
* - 2
|
||||
- Two bits are transferred per clock cycle per lane.
|
||||
* - bits_per_sample
|
||||
- Number of bits per sample.
|
||||
* - k
|
||||
- 16 for D-PHY and 7 for C-PHY
|
||||
|
||||
The transmitter drivers must, if possible, configure the CSI-2
|
||||
transmitter to *LP-11 mode* whenever the transmitter is powered on but
|
||||
not active, and maintain *LP-11 mode* until stream on. Only at stream
|
||||
on should the transmitter activate the clock on the clock lane and
|
||||
transition to *HS mode*.
|
||||
|
||||
Some transmitters do this automatically but some have to be explicitly
|
||||
programmed to do so, and some are unable to do so altogether due to
|
||||
hardware constraints.
|
||||
|
||||
Stopping the transmitter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A transmitter stops sending the stream of images as a result of
|
||||
calling the ``.s_stream()`` callback. Some transmitters may stop the
|
||||
stream at a frame boundary whereas others stop immediately,
|
||||
effectively leaving the current frame unfinished. The receiver driver
|
||||
should not make assumptions either way, but function properly in both
|
||||
cases.
|
||||
|
||||
Receiver drivers
|
||||
----------------
|
||||
|
||||
Before the receiver driver may enable the CSI-2 transmitter by using
|
||||
the :c:type:`v4l2_subdev_video_ops`->s_stream(), it must have powered
|
||||
the transmitter up by using the
|
||||
:c:type:`v4l2_subdev_core_ops`->s_power() callback. This may take
|
||||
place either indirectly by using :c:func:`v4l2_pipeline_pm_get` or
|
||||
directly.
|
||||
|
||||
Formats
|
||||
-------
|
||||
|
||||
The media bus pixel codes document parallel formats. Should the pixel data be
|
||||
transported over a serial bus, the media bus pixel code that describes a
|
||||
parallel format that transfers a sample on a single clock cycle is used.
|
@ -37,7 +37,7 @@ Documentation/userspace-api/media/index.rst
|
||||
rc-core
|
||||
mc-core
|
||||
cec-core
|
||||
csi2
|
||||
tx-rx
|
||||
camera-sensor
|
||||
|
||||
drivers/index
|
||||
|
133
Documentation/driver-api/media/tx-rx.rst
Normal file
133
Documentation/driver-api/media/tx-rx.rst
Normal file
@ -0,0 +1,133 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
.. _transmitter-receiver:
|
||||
|
||||
Pixel data transmitter and receiver drivers
|
||||
===========================================
|
||||
|
||||
V4L2 supports various devices that transmit and receive pixel data. Examples of
|
||||
these devices include a camera sensor, a TV tuner and a parallel or a CSI-2
|
||||
receiver in an SoC.
|
||||
|
||||
Bus types
|
||||
---------
|
||||
|
||||
The following busses are the most common. This section discusses these two only.
|
||||
|
||||
MIPI CSI-2
|
||||
^^^^^^^^^^
|
||||
|
||||
CSI-2 is a data bus intended for transferring images from cameras to
|
||||
the host SoC. It is defined by the `MIPI alliance`_.
|
||||
|
||||
.. _`MIPI alliance`: https://www.mipi.org/
|
||||
|
||||
Parallel
|
||||
^^^^^^^^
|
||||
|
||||
`BT.601`_ and `BT.656`_ are the most common parallel busses.
|
||||
|
||||
.. _`BT.601`: https://en.wikipedia.org/wiki/Rec._601
|
||||
.. _`BT.656`: https://en.wikipedia.org/wiki/ITU-R_BT.656
|
||||
|
||||
Transmitter drivers
|
||||
-------------------
|
||||
|
||||
Transmitter drivers generally need to provide the receiver drivers with the
|
||||
configuration of the transmitter. What is required depends on the type of the
|
||||
bus. These are common for both busses.
|
||||
|
||||
Media bus pixel code
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
See :ref:`v4l2-mbus-pixelcode`.
|
||||
|
||||
Link frequency
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
|
||||
receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
|
||||
|
||||
``.s_stream()`` callback
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The struct struct v4l2_subdev_video_ops->s_stream() callback is used by the
|
||||
receiver driver to control the transmitter driver's streaming state.
|
||||
|
||||
|
||||
CSI-2 transmitter drivers
|
||||
-------------------------
|
||||
|
||||
Pixel rate
|
||||
^^^^^^^^^^
|
||||
|
||||
The pixel rate on the bus is calculated as follows::
|
||||
|
||||
pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
|
||||
|
||||
where
|
||||
|
||||
.. list-table:: variables in pixel rate calculation
|
||||
:header-rows: 1
|
||||
|
||||
* - variable or constant
|
||||
- description
|
||||
* - link_freq
|
||||
- The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item.
|
||||
* - nr_of_lanes
|
||||
- Number of data lanes used on the CSI-2 link. This can
|
||||
be obtained from the OF endpoint configuration.
|
||||
* - 2
|
||||
- Data is transferred on both rising and falling edge of the signal.
|
||||
* - bits_per_sample
|
||||
- Number of bits per sample.
|
||||
* - k
|
||||
- 16 for D-PHY and 7 for C-PHY
|
||||
|
||||
.. note::
|
||||
|
||||
The pixel rate calculated this way is **not** the same thing as the
|
||||
pixel rate on the camera sensor's pixel array which is indicated by the
|
||||
:ref:`V4L2_CID_PIXEL_RATE <v4l2-cid-pixel-rate>` control.
|
||||
|
||||
LP-11 and LP-111 modes
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
As part of transitioning to high speed mode, a CSI-2 transmitter typically
|
||||
briefly sets the bus to LP-11 or LP-111 state, depending on the PHY. This period
|
||||
may be as short as 100 µs, during which the receiver observes this state and
|
||||
proceeds its own part of high speed mode transition.
|
||||
|
||||
Most receivers are capable of autonomously handling this once the software has
|
||||
configured them to do so, but there are receivers which require software
|
||||
involvement in observing LP-11 or LP-111 state. 100 µs is a brief period to hit
|
||||
in software, especially when there is no interrupt telling something is
|
||||
happening.
|
||||
|
||||
One way to address this is to configure the transmitter side explicitly to LP-11
|
||||
or LP-111 mode, which requires support from the transmitter hardware. This is
|
||||
not universally available. Many devices return to this state once streaming is
|
||||
stopped while the state after power-on is LP-00 or LP-000.
|
||||
|
||||
The ``.pre_streamon()`` callback may be used to prepare a transmitter for
|
||||
transitioning to streaming state, but not yet start streaming. Similarly, the
|
||||
``.post_streamoff()`` callback is used to undo what was done by the
|
||||
``.pre_streamon()`` callback. The caller of ``.pre_streamon()`` is thus required
|
||||
to call ``.post_streamoff()`` for each successful call of ``.pre_streamon()``.
|
||||
|
||||
In the context of CSI-2, the ``.pre_streamon()`` callback is used to transition
|
||||
the transmitter to the LP-11 or LP-111 mode. This also requires powering on the
|
||||
device, so this should be only done when it is needed.
|
||||
|
||||
Receiver drivers that do not need explicit LP-11 or LP-111 mode setup are waived
|
||||
from calling the two callbacks.
|
||||
|
||||
Stopping the transmitter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A transmitter stops sending the stream of images as a result of
|
||||
calling the ``.s_stream()`` callback. Some transmitters may stop the
|
||||
stream at a frame boundary whereas others stop immediately,
|
||||
effectively leaving the current frame unfinished. The receiver driver
|
||||
should not make assumptions either way, but function properly in both
|
||||
cases.
|
@ -140,7 +140,7 @@ ignore define CEC_OP_REC_SEQ_TUESDAY
|
||||
ignore define CEC_OP_REC_SEQ_WEDNESDAY
|
||||
ignore define CEC_OP_REC_SEQ_THURSDAY
|
||||
ignore define CEC_OP_REC_SEQ_FRIDAY
|
||||
ignore define CEC_OP_REC_SEQ_SATERDAY
|
||||
ignore define CEC_OP_REC_SEQ_SATURDAY
|
||||
ignore define CEC_OP_REC_SEQ_ONCE_ONLY
|
||||
|
||||
ignore define CEC_MSG_CLEAR_DIGITAL_TIMER
|
||||
|
@ -1174,7 +1174,24 @@ enum v4l2_mpeg_video_h264_entropy_mode -
|
||||
Cyclic intra macroblock refresh. This is the number of continuous
|
||||
macroblocks refreshed every frame. Each frame a successive set of
|
||||
macroblocks is refreshed until the cycle completes and starts from
|
||||
the top of the frame. Applicable to H264, H263 and MPEG4 encoder.
|
||||
the top of the frame. Setting this control to zero means that
|
||||
macroblocks will not be refreshed. Note that this control will not
|
||||
take effect when ``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD`` control
|
||||
is set to non zero value.
|
||||
Applicable to H264, H263 and MPEG4 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD (integer)``
|
||||
Intra macroblock refresh period. This sets the period to refresh
|
||||
the whole frame. In other words, this defines the number of frames
|
||||
for which the whole frame will be intra-refreshed. An example:
|
||||
setting period to 1 means that the whole frame will be refreshed,
|
||||
setting period to 2 means that the half of macroblocks will be
|
||||
intra-refreshed on frameX and the other half of macroblocks
|
||||
will be refreshed in frameX + 1 and so on. Setting the period to
|
||||
zero means no period is specified.
|
||||
Note that if the client sets this control to non zero value the
|
||||
``V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB`` control shall be
|
||||
ignored. Applicable to H264 and HEVC encoders.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE (boolean)``
|
||||
Frame level rate control enable. If this control is disabled then
|
||||
@ -3000,6 +3017,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
||||
* - __u8
|
||||
- ``pic_struct``
|
||||
-
|
||||
* - __u32
|
||||
- ``slice_segment_addr``
|
||||
-
|
||||
* - __u8
|
||||
- ``ref_idx_l0[V4L2_HEVC_DPB_ENTRIES_NUM_MAX]``
|
||||
- The list of L0 reference elements as indices in the DPB.
|
||||
|
@ -20,25 +20,26 @@ Image Process Control IDs
|
||||
``V4L2_CID_IMAGE_PROC_CLASS (class)``
|
||||
The IMAGE_PROC class descriptor.
|
||||
|
||||
.. _v4l2-cid-link-freq:
|
||||
|
||||
``V4L2_CID_LINK_FREQ (integer menu)``
|
||||
Data bus frequency. Together with the media bus pixel code, bus type
|
||||
(clock cycles per sample), the data bus frequency defines the pixel
|
||||
rate (``V4L2_CID_PIXEL_RATE``) in the pixel array (or possibly
|
||||
elsewhere, if the device is not an image sensor). The frame rate can
|
||||
be calculated from the pixel clock, image width and height and
|
||||
horizontal and vertical blanking. While the pixel rate control may
|
||||
be defined elsewhere than in the subdev containing the pixel array,
|
||||
the frame rate cannot be obtained from that information. This is
|
||||
because only on the pixel array it can be assumed that the vertical
|
||||
and horizontal blanking information is exact: no other blanking is
|
||||
allowed in the pixel array. The selection of frame rate is performed
|
||||
by selecting the desired horizontal and vertical blanking. The unit
|
||||
of this control is Hz.
|
||||
The frequency of the data bus (e.g. parallel or CSI-2).
|
||||
|
||||
.. _v4l2-cid-pixel-rate:
|
||||
|
||||
``V4L2_CID_PIXEL_RATE (64-bit integer)``
|
||||
Pixel rate in the source pads of the subdev. This control is
|
||||
Pixel sampling rate in the device's pixel array. This control is
|
||||
read-only and its unit is pixels / second.
|
||||
|
||||
Some devices use horizontal and vertical balanking to configure the frame
|
||||
rate. The frame rate can be calculated from the pixel rate, analogue crop
|
||||
rectangle as well as horizontal and vertical blanking. The pixel rate
|
||||
control may be present in a different sub-device than the blanking controls
|
||||
and the analogue crop rectangle configuration.
|
||||
|
||||
The configuration of the frame rate is performed by selecting the desired
|
||||
horizontal and vertical blanking. The unit of this control is Hz.
|
||||
|
||||
``V4L2_CID_TEST_PATTERN (menu)``
|
||||
Some capture/display/sensor devices have the capability to generate
|
||||
test pattern images. These hardware specific test patterns can be
|
||||
|
27
MAINTAINERS
27
MAINTAINERS
@ -13833,6 +13833,15 @@ T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/ov8856.yaml
|
||||
F: drivers/media/i2c/ov8856.c
|
||||
|
||||
OMNIVISION OV9282 SENSOR DRIVER
|
||||
M: Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
|
||||
F: drivers/media/i2c/ov9282.c
|
||||
|
||||
OMNIVISION OV9640 SENSOR DRIVER
|
||||
M: Petr Cvek <petrcvekcz@gmail.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
@ -17366,6 +17375,15 @@ T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
|
||||
F: drivers/media/i2c/imx334.c
|
||||
|
||||
SONY IMX335 SENSOR DRIVER
|
||||
M: Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx335.yaml
|
||||
F: drivers/media/i2c/imx335.c
|
||||
|
||||
SONY IMX355 SENSOR DRIVER
|
||||
M: Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
@ -17373,6 +17391,15 @@ S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: drivers/media/i2c/imx355.c
|
||||
|
||||
SONY IMX412 SENSOR DRIVER
|
||||
M: Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
|
||||
F: drivers/media/i2c/imx412.c
|
||||
|
||||
SONY MEMORYSTICK SUBSYSTEM
|
||||
M: Maxim Levitsky <maximlevitsky@gmail.com>
|
||||
M: Alex Dubov <oakad@yahoo.com>
|
||||
|
@ -209,8 +209,8 @@ struct cec_pin {
|
||||
u32 work_pin_events_dropped_cnt;
|
||||
ktime_t timer_ts;
|
||||
u32 timer_cnt;
|
||||
u32 timer_100ms_overruns;
|
||||
u32 timer_300ms_overruns;
|
||||
u32 timer_100us_overruns;
|
||||
u32 timer_300us_overruns;
|
||||
u32 timer_max_overrun;
|
||||
u32 timer_sum_overrun;
|
||||
|
||||
|
@ -854,9 +854,9 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
|
||||
if (delta > 100 && pin->state != CEC_ST_IDLE) {
|
||||
/* Keep track of timer overruns */
|
||||
pin->timer_sum_overrun += delta;
|
||||
pin->timer_100ms_overruns++;
|
||||
pin->timer_100us_overruns++;
|
||||
if (delta > 300)
|
||||
pin->timer_300ms_overruns++;
|
||||
pin->timer_300us_overruns++;
|
||||
if (delta > pin->timer_max_overrun)
|
||||
pin->timer_max_overrun = delta;
|
||||
}
|
||||
@ -1207,15 +1207,15 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
||||
seq_printf(file, "cec pin events dropped: %u\n",
|
||||
pin->work_pin_events_dropped_cnt);
|
||||
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
|
||||
if (pin->timer_100ms_overruns) {
|
||||
seq_printf(file, "timer overruns > 100ms: %u of %u\n",
|
||||
pin->timer_100ms_overruns, pin->timer_cnt);
|
||||
seq_printf(file, "timer overruns > 300ms: %u of %u\n",
|
||||
pin->timer_300ms_overruns, pin->timer_cnt);
|
||||
if (pin->timer_100us_overruns) {
|
||||
seq_printf(file, "timer overruns > 100us: %u of %u\n",
|
||||
pin->timer_100us_overruns, pin->timer_cnt);
|
||||
seq_printf(file, "timer overruns > 300us: %u of %u\n",
|
||||
pin->timer_300us_overruns, pin->timer_cnt);
|
||||
seq_printf(file, "max timer overrun: %u usecs\n",
|
||||
pin->timer_max_overrun);
|
||||
seq_printf(file, "avg timer overrun: %u usecs\n",
|
||||
pin->timer_sum_overrun / pin->timer_100ms_overruns);
|
||||
pin->timer_sum_overrun / pin->timer_100us_overruns);
|
||||
}
|
||||
if (pin->rx_start_bit_low_too_short_cnt)
|
||||
seq_printf(file,
|
||||
@ -1245,8 +1245,8 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
|
||||
seq_printf(file, "tx detected low drive: %u\n", pin->tx_low_drive_cnt);
|
||||
pin->work_pin_events_dropped_cnt = 0;
|
||||
pin->timer_cnt = 0;
|
||||
pin->timer_100ms_overruns = 0;
|
||||
pin->timer_300ms_overruns = 0;
|
||||
pin->timer_100us_overruns = 0;
|
||||
pin->timer_300us_overruns = 0;
|
||||
pin->timer_max_overrun = 0;
|
||||
pin->timer_sum_overrun = 0;
|
||||
pin->rx_start_bit_low_too_short_cnt = 0;
|
||||
|
@ -305,14 +305,16 @@ static int stm32_cec_probe(struct platform_device *pdev)
|
||||
|
||||
cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec");
|
||||
if (IS_ERR(cec->clk_hdmi_cec) &&
|
||||
PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_unprepare_cec_clk;
|
||||
}
|
||||
|
||||
if (!IS_ERR(cec->clk_hdmi_cec)) {
|
||||
ret = clk_prepare(cec->clk_hdmi_cec);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n");
|
||||
return ret;
|
||||
goto err_unprepare_cec_clk;
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,19 +326,27 @@ static int stm32_cec_probe(struct platform_device *pdev)
|
||||
CEC_NAME, caps, CEC_MAX_LOG_ADDRS);
|
||||
ret = PTR_ERR_OR_ZERO(cec->adap);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_unprepare_hdmi_cec_clk;
|
||||
|
||||
ret = cec_register_adapter(cec->adap, &pdev->dev);
|
||||
if (ret) {
|
||||
cec_delete_adapter(cec->adap);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto err_delete_adapter;
|
||||
|
||||
cec_hw_init(cec);
|
||||
|
||||
platform_set_drvdata(pdev, cec);
|
||||
|
||||
return 0;
|
||||
|
||||
err_delete_adapter:
|
||||
cec_delete_adapter(cec->adap);
|
||||
|
||||
err_unprepare_hdmi_cec_clk:
|
||||
clk_unprepare(cec->clk_hdmi_cec);
|
||||
|
||||
err_unprepare_cec_clk:
|
||||
clk_unprepare(cec->clk_cec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_cec_remove(struct platform_device *pdev)
|
||||
|
@ -366,7 +366,11 @@ static int tegra_cec_probe(struct platform_device *pdev)
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
clk_prepare_enable(cec->clk);
|
||||
ret = clk_prepare_enable(cec->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to prepare clock for CEC\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* set context info. */
|
||||
cec->dev = &pdev->dev;
|
||||
@ -446,9 +450,7 @@ static int tegra_cec_resume(struct platform_device *pdev)
|
||||
|
||||
dev_notice(&pdev->dev, "Resuming\n");
|
||||
|
||||
clk_prepare_enable(cec->clk);
|
||||
|
||||
return 0;
|
||||
return clk_prepare_enable(cec->clk);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1172,7 +1172,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
|
||||
"%s: Error attaching frontend %d\n",
|
||||
KBUILD_MODNAME, demod);
|
||||
goto error1;
|
||||
break;
|
||||
case 1:
|
||||
/* new priv instance */
|
||||
priv->i2c = i2c;
|
||||
|
@ -2107,32 +2107,55 @@ static void dib8000_load_ana_fe_coefs(struct dib8000_state *state, const s16 *an
|
||||
dib8000_write_word(state, 117 + mode, ana_fe[mode]);
|
||||
}
|
||||
|
||||
static const u16 lut_prbs_2k[14] = {
|
||||
0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
|
||||
static const u16 lut_prbs_2k[13] = {
|
||||
0x423, 0x009, 0x5C7,
|
||||
0x7A6, 0x3D8, 0x527,
|
||||
0x7FF, 0x79B, 0x3D6,
|
||||
0x3A2, 0x53B, 0x2F4,
|
||||
0x213
|
||||
};
|
||||
static const u16 lut_prbs_4k[14] = {
|
||||
0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
|
||||
|
||||
static const u16 lut_prbs_4k[13] = {
|
||||
0x208, 0x0C3, 0x7B9,
|
||||
0x423, 0x5C7, 0x3D8,
|
||||
0x7FF, 0x3D6, 0x53B,
|
||||
0x213, 0x029, 0x0D0,
|
||||
0x48E
|
||||
};
|
||||
static const u16 lut_prbs_8k[14] = {
|
||||
0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
|
||||
|
||||
static const u16 lut_prbs_8k[13] = {
|
||||
0x740, 0x069, 0x7DD,
|
||||
0x208, 0x7B9, 0x5C7,
|
||||
0x7FF, 0x53B, 0x029,
|
||||
0x48E, 0x4C4, 0x367,
|
||||
0x684
|
||||
};
|
||||
|
||||
static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
|
||||
{
|
||||
int sub_channel_prbs_group = 0;
|
||||
int prbs_group;
|
||||
|
||||
sub_channel_prbs_group = (subchannel / 3) + 1;
|
||||
dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
|
||||
sub_channel_prbs_group = subchannel / 3;
|
||||
if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k))
|
||||
return 0;
|
||||
|
||||
switch (state->fe[0]->dtv_property_cache.transmission_mode) {
|
||||
case TRANSMISSION_MODE_2K:
|
||||
return lut_prbs_2k[sub_channel_prbs_group];
|
||||
prbs_group = lut_prbs_2k[sub_channel_prbs_group];
|
||||
break;
|
||||
case TRANSMISSION_MODE_4K:
|
||||
return lut_prbs_4k[sub_channel_prbs_group];
|
||||
prbs_group = lut_prbs_4k[sub_channel_prbs_group];
|
||||
break;
|
||||
default:
|
||||
case TRANSMISSION_MODE_8K:
|
||||
return lut_prbs_8k[sub_channel_prbs_group];
|
||||
prbs_group = lut_prbs_8k[sub_channel_prbs_group];
|
||||
}
|
||||
|
||||
dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n",
|
||||
sub_channel_prbs_group, subchannel, prbs_group);
|
||||
|
||||
return prbs_group;
|
||||
}
|
||||
|
||||
static void dib8000_set_13seg_channel(struct dib8000_state *state)
|
||||
@ -2409,10 +2432,8 @@ static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq
|
||||
/* TSB or ISDBT ? apply it now */
|
||||
if (c->isdbt_sb_mode) {
|
||||
dib8000_set_sb_channel(state);
|
||||
if (c->isdbt_sb_subchannel < 14)
|
||||
init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel);
|
||||
else
|
||||
init_prbs = 0;
|
||||
init_prbs = dib8000_get_init_prbs(state,
|
||||
c->isdbt_sb_subchannel);
|
||||
} else {
|
||||
dib8000_set_13seg_channel(state);
|
||||
init_prbs = 0xfff;
|
||||
@ -3004,6 +3025,7 @@ static int dib8000_tune(struct dvb_frontend *fe)
|
||||
|
||||
unsigned long *timeout = &state->timeout;
|
||||
unsigned long now = jiffies;
|
||||
u16 init_prbs;
|
||||
#ifdef DIB8000_AGC_FREEZE
|
||||
u16 agc1, agc2;
|
||||
#endif
|
||||
@ -3302,8 +3324,10 @@ static int dib8000_tune(struct dvb_frontend *fe)
|
||||
break;
|
||||
|
||||
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
|
||||
if (state->subchannel <= 41) {
|
||||
dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
|
||||
init_prbs = dib8000_get_init_prbs(state, state->subchannel);
|
||||
|
||||
if (init_prbs) {
|
||||
dib8000_set_subchannel_prbs(state, init_prbs);
|
||||
*tune_state = CT_DEMOD_STEP_9;
|
||||
} else {
|
||||
*tune_state = CT_DEMOD_STOP;
|
||||
|
@ -842,6 +842,20 @@ config VIDEO_IMX334
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx334.
|
||||
|
||||
config VIDEO_IMX335
|
||||
tristate "Sony IMX335 sensor support"
|
||||
depends on OF_GPIO
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the Sony
|
||||
IMX335 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx335.
|
||||
|
||||
config VIDEO_IMX355
|
||||
tristate "Sony IMX355 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
@ -854,6 +868,20 @@ config VIDEO_IMX355
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx355.
|
||||
|
||||
config VIDEO_IMX412
|
||||
tristate "Sony IMX412 sensor support"
|
||||
depends on OF_GPIO
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the Sony
|
||||
IMX412 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx412.
|
||||
|
||||
config VIDEO_OV02A10
|
||||
tristate "OmniVision OV02A10 sensor support"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
@ -1103,6 +1131,20 @@ config VIDEO_OV8865
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov8865.
|
||||
|
||||
config VIDEO_OV9282
|
||||
tristate "OmniVision OV9282 sensor support"
|
||||
depends on OF_GPIO
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the OmniVision
|
||||
OV9282 camera sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov9282.
|
||||
|
||||
config VIDEO_OV9640
|
||||
tristate "OmniVision OV9640 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
|
@ -84,6 +84,7 @@ obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
|
||||
obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
|
||||
obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
|
||||
obj-$(CONFIG_VIDEO_OV8865) += ov8865.o
|
||||
obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
|
||||
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
|
||||
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
|
||||
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
|
||||
@ -124,11 +125,12 @@ obj-$(CONFIG_VIDEO_IMX274) += imx274.o
|
||||
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
|
||||
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
|
||||
obj-$(CONFIG_VIDEO_IMX334) += imx334.o
|
||||
obj-$(CONFIG_VIDEO_IMX335) += imx335.o
|
||||
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
|
||||
obj-$(CONFIG_VIDEO_IMX412) += imx412.o
|
||||
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
|
||||
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
|
||||
obj-$(CONFIG_VIDEO_RDACM20) += rdacm20.o
|
||||
obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
|
||||
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
|
||||
|
||||
obj-$(CONFIG_SDR_MAX2175) += max2175.o
|
||||
|
@ -94,6 +94,7 @@
|
||||
#define ADV7180_REG_SHAP_FILTER_CTL_1 0x0017
|
||||
#define ADV7180_REG_CTRL_2 0x001d
|
||||
#define ADV7180_REG_VSYNC_FIELD_CTL_1 0x0031
|
||||
#define ADV7180_VSYNC_FIELD_CTL_1_NEWAV 0x12
|
||||
#define ADV7180_REG_MANUAL_WIN_CTL_1 0x003d
|
||||
#define ADV7180_REG_MANUAL_WIN_CTL_2 0x003e
|
||||
#define ADV7180_REG_MANUAL_WIN_CTL_3 0x003f
|
||||
@ -205,6 +206,7 @@ struct adv7180_state {
|
||||
struct mutex mutex; /* mutual excl. when accessing chip */
|
||||
int irq;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
struct gpio_desc *rst_gpio;
|
||||
v4l2_std_id curr_norm;
|
||||
bool powered;
|
||||
bool streaming;
|
||||
@ -216,6 +218,7 @@ struct adv7180_state {
|
||||
struct i2c_client *vpp_client;
|
||||
const struct adv7180_chip_info *chip_info;
|
||||
enum v4l2_field field;
|
||||
bool force_bt656_4;
|
||||
};
|
||||
#define to_adv7180_sd(_ctrl) (&container_of(_ctrl->handler, \
|
||||
struct adv7180_state, \
|
||||
@ -484,6 +487,19 @@ static void adv7180_set_power_pin(struct adv7180_state *state, bool on)
|
||||
}
|
||||
}
|
||||
|
||||
static void adv7180_set_reset_pin(struct adv7180_state *state, bool on)
|
||||
{
|
||||
if (!state->rst_gpio)
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
gpiod_set_value_cansleep(state->rst_gpio, 1);
|
||||
} else {
|
||||
gpiod_set_value_cansleep(state->rst_gpio, 0);
|
||||
usleep_range(5000, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
static int adv7180_set_power(struct adv7180_state *state, bool on)
|
||||
{
|
||||
u8 val;
|
||||
@ -963,10 +979,26 @@ static int adv7182_init(struct adv7180_state *state)
|
||||
adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
|
||||
adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
|
||||
} else {
|
||||
if (state->chip_info->flags & ADV7180_FLAG_V2)
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
|
||||
0x17);
|
||||
if (state->chip_info->flags & ADV7180_FLAG_V2) {
|
||||
if (state->force_bt656_4) {
|
||||
/* ITU-R BT.656-4 compatible */
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
|
||||
ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
|
||||
/* Manually set NEWAVMODE */
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_VSYNC_FIELD_CTL_1,
|
||||
ADV7180_VSYNC_FIELD_CTL_1_NEWAV);
|
||||
/* Manually set V bit end position in NTSC mode */
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_NTSC_V_BIT_END,
|
||||
ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
|
||||
} else {
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
|
||||
0x17);
|
||||
}
|
||||
}
|
||||
else
|
||||
adv7180_write(state,
|
||||
ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
|
||||
@ -1263,6 +1295,7 @@ static int init_device(struct adv7180_state *state)
|
||||
mutex_lock(&state->mutex);
|
||||
|
||||
adv7180_set_power_pin(state, true);
|
||||
adv7180_set_reset_pin(state, false);
|
||||
|
||||
adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES);
|
||||
usleep_range(5000, 10000);
|
||||
@ -1314,6 +1347,7 @@ out_unlock:
|
||||
static int adv7180_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct adv7180_state *state;
|
||||
struct v4l2_subdev *sd;
|
||||
int ret;
|
||||
@ -1338,6 +1372,17 @@ static int adv7180_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
}
|
||||
|
||||
state->rst_gpio = devm_gpiod_get_optional(&client->dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(state->rst_gpio)) {
|
||||
ret = PTR_ERR(state->rst_gpio);
|
||||
v4l_err(client, "request for reset pin failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "adv,force-bt656-4"))
|
||||
state->force_bt656_4 = true;
|
||||
|
||||
if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
|
||||
state->csi_client = i2c_new_dummy_device(client->adapter,
|
||||
ADV7180_DEFAULT_CSI_I2C_ADDR);
|
||||
@ -1392,11 +1437,19 @@ static int adv7180_probe(struct i2c_client *client,
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
|
||||
v4l_info(client, "chip found @ 0x%02x (%s)\n",
|
||||
client->addr, client->adapter->name);
|
||||
mutex_lock(&state->mutex);
|
||||
ret = adv7180_read(state, ADV7180_REG_IDENT);
|
||||
mutex_unlock(&state->mutex);
|
||||
if (ret < 0)
|
||||
goto err_v4l2_async_unregister;
|
||||
|
||||
v4l_info(client, "chip id 0x%x found @ 0x%02x (%s)\n",
|
||||
ret, client->addr, client->adapter->name);
|
||||
|
||||
return 0;
|
||||
|
||||
err_v4l2_async_unregister:
|
||||
v4l2_async_unregister_subdev(sd);
|
||||
err_free_irq:
|
||||
if (state->irq > 0)
|
||||
free_irq(client->irq, state);
|
||||
@ -1428,6 +1481,7 @@ static int adv7180_remove(struct i2c_client *client)
|
||||
i2c_unregister_device(state->vpp_client);
|
||||
i2c_unregister_device(state->csi_client);
|
||||
|
||||
adv7180_set_reset_pin(state, true);
|
||||
adv7180_set_power_pin(state, false);
|
||||
|
||||
mutex_destroy(&state->mutex);
|
||||
|
@ -1943,6 +1943,51 @@ static int ccs_set_stream(struct v4l2_subdev *subdev, int enable)
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int ccs_pre_streamon(struct v4l2_subdev *subdev, u32 flags)
|
||||
{
|
||||
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
int rval;
|
||||
|
||||
if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
|
||||
switch (sensor->hwcfg.csi_signalling_mode) {
|
||||
case CCS_CSI_SIGNALING_MODE_CSI_2_DPHY:
|
||||
if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
|
||||
CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_DPHY))
|
||||
return -EACCES;
|
||||
break;
|
||||
case CCS_CSI_SIGNALING_MODE_CSI_2_CPHY:
|
||||
if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY_2) &
|
||||
CCS_PHY_CTRL_CAPABILITY_2_MANUAL_LP_CPHY))
|
||||
return -EACCES;
|
||||
break;
|
||||
default:
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
rval = ccs_pm_get_init(sensor);
|
||||
if (rval)
|
||||
return rval;
|
||||
|
||||
if (flags & V4L2_SUBDEV_PRE_STREAMON_FL_MANUAL_LP) {
|
||||
rval = ccs_write(sensor, MANUAL_LP_CTRL,
|
||||
CCS_MANUAL_LP_CTRL_ENABLE);
|
||||
if (rval)
|
||||
pm_runtime_put(&client->dev);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int ccs_post_streamoff(struct v4l2_subdev *subdev)
|
||||
{
|
||||
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
|
||||
return pm_runtime_put(&client->dev);
|
||||
}
|
||||
|
||||
static int ccs_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||
struct v4l2_subdev_state *sd_state,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
@ -2673,8 +2718,7 @@ static int ccs_get_skip_top_lines(struct v4l2_subdev *subdev, u32 *lines)
|
||||
*/
|
||||
|
||||
static ssize_t
|
||||
ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
nvm_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
@ -2704,11 +2748,10 @@ ccs_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
|
||||
*/
|
||||
return rval;
|
||||
}
|
||||
static DEVICE_ATTR(nvm, S_IRUGO, ccs_sysfs_nvm_read, NULL);
|
||||
static DEVICE_ATTR_RO(nvm);
|
||||
|
||||
static ssize_t
|
||||
ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
ident_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
|
||||
struct ccs_sensor *sensor = to_ccs_sensor(subdev);
|
||||
@ -2723,8 +2766,7 @@ ccs_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
|
||||
minfo->smia_manufacturer_id, minfo->model_id,
|
||||
minfo->revision_number) + 1;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(ident, S_IRUGO, ccs_sysfs_ident_read, NULL);
|
||||
static DEVICE_ATTR_RO(ident);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* V4L2 subdev core operations
|
||||
@ -3058,6 +3100,8 @@ static int ccs_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
|
||||
static const struct v4l2_subdev_video_ops ccs_video_ops = {
|
||||
.s_stream = ccs_set_stream,
|
||||
.pre_streamon = ccs_pre_streamon,
|
||||
.post_streamoff = ccs_post_streamoff,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops ccs_pad_ops = {
|
||||
|
@ -1237,8 +1237,7 @@ out_poweroff:
|
||||
* sysfs attributes
|
||||
*/
|
||||
static ssize_t
|
||||
et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
priv_mem_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct v4l2_subdev *subdev = dev_get_drvdata(dev);
|
||||
struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
|
||||
@ -1251,7 +1250,7 @@ et8ek8_priv_mem_read(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
return ET8EK8_PRIV_MEM_SIZE;
|
||||
}
|
||||
static DEVICE_ATTR(priv_mem, 0444, et8ek8_priv_mem_read, NULL);
|
||||
static DEVICE_ATTR_RO(priv_mem);
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* V4L2 subdev core operations
|
||||
|
@ -23,7 +23,7 @@
|
||||
#define IMX258_CHIP_ID 0x0258
|
||||
|
||||
/* V_TIMING internal */
|
||||
#define IMX258_VTS_30FPS 0x0c98
|
||||
#define IMX258_VTS_30FPS 0x0c50
|
||||
#define IMX258_VTS_30FPS_2K 0x0638
|
||||
#define IMX258_VTS_30FPS_VGA 0x034c
|
||||
#define IMX258_VTS_MAX 0xffff
|
||||
@ -47,7 +47,7 @@
|
||||
/* Analog gain control */
|
||||
#define IMX258_REG_ANALOG_GAIN 0x0204
|
||||
#define IMX258_ANA_GAIN_MIN 0
|
||||
#define IMX258_ANA_GAIN_MAX 0x1fff
|
||||
#define IMX258_ANA_GAIN_MAX 480
|
||||
#define IMX258_ANA_GAIN_STEP 1
|
||||
#define IMX258_ANA_GAIN_DEFAULT 0x0
|
||||
|
||||
|
1129
drivers/media/i2c/imx335.c
Normal file
1129
drivers/media/i2c/imx335.c
Normal file
File diff suppressed because it is too large
Load Diff
1272
drivers/media/i2c/imx412.c
Normal file
1272
drivers/media/i2c/imx412.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@
|
||||
#define OV2740_REG_MWB_R_GAIN 0x500a
|
||||
#define OV2740_REG_MWB_G_GAIN 0x500c
|
||||
#define OV2740_REG_MWB_B_GAIN 0x500e
|
||||
#define OV2740_DGTL_GAIN_MIN 0
|
||||
#define OV2740_DGTL_GAIN_MIN 1024
|
||||
#define OV2740_DGTL_GAIN_MAX 4095
|
||||
#define OV2740_DGTL_GAIN_STEP 1
|
||||
#define OV2740_DGTL_GAIN_DEFAULT 1024
|
||||
@ -61,6 +61,12 @@
|
||||
#define OV2740_TEST_PATTERN_ENABLE BIT(7)
|
||||
#define OV2740_TEST_PATTERN_BAR_SHIFT 2
|
||||
|
||||
/* Group Access */
|
||||
#define OV2740_REG_GROUP_ACCESS 0x3208
|
||||
#define OV2740_GROUP_HOLD_START 0x0
|
||||
#define OV2740_GROUP_HOLD_END 0x10
|
||||
#define OV2740_GROUP_HOLD_LAUNCH 0xa0
|
||||
|
||||
/* ISP CTRL00 */
|
||||
#define OV2740_REG_ISP_CTRL00 0x5000
|
||||
/* ISP CTRL01 */
|
||||
@ -438,6 +444,11 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
|
||||
OV2740_GROUP_HOLD_START);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_R_GAIN, 2, d_gain);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -446,7 +457,18 @@ static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
|
||||
ret = ov2740_write_reg(ov2740, OV2740_REG_MWB_B_GAIN, 2, d_gain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
|
||||
OV2740_GROUP_HOLD_END);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov2740_write_reg(ov2740, OV2740_REG_GROUP_ACCESS, 1,
|
||||
OV2740_GROUP_HOLD_LAUNCH);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov2740_test_pattern(struct ov2740 *ov2740, u32 pattern)
|
||||
|
@ -135,7 +135,9 @@ struct ov5640_pixfmt {
|
||||
static const struct ov5640_pixfmt ov5640_formats[] = {
|
||||
{ MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
|
||||
{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_UYVY8_1X16, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_YUYV8_1X16, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
|
||||
{ MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
|
||||
@ -2338,11 +2340,13 @@ static int ov5640_set_framefmt(struct ov5640_dev *sensor,
|
||||
u8 fmt, mux;
|
||||
|
||||
switch (format->code) {
|
||||
case MEDIA_BUS_FMT_UYVY8_1X16:
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
/* YUV422, UYVY */
|
||||
fmt = 0x3f;
|
||||
mux = OV5640_FMT_MUX_YUV422;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_YUYV8_1X16:
|
||||
case MEDIA_BUS_FMT_YUYV8_2X8:
|
||||
/* YUV422, YUYV */
|
||||
fmt = 0x30;
|
||||
|
@ -2304,25 +2304,26 @@ static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
|
||||
|
||||
clk_set_rate(ov8856->xvclk, xvclk_rate);
|
||||
xvclk_rate = clk_get_rate(ov8856->xvclk);
|
||||
|
||||
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ov8856->reset_gpio))
|
||||
return PTR_ERR(ov8856->reset_gpio);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
|
||||
ov8856->supplies[i].supply = ov8856_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev,
|
||||
ARRAY_SIZE(ov8856_supply_names),
|
||||
ov8856->supplies);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (xvclk_rate != OV8856_XVCLK_19_2)
|
||||
dev_warn(dev, "external clock rate %u is unsupported",
|
||||
xvclk_rate);
|
||||
|
||||
ov8856->reset_gpio = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ov8856->reset_gpio))
|
||||
return PTR_ERR(ov8856->reset_gpio);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ov8856_supply_names); i++)
|
||||
ov8856->supplies[i].supply = ov8856_supply_names[i];
|
||||
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ov8856_supply_names),
|
||||
ov8856->supplies);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
|
||||
if (!ep)
|
||||
return -ENXIO;
|
||||
|
1137
drivers/media/i2c/ov9282.c
Normal file
1137
drivers/media/i2c/ov9282.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -60,6 +60,12 @@
|
||||
#define OV9734_TEST_PATTERN_ENABLE BIT(7)
|
||||
#define OV9734_TEST_PATTERN_BAR_SHIFT 2
|
||||
|
||||
/* Group Access */
|
||||
#define OV9734_REG_GROUP_ACCESS 0x3208
|
||||
#define OV9734_GROUP_HOLD_START 0x0
|
||||
#define OV9734_GROUP_HOLD_END 0x10
|
||||
#define OV9734_GROUP_HOLD_LAUNCH 0xa0
|
||||
|
||||
enum {
|
||||
OV9734_LINK_FREQ_180MHZ_INDEX,
|
||||
};
|
||||
@ -433,6 +439,11 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
|
||||
OV9734_GROUP_HOLD_START);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_R_GAIN, 2, d_gain);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -441,7 +452,18 @@ static int ov9734_update_digital_gain(struct ov9734 *ov9734, u32 d_gain)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
|
||||
ret = ov9734_write_reg(ov9734, OV9734_REG_MWB_B_GAIN, 2, d_gain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
|
||||
OV9734_GROUP_HOLD_END);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov9734_write_reg(ov9734, OV9734_REG_GROUP_ACCESS, 1,
|
||||
OV9734_GROUP_HOLD_LAUNCH);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov9734_test_pattern(struct ov9734 *ov9734, u32 pattern)
|
||||
|
@ -563,7 +563,7 @@ static void tda1997x_delayed_work_enable_hpd(struct work_struct *work)
|
||||
delayed_work_enable_hpd);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
|
||||
v4l2_dbg(2, debug, sd, "%s:\n", __func__);
|
||||
v4l2_dbg(2, debug, sd, "%s\n", __func__);
|
||||
|
||||
/* Set HPD high */
|
||||
tda1997x_manual_hpd(sd, HPD_HIGH_OTHER);
|
||||
@ -1107,7 +1107,8 @@ tda1997x_detect_std(struct tda1997x_state *state,
|
||||
hper = io_read16(sd, REG_H_PER) & MASK_HPER;
|
||||
hsper = io_read16(sd, REG_HS_WIDTH) & MASK_HSWIDTH;
|
||||
v4l2_dbg(1, debug, sd, "Signal Timings: %u/%u/%u\n", vper, hper, hsper);
|
||||
if (!vper || !hper || !hsper)
|
||||
|
||||
if (!state->input_detect[0] && !state->input_detect[1])
|
||||
return -ENOLINK;
|
||||
|
||||
for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
|
||||
@ -1695,14 +1696,15 @@ static int tda1997x_query_dv_timings(struct v4l2_subdev *sd,
|
||||
struct v4l2_dv_timings *timings)
|
||||
{
|
||||
struct tda1997x_state *state = to_state(sd);
|
||||
int ret;
|
||||
|
||||
v4l_dbg(1, debug, state->client, "%s\n", __func__);
|
||||
memset(timings, 0, sizeof(struct v4l2_dv_timings));
|
||||
mutex_lock(&state->lock);
|
||||
tda1997x_detect_std(state, timings);
|
||||
ret = tda1997x_detect_std(state, timings);
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_video_ops tda1997x_video_ops = {
|
||||
@ -2233,6 +2235,7 @@ static int tda1997x_core_init(struct v4l2_subdev *sd)
|
||||
/* get initial HDMI status */
|
||||
state->hdmi_status = io_read(sd, REG_HDMI_FLAGS);
|
||||
|
||||
io_write(sd, REG_EDID_ENABLE, EDID_ENABLE_A_EN | EDID_ENABLE_B_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -964,7 +964,7 @@ static int tvp5150_enable(struct v4l2_subdev *sd)
|
||||
|
||||
/*
|
||||
* Enable the YCbCr and clock outputs. In discrete sync mode
|
||||
* (non-BT.656) additionally enable the the sync outputs.
|
||||
* (non-BT.656) additionally enable the sync outputs.
|
||||
*/
|
||||
switch (decoder->mbus_type) {
|
||||
case V4L2_MBUS_PARALLEL:
|
||||
|
@ -556,7 +556,7 @@ static const struct media_file_operations media_device_fops = {
|
||||
* sysfs
|
||||
*/
|
||||
|
||||
static ssize_t show_model(struct device *cd,
|
||||
static ssize_t model_show(struct device *cd,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct media_devnode *devnode = to_media_devnode(cd);
|
||||
@ -565,7 +565,7 @@ static ssize_t show_model(struct device *cd,
|
||||
return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
|
||||
static DEVICE_ATTR_RO(model);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Registration/unregistration
|
||||
|
@ -78,27 +78,53 @@
|
||||
#define IVTV_PCI_ID_SONY 0x104d
|
||||
|
||||
/* hardware flags, no gaps allowed */
|
||||
#define IVTV_HW_CX25840 (1 << 0)
|
||||
#define IVTV_HW_SAA7115 (1 << 1)
|
||||
#define IVTV_HW_SAA7127 (1 << 2)
|
||||
#define IVTV_HW_MSP34XX (1 << 3)
|
||||
#define IVTV_HW_TUNER (1 << 4)
|
||||
#define IVTV_HW_WM8775 (1 << 5)
|
||||
#define IVTV_HW_CS53L32A (1 << 6)
|
||||
#define IVTV_HW_TVEEPROM (1 << 7)
|
||||
#define IVTV_HW_SAA7114 (1 << 8)
|
||||
#define IVTV_HW_UPD64031A (1 << 9)
|
||||
#define IVTV_HW_UPD6408X (1 << 10)
|
||||
#define IVTV_HW_SAA717X (1 << 11)
|
||||
#define IVTV_HW_WM8739 (1 << 12)
|
||||
#define IVTV_HW_VP27SMPX (1 << 13)
|
||||
#define IVTV_HW_M52790 (1 << 14)
|
||||
#define IVTV_HW_GPIO (1 << 15)
|
||||
#define IVTV_HW_I2C_IR_RX_AVER (1 << 16)
|
||||
#define IVTV_HW_I2C_IR_RX_HAUP_EXT (1 << 17) /* External before internal */
|
||||
#define IVTV_HW_I2C_IR_RX_HAUP_INT (1 << 18)
|
||||
#define IVTV_HW_Z8F0811_IR_HAUP (1 << 19)
|
||||
#define IVTV_HW_I2C_IR_RX_ADAPTEC (1 << 20)
|
||||
enum ivtv_hw_bits {
|
||||
IVTV_HW_BIT_CX25840,
|
||||
IVTV_HW_BIT_SAA7115,
|
||||
IVTV_HW_BIT_SAA7127,
|
||||
IVTV_HW_BIT_MSP34XX,
|
||||
IVTV_HW_BIT_TUNER,
|
||||
IVTV_HW_BIT_WM8775,
|
||||
IVTV_HW_BIT_CS53L32A,
|
||||
IVTV_HW_BIT_TVEEPROM,
|
||||
IVTV_HW_BIT_SAA7114,
|
||||
IVTV_HW_BIT_UPD64031A,
|
||||
IVTV_HW_BIT_UPD6408X,
|
||||
IVTV_HW_BIT_SAA717X,
|
||||
IVTV_HW_BIT_WM8739,
|
||||
IVTV_HW_BIT_VP27SMPX,
|
||||
IVTV_HW_BIT_M52790,
|
||||
IVTV_HW_BIT_GPIO,
|
||||
IVTV_HW_BIT_I2C_IR_RX_AVER,
|
||||
IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT, /* External before internal */
|
||||
IVTV_HW_BIT_I2C_IR_RX_HAUP_INT,
|
||||
IVTV_HW_BIT_Z8F0811_IR_HAUP,
|
||||
IVTV_HW_BIT_I2C_IR_RX_ADAPTEC,
|
||||
|
||||
IVTV_HW_MAX_BITS /* Should be the last one */
|
||||
};
|
||||
|
||||
#define IVTV_HW_CX25840 BIT(IVTV_HW_BIT_CX25840)
|
||||
#define IVTV_HW_SAA7115 BIT(IVTV_HW_BIT_SAA7115)
|
||||
#define IVTV_HW_SAA7127 BIT(IVTV_HW_BIT_SAA7127)
|
||||
#define IVTV_HW_MSP34XX BIT(IVTV_HW_BIT_MSP34XX)
|
||||
#define IVTV_HW_TUNER BIT(IVTV_HW_BIT_TUNER)
|
||||
#define IVTV_HW_WM8775 BIT(IVTV_HW_BIT_WM8775)
|
||||
#define IVTV_HW_CS53L32A BIT(IVTV_HW_BIT_CS53L32A)
|
||||
#define IVTV_HW_TVEEPROM BIT(IVTV_HW_BIT_TVEEPROM)
|
||||
#define IVTV_HW_SAA7114 BIT(IVTV_HW_BIT_SAA7114)
|
||||
#define IVTV_HW_UPD64031A BIT(IVTV_HW_BIT_UPD64031A)
|
||||
#define IVTV_HW_UPD6408X BIT(IVTV_HW_BIT_UPD6408X)
|
||||
#define IVTV_HW_SAA717X BIT(IVTV_HW_BIT_SAA717X)
|
||||
#define IVTV_HW_WM8739 BIT(IVTV_HW_BIT_WM8739)
|
||||
#define IVTV_HW_VP27SMPX BIT(IVTV_HW_BIT_VP27SMPX)
|
||||
#define IVTV_HW_M52790 BIT(IVTV_HW_BIT_M52790)
|
||||
#define IVTV_HW_GPIO BIT(IVTV_HW_BIT_GPIO)
|
||||
#define IVTV_HW_I2C_IR_RX_AVER BIT(IVTV_HW_BIT_I2C_IR_RX_AVER)
|
||||
#define IVTV_HW_I2C_IR_RX_HAUP_EXT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_EXT)
|
||||
#define IVTV_HW_I2C_IR_RX_HAUP_INT BIT(IVTV_HW_BIT_I2C_IR_RX_HAUP_INT)
|
||||
#define IVTV_HW_Z8F0811_IR_HAUP BIT(IVTV_HW_BIT_Z8F0811_IR_HAUP)
|
||||
#define IVTV_HW_I2C_IR_RX_ADAPTEC BIT(IVTV_HW_BIT_I2C_IR_RX_ADAPTEC)
|
||||
|
||||
#define IVTV_HW_SAA711X (IVTV_HW_SAA7115 | IVTV_HW_SAA7114)
|
||||
|
||||
|
@ -85,7 +85,7 @@
|
||||
#define IVTV_ADAPTEC_IR_ADDR 0x6b
|
||||
|
||||
/* This array should match the IVTV_HW_ defines */
|
||||
static const u8 hw_addrs[] = {
|
||||
static const u8 hw_addrs[IVTV_HW_MAX_BITS] = {
|
||||
IVTV_CX25840_I2C_ADDR,
|
||||
IVTV_SAA7115_I2C_ADDR,
|
||||
IVTV_SAA7127_I2C_ADDR,
|
||||
@ -110,7 +110,7 @@ static const u8 hw_addrs[] = {
|
||||
};
|
||||
|
||||
/* This array should match the IVTV_HW_ defines */
|
||||
static const char * const hw_devicenames[] = {
|
||||
static const char * const hw_devicenames[IVTV_HW_MAX_BITS] = {
|
||||
"cx25840",
|
||||
"saa7115",
|
||||
"saa7127_auto", /* saa7127 or saa7129 */
|
||||
@ -240,10 +240,16 @@ void ivtv_i2c_new_ir_legacy(struct ivtv *itv)
|
||||
|
||||
int ivtv_i2c_register(struct ivtv *itv, unsigned idx)
|
||||
{
|
||||
struct v4l2_subdev *sd;
|
||||
struct i2c_adapter *adap = &itv->i2c_adap;
|
||||
const char *type = hw_devicenames[idx];
|
||||
u32 hw = 1 << idx;
|
||||
struct v4l2_subdev *sd;
|
||||
const char *type;
|
||||
u32 hw;
|
||||
|
||||
if (idx >= IVTV_HW_MAX_BITS)
|
||||
return -ENODEV;
|
||||
|
||||
type = hw_devicenames[idx];
|
||||
hw = 1 << idx;
|
||||
|
||||
if (hw == IVTV_HW_TUNER) {
|
||||
/* special tuner handling */
|
||||
|
@ -1215,15 +1215,13 @@ static int alsa_device_exit(struct saa7134_dev *dev)
|
||||
static int saa7134_alsa_init(void)
|
||||
{
|
||||
struct saa7134_dev *dev = NULL;
|
||||
struct list_head *list;
|
||||
|
||||
saa7134_dmasound_init = alsa_device_init;
|
||||
saa7134_dmasound_exit = alsa_device_exit;
|
||||
|
||||
pr_info("saa7134 ALSA driver for DMA sound loaded\n");
|
||||
|
||||
list_for_each(list,&saa7134_devlist) {
|
||||
dev = list_entry(list, struct saa7134_dev, devlist);
|
||||
list_for_each_entry(dev, &saa7134_devlist, devlist) {
|
||||
if (dev->pci->device == PCI_DEVICE_ID_PHILIPS_SAA7130)
|
||||
pr_info("%s/alsa: %s doesn't support digital audio\n",
|
||||
dev->name, saa7134_boards[dev->board].name);
|
||||
|
@ -223,7 +223,8 @@ int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
|
||||
__le32 *cpu;
|
||||
dma_addr_t dma_addr = 0;
|
||||
|
||||
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
|
||||
cpu = dma_alloc_coherent(&pci->dev, SAA7134_PGTABLE_SIZE, &dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (NULL == cpu)
|
||||
return -ENOMEM;
|
||||
pt->size = SAA7134_PGTABLE_SIZE;
|
||||
@ -254,7 +255,7 @@ void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
|
||||
{
|
||||
if (NULL == pt->cpu)
|
||||
return;
|
||||
pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
|
||||
dma_free_coherent(&pci->dev, pt->size, pt->cpu, pt->dma);
|
||||
pt->cpu = NULL;
|
||||
}
|
||||
|
||||
@ -1092,7 +1093,7 @@ static int saa7134_initdev(struct pci_dev *pci_dev,
|
||||
dev->pci_lat,
|
||||
(unsigned long long)pci_resource_start(pci_dev, 0));
|
||||
pci_set_master(pci_dev);
|
||||
err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
|
||||
err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
|
||||
if (err) {
|
||||
pr_warn("%s: Oops: no 32bit PCI DMA ???\n", dev->name);
|
||||
goto err_v4l2_unregister;
|
||||
|
@ -549,9 +549,6 @@ int saa7164_cmd_send(struct saa7164_dev *dev, u8 id, enum tmComResCmd command,
|
||||
/* See of other commands are on the bus */
|
||||
if (saa7164_cmd_dequeue(dev) != SAA_OK)
|
||||
printk(KERN_ERR "dequeue(3) failed\n");
|
||||
|
||||
continue;
|
||||
|
||||
} /* (loop) */
|
||||
|
||||
/* Release the sequence number allocation */
|
||||
|
@ -663,7 +663,7 @@
|
||||
#define TW5864_SYNC 0x8008
|
||||
/* Define controls in register TW5864_SYNC */
|
||||
/*
|
||||
* 0 vlc stream to syncrous port
|
||||
* 0 vlc stream to synchronous port
|
||||
* 1 vlc stream to ddr buffers
|
||||
*/
|
||||
#define TW5864_SYNC_CFG BIT(7)
|
||||
|
@ -255,6 +255,23 @@ static void isc_sama5d2_config_rlp(struct isc_device *isc)
|
||||
struct regmap *regmap = isc->regmap;
|
||||
u32 rlp_mode = isc->config.rlp_cfg_mode;
|
||||
|
||||
/*
|
||||
* In sama5d2, the YUV planar modes and the YUYV modes are treated
|
||||
* in the same way in RLP register.
|
||||
* Normally, YYCC mode should be Luma(n) - Color B(n) - Color R (n)
|
||||
* and YCYC should be Luma(n + 1) - Color B (n) - Luma (n) - Color R (n)
|
||||
* but in sama5d2, the YCYC mode does not exist, and YYCC must be
|
||||
* selected for both planar and interleaved modes, as in fact
|
||||
* both modes are supported.
|
||||
*
|
||||
* Thus, if the YCYC mode is selected, replace it with the
|
||||
* sama5d2-compliant mode which is YYCC .
|
||||
*/
|
||||
if ((rlp_mode & ISC_RLP_CFG_MODE_YCYC) == ISC_RLP_CFG_MODE_YCYC) {
|
||||
rlp_mode &= ~ISC_RLP_CFG_MODE_MASK;
|
||||
rlp_mode |= ISC_RLP_CFG_MODE_YYCC;
|
||||
}
|
||||
|
||||
regmap_update_bits(regmap, ISC_RLP_CFG + isc->offsets.rlp,
|
||||
ISC_RLP_CFG_MODE_MASK, rlp_mode);
|
||||
}
|
||||
|
@ -2053,17 +2053,25 @@ static int __coda_start_decoding(struct coda_ctx *ctx)
|
||||
u32 src_fourcc, dst_fourcc;
|
||||
int ret;
|
||||
|
||||
if (!ctx->initialized) {
|
||||
ret = __coda_decoder_seq_init(ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
|
||||
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
|
||||
src_fourcc = q_data_src->fourcc;
|
||||
dst_fourcc = q_data_dst->fourcc;
|
||||
|
||||
if (!ctx->initialized) {
|
||||
ret = __coda_decoder_seq_init(ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
|
||||
CODA9_FRAME_TILED2LINEAR);
|
||||
if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
|
||||
ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
|
||||
if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
|
||||
ctx->frame_mem_ctrl |= (0x3 << 9) |
|
||||
((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
|
||||
}
|
||||
|
||||
coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
|
||||
|
||||
ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
|
||||
|
@ -189,7 +189,7 @@ int vpfe_register_ccdc_device(const struct ccdc_hw_device *dev)
|
||||
if (!ccdc_cfg) {
|
||||
/*
|
||||
* TODO. Will this ever happen? if so, we need to fix it.
|
||||
* Proabably we need to add the request to a linked list and
|
||||
* Probably we need to add the request to a linked list and
|
||||
* walk through it during vpfe probe
|
||||
*/
|
||||
printk(KERN_ERR "vpfe capture not initialized\n");
|
||||
|
@ -1238,8 +1238,8 @@ static const struct media_device_ops fimc_md_ops = {
|
||||
.link_notify = fimc_md_link_notify,
|
||||
};
|
||||
|
||||
static ssize_t fimc_md_sysfs_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t subdev_conf_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fimc_md *fmd = dev_get_drvdata(dev);
|
||||
|
||||
@ -1249,9 +1249,9 @@ static ssize_t fimc_md_sysfs_show(struct device *dev,
|
||||
return strscpy(buf, "V4L2 video node only API (vid-dev)\n", PAGE_SIZE);
|
||||
}
|
||||
|
||||
static ssize_t fimc_md_sysfs_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t subdev_conf_mode_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fimc_md *fmd = dev_get_drvdata(dev);
|
||||
bool subdev_api;
|
||||
@ -1278,8 +1278,7 @@ static ssize_t fimc_md_sysfs_store(struct device *dev,
|
||||
* sub-dev - for media controller API, subdevs must be configured in user
|
||||
* space before starting streaming.
|
||||
*/
|
||||
static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO,
|
||||
fimc_md_sysfs_show, fimc_md_sysfs_store);
|
||||
static DEVICE_ATTR_RW(subdev_conf_mode);
|
||||
|
||||
static int cam_clk_prepare(struct clk_hw *hw)
|
||||
{
|
||||
|
@ -692,7 +692,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame)
|
||||
* Scatter/gather mode requires stopping the controller between
|
||||
* frames so we can put in a new DMA descriptor array. If no new
|
||||
* buffer exists at frame completion, the controller is left stopped;
|
||||
* this function is charged with gettig things going again.
|
||||
* this function is charged with getting things going again.
|
||||
*/
|
||||
static void mcam_sg_restart(struct mcam_camera *cam)
|
||||
{
|
||||
|
@ -2037,8 +2037,10 @@ static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
|
||||
mutex_lock(&isp->media_dev.graph_mutex);
|
||||
|
||||
ret = media_entity_enum_init(&isp->crashed, &isp->media_dev);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
mutex_unlock(&isp->media_dev.graph_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
|
||||
if (sd->notifier != &isp->notifier)
|
||||
|
@ -234,6 +234,7 @@ struct venc_controls {
|
||||
u32 h264_loop_filter_mode;
|
||||
s32 h264_loop_filter_alpha;
|
||||
s32 h264_loop_filter_beta;
|
||||
u32 h264_8x8_transform;
|
||||
|
||||
u32 hevc_i_qp;
|
||||
u32 hevc_p_qp;
|
||||
@ -256,6 +257,7 @@ struct venc_controls {
|
||||
|
||||
u32 header_mode;
|
||||
bool aud_enable;
|
||||
u32 intra_refresh_period;
|
||||
|
||||
struct {
|
||||
u32 h264;
|
||||
|
@ -1137,6 +1137,9 @@ int venus_helper_set_format_constraints(struct venus_inst *inst)
|
||||
if (!IS_V6(inst->core))
|
||||
return 0;
|
||||
|
||||
if (inst->opb_fmt == HFI_COLOR_FORMAT_NV12_UBWC)
|
||||
return 0;
|
||||
|
||||
pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
|
||||
pconstraint.num_planes = 2;
|
||||
pconstraint.plane_format[0].stride_multiples = 128;
|
||||
|
@ -1239,6 +1239,14 @@ pkt_session_set_property_4xx(struct hfi_session_set_property_pkt *pkt,
|
||||
break;
|
||||
}
|
||||
|
||||
case HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8: {
|
||||
struct hfi_h264_8x8_transform *in = pdata, *tm = prop_data;
|
||||
|
||||
tm->enable_type = in->enable_type;
|
||||
pkt->shdr.hdr.size += sizeof(u32) + sizeof(*tm);
|
||||
break;
|
||||
}
|
||||
|
||||
case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
|
||||
case HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
|
||||
case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE:
|
||||
|
@ -507,6 +507,7 @@
|
||||
#define HFI_PROPERTY_PARAM_VENC_MAX_NUM_B_FRAMES 0x2005020
|
||||
#define HFI_PROPERTY_PARAM_VENC_H264_VUI_BITSTREAM_RESTRC 0x2005021
|
||||
#define HFI_PROPERTY_PARAM_VENC_PRESERVE_TEXT_QUALITY 0x2005023
|
||||
#define HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8 0x2005025
|
||||
#define HFI_PROPERTY_PARAM_VENC_HIER_P_MAX_NUM_ENH_LAYER 0x2005026
|
||||
#define HFI_PROPERTY_PARAM_VENC_DISABLE_RC_TIMESTAMP 0x2005027
|
||||
#define HFI_PROPERTY_PARAM_VENC_INITIAL_QP 0x2005028
|
||||
@ -562,6 +563,10 @@ struct hfi_bitrate {
|
||||
u32 layer_id;
|
||||
};
|
||||
|
||||
struct hfi_h264_8x8_transform {
|
||||
u32 enable_type;
|
||||
};
|
||||
|
||||
#define HFI_CAPABILITY_FRAME_WIDTH 0x01
|
||||
#define HFI_CAPABILITY_FRAME_HEIGHT 0x02
|
||||
#define HFI_CAPABILITY_MBS_PER_FRAME 0x03
|
||||
|
@ -261,7 +261,7 @@ sys_get_prop_image_version(struct device *dev,
|
||||
|
||||
smem_tbl_ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY,
|
||||
SMEM_IMG_VER_TBL, &smem_blk_sz);
|
||||
if (smem_tbl_ptr && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
|
||||
if (!IS_ERR(smem_tbl_ptr) && smem_blk_sz >= SMEM_IMG_OFFSET_VENUS + VER_STR_SZ)
|
||||
memcpy(smem_tbl_ptr + SMEM_IMG_OFFSET_VENUS,
|
||||
img_ver, VER_STR_SZ);
|
||||
}
|
||||
|
@ -183,6 +183,8 @@ venc_try_fmt_common(struct venus_inst *inst, struct v4l2_format *f)
|
||||
else
|
||||
return NULL;
|
||||
fmt = find_format(inst, pixmp->pixelformat, f->type);
|
||||
if (!fmt)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixmp->width = clamp(pixmp->width, frame_width_min(inst),
|
||||
@ -547,6 +549,7 @@ static int venc_set_properties(struct venus_inst *inst)
|
||||
struct hfi_quantization_range quant_range;
|
||||
struct hfi_enable en;
|
||||
struct hfi_ltr_mode ltr_mode;
|
||||
struct hfi_intra_refresh intra_refresh = {};
|
||||
u32 ptype, rate_control, bitrate;
|
||||
u32 profile, level;
|
||||
int ret;
|
||||
@ -567,6 +570,7 @@ static int venc_set_properties(struct venus_inst *inst)
|
||||
struct hfi_h264_vui_timing_info info;
|
||||
struct hfi_h264_entropy_control entropy;
|
||||
struct hfi_h264_db_control deblock;
|
||||
struct hfi_h264_8x8_transform h264_transform;
|
||||
|
||||
ptype = HFI_PROPERTY_PARAM_VENC_H264_VUI_TIMING_INFO;
|
||||
info.enable = 1;
|
||||
@ -597,6 +601,17 @@ static int venc_set_properties(struct venus_inst *inst)
|
||||
ret = hfi_session_set_property(inst, ptype, &deblock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ptype = HFI_PROPERTY_PARAM_VENC_H264_TRANSFORM_8X8;
|
||||
h264_transform.enable_type = 0;
|
||||
if (ctr->profile.h264 == HFI_H264_PROFILE_HIGH ||
|
||||
ctr->profile.h264 == HFI_H264_PROFILE_CONSTRAINED_HIGH)
|
||||
h264_transform.enable_type = ctr->h264_8x8_transform;
|
||||
|
||||
ret = hfi_session_set_property(inst, ptype, &h264_transform);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
if (inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
|
||||
@ -802,6 +817,31 @@ static int venc_set_properties(struct venus_inst *inst)
|
||||
en.enable = 1;
|
||||
|
||||
ret = hfi_session_set_property(inst, ptype, &en);
|
||||
}
|
||||
|
||||
if ((inst->fmt_cap->pixfmt == V4L2_PIX_FMT_H264 ||
|
||||
inst->fmt_cap->pixfmt == V4L2_PIX_FMT_HEVC) &&
|
||||
(rate_control == HFI_RATE_CONTROL_CBR_VFR ||
|
||||
rate_control == HFI_RATE_CONTROL_CBR_CFR)) {
|
||||
intra_refresh.mode = HFI_INTRA_REFRESH_NONE;
|
||||
intra_refresh.cir_mbs = 0;
|
||||
|
||||
if (ctr->intra_refresh_period) {
|
||||
u32 mbs;
|
||||
|
||||
mbs = ALIGN(inst->width, 16) * ALIGN(inst->height, 16);
|
||||
mbs /= 16 * 16;
|
||||
if (mbs % ctr->intra_refresh_period)
|
||||
mbs++;
|
||||
mbs /= ctr->intra_refresh_period;
|
||||
|
||||
intra_refresh.mode = HFI_INTRA_REFRESH_RANDOM;
|
||||
intra_refresh.cir_mbs = mbs;
|
||||
}
|
||||
|
||||
ptype = HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
|
||||
|
||||
ret = hfi_session_set_property(inst, ptype, &intra_refresh);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
#define SLICE_BYTE_SIZE_MAX 1024
|
||||
#define SLICE_BYTE_SIZE_MIN 1024
|
||||
#define SLICE_MB_SIZE_MAX 300
|
||||
#define INTRA_REFRESH_MBS_MAX 300
|
||||
#define AT_SLICE_BOUNDARY \
|
||||
V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
|
||||
#define MAX_LTR_FRAME_COUNT 4
|
||||
@ -227,8 +226,6 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
}
|
||||
mutex_unlock(&inst->lock);
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
|
||||
ret = venc_calc_bpframes(ctrl->val, ctr->num_b_frames, &bframes,
|
||||
&ctr->num_p_frames);
|
||||
@ -319,6 +316,28 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY:
|
||||
ctr->mastering = *ctrl->p_new.p_hdr10_mastering;
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
|
||||
ctr->intra_refresh_period = ctrl->val;
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
|
||||
if (ctr->profile.h264 != HFI_H264_PROFILE_HIGH &&
|
||||
ctr->profile.h264 != HFI_H264_PROFILE_CONSTRAINED_HIGH)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* In video firmware, 8x8 transform is supported only for
|
||||
* high profile(HP) and constrained high profile(CHP).
|
||||
* If client wants to disable 8x8 transform for HP/CHP,
|
||||
* it is better to set profile as main profile(MP).
|
||||
* Because there is no difference between HP and MP
|
||||
* if we disable 8x8 transform for HP.
|
||||
*/
|
||||
|
||||
if (ctrl->val == 0)
|
||||
return -EINVAL;
|
||||
|
||||
ctr->h264_8x8_transform = ctrl->val;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -334,7 +353,7 @@ int venc_ctrl_init(struct venus_inst *inst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 57);
|
||||
ret = v4l2_ctrl_handler_init(&inst->ctrl_handler, 58);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -437,6 +456,9 @@ int venc_ctrl_init(struct venus_inst *inst)
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_H264_I_FRAME_MIN_QP, 1, 51, 1, 1);
|
||||
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM, 0, 1, 1, 0);
|
||||
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_H264_P_FRAME_MIN_QP, 1, 51, 1, 1);
|
||||
|
||||
@ -502,10 +524,6 @@ int venc_ctrl_init(struct venus_inst *inst)
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
|
||||
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB,
|
||||
0, INTRA_REFRESH_MBS_MAX, 1, 0);
|
||||
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, (1 << 16) - 1, 1, 30);
|
||||
|
||||
@ -564,6 +582,10 @@ int venc_ctrl_init(struct venus_inst *inst)
|
||||
V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY,
|
||||
v4l2_ctrl_ptr_create(NULL));
|
||||
|
||||
v4l2_ctrl_new_std(&inst->ctrl_handler, &venc_ctrl_ops,
|
||||
V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD, 0,
|
||||
((4096 * 2304) >> 8), 1, 0);
|
||||
|
||||
ret = inst->ctrl_handler.error;
|
||||
if (ret)
|
||||
goto err;
|
||||
|
@ -253,8 +253,8 @@ static int rvin_try_format(struct rvin_dev *vin, u32 which,
|
||||
int ret;
|
||||
|
||||
sd_state = v4l2_subdev_alloc_state(sd);
|
||||
if (sd_state == NULL)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(sd_state))
|
||||
return PTR_ERR(sd_state);
|
||||
|
||||
if (!rvin_format_from_pixel(vin, pix->pixelformat))
|
||||
pix->pixelformat = RVIN_DEFAULT_FORMAT;
|
||||
|
@ -863,12 +863,12 @@ static int rga_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(rga->m2m_dev)) {
|
||||
v4l2_err(&rga->v4l2_dev, "Failed to init mem2mem device\n");
|
||||
ret = PTR_ERR(rga->m2m_dev);
|
||||
goto unreg_video_dev;
|
||||
goto rel_vdev;
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(rga->dev);
|
||||
if (ret < 0)
|
||||
goto unreg_video_dev;
|
||||
goto rel_vdev;
|
||||
|
||||
rga->version.major = (rga_read(rga, RGA_VERSION_INFO) >> 24) & 0xFF;
|
||||
rga->version.minor = (rga_read(rga, RGA_VERSION_INFO) >> 20) & 0x0F;
|
||||
@ -882,11 +882,23 @@ static int rga_probe(struct platform_device *pdev)
|
||||
rga->cmdbuf_virt = dma_alloc_attrs(rga->dev, RGA_CMDBUF_SIZE,
|
||||
&rga->cmdbuf_phy, GFP_KERNEL,
|
||||
DMA_ATTR_WRITE_COMBINE);
|
||||
if (!rga->cmdbuf_virt) {
|
||||
ret = -ENOMEM;
|
||||
goto rel_vdev;
|
||||
}
|
||||
|
||||
rga->src_mmu_pages =
|
||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
||||
if (!rga->src_mmu_pages) {
|
||||
ret = -ENOMEM;
|
||||
goto free_dma;
|
||||
}
|
||||
rga->dst_mmu_pages =
|
||||
(unsigned int *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 3);
|
||||
if (rga->dst_mmu_pages) {
|
||||
ret = -ENOMEM;
|
||||
goto free_src_pages;
|
||||
}
|
||||
|
||||
def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3;
|
||||
def_frame.size = def_frame.stride * def_frame.height;
|
||||
@ -894,7 +906,7 @@ static int rga_probe(struct platform_device *pdev)
|
||||
ret = video_register_device(vfd, VFL_TYPE_VIDEO, -1);
|
||||
if (ret) {
|
||||
v4l2_err(&rga->v4l2_dev, "Failed to register video device\n");
|
||||
goto rel_vdev;
|
||||
goto free_dst_pages;
|
||||
}
|
||||
|
||||
v4l2_info(&rga->v4l2_dev, "Registered %s as /dev/%s\n",
|
||||
@ -902,10 +914,15 @@ static int rga_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
free_dst_pages:
|
||||
free_pages((unsigned long)rga->dst_mmu_pages, 3);
|
||||
free_src_pages:
|
||||
free_pages((unsigned long)rga->src_mmu_pages, 3);
|
||||
free_dma:
|
||||
dma_free_attrs(rga->dev, RGA_CMDBUF_SIZE, rga->cmdbuf_virt,
|
||||
rga->cmdbuf_phy, DMA_ATTR_WRITE_COMBINE);
|
||||
rel_vdev:
|
||||
video_device_release(vfd);
|
||||
unreg_video_dev:
|
||||
video_unregister_device(rga->vfd);
|
||||
unreg_v4l2_dev:
|
||||
v4l2_device_unregister(&rga->v4l2_dev);
|
||||
err_put_clk:
|
||||
|
@ -750,7 +750,7 @@ static int rkisp1_vb2_queue_setup(struct vb2_queue *queue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
static int rkisp1_vb2_buf_init(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct rkisp1_buffer *ispbuf =
|
||||
@ -780,6 +780,15 @@ static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap)
|
||||
swap(ispbuf->buff_addr[RKISP1_PLANE_CR],
|
||||
ispbuf->buff_addr[RKISP1_PLANE_CB]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
|
||||
struct rkisp1_buffer *ispbuf =
|
||||
container_of(vbuf, struct rkisp1_buffer, vb);
|
||||
struct rkisp1_capture *cap = vb->vb2_queue->drv_priv;
|
||||
|
||||
spin_lock_irq(&cap->buf.lock);
|
||||
list_add_tail(&ispbuf->queue, &cap->buf.queue);
|
||||
@ -1039,6 +1048,7 @@ err_ret_buffers:
|
||||
|
||||
static const struct vb2_ops rkisp1_vb2_ops = {
|
||||
.queue_setup = rkisp1_vb2_queue_setup,
|
||||
.buf_init = rkisp1_vb2_buf_init,
|
||||
.buf_queue = rkisp1_vb2_buf_queue,
|
||||
.buf_prepare = rkisp1_vb2_buf_prepare,
|
||||
.wait_prepare = vb2_ops_wait_prepare,
|
||||
|
@ -156,15 +156,11 @@ struct rkisp1_vdev_node {
|
||||
* @vb: vb2 buffer
|
||||
* @queue: entry of the buffer in the queue
|
||||
* @buff_addr: dma addresses of each plane, used only by the capture devices: selfpath, mainpath
|
||||
* @vaddr: virtual address for buffers used by params and stats devices
|
||||
*/
|
||||
struct rkisp1_buffer {
|
||||
struct vb2_v4l2_buffer vb;
|
||||
struct list_head queue;
|
||||
union {
|
||||
u32 buff_addr[VIDEO_MAX_PLANES];
|
||||
void *vaddr;
|
||||
};
|
||||
u32 buff_addr[VIDEO_MAX_PLANES];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1143,7 +1143,7 @@ static void rkisp1_params_apply_params_cfg(struct rkisp1_params *params,
|
||||
cur_buf = list_first_entry(¶ms->params,
|
||||
struct rkisp1_buffer, queue);
|
||||
|
||||
new_params = (struct rkisp1_params_cfg *)(cur_buf->vaddr);
|
||||
new_params = (struct rkisp1_params_cfg *)vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
|
||||
|
||||
rkisp1_isp_isr_other_config(params, new_params);
|
||||
rkisp1_isp_isr_meas_config(params, new_params);
|
||||
@ -1382,7 +1382,6 @@ static void rkisp1_params_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
struct rkisp1_params *params = vq->drv_priv;
|
||||
|
||||
params_buf->vaddr = vb2_plane_vaddr(vb, 0);
|
||||
spin_lock_irq(¶ms->config_lock);
|
||||
list_add_tail(¶ms_buf->queue, ¶ms->params);
|
||||
spin_unlock_irq(¶ms->config_lock);
|
||||
|
@ -112,7 +112,6 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
struct rkisp1_stats *stats_dev = vq->drv_priv;
|
||||
|
||||
stats_buf->vaddr = vb2_plane_vaddr(vb, 0);
|
||||
|
||||
spin_lock_irq(&stats_dev->lock);
|
||||
list_add_tail(&stats_buf->queue, &stats_dev->stat);
|
||||
@ -305,9 +304,8 @@ rkisp1_stats_send_measurement(struct rkisp1_stats *stats, u32 isp_ris)
|
||||
if (!cur_buf)
|
||||
return;
|
||||
|
||||
cur_stat_buf =
|
||||
(struct rkisp1_stat_buffer *)(cur_buf->vaddr);
|
||||
|
||||
cur_stat_buf = (struct rkisp1_stat_buffer *)
|
||||
vb2_plane_vaddr(&cur_buf->vb.vb2_buf, 0);
|
||||
if (isp_ris & RKISP1_CIF_ISP_AWB_DONE)
|
||||
rkisp1_stats_get_awb_meas(stats, cur_stat_buf);
|
||||
|
||||
|
@ -1418,7 +1418,7 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
|
||||
if (test_and_clear_bit(0, &dev->hw_lock) == 0)
|
||||
mfc_err("Failed to unlock hardware\n");
|
||||
|
||||
/* This is in deed imporant, as no operation has been
|
||||
/* This is indeed important, as no operation has been
|
||||
* scheduled, reduce the clock count as no one will
|
||||
* ever do this, because no interrupt related to this try_run
|
||||
* will ever come from hardware. */
|
||||
|
@ -175,8 +175,7 @@ int delta_ipc_open(struct delta_ctx *pctx, const char *name,
|
||||
msg.ipc_buf_size = ipc_buf_size;
|
||||
msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
|
||||
|
||||
memcpy(msg.name, name, sizeof(msg.name));
|
||||
msg.name[sizeof(msg.name) - 1] = 0;
|
||||
strscpy(msg.name, name, sizeof(msg.name));
|
||||
|
||||
msg.param_size = param->size;
|
||||
memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
|
||||
|
@ -45,22 +45,30 @@ static inline void camerarx_write(struct cal_camerarx *phy, u32 offset, u32 val)
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static s64 cal_camerarx_get_external_rate(struct cal_camerarx *phy)
|
||||
static s64 cal_camerarx_get_ext_link_freq(struct cal_camerarx *phy)
|
||||
{
|
||||
struct v4l2_ctrl *ctrl;
|
||||
s64 rate;
|
||||
struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 = &phy->endpoint.bus.mipi_csi2;
|
||||
u32 num_lanes = mipi_csi2->num_data_lanes;
|
||||
const struct cal_format_info *fmtinfo;
|
||||
u32 bpp;
|
||||
s64 freq;
|
||||
|
||||
ctrl = v4l2_ctrl_find(phy->sensor->ctrl_handler, V4L2_CID_PIXEL_RATE);
|
||||
if (!ctrl) {
|
||||
phy_err(phy, "no pixel rate control in subdev: %s\n",
|
||||
phy->sensor->name);
|
||||
return -EPIPE;
|
||||
fmtinfo = cal_format_by_code(phy->formats[CAL_CAMERARX_PAD_SINK].code);
|
||||
if (!fmtinfo)
|
||||
return -EINVAL;
|
||||
|
||||
bpp = fmtinfo->bpp;
|
||||
|
||||
freq = v4l2_get_link_freq(phy->source->ctrl_handler, bpp, 2 * num_lanes);
|
||||
if (freq < 0) {
|
||||
phy_err(phy, "failed to get link freq for subdev '%s'\n",
|
||||
phy->source->name);
|
||||
return freq;
|
||||
}
|
||||
|
||||
rate = v4l2_ctrl_g_ctrl_int64(ctrl);
|
||||
phy_dbg(3, phy, "sensor Pixel Rate: %llu\n", rate);
|
||||
phy_dbg(3, phy, "Source Link Freq: %llu\n", freq);
|
||||
|
||||
return rate;
|
||||
return freq;
|
||||
}
|
||||
|
||||
static void cal_camerarx_lane_config(struct cal_camerarx *phy)
|
||||
@ -116,34 +124,19 @@ void cal_camerarx_disable(struct cal_camerarx *phy)
|
||||
#define TCLK_MISS 1
|
||||
#define TCLK_SETTLE 14
|
||||
|
||||
static void cal_camerarx_config(struct cal_camerarx *phy, s64 external_rate)
|
||||
static void cal_camerarx_config(struct cal_camerarx *phy, s64 link_freq)
|
||||
{
|
||||
unsigned int reg0, reg1;
|
||||
unsigned int ths_term, ths_settle;
|
||||
unsigned int csi2_ddrclk_khz;
|
||||
struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2 =
|
||||
&phy->endpoint.bus.mipi_csi2;
|
||||
u32 num_lanes = mipi_csi2->num_data_lanes;
|
||||
|
||||
/* DPHY timing configuration */
|
||||
|
||||
/*
|
||||
* CSI-2 is DDR and we only count used lanes.
|
||||
*
|
||||
* csi2_ddrclk_khz = external_rate / 1000
|
||||
* / (2 * num_lanes) * phy->fmtinfo->bpp;
|
||||
*/
|
||||
csi2_ddrclk_khz = div_s64(external_rate * phy->fmtinfo->bpp,
|
||||
2 * num_lanes * 1000);
|
||||
|
||||
phy_dbg(1, phy, "csi2_ddrclk_khz: %d\n", csi2_ddrclk_khz);
|
||||
|
||||
/* THS_TERM: Programmed value = floor(20 ns/DDRClk period) */
|
||||
ths_term = 20 * csi2_ddrclk_khz / 1000000;
|
||||
ths_term = div_s64(20 * link_freq, 1000 * 1000 * 1000);
|
||||
phy_dbg(1, phy, "ths_term: %d (0x%02x)\n", ths_term, ths_term);
|
||||
|
||||
/* THS_SETTLE: Programmed value = floor(105 ns/DDRClk period) + 4 */
|
||||
ths_settle = (105 * csi2_ddrclk_khz / 1000000) + 4;
|
||||
ths_settle = div_s64(105 * link_freq, 1000 * 1000 * 1000) + 4;
|
||||
phy_dbg(1, phy, "ths_settle: %d (0x%02x)\n", ths_settle, ths_settle);
|
||||
|
||||
reg0 = camerarx_read(phy, CAL_CSI2_PHY_REG0);
|
||||
@ -240,24 +233,41 @@ static void cal_camerarx_enable_irqs(struct cal_camerarx *phy)
|
||||
CAL_CSI2_COMPLEXIO_IRQ_FIFO_OVR_MASK |
|
||||
CAL_CSI2_COMPLEXIO_IRQ_SHORT_PACKET_MASK |
|
||||
CAL_CSI2_COMPLEXIO_IRQ_ECC_NO_CORRECTION_MASK;
|
||||
const u32 vc_err_mask =
|
||||
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(0) |
|
||||
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(1) |
|
||||
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(2) |
|
||||
CAL_CSI2_VC_IRQ_CS_IRQ_MASK(3) |
|
||||
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(0) |
|
||||
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(1) |
|
||||
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(2) |
|
||||
CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(3);
|
||||
|
||||
/* Enable CIO error IRQs. */
|
||||
/* Enable CIO & VC error IRQs. */
|
||||
cal_write(phy->cal, CAL_HL_IRQENABLE_SET(0),
|
||||
CAL_HL_IRQ_CIO_MASK(phy->instance));
|
||||
CAL_HL_IRQ_CIO_MASK(phy->instance) |
|
||||
CAL_HL_IRQ_VC_MASK(phy->instance));
|
||||
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance),
|
||||
cio_err_mask);
|
||||
cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance),
|
||||
vc_err_mask);
|
||||
}
|
||||
|
||||
static void cal_camerarx_disable_irqs(struct cal_camerarx *phy)
|
||||
{
|
||||
/* Disable CIO error irqs */
|
||||
cal_write(phy->cal, CAL_HL_IRQENABLE_CLR(0),
|
||||
CAL_HL_IRQ_CIO_MASK(phy->instance));
|
||||
CAL_HL_IRQ_CIO_MASK(phy->instance) |
|
||||
CAL_HL_IRQ_VC_MASK(phy->instance));
|
||||
cal_write(phy->cal, CAL_CSI2_COMPLEXIO_IRQENABLE(phy->instance), 0);
|
||||
cal_write(phy->cal, CAL_CSI2_VC_IRQENABLE(phy->instance), 0);
|
||||
}
|
||||
|
||||
static void cal_camerarx_ppi_enable(struct cal_camerarx *phy)
|
||||
{
|
||||
cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
|
||||
1, CAL_CSI2_PPI_CTRL_ECC_EN_MASK);
|
||||
|
||||
cal_write_field(phy->cal, CAL_CSI2_PPI_CTRL(phy->instance),
|
||||
1, CAL_CSI2_PPI_CTRL_IF_EN_MASK);
|
||||
}
|
||||
@ -270,16 +280,21 @@ static void cal_camerarx_ppi_disable(struct cal_camerarx *phy)
|
||||
|
||||
static int cal_camerarx_start(struct cal_camerarx *phy)
|
||||
{
|
||||
s64 external_rate;
|
||||
s64 link_freq;
|
||||
u32 sscounter;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
external_rate = cal_camerarx_get_external_rate(phy);
|
||||
if (external_rate < 0)
|
||||
return external_rate;
|
||||
if (phy->enable_count > 0) {
|
||||
phy->enable_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = v4l2_subdev_call(phy->sensor, core, s_power, 1);
|
||||
link_freq = cal_camerarx_get_ext_link_freq(phy);
|
||||
if (link_freq < 0)
|
||||
return link_freq;
|
||||
|
||||
ret = v4l2_subdev_call(phy->source, core, s_power, 1);
|
||||
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV) {
|
||||
phy_err(phy, "power on failed in subdev\n");
|
||||
return ret;
|
||||
@ -311,7 +326,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
|
||||
* 2. CSI PHY and link initialization sequence.
|
||||
*
|
||||
* a. Deassert the CSI-2 PHY reset. Do not wait for reset completion
|
||||
* at this point, as it requires the external sensor to send the
|
||||
* at this point, as it requires the external source to send the
|
||||
* CSI-2 HS clock.
|
||||
*/
|
||||
cal_write_field(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance),
|
||||
@ -325,7 +340,7 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
|
||||
camerarx_read(phy, CAL_CSI2_PHY_REG0);
|
||||
|
||||
/* Program the PHY timing parameters. */
|
||||
cal_camerarx_config(phy, external_rate);
|
||||
cal_camerarx_config(phy, link_freq);
|
||||
|
||||
/*
|
||||
* b. Assert the FORCERXMODE signal.
|
||||
@ -370,12 +385,12 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
|
||||
cal_camerarx_power(phy, true);
|
||||
|
||||
/*
|
||||
* Start the sensor to enable the CSI-2 HS clock. We can now wait for
|
||||
* Start the source to enable the CSI-2 HS clock. We can now wait for
|
||||
* CSI-2 PHY reset to complete.
|
||||
*/
|
||||
ret = v4l2_subdev_call(phy->sensor, video, s_stream, 1);
|
||||
ret = v4l2_subdev_call(phy->source, video, s_stream, 1);
|
||||
if (ret) {
|
||||
v4l2_subdev_call(phy->sensor, core, s_power, 0);
|
||||
v4l2_subdev_call(phy->source, core, s_power, 0);
|
||||
cal_camerarx_disable_irqs(phy);
|
||||
phy_err(phy, "stream on failed in subdev\n");
|
||||
return ret;
|
||||
@ -399,14 +414,18 @@ static int cal_camerarx_start(struct cal_camerarx *phy)
|
||||
/* Finally, enable the PHY Protocol Interface (PPI). */
|
||||
cal_camerarx_ppi_enable(phy);
|
||||
|
||||
phy->enable_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cal_camerarx_stop(struct cal_camerarx *phy)
|
||||
{
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (--phy->enable_count > 0)
|
||||
return;
|
||||
|
||||
cal_camerarx_ppi_disable(phy);
|
||||
|
||||
cal_camerarx_disable_irqs(phy);
|
||||
@ -418,27 +437,17 @@ static void cal_camerarx_stop(struct cal_camerarx *phy)
|
||||
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL,
|
||||
CAL_CSI2_COMPLEXIO_CFG_RESET_CTRL_MASK);
|
||||
|
||||
/* Wait for power down completion */
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (cal_read_field(phy->cal,
|
||||
CAL_CSI2_COMPLEXIO_CFG(phy->instance),
|
||||
CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_MASK) ==
|
||||
CAL_CSI2_COMPLEXIO_CFG_RESET_DONE_RESETONGOING)
|
||||
break;
|
||||
usleep_range(1000, 1100);
|
||||
}
|
||||
phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset (%d) %s\n",
|
||||
phy_dbg(3, phy, "CAL_CSI2_COMPLEXIO_CFG(%d) = 0x%08x Complex IO in Reset\n",
|
||||
phy->instance,
|
||||
cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)), i,
|
||||
(i >= 10) ? "(timeout)" : "");
|
||||
cal_read(phy->cal, CAL_CSI2_COMPLEXIO_CFG(phy->instance)));
|
||||
|
||||
/* Disable the phy */
|
||||
cal_camerarx_disable(phy);
|
||||
|
||||
if (v4l2_subdev_call(phy->sensor, video, s_stream, 0))
|
||||
if (v4l2_subdev_call(phy->source, video, s_stream, 0))
|
||||
phy_err(phy, "stream off failed in subdev\n");
|
||||
|
||||
ret = v4l2_subdev_call(phy->sensor, core, s_power, 0);
|
||||
ret = v4l2_subdev_call(phy->source, core, s_power, 0);
|
||||
if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
|
||||
phy_err(phy, "power off failed in subdev\n");
|
||||
}
|
||||
@ -558,16 +567,16 @@ static int cal_camerarx_parse_dt(struct cal_camerarx *phy)
|
||||
endpoint->bus.mipi_csi2.flags);
|
||||
|
||||
/* Retrieve the connected device and store it for later use. */
|
||||
phy->sensor_ep_node = of_graph_get_remote_endpoint(ep_node);
|
||||
phy->sensor_node = of_graph_get_port_parent(phy->sensor_ep_node);
|
||||
if (!phy->sensor_node) {
|
||||
phy->source_ep_node = of_graph_get_remote_endpoint(ep_node);
|
||||
phy->source_node = of_graph_get_port_parent(phy->source_ep_node);
|
||||
if (!phy->source_node) {
|
||||
phy_dbg(3, phy, "Can't get remote parent\n");
|
||||
of_node_put(phy->sensor_ep_node);
|
||||
of_node_put(phy->source_ep_node);
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
phy_dbg(1, phy, "Found connected device %pOFn\n", phy->sensor_node);
|
||||
phy_dbg(1, phy, "Found connected device %pOFn\n", phy->source_node);
|
||||
|
||||
done:
|
||||
of_node_put(ep_node);
|
||||
@ -602,12 +611,18 @@ cal_camerarx_get_pad_format(struct cal_camerarx *phy,
|
||||
static int cal_camerarx_sd_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct cal_camerarx *phy = to_cal_camerarx(sd);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
if (enable)
|
||||
return cal_camerarx_start(phy);
|
||||
ret = cal_camerarx_start(phy);
|
||||
else
|
||||
cal_camerarx_stop(phy);
|
||||
|
||||
cal_camerarx_stop(phy);
|
||||
return 0;
|
||||
mutex_unlock(&phy->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
@ -615,27 +630,36 @@ static int cal_camerarx_sd_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
struct cal_camerarx *phy = to_cal_camerarx(sd);
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
/* No transcoding, source and sink codes must match. */
|
||||
if (code->pad == CAL_CAMERARX_PAD_SOURCE) {
|
||||
if (cal_rx_pad_is_source(code->pad)) {
|
||||
struct v4l2_mbus_framefmt *fmt;
|
||||
|
||||
if (code->index > 0)
|
||||
return -EINVAL;
|
||||
if (code->index > 0) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fmt = cal_camerarx_get_pad_format(phy, sd_state,
|
||||
CAL_CAMERARX_PAD_SINK,
|
||||
code->which);
|
||||
code->code = fmt->code;
|
||||
return 0;
|
||||
} else {
|
||||
if (code->index >= cal_num_formats) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
code->code = cal_formats[code->index].code;
|
||||
}
|
||||
|
||||
if (code->index >= cal_num_formats)
|
||||
return -EINVAL;
|
||||
out:
|
||||
mutex_unlock(&phy->mutex);
|
||||
|
||||
code->code = cal_formats[code->index].code;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
|
||||
@ -644,38 +668,46 @@ static int cal_camerarx_sd_enum_frame_size(struct v4l2_subdev *sd,
|
||||
{
|
||||
struct cal_camerarx *phy = to_cal_camerarx(sd);
|
||||
const struct cal_format_info *fmtinfo;
|
||||
int ret = 0;
|
||||
|
||||
if (fse->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
/* No transcoding, source and sink formats must match. */
|
||||
if (fse->pad == CAL_CAMERARX_PAD_SOURCE) {
|
||||
if (cal_rx_pad_is_source(fse->pad)) {
|
||||
struct v4l2_mbus_framefmt *fmt;
|
||||
|
||||
fmt = cal_camerarx_get_pad_format(phy, sd_state,
|
||||
CAL_CAMERARX_PAD_SINK,
|
||||
fse->which);
|
||||
if (fse->code != fmt->code)
|
||||
return -EINVAL;
|
||||
if (fse->code != fmt->code) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fse->min_width = fmt->width;
|
||||
fse->max_width = fmt->width;
|
||||
fse->min_height = fmt->height;
|
||||
fse->max_height = fmt->height;
|
||||
} else {
|
||||
fmtinfo = cal_format_by_code(fse->code);
|
||||
if (!fmtinfo) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
|
||||
fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
|
||||
fse->min_height = CAL_MIN_HEIGHT_LINES;
|
||||
fse->max_height = CAL_MAX_HEIGHT_LINES;
|
||||
}
|
||||
|
||||
fmtinfo = cal_format_by_code(fse->code);
|
||||
if (!fmtinfo)
|
||||
return -EINVAL;
|
||||
out:
|
||||
mutex_unlock(&phy->mutex);
|
||||
|
||||
fse->min_width = CAL_MIN_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
|
||||
fse->max_width = CAL_MAX_WIDTH_BYTES * 8 / ALIGN(fmtinfo->bpp, 8);
|
||||
fse->min_height = CAL_MIN_HEIGHT_LINES;
|
||||
fse->max_height = CAL_MAX_HEIGHT_LINES;
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
|
||||
@ -685,10 +717,14 @@ static int cal_camerarx_sd_get_fmt(struct v4l2_subdev *sd,
|
||||
struct cal_camerarx *phy = to_cal_camerarx(sd);
|
||||
struct v4l2_mbus_framefmt *fmt;
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
fmt = cal_camerarx_get_pad_format(phy, sd_state, format->pad,
|
||||
format->which);
|
||||
format->format = *fmt;
|
||||
|
||||
mutex_unlock(&phy->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -702,21 +738,18 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
|
||||
unsigned int bpp;
|
||||
|
||||
/* No transcoding, source and sink formats must match. */
|
||||
if (format->pad == CAL_CAMERARX_PAD_SOURCE)
|
||||
if (cal_rx_pad_is_source(format->pad))
|
||||
return cal_camerarx_sd_get_fmt(sd, sd_state, format);
|
||||
|
||||
/*
|
||||
* Default to the first format is the requested media bus code isn't
|
||||
* Default to the first format if the requested media bus code isn't
|
||||
* supported.
|
||||
*/
|
||||
fmtinfo = cal_format_by_code(format->format.code);
|
||||
if (!fmtinfo)
|
||||
fmtinfo = &cal_formats[0];
|
||||
|
||||
/*
|
||||
* Clamp the size, update the code. The field and colorspace are
|
||||
* accepted as-is.
|
||||
*/
|
||||
/* Clamp the size, update the code. The colorspace is accepted as-is. */
|
||||
bpp = ALIGN(fmtinfo->bpp, 8);
|
||||
|
||||
format->format.width = clamp_t(unsigned int, format->format.width,
|
||||
@ -726,20 +759,23 @@ static int cal_camerarx_sd_set_fmt(struct v4l2_subdev *sd,
|
||||
CAL_MIN_HEIGHT_LINES,
|
||||
CAL_MAX_HEIGHT_LINES);
|
||||
format->format.code = fmtinfo->code;
|
||||
format->format.field = V4L2_FIELD_NONE;
|
||||
|
||||
/* Store the format and propagate it to the source pad. */
|
||||
|
||||
mutex_lock(&phy->mutex);
|
||||
|
||||
fmt = cal_camerarx_get_pad_format(phy, sd_state,
|
||||
CAL_CAMERARX_PAD_SINK,
|
||||
format->which);
|
||||
*fmt = format->format;
|
||||
|
||||
fmt = cal_camerarx_get_pad_format(phy, sd_state,
|
||||
CAL_CAMERARX_PAD_SOURCE,
|
||||
CAL_CAMERARX_PAD_FIRST_SOURCE,
|
||||
format->which);
|
||||
*fmt = format->format;
|
||||
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
phy->fmtinfo = fmtinfo;
|
||||
mutex_unlock(&phy->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -798,6 +834,7 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
|
||||
struct platform_device *pdev = to_platform_device(cal->dev);
|
||||
struct cal_camerarx *phy;
|
||||
struct v4l2_subdev *sd;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
phy = kzalloc(sizeof(*phy), GFP_KERNEL);
|
||||
@ -807,6 +844,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
|
||||
phy->cal = cal;
|
||||
phy->instance = instance;
|
||||
|
||||
mutex_init(&phy->mutex);
|
||||
|
||||
phy->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
(instance == 0) ?
|
||||
"cal_rx_core0" :
|
||||
@ -838,14 +877,17 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
|
||||
sd->dev = cal->dev;
|
||||
|
||||
phy->pads[CAL_CAMERARX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
|
||||
phy->pads[CAL_CAMERARX_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
|
||||
for (i = CAL_CAMERARX_PAD_FIRST_SOURCE; i < CAL_CAMERARX_NUM_PADS; ++i)
|
||||
phy->pads[i].flags = MEDIA_PAD_FL_SOURCE;
|
||||
sd->entity.ops = &cal_camerarx_media_ops;
|
||||
ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(phy->pads),
|
||||
phy->pads);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
cal_camerarx_sd_init_cfg(sd, NULL);
|
||||
ret = cal_camerarx_sd_init_cfg(sd, NULL);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = v4l2_device_register_subdev(&cal->v4l2_dev, sd);
|
||||
if (ret)
|
||||
@ -866,7 +908,8 @@ void cal_camerarx_destroy(struct cal_camerarx *phy)
|
||||
|
||||
v4l2_device_unregister_subdev(&phy->subdev);
|
||||
media_entity_cleanup(&phy->subdev.entity);
|
||||
of_node_put(phy->sensor_ep_node);
|
||||
of_node_put(phy->sensor_node);
|
||||
of_node_put(phy->source_ep_node);
|
||||
of_node_put(phy->source_node);
|
||||
mutex_destroy(&phy->mutex);
|
||||
kfree(phy);
|
||||
}
|
||||
|
@ -102,8 +102,8 @@ static const struct cal_format_info *find_format_by_code(struct cal_ctx *ctx,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int cal_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
static int cal_legacy_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
const struct cal_format_info *fmtinfo;
|
||||
@ -128,7 +128,7 @@ static int __subdev_get_format(struct cal_ctx *ctx,
|
||||
sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
sd_fmt.pad = 0;
|
||||
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, get_fmt, NULL, &sd_fmt);
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, get_fmt, NULL, &sd_fmt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -151,7 +151,7 @@ static int __subdev_set_format(struct cal_ctx *ctx,
|
||||
sd_fmt.pad = 0;
|
||||
*mbus_fmt = *fmt;
|
||||
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, set_fmt, NULL, &sd_fmt);
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, set_fmt, NULL, &sd_fmt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -189,8 +189,8 @@ static void cal_calc_format_size(struct cal_ctx *ctx,
|
||||
f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
|
||||
}
|
||||
|
||||
static int cal_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int cal_legacy_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
const struct cal_format_info *fmtinfo;
|
||||
@ -216,7 +216,7 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
fse.code = fmtinfo->code;
|
||||
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
for (fse.index = 0; ; fse.index++) {
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size,
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size,
|
||||
NULL, &fse);
|
||||
if (ret)
|
||||
break;
|
||||
@ -249,8 +249,8 @@ static int cal_try_fmt_vid_cap(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
static int cal_legacy_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *f)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
struct vb2_queue *q = &ctx->vb_vidq;
|
||||
@ -266,7 +266,7 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = cal_try_fmt_vid_cap(file, priv, f);
|
||||
ret = cal_legacy_try_fmt_vid_cap(file, priv, f);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -300,8 +300,8 @@ static int cal_s_fmt_vid_cap(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_enum_framesizes(struct file *file, void *fh,
|
||||
struct v4l2_frmsizeenum *fsize)
|
||||
static int cal_legacy_enum_framesizes(struct file *file, void *fh,
|
||||
struct v4l2_frmsizeenum *fsize)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
const struct cal_format_info *fmtinfo;
|
||||
@ -321,7 +321,7 @@ static int cal_enum_framesizes(struct file *file, void *fh,
|
||||
fse.code = fmtinfo->code;
|
||||
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_size, NULL,
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_size, NULL,
|
||||
&fse);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -337,8 +337,8 @@ static int cal_enum_framesizes(struct file *file, void *fh,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_enum_input(struct file *file, void *priv,
|
||||
struct v4l2_input *inp)
|
||||
static int cal_legacy_enum_input(struct file *file, void *priv,
|
||||
struct v4l2_input *inp)
|
||||
{
|
||||
if (inp->index > 0)
|
||||
return -EINVAL;
|
||||
@ -348,20 +348,20 @@ static int cal_enum_input(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_g_input(struct file *file, void *priv, unsigned int *i)
|
||||
static int cal_legacy_g_input(struct file *file, void *priv, unsigned int *i)
|
||||
{
|
||||
*i = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_s_input(struct file *file, void *priv, unsigned int i)
|
||||
static int cal_legacy_s_input(struct file *file, void *priv, unsigned int i)
|
||||
{
|
||||
return i > 0 ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
/* timeperframe is arbitrary and continuous */
|
||||
static int cal_enum_frameintervals(struct file *file, void *priv,
|
||||
struct v4l2_frmivalenum *fival)
|
||||
static int cal_legacy_enum_frameintervals(struct file *file, void *priv,
|
||||
struct v4l2_frmivalenum *fival)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
const struct cal_format_info *fmtinfo;
|
||||
@ -378,7 +378,7 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
|
||||
return -EINVAL;
|
||||
|
||||
fie.code = fmtinfo->code;
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_frame_interval,
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_frame_interval,
|
||||
NULL, &fie);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -388,13 +388,27 @@ static int cal_enum_frameintervals(struct file *file, void *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
|
||||
static int cal_legacy_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
|
||||
return v4l2_g_parm_cap(video_devdata(file), ctx->phy->source, a);
|
||||
}
|
||||
|
||||
static int cal_legacy_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
|
||||
{
|
||||
struct cal_ctx *ctx = video_drvdata(file);
|
||||
|
||||
return v4l2_s_parm_cap(video_devdata(file), ctx->phy->source, a);
|
||||
}
|
||||
|
||||
static const struct v4l2_ioctl_ops cal_ioctl_legacy_ops = {
|
||||
.vidioc_querycap = cal_querycap,
|
||||
.vidioc_enum_fmt_vid_cap = cal_enum_fmt_vid_cap,
|
||||
.vidioc_enum_fmt_vid_cap = cal_legacy_enum_fmt_vid_cap,
|
||||
.vidioc_g_fmt_vid_cap = cal_g_fmt_vid_cap,
|
||||
.vidioc_try_fmt_vid_cap = cal_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = cal_s_fmt_vid_cap,
|
||||
.vidioc_enum_framesizes = cal_enum_framesizes,
|
||||
.vidioc_try_fmt_vid_cap = cal_legacy_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = cal_legacy_s_fmt_vid_cap,
|
||||
.vidioc_enum_framesizes = cal_legacy_enum_framesizes,
|
||||
.vidioc_reqbufs = vb2_ioctl_reqbufs,
|
||||
.vidioc_create_bufs = vb2_ioctl_create_bufs,
|
||||
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
|
||||
@ -402,15 +416,17 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
|
||||
.vidioc_qbuf = vb2_ioctl_qbuf,
|
||||
.vidioc_dqbuf = vb2_ioctl_dqbuf,
|
||||
.vidioc_expbuf = vb2_ioctl_expbuf,
|
||||
.vidioc_enum_input = cal_enum_input,
|
||||
.vidioc_g_input = cal_g_input,
|
||||
.vidioc_s_input = cal_s_input,
|
||||
.vidioc_enum_frameintervals = cal_enum_frameintervals,
|
||||
.vidioc_enum_input = cal_legacy_enum_input,
|
||||
.vidioc_g_input = cal_legacy_g_input,
|
||||
.vidioc_s_input = cal_legacy_s_input,
|
||||
.vidioc_enum_frameintervals = cal_legacy_enum_frameintervals,
|
||||
.vidioc_streamon = vb2_ioctl_streamon,
|
||||
.vidioc_streamoff = vb2_ioctl_streamoff,
|
||||
.vidioc_log_status = v4l2_ctrl_log_status,
|
||||
.vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
|
||||
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
|
||||
.vidioc_g_parm = cal_legacy_g_parm,
|
||||
.vidioc_s_parm = cal_legacy_s_parm,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
@ -421,13 +437,28 @@ static const struct v4l2_ioctl_ops cal_ioctl_video_ops = {
|
||||
static int cal_mc_enum_fmt_vid_cap(struct file *file, void *priv,
|
||||
struct v4l2_fmtdesc *f)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int idx;
|
||||
|
||||
if (f->index >= cal_num_formats)
|
||||
return -EINVAL;
|
||||
|
||||
f->pixelformat = cal_formats[f->index].fourcc;
|
||||
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
idx = 0;
|
||||
|
||||
return 0;
|
||||
for (i = 0; i < cal_num_formats; ++i) {
|
||||
if (f->mbus_code && cal_formats[i].code != f->mbus_code)
|
||||
continue;
|
||||
|
||||
if (idx == f->index) {
|
||||
f->pixelformat = cal_formats[i].fourcc;
|
||||
f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void cal_mc_try_fmt(struct cal_ctx *ctx, struct v4l2_format *f,
|
||||
@ -656,8 +687,13 @@ static void cal_release_buffers(struct cal_ctx *ctx,
|
||||
static int cal_video_check_format(struct cal_ctx *ctx)
|
||||
{
|
||||
const struct v4l2_mbus_framefmt *format;
|
||||
struct media_pad *remote_pad;
|
||||
|
||||
format = &ctx->phy->formats[CAL_CAMERARX_PAD_SOURCE];
|
||||
remote_pad = media_entity_remote_pad(&ctx->pad);
|
||||
if (!remote_pad)
|
||||
return -ENODEV;
|
||||
|
||||
format = &ctx->phy->formats[remote_pad->index];
|
||||
|
||||
if (ctx->fmtinfo->code != format->code ||
|
||||
ctx->v_fmt.fmt.pix.height != format->height ||
|
||||
@ -692,9 +728,15 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
goto error_pipeline;
|
||||
}
|
||||
|
||||
ret = cal_ctx_prepare(ctx);
|
||||
if (ret) {
|
||||
ctx_err(ctx, "Failed to prepare context: %d\n", ret);
|
||||
goto error_pipeline;
|
||||
}
|
||||
|
||||
spin_lock_irq(&ctx->dma.lock);
|
||||
buf = list_first_entry(&ctx->dma.queue, struct cal_buffer, list);
|
||||
ctx->dma.pending = buf;
|
||||
ctx->dma.active = buf;
|
||||
list_del(&buf->list);
|
||||
spin_unlock_irq(&ctx->dma.lock);
|
||||
|
||||
@ -719,6 +761,7 @@ static int cal_start_streaming(struct vb2_queue *vq, unsigned int count)
|
||||
error_stop:
|
||||
cal_ctx_stop(ctx);
|
||||
pm_runtime_put_sync(ctx->cal->dev);
|
||||
cal_ctx_unprepare(ctx);
|
||||
|
||||
error_pipeline:
|
||||
media_pipeline_stop(&ctx->vdev.entity);
|
||||
@ -738,6 +781,8 @@ static void cal_stop_streaming(struct vb2_queue *vq)
|
||||
|
||||
pm_runtime_put_sync(ctx->cal->dev);
|
||||
|
||||
cal_ctx_unprepare(ctx);
|
||||
|
||||
cal_release_buffers(ctx, VB2_BUF_STATE_ERROR);
|
||||
|
||||
media_pipeline_stop(&ctx->vdev.entity);
|
||||
@ -785,20 +830,20 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
|
||||
memset(&mbus_code, 0, sizeof(mbus_code));
|
||||
mbus_code.index = j;
|
||||
mbus_code.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
ret = v4l2_subdev_call(ctx->phy->sensor, pad, enum_mbus_code,
|
||||
ret = v4l2_subdev_call(ctx->phy->source, pad, enum_mbus_code,
|
||||
NULL, &mbus_code);
|
||||
if (ret == -EINVAL)
|
||||
break;
|
||||
|
||||
if (ret) {
|
||||
ctx_err(ctx, "Error enumerating mbus codes in subdev %s: %d\n",
|
||||
ctx->phy->sensor->name, ret);
|
||||
ctx->phy->source->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx_dbg(2, ctx,
|
||||
"subdev %s: code: %04x idx: %u\n",
|
||||
ctx->phy->sensor->name, mbus_code.code, j);
|
||||
ctx->phy->source->name, mbus_code.code, j);
|
||||
|
||||
for (k = 0; k < cal_num_formats; k++) {
|
||||
fmtinfo = &cal_formats[k];
|
||||
@ -816,7 +861,7 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
|
||||
|
||||
if (i == 0) {
|
||||
ctx_err(ctx, "No suitable format reported by subdev %s\n",
|
||||
ctx->phy->sensor->name);
|
||||
ctx->phy->source->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -841,22 +886,57 @@ static int cal_ctx_v4l2_init_formats(struct cal_ctx *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cal_ctx_v4l2_init_mc_format(struct cal_ctx *ctx)
|
||||
{
|
||||
const struct cal_format_info *fmtinfo;
|
||||
struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix;
|
||||
|
||||
fmtinfo = cal_format_by_code(MEDIA_BUS_FMT_UYVY8_2X8);
|
||||
if (!fmtinfo)
|
||||
return -EINVAL;
|
||||
|
||||
pix_fmt->width = 640;
|
||||
pix_fmt->height = 480;
|
||||
pix_fmt->field = V4L2_FIELD_NONE;
|
||||
pix_fmt->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
pix_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
|
||||
pix_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
|
||||
pix_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
|
||||
pix_fmt->pixelformat = fmtinfo->fourcc;
|
||||
|
||||
ctx->v_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
/* Save current format */
|
||||
cal_calc_format_size(ctx, fmtinfo, &ctx->v_fmt);
|
||||
ctx->fmtinfo = fmtinfo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cal_ctx_v4l2_register(struct cal_ctx *ctx)
|
||||
{
|
||||
struct video_device *vfd = &ctx->vdev;
|
||||
int ret;
|
||||
|
||||
ret = cal_ctx_v4l2_init_formats(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!cal_mc_api) {
|
||||
struct v4l2_ctrl_handler *hdl = &ctx->ctrl_handler;
|
||||
|
||||
ret = v4l2_ctrl_add_handler(hdl, ctx->phy->sensor->ctrl_handler,
|
||||
ret = cal_ctx_v4l2_init_formats(ctx);
|
||||
if (ret) {
|
||||
ctx_err(ctx, "Failed to init formats: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = v4l2_ctrl_add_handler(hdl, ctx->phy->source->ctrl_handler,
|
||||
NULL, true);
|
||||
if (ret < 0) {
|
||||
ctx_err(ctx, "Failed to add sensor ctrl handler\n");
|
||||
ctx_err(ctx, "Failed to add source ctrl handler\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
ret = cal_ctx_v4l2_init_mc_format(ctx);
|
||||
if (ret) {
|
||||
ctx_err(ctx, "Failed to init format: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -868,13 +948,13 @@ int cal_ctx_v4l2_register(struct cal_ctx *ctx)
|
||||
}
|
||||
|
||||
ret = media_create_pad_link(&ctx->phy->subdev.entity,
|
||||
CAL_CAMERARX_PAD_SOURCE,
|
||||
CAL_CAMERARX_PAD_FIRST_SOURCE,
|
||||
&vfd->entity, 0,
|
||||
MEDIA_LNK_FL_IMMUTABLE |
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret) {
|
||||
ctx_err(ctx, "Failed to create media link for context %u\n",
|
||||
ctx->index);
|
||||
ctx->dma_ctx);
|
||||
video_unregister_device(vfd);
|
||||
return ret;
|
||||
}
|
||||
@ -926,9 +1006,9 @@ int cal_ctx_v4l2_init(struct cal_ctx *ctx)
|
||||
| (cal_mc_api ? V4L2_CAP_IO_MC : 0);
|
||||
vfd->v4l2_dev = &ctx->cal->v4l2_dev;
|
||||
vfd->queue = q;
|
||||
snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->index);
|
||||
snprintf(vfd->name, sizeof(vfd->name), "CAL output %u", ctx->dma_ctx);
|
||||
vfd->release = video_device_release_empty;
|
||||
vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_video_ops;
|
||||
vfd->ioctl_ops = cal_mc_api ? &cal_ioctl_mc_ops : &cal_ioctl_legacy_ops;
|
||||
vfd->lock = &ctx->mutex;
|
||||
video_set_drvdata(vfd, ctx);
|
||||
|
||||
|
@ -290,11 +290,42 @@ void cal_quickdump_regs(struct cal_dev *cal)
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define CAL_MAX_PIX_PROC 4
|
||||
|
||||
static int cal_reserve_pix_proc(struct cal_dev *cal)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
spin_lock(&cal->v4l2_dev.lock);
|
||||
|
||||
ret = find_first_zero_bit(&cal->reserved_pix_proc_mask, CAL_MAX_PIX_PROC);
|
||||
|
||||
if (ret == CAL_MAX_PIX_PROC) {
|
||||
spin_unlock(&cal->v4l2_dev.lock);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
cal->reserved_pix_proc_mask |= BIT(ret);
|
||||
|
||||
spin_unlock(&cal->v4l2_dev.lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cal_release_pix_proc(struct cal_dev *cal, unsigned int pix_proc_num)
|
||||
{
|
||||
spin_lock(&cal->v4l2_dev.lock);
|
||||
|
||||
cal->reserved_pix_proc_mask &= ~BIT(pix_proc_num);
|
||||
|
||||
spin_unlock(&cal->v4l2_dev.lock);
|
||||
}
|
||||
|
||||
static void cal_ctx_csi2_config(struct cal_ctx *ctx)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index));
|
||||
val = cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx));
|
||||
cal_set_field(&val, ctx->cport, CAL_CSI2_CTX_CPORT_MASK);
|
||||
/*
|
||||
* DT type: MIPI CSI-2 Specs
|
||||
@ -304,15 +335,16 @@ static void cal_ctx_csi2_config(struct cal_ctx *ctx)
|
||||
* 0x2A: RAW8 1 pixel = 1 byte
|
||||
* 0x1E: YUV422 2 pixels = 4 bytes
|
||||
*/
|
||||
cal_set_field(&val, 0x1, CAL_CSI2_CTX_DT_MASK);
|
||||
cal_set_field(&val, 0, CAL_CSI2_CTX_VC_MASK);
|
||||
cal_set_field(&val, ctx->datatype, CAL_CSI2_CTX_DT_MASK);
|
||||
cal_set_field(&val, ctx->vc, CAL_CSI2_CTX_VC_MASK);
|
||||
cal_set_field(&val, ctx->v_fmt.fmt.pix.height, CAL_CSI2_CTX_LINES_MASK);
|
||||
cal_set_field(&val, CAL_CSI2_CTX_ATT_PIX, CAL_CSI2_CTX_ATT_MASK);
|
||||
cal_set_field(&val, CAL_CSI2_CTX_PACK_MODE_LINE,
|
||||
CAL_CSI2_CTX_PACK_MODE_MASK);
|
||||
cal_write(ctx->cal, CAL_CSI2_CTX0(ctx->index), val);
|
||||
ctx_dbg(3, ctx, "CAL_CSI2_CTX0(%d) = 0x%08x\n", ctx->index,
|
||||
cal_read(ctx->cal, CAL_CSI2_CTX0(ctx->index)));
|
||||
cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), val);
|
||||
ctx_dbg(3, ctx, "CAL_CSI2_CTX(%u, %u) = 0x%08x\n",
|
||||
ctx->phy->instance, ctx->csi2_ctx,
|
||||
cal_read(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx)));
|
||||
}
|
||||
|
||||
static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
|
||||
@ -354,16 +386,16 @@ static void cal_ctx_pix_proc_config(struct cal_ctx *ctx)
|
||||
break;
|
||||
}
|
||||
|
||||
val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->index));
|
||||
val = cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc));
|
||||
cal_set_field(&val, extract, CAL_PIX_PROC_EXTRACT_MASK);
|
||||
cal_set_field(&val, CAL_PIX_PROC_DPCMD_BYPASS, CAL_PIX_PROC_DPCMD_MASK);
|
||||
cal_set_field(&val, CAL_PIX_PROC_DPCME_BYPASS, CAL_PIX_PROC_DPCME_MASK);
|
||||
cal_set_field(&val, pack, CAL_PIX_PROC_PACK_MASK);
|
||||
cal_set_field(&val, ctx->cport, CAL_PIX_PROC_CPORT_MASK);
|
||||
cal_set_field(&val, 1, CAL_PIX_PROC_EN_MASK);
|
||||
cal_write(ctx->cal, CAL_PIX_PROC(ctx->index), val);
|
||||
ctx_dbg(3, ctx, "CAL_PIX_PROC(%d) = 0x%08x\n", ctx->index,
|
||||
cal_read(ctx->cal, CAL_PIX_PROC(ctx->index)));
|
||||
cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), val);
|
||||
ctx_dbg(3, ctx, "CAL_PIX_PROC(%u) = 0x%08x\n", ctx->pix_proc,
|
||||
cal_read(ctx->cal, CAL_PIX_PROC(ctx->pix_proc)));
|
||||
}
|
||||
|
||||
static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
|
||||
@ -371,27 +403,25 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
|
||||
unsigned int stride = ctx->v_fmt.fmt.pix.bytesperline;
|
||||
u32 val;
|
||||
|
||||
val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
|
||||
val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
|
||||
cal_set_field(&val, ctx->cport, CAL_WR_DMA_CTRL_CPORT_MASK);
|
||||
cal_set_field(&val, ctx->v_fmt.fmt.pix.height,
|
||||
CAL_WR_DMA_CTRL_YSIZE_MASK);
|
||||
cal_set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
|
||||
CAL_WR_DMA_CTRL_DTAG_MASK);
|
||||
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
|
||||
CAL_WR_DMA_CTRL_MODE_MASK);
|
||||
cal_set_field(&val, CAL_WR_DMA_CTRL_PATTERN_LINEAR,
|
||||
CAL_WR_DMA_CTRL_PATTERN_MASK);
|
||||
cal_set_field(&val, 1, CAL_WR_DMA_CTRL_STALL_RD_MASK);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->index,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index)));
|
||||
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_CTRL(%d) = 0x%08x\n", ctx->dma_ctx,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx)));
|
||||
|
||||
cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->index),
|
||||
cal_write_field(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx),
|
||||
stride / 16, CAL_WR_DMA_OFST_MASK);
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->index,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->index)));
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_OFST(%d) = 0x%08x\n", ctx->dma_ctx,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_OFST(ctx->dma_ctx)));
|
||||
|
||||
val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index));
|
||||
val = cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx));
|
||||
/* 64 bit word means no skipping */
|
||||
cal_set_field(&val, 0, CAL_WR_DMA_XSIZE_XSKIP_MASK);
|
||||
/*
|
||||
@ -400,34 +430,32 @@ static void cal_ctx_wr_dma_config(struct cal_ctx *ctx)
|
||||
* written per line.
|
||||
*/
|
||||
cal_set_field(&val, stride / 8, CAL_WR_DMA_XSIZE_MASK);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index), val);
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->index,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->index)));
|
||||
|
||||
val = cal_read(ctx->cal, CAL_CTRL);
|
||||
cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
|
||||
CAL_CTRL_BURSTSIZE_MASK);
|
||||
cal_set_field(&val, 0xF, CAL_CTRL_TAGCNT_MASK);
|
||||
cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
|
||||
CAL_CTRL_POSTED_WRITES_MASK);
|
||||
cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGL_MASK);
|
||||
cal_set_field(&val, 0xFF, CAL_CTRL_MFLAGH_MASK);
|
||||
cal_write(ctx->cal, CAL_CTRL, val);
|
||||
ctx_dbg(3, ctx, "CAL_CTRL = 0x%08x\n", cal_read(ctx->cal, CAL_CTRL));
|
||||
cal_write(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx), val);
|
||||
ctx_dbg(3, ctx, "CAL_WR_DMA_XSIZE(%d) = 0x%08x\n", ctx->dma_ctx,
|
||||
cal_read(ctx->cal, CAL_WR_DMA_XSIZE(ctx->dma_ctx)));
|
||||
}
|
||||
|
||||
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr)
|
||||
{
|
||||
cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->index), addr);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_ADDR(ctx->dma_ctx), addr);
|
||||
}
|
||||
|
||||
static void cal_ctx_wr_dma_enable(struct cal_ctx *ctx)
|
||||
{
|
||||
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
|
||||
|
||||
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
|
||||
CAL_WR_DMA_CTRL_MODE_MASK);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
|
||||
}
|
||||
|
||||
static void cal_ctx_wr_dma_disable(struct cal_ctx *ctx)
|
||||
{
|
||||
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->index));
|
||||
u32 val = cal_read(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx));
|
||||
|
||||
cal_set_field(&val, CAL_WR_DMA_CTRL_MODE_DIS,
|
||||
CAL_WR_DMA_CTRL_MODE_MASK);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->index), val);
|
||||
cal_write(ctx->cal, CAL_WR_DMA_CTRL(ctx->dma_ctx), val);
|
||||
}
|
||||
|
||||
static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
|
||||
@ -441,6 +469,31 @@ static bool cal_ctx_wr_dma_stopped(struct cal_ctx *ctx)
|
||||
return stopped;
|
||||
}
|
||||
|
||||
int cal_ctx_prepare(struct cal_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ctx->use_pix_proc = !ctx->fmtinfo->meta;
|
||||
|
||||
if (ctx->use_pix_proc) {
|
||||
ret = cal_reserve_pix_proc(ctx->cal);
|
||||
if (ret < 0) {
|
||||
ctx_err(ctx, "Failed to reserve pix proc: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->pix_proc = ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cal_ctx_unprepare(struct cal_ctx *ctx)
|
||||
{
|
||||
if (ctx->use_pix_proc)
|
||||
cal_release_pix_proc(ctx->cal, ctx->pix_proc);
|
||||
}
|
||||
|
||||
void cal_ctx_start(struct cal_ctx *ctx)
|
||||
{
|
||||
ctx->sequence = 0;
|
||||
@ -448,14 +501,17 @@ void cal_ctx_start(struct cal_ctx *ctx)
|
||||
|
||||
/* Configure the CSI-2, pixel processing and write DMA contexts. */
|
||||
cal_ctx_csi2_config(ctx);
|
||||
cal_ctx_pix_proc_config(ctx);
|
||||
if (ctx->use_pix_proc)
|
||||
cal_ctx_pix_proc_config(ctx);
|
||||
cal_ctx_wr_dma_config(ctx);
|
||||
|
||||
/* Enable IRQ_WDMA_END and IRQ_WDMA_START. */
|
||||
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(1),
|
||||
CAL_HL_IRQ_MASK(ctx->index));
|
||||
CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
|
||||
cal_write(ctx->cal, CAL_HL_IRQENABLE_SET(2),
|
||||
CAL_HL_IRQ_MASK(ctx->index));
|
||||
CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
|
||||
|
||||
cal_ctx_wr_dma_enable(ctx);
|
||||
}
|
||||
|
||||
void cal_ctx_stop(struct cal_ctx *ctx)
|
||||
@ -479,11 +535,18 @@ void cal_ctx_stop(struct cal_ctx *ctx)
|
||||
|
||||
/* Disable IRQ_WDMA_END and IRQ_WDMA_START. */
|
||||
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(1),
|
||||
CAL_HL_IRQ_MASK(ctx->index));
|
||||
CAL_HL_IRQ_WDMA_END_MASK(ctx->dma_ctx));
|
||||
cal_write(ctx->cal, CAL_HL_IRQENABLE_CLR(2),
|
||||
CAL_HL_IRQ_MASK(ctx->index));
|
||||
CAL_HL_IRQ_WDMA_START_MASK(ctx->dma_ctx));
|
||||
|
||||
ctx->dma.state = CAL_DMA_STOPPED;
|
||||
|
||||
/* Disable CSI2 context */
|
||||
cal_write(ctx->cal, CAL_CSI2_CTX(ctx->phy->instance, ctx->csi2_ctx), 0);
|
||||
|
||||
/* Disable pix proc */
|
||||
if (ctx->use_pix_proc)
|
||||
cal_write(ctx->cal, CAL_PIX_PROC(ctx->pix_proc), 0);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
@ -577,6 +640,16 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
|
||||
cal_write(cal, CAL_CSI2_COMPLEXIO_IRQSTATUS(i),
|
||||
cio_stat);
|
||||
}
|
||||
|
||||
if (status & CAL_HL_IRQ_VC_MASK(i)) {
|
||||
u32 vc_stat = cal_read(cal, CAL_CSI2_VC_IRQSTATUS(i));
|
||||
|
||||
dev_err_ratelimited(cal->dev,
|
||||
"CIO%u VC error: %#08x\n",
|
||||
i, vc_stat);
|
||||
|
||||
cal_write(cal, CAL_CSI2_VC_IRQSTATUS(i), vc_stat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -588,8 +661,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
|
||||
/* Clear Interrupt status */
|
||||
cal_write(cal, CAL_HL_IRQSTATUS(1), status);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
|
||||
if (status & CAL_HL_IRQ_MASK(i))
|
||||
for (i = 0; i < cal->num_contexts; ++i) {
|
||||
if (status & CAL_HL_IRQ_WDMA_END_MASK(i))
|
||||
cal_irq_wdma_end(cal->ctx[i]);
|
||||
}
|
||||
}
|
||||
@ -602,8 +675,8 @@ static irqreturn_t cal_irq(int irq_cal, void *data)
|
||||
/* Clear Interrupt status */
|
||||
cal_write(cal, CAL_HL_IRQSTATUS(2), status);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
|
||||
if (status & CAL_HL_IRQ_MASK(i))
|
||||
for (i = 0; i < cal->num_contexts; ++i) {
|
||||
if (status & CAL_HL_IRQ_WDMA_START_MASK(i))
|
||||
cal_irq_wdma_start(cal->ctx[i]);
|
||||
}
|
||||
}
|
||||
@ -635,20 +708,20 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
|
||||
int pad;
|
||||
int ret;
|
||||
|
||||
if (phy->sensor) {
|
||||
if (phy->source) {
|
||||
phy_info(phy, "Rejecting subdev %s (Already set!!)",
|
||||
subdev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
phy->sensor = subdev;
|
||||
phy_dbg(1, phy, "Using sensor %s for capture\n", subdev->name);
|
||||
phy->source = subdev;
|
||||
phy_dbg(1, phy, "Using source %s for capture\n", subdev->name);
|
||||
|
||||
pad = media_entity_get_fwnode_pad(&subdev->entity,
|
||||
of_fwnode_handle(phy->sensor_ep_node),
|
||||
of_fwnode_handle(phy->source_ep_node),
|
||||
MEDIA_PAD_FL_SOURCE);
|
||||
if (pad < 0) {
|
||||
phy_err(phy, "Sensor %s has no connected source pad\n",
|
||||
phy_err(phy, "Source %s has no connected source pad\n",
|
||||
subdev->name);
|
||||
return pad;
|
||||
}
|
||||
@ -658,7 +731,7 @@ static int cal_async_notifier_bound(struct v4l2_async_notifier *notifier,
|
||||
MEDIA_LNK_FL_IMMUTABLE |
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret) {
|
||||
phy_err(phy, "Failed to create media link for sensor %s\n",
|
||||
phy_err(phy, "Failed to create media link for source %s\n",
|
||||
subdev->name);
|
||||
return ret;
|
||||
}
|
||||
@ -670,15 +743,30 @@ static int cal_async_notifier_complete(struct v4l2_async_notifier *notifier)
|
||||
{
|
||||
struct cal_dev *cal = container_of(notifier, struct cal_dev, notifier);
|
||||
unsigned int i;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); ++i) {
|
||||
if (cal->ctx[i])
|
||||
cal_ctx_v4l2_register(cal->ctx[i]);
|
||||
for (i = 0; i < cal->num_contexts; ++i) {
|
||||
ret = cal_ctx_v4l2_register(cal->ctx[i]);
|
||||
if (ret)
|
||||
goto err_ctx_unreg;
|
||||
}
|
||||
|
||||
if (cal_mc_api)
|
||||
ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
|
||||
if (!cal_mc_api)
|
||||
return 0;
|
||||
|
||||
ret = v4l2_device_register_subdev_nodes(&cal->v4l2_dev);
|
||||
if (ret)
|
||||
goto err_ctx_unreg;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ctx_unreg:
|
||||
for (; i > 0; --i) {
|
||||
if (!cal->ctx[i - 1])
|
||||
continue;
|
||||
|
||||
cal_ctx_v4l2_unregister(cal->ctx[i - 1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -701,10 +789,10 @@ static int cal_async_notifier_register(struct cal_dev *cal)
|
||||
struct cal_v4l2_async_subdev *casd;
|
||||
struct fwnode_handle *fwnode;
|
||||
|
||||
if (!phy->sensor_node)
|
||||
if (!phy->source_node)
|
||||
continue;
|
||||
|
||||
fwnode = of_fwnode_handle(phy->sensor_node);
|
||||
fwnode = of_fwnode_handle(phy->source_node);
|
||||
casd = v4l2_async_notifier_add_fwnode_subdev(&cal->notifier,
|
||||
fwnode,
|
||||
struct cal_v4l2_async_subdev);
|
||||
@ -777,10 +865,8 @@ static void cal_media_unregister(struct cal_dev *cal)
|
||||
unsigned int i;
|
||||
|
||||
/* Unregister all the V4L2 video devices. */
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
|
||||
if (cal->ctx[i])
|
||||
cal_ctx_v4l2_unregister(cal->ctx[i]);
|
||||
}
|
||||
for (i = 0; i < cal->num_contexts; i++)
|
||||
cal_ctx_v4l2_unregister(cal->ctx[i]);
|
||||
|
||||
cal_async_notifier_unregister(cal);
|
||||
media_device_unregister(&cal->mdev);
|
||||
@ -825,13 +911,6 @@ static int cal_media_init(struct cal_dev *cal)
|
||||
*/
|
||||
static void cal_media_cleanup(struct cal_dev *cal)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
|
||||
if (cal->ctx[i])
|
||||
cal_ctx_v4l2_cleanup(cal->ctx[i]);
|
||||
}
|
||||
|
||||
v4l2_device_unregister(&cal->v4l2_dev);
|
||||
media_device_cleanup(&cal->mdev);
|
||||
|
||||
@ -848,14 +927,17 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
|
||||
struct cal_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
ctx = devm_kzalloc(cal->dev, sizeof(*ctx), GFP_KERNEL);
|
||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->cal = cal;
|
||||
ctx->phy = cal->phy[inst];
|
||||
ctx->index = inst;
|
||||
ctx->dma_ctx = inst;
|
||||
ctx->csi2_ctx = inst;
|
||||
ctx->cport = inst;
|
||||
ctx->vc = 0;
|
||||
ctx->datatype = CAL_CSI2_CTX_DT_ANY;
|
||||
|
||||
ret = cal_ctx_v4l2_init(ctx);
|
||||
if (ret)
|
||||
@ -864,6 +946,13 @@ static struct cal_ctx *cal_ctx_create(struct cal_dev *cal, int inst)
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void cal_ctx_destroy(struct cal_ctx *ctx)
|
||||
{
|
||||
cal_ctx_v4l2_cleanup(ctx);
|
||||
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
static const struct of_device_id cal_of_match[] = {
|
||||
{
|
||||
.compatible = "ti,dra72-cal",
|
||||
@ -976,7 +1065,6 @@ static int cal_init_camerarx_regmap(struct cal_dev *cal)
|
||||
static int cal_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct cal_dev *cal;
|
||||
struct cal_ctx *ctx;
|
||||
bool connected = false;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
@ -1045,7 +1133,7 @@ static int cal_probe(struct platform_device *pdev)
|
||||
goto error_camerarx;
|
||||
}
|
||||
|
||||
if (cal->phy[i]->sensor_node)
|
||||
if (cal->phy[i]->source_node)
|
||||
connected = true;
|
||||
}
|
||||
|
||||
@ -1057,15 +1145,17 @@ static int cal_probe(struct platform_device *pdev)
|
||||
|
||||
/* Create contexts. */
|
||||
for (i = 0; i < cal->data->num_csi2_phy; ++i) {
|
||||
if (!cal->phy[i]->sensor_node)
|
||||
if (!cal->phy[i]->source_node)
|
||||
continue;
|
||||
|
||||
cal->ctx[i] = cal_ctx_create(cal, i);
|
||||
if (!cal->ctx[i]) {
|
||||
cal_err(cal, "Failed to create context %u\n", i);
|
||||
cal->ctx[cal->num_contexts] = cal_ctx_create(cal, i);
|
||||
if (!cal->ctx[cal->num_contexts]) {
|
||||
cal_err(cal, "Failed to create context %u\n", cal->num_contexts);
|
||||
ret = -ENODEV;
|
||||
goto error_context;
|
||||
}
|
||||
|
||||
cal->num_contexts++;
|
||||
}
|
||||
|
||||
/* Register the media device. */
|
||||
@ -1076,11 +1166,8 @@ static int cal_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
error_context:
|
||||
for (i = 0; i < ARRAY_SIZE(cal->ctx); i++) {
|
||||
ctx = cal->ctx[i];
|
||||
if (ctx)
|
||||
cal_ctx_v4l2_cleanup(ctx);
|
||||
}
|
||||
for (i = 0; i < cal->num_contexts; i++)
|
||||
cal_ctx_destroy(cal->ctx[i]);
|
||||
|
||||
error_camerarx:
|
||||
for (i = 0; i < cal->data->num_csi2_phy; i++)
|
||||
@ -1106,16 +1193,17 @@ static int cal_remove(struct platform_device *pdev)
|
||||
|
||||
cal_media_unregister(cal);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cal->phy); i++) {
|
||||
if (cal->phy[i])
|
||||
cal_camerarx_disable(cal->phy[i]);
|
||||
}
|
||||
for (i = 0; i < cal->data->num_csi2_phy; i++)
|
||||
cal_camerarx_disable(cal->phy[i]);
|
||||
|
||||
cal_media_cleanup(cal);
|
||||
for (i = 0; i < cal->num_contexts; i++)
|
||||
cal_ctx_destroy(cal->ctx[i]);
|
||||
|
||||
for (i = 0; i < cal->data->num_csi2_phy; i++)
|
||||
cal_camerarx_destroy(cal->phy[i]);
|
||||
|
||||
cal_media_cleanup(cal);
|
||||
|
||||
if (ret >= 0)
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
@ -1127,6 +1215,7 @@ static int cal_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct cal_dev *cal = dev_get_drvdata(dev);
|
||||
unsigned int i;
|
||||
u32 val;
|
||||
|
||||
if (cal->data->flags & DRA72_CAL_PRE_ES2_LDO_DISABLE) {
|
||||
/*
|
||||
@ -1143,6 +1232,17 @@ static int cal_runtime_resume(struct device *dev)
|
||||
*/
|
||||
cal_write(cal, CAL_HL_IRQENABLE_SET(0), CAL_HL_IRQ_OCPO_ERR_MASK);
|
||||
|
||||
val = cal_read(cal, CAL_CTRL);
|
||||
cal_set_field(&val, CAL_CTRL_BURSTSIZE_BURST128,
|
||||
CAL_CTRL_BURSTSIZE_MASK);
|
||||
cal_set_field(&val, 0xf, CAL_CTRL_TAGCNT_MASK);
|
||||
cal_set_field(&val, CAL_CTRL_POSTED_WRITES_NONPOSTED,
|
||||
CAL_CTRL_POSTED_WRITES_MASK);
|
||||
cal_set_field(&val, 0xff, CAL_CTRL_MFLAGL_MASK);
|
||||
cal_set_field(&val, 0xff, CAL_CTRL_MFLAGH_MASK);
|
||||
cal_write(cal, CAL_CTRL, val);
|
||||
cal_dbg(3, cal, "CAL_CTRL = 0x%08x\n", cal_read(cal, CAL_CTRL));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
|
||||
#define CAL_MODULE_NAME "cal"
|
||||
#define CAL_NUM_CONTEXT 2
|
||||
#define CAL_MAX_NUM_CONTEXT 8
|
||||
#define CAL_NUM_CSI2_PORTS 2
|
||||
|
||||
/*
|
||||
@ -44,7 +44,22 @@
|
||||
#define CAL_MAX_HEIGHT_LINES 16383
|
||||
|
||||
#define CAL_CAMERARX_PAD_SINK 0
|
||||
#define CAL_CAMERARX_PAD_SOURCE 1
|
||||
#define CAL_CAMERARX_PAD_FIRST_SOURCE 1
|
||||
#define CAL_CAMERARX_NUM_SOURCE_PADS 1
|
||||
#define CAL_CAMERARX_NUM_PADS (1 + CAL_CAMERARX_NUM_SOURCE_PADS)
|
||||
|
||||
static inline bool cal_rx_pad_is_sink(u32 pad)
|
||||
{
|
||||
/* Camera RX has 1 sink pad, and N source pads */
|
||||
return pad == 0;
|
||||
}
|
||||
|
||||
static inline bool cal_rx_pad_is_source(u32 pad)
|
||||
{
|
||||
/* Camera RX has 1 sink pad, and N source pads */
|
||||
return pad >= CAL_CAMERARX_PAD_FIRST_SOURCE &&
|
||||
pad <= CAL_CAMERARX_NUM_SOURCE_PADS;
|
||||
}
|
||||
|
||||
struct device;
|
||||
struct device_node;
|
||||
@ -73,6 +88,7 @@ struct cal_format_info {
|
||||
u32 code;
|
||||
/* Bits per pixel */
|
||||
u8 bpp;
|
||||
bool meta;
|
||||
};
|
||||
|
||||
/* buffer for one video frame */
|
||||
@ -149,22 +165,29 @@ struct cal_data {
|
||||
struct cal_camerarx {
|
||||
void __iomem *base;
|
||||
struct resource *res;
|
||||
struct device *dev;
|
||||
struct regmap_field *fields[F_MAX_FIELDS];
|
||||
|
||||
struct cal_dev *cal;
|
||||
unsigned int instance;
|
||||
|
||||
struct v4l2_fwnode_endpoint endpoint;
|
||||
struct device_node *sensor_ep_node;
|
||||
struct device_node *sensor_node;
|
||||
struct v4l2_subdev *sensor;
|
||||
struct device_node *source_ep_node;
|
||||
struct device_node *source_node;
|
||||
struct v4l2_subdev *source;
|
||||
struct media_pipeline pipe;
|
||||
|
||||
struct v4l2_subdev subdev;
|
||||
struct media_pad pads[2];
|
||||
struct v4l2_mbus_framefmt formats[2];
|
||||
const struct cal_format_info *fmtinfo;
|
||||
struct media_pad pads[CAL_CAMERARX_NUM_PADS];
|
||||
struct v4l2_mbus_framefmt formats[CAL_CAMERARX_NUM_PADS];
|
||||
|
||||
/*
|
||||
* Lock for camerarx ops. Protects:
|
||||
* - formats
|
||||
* - enable_count
|
||||
*/
|
||||
struct mutex mutex;
|
||||
|
||||
unsigned int enable_count;
|
||||
};
|
||||
|
||||
struct cal_dev {
|
||||
@ -184,11 +207,14 @@ struct cal_dev {
|
||||
/* Camera Core Module handle */
|
||||
struct cal_camerarx *phy[CAL_NUM_CSI2_PORTS];
|
||||
|
||||
struct cal_ctx *ctx[CAL_NUM_CONTEXT];
|
||||
u32 num_contexts;
|
||||
struct cal_ctx *ctx[CAL_MAX_NUM_CONTEXT];
|
||||
|
||||
struct media_device mdev;
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct v4l2_async_notifier notifier;
|
||||
|
||||
unsigned long reserved_pix_proc_mask;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -212,14 +238,20 @@ struct cal_ctx {
|
||||
/* Used to store current pixel format */
|
||||
struct v4l2_format v_fmt;
|
||||
|
||||
/* Current subdev enumerated format */
|
||||
/* Current subdev enumerated format (legacy) */
|
||||
const struct cal_format_info **active_fmt;
|
||||
unsigned int num_active_fmt;
|
||||
|
||||
unsigned int sequence;
|
||||
struct vb2_queue vb_vidq;
|
||||
unsigned int index;
|
||||
unsigned int cport;
|
||||
u8 dma_ctx;
|
||||
u8 cport;
|
||||
u8 csi2_ctx;
|
||||
u8 pix_proc;
|
||||
u8 vc;
|
||||
u8 datatype;
|
||||
|
||||
bool use_pix_proc;
|
||||
};
|
||||
|
||||
extern unsigned int cal_debug;
|
||||
@ -237,11 +269,11 @@ extern bool cal_mc_api;
|
||||
dev_err((cal)->dev, fmt, ##arg)
|
||||
|
||||
#define ctx_dbg(level, ctx, fmt, arg...) \
|
||||
cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
|
||||
cal_dbg(level, (ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
|
||||
#define ctx_info(ctx, fmt, arg...) \
|
||||
cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
|
||||
cal_info((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
|
||||
#define ctx_err(ctx, fmt, arg...) \
|
||||
cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->index, ##arg)
|
||||
cal_err((ctx)->cal, "ctx%u: " fmt, (ctx)->dma_ctx, ##arg)
|
||||
|
||||
#define phy_dbg(level, phy, fmt, arg...) \
|
||||
cal_dbg(level, (phy)->cal, "phy%u: " fmt, (phy)->instance, ##arg)
|
||||
@ -297,6 +329,8 @@ struct cal_camerarx *cal_camerarx_create(struct cal_dev *cal,
|
||||
unsigned int instance);
|
||||
void cal_camerarx_destroy(struct cal_camerarx *phy);
|
||||
|
||||
int cal_ctx_prepare(struct cal_ctx *ctx);
|
||||
void cal_ctx_unprepare(struct cal_ctx *ctx);
|
||||
void cal_ctx_set_dma_addr(struct cal_ctx *ctx, dma_addr_t addr);
|
||||
void cal_ctx_start(struct cal_ctx *ctx);
|
||||
void cal_ctx_stop(struct cal_ctx *ctx);
|
||||
|
@ -72,22 +72,8 @@
|
||||
#define CAL_CSI2_TIMING(m) (0x314U + (m) * 0x80U)
|
||||
#define CAL_CSI2_VC_IRQENABLE(m) (0x318U + (m) * 0x80U)
|
||||
#define CAL_CSI2_VC_IRQSTATUS(m) (0x328U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX0(m) (0x330U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX1(m) (0x334U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX2(m) (0x338U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX3(m) (0x33cU + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX4(m) (0x340U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX5(m) (0x344U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX6(m) (0x348U + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX7(m) (0x34cU + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS0(m) (0x350U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS1(m) (0x354U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS2(m) (0x358U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS3(m) (0x35cU + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS4(m) (0x360U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS5(m) (0x364U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS6(m) (0x368U + (m) * 0x80U)
|
||||
#define CAL_CSI2_STATUS7(m) (0x36cU + (m) * 0x80U)
|
||||
#define CAL_CSI2_CTX(phy, csi2_ctx) (0x330U + (phy) * 0x80U + (csi2_ctx) * 4)
|
||||
#define CAL_CSI2_STATUS(phy, csi2_ctx) (0x350U + (phy) * 0x80U + (csi2_ctx) * 4)
|
||||
|
||||
/* CAL CSI2 PHY register offsets */
|
||||
#define CAL_CSI2_PHY_REG0 0x000
|
||||
@ -139,7 +125,8 @@
|
||||
#define CAL_HL_IRQ_EOI_LINE_NUMBER_READ0 0
|
||||
#define CAL_HL_IRQ_EOI_LINE_NUMBER_EOI0 0
|
||||
|
||||
#define CAL_HL_IRQ_MASK(m) BIT(m)
|
||||
#define CAL_HL_IRQ_WDMA_END_MASK(m) BIT(m)
|
||||
#define CAL_HL_IRQ_WDMA_START_MASK(m) BIT(m)
|
||||
|
||||
#define CAL_HL_IRQ_OCPO_ERR_MASK BIT(6)
|
||||
|
||||
@ -419,32 +406,16 @@
|
||||
#define CAL_CSI2_TIMING_STOP_STATE_X16_IO1_MASK BIT(14)
|
||||
#define CAL_CSI2_TIMING_FORCE_RX_MODE_IO1_MASK BIT(15)
|
||||
|
||||
#define CAL_CSI2_VC_IRQ_FS_IRQ_0_MASK BIT(0)
|
||||
#define CAL_CSI2_VC_IRQ_FE_IRQ_0_MASK BIT(1)
|
||||
#define CAL_CSI2_VC_IRQ_LS_IRQ_0_MASK BIT(2)
|
||||
#define CAL_CSI2_VC_IRQ_LE_IRQ_0_MASK BIT(3)
|
||||
#define CAL_CSI2_VC_IRQ_CS_IRQ_0_MASK BIT(4)
|
||||
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_0_MASK BIT(5)
|
||||
#define CAL_CSI2_VC_IRQ_FS_IRQ_1_MASK BIT(8)
|
||||
#define CAL_CSI2_VC_IRQ_FE_IRQ_1_MASK BIT(9)
|
||||
#define CAL_CSI2_VC_IRQ_LS_IRQ_1_MASK BIT(10)
|
||||
#define CAL_CSI2_VC_IRQ_LE_IRQ_1_MASK BIT(11)
|
||||
#define CAL_CSI2_VC_IRQ_CS_IRQ_1_MASK BIT(12)
|
||||
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_1_MASK BIT(13)
|
||||
#define CAL_CSI2_VC_IRQ_FS_IRQ_2_MASK BIT(16)
|
||||
#define CAL_CSI2_VC_IRQ_FE_IRQ_2_MASK BIT(17)
|
||||
#define CAL_CSI2_VC_IRQ_LS_IRQ_2_MASK BIT(18)
|
||||
#define CAL_CSI2_VC_IRQ_LE_IRQ_2_MASK BIT(19)
|
||||
#define CAL_CSI2_VC_IRQ_CS_IRQ_2_MASK BIT(20)
|
||||
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_2_MASK BIT(21)
|
||||
#define CAL_CSI2_VC_IRQ_FS_IRQ_3_MASK BIT(24)
|
||||
#define CAL_CSI2_VC_IRQ_FE_IRQ_3_MASK BIT(25)
|
||||
#define CAL_CSI2_VC_IRQ_LS_IRQ_3_MASK BIT(26)
|
||||
#define CAL_CSI2_VC_IRQ_LE_IRQ_3_MASK BIT(27)
|
||||
#define CAL_CSI2_VC_IRQ_CS_IRQ_3_MASK BIT(28)
|
||||
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION0_IRQ_3_MASK BIT(29)
|
||||
#define CAL_CSI2_VC_IRQ_FS_IRQ_MASK(n) BIT(0 + ((n) * 8))
|
||||
#define CAL_CSI2_VC_IRQ_FE_IRQ_MASK(n) BIT(1 + ((n) * 8))
|
||||
#define CAL_CSI2_VC_IRQ_LS_IRQ_MASK(n) BIT(2 + ((n) * 8))
|
||||
#define CAL_CSI2_VC_IRQ_LE_IRQ_MASK(n) BIT(3 + ((n) * 8))
|
||||
#define CAL_CSI2_VC_IRQ_CS_IRQ_MASK(n) BIT(4 + ((n) * 8))
|
||||
#define CAL_CSI2_VC_IRQ_ECC_CORRECTION_IRQ_MASK(n) BIT(5 + ((n) * 8))
|
||||
|
||||
#define CAL_CSI2_CTX_DT_MASK GENMASK(5, 0)
|
||||
#define CAL_CSI2_CTX_DT_DISABLED 0
|
||||
#define CAL_CSI2_CTX_DT_ANY 1
|
||||
#define CAL_CSI2_CTX_VC_MASK GENMASK(7, 6)
|
||||
#define CAL_CSI2_CTX_CPORT_MASK GENMASK(12, 8)
|
||||
#define CAL_CSI2_CTX_ATT_MASK BIT(13)
|
||||
|
@ -676,9 +676,9 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
|
||||
* rectangles.
|
||||
*/
|
||||
entity->config = v4l2_subdev_alloc_state(&entity->subdev);
|
||||
if (entity->config == NULL) {
|
||||
if (IS_ERR(entity->config)) {
|
||||
media_entity_cleanup(&entity->subdev.entity);
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(entity->config);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -246,6 +246,16 @@ config IR_MESON
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called meson-ir.
|
||||
|
||||
config IR_MESON_TX
|
||||
tristate "Amlogic Meson IR TX"
|
||||
depends on ARCH_MESON || COMPILE_TEST
|
||||
help
|
||||
Say Y if you want to use the IR transmitter available on
|
||||
Amlogic Meson SoCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called meson-ir-tx.
|
||||
|
||||
config IR_MTK
|
||||
tristate "Mediatek IR remote receiver"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
@ -28,6 +28,7 @@ obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
|
||||
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
|
||||
obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
|
||||
obj-$(CONFIG_IR_MESON) += meson-ir.o
|
||||
obj-$(CONFIG_IR_MESON_TX) += meson-ir-tx.o
|
||||
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
|
||||
obj-$(CONFIG_IR_ENE) += ene_ir.o
|
||||
obj-$(CONFIG_IR_REDRAT3) += redrat3.o
|
||||
|
@ -1052,7 +1052,7 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
|
||||
rdev->device_name = "ENE eHome Infrared Remote Receiver";
|
||||
|
||||
if (dev->hw_learning_and_tx_capable) {
|
||||
rdev->s_learning_mode = ene_set_learning_mode;
|
||||
rdev->s_wideband_receiver = ene_set_learning_mode;
|
||||
init_completion(&dev->tx_complete);
|
||||
rdev->tx_ir = ene_transmit;
|
||||
rdev->s_tx_mask = ene_set_tx_mask;
|
||||
|
@ -412,7 +412,7 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
val |= LIRC_CAN_SET_REC_CARRIER |
|
||||
LIRC_CAN_SET_REC_CARRIER_RANGE;
|
||||
|
||||
if (dev->s_learning_mode)
|
||||
if (dev->s_wideband_receiver)
|
||||
val |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
|
||||
|
||||
if (dev->s_carrier_report)
|
||||
@ -519,10 +519,10 @@ static long lirc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
break;
|
||||
|
||||
case LIRC_SET_WIDEBAND_RECEIVER:
|
||||
if (!dev->s_learning_mode)
|
||||
if (!dev->s_wideband_receiver)
|
||||
ret = -ENOTTY;
|
||||
else
|
||||
ret = dev->s_learning_mode(dev, !!val);
|
||||
ret = dev->s_wideband_receiver(dev, !!val);
|
||||
break;
|
||||
|
||||
case LIRC_SET_MEASURE_CARRIER_MODE:
|
||||
|
@ -1630,7 +1630,7 @@ static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
|
||||
rc->tx_ir = mceusb_tx_ir;
|
||||
}
|
||||
if (ir->flags.rx2 > 0) {
|
||||
rc->s_learning_mode = mceusb_set_rx_wideband;
|
||||
rc->s_wideband_receiver = mceusb_set_rx_wideband;
|
||||
rc->s_carrier_report = mceusb_set_rx_carrier_report;
|
||||
}
|
||||
rc->driver_name = DRIVER_NAME;
|
||||
|
407
drivers/media/rc/meson-ir-tx.c
Normal file
407
drivers/media/rc/meson-ir-tx.c
Normal file
@ -0,0 +1,407 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/**
|
||||
* meson-ir-tx.c - Amlogic Meson IR TX driver
|
||||
*
|
||||
* Copyright (c) 2021, SberDevices. All Rights Reserved.
|
||||
*
|
||||
* Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#define DEVICE_NAME "Meson IR TX"
|
||||
#define DRIVER_NAME "meson-ir-tx"
|
||||
|
||||
#define MIRTX_DEFAULT_CARRIER 38000
|
||||
#define MIRTX_DEFAULT_DUTY_CYCLE 50
|
||||
#define MIRTX_FIFO_THD 32
|
||||
|
||||
#define IRB_MOD_1US_CLK_RATE 1000000
|
||||
|
||||
#define IRB_FIFO_LEN 128
|
||||
|
||||
#define IRB_ADDR0 0x0
|
||||
#define IRB_ADDR1 0x4
|
||||
#define IRB_ADDR2 0x8
|
||||
#define IRB_ADDR3 0xc
|
||||
|
||||
#define IRB_MAX_DELAY (1 << 10)
|
||||
#define IRB_DELAY_MASK (IRB_MAX_DELAY - 1)
|
||||
|
||||
/* IRCTRL_IR_BLASTER_ADDR0 */
|
||||
#define IRB_MOD_CLK(x) ((x) << 12)
|
||||
#define IRB_MOD_SYS_CLK 0
|
||||
#define IRB_MOD_XTAL3_CLK 1
|
||||
#define IRB_MOD_1US_CLK 2
|
||||
#define IRB_MOD_10US_CLK 3
|
||||
#define IRB_INIT_HIGH BIT(2)
|
||||
#define IRB_ENABLE BIT(0)
|
||||
|
||||
/* IRCTRL_IR_BLASTER_ADDR2 */
|
||||
#define IRB_MOD_COUNT(lo, hi) ((((lo) - 1) << 16) | ((hi) - 1))
|
||||
|
||||
/* IRCTRL_IR_BLASTER_ADDR2 */
|
||||
#define IRB_WRITE_FIFO BIT(16)
|
||||
#define IRB_MOD_ENABLE BIT(12)
|
||||
#define IRB_TB_1US (0x0 << 10)
|
||||
#define IRB_TB_10US (0x1 << 10)
|
||||
#define IRB_TB_100US (0x2 << 10)
|
||||
#define IRB_TB_MOD_CLK (0x3 << 10)
|
||||
|
||||
/* IRCTRL_IR_BLASTER_ADDR3 */
|
||||
#define IRB_FIFO_THD_PENDING BIT(16)
|
||||
#define IRB_FIFO_IRQ_ENABLE BIT(8)
|
||||
|
||||
struct meson_irtx {
|
||||
struct device *dev;
|
||||
void __iomem *reg_base;
|
||||
u32 *buf;
|
||||
unsigned int buf_len;
|
||||
unsigned int buf_head;
|
||||
unsigned int carrier;
|
||||
unsigned int duty_cycle;
|
||||
/* Locks buf */
|
||||
spinlock_t lock;
|
||||
struct completion completion;
|
||||
unsigned long clk_rate;
|
||||
};
|
||||
|
||||
static void meson_irtx_set_mod(struct meson_irtx *ir)
|
||||
{
|
||||
unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier);
|
||||
unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100);
|
||||
unsigned int space_cnt = cnt - pulse_cnt;
|
||||
|
||||
dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n",
|
||||
ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt,
|
||||
100 * pulse_cnt / cnt);
|
||||
|
||||
writel(IRB_MOD_COUNT(pulse_cnt, space_cnt),
|
||||
ir->reg_base + IRB_ADDR1);
|
||||
}
|
||||
|
||||
static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr)
|
||||
{
|
||||
/*
|
||||
* Disable the TX, set modulator clock tick and set initialize
|
||||
* output to be high. Set up carrier frequency and duty cycle. Then
|
||||
* unset initialize output. Enable FIFO interrupt, set FIFO interrupt
|
||||
* threshold. Finally, enable the transmitter back.
|
||||
*/
|
||||
writel(~IRB_ENABLE & (IRB_MOD_CLK(clk_nr) | IRB_INIT_HIGH),
|
||||
ir->reg_base + IRB_ADDR0);
|
||||
meson_irtx_set_mod(ir);
|
||||
writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH,
|
||||
ir->reg_base + IRB_ADDR0);
|
||||
writel(IRB_FIFO_IRQ_ENABLE | MIRTX_FIFO_THD,
|
||||
ir->reg_base + IRB_ADDR3);
|
||||
writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE,
|
||||
ir->reg_base + IRB_ADDR0);
|
||||
}
|
||||
|
||||
static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time)
|
||||
{
|
||||
unsigned int delay;
|
||||
unsigned int tb = IRB_TB_MOD_CLK;
|
||||
unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier);
|
||||
|
||||
delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
|
||||
|
||||
return ((IRB_WRITE_FIFO | IRB_MOD_ENABLE) | tb | delay);
|
||||
}
|
||||
|
||||
static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time)
|
||||
{
|
||||
unsigned int delay;
|
||||
unsigned int tb = IRB_TB_100US;
|
||||
unsigned int tb_us = 100;
|
||||
|
||||
if (time <= IRB_MAX_DELAY) {
|
||||
tb = IRB_TB_1US;
|
||||
tb_us = 1;
|
||||
} else if (time <= 10 * IRB_MAX_DELAY) {
|
||||
tb = IRB_TB_10US;
|
||||
tb_us = 10;
|
||||
} else if (time <= 100 * IRB_MAX_DELAY) {
|
||||
tb = IRB_TB_100US;
|
||||
tb_us = 100;
|
||||
}
|
||||
|
||||
delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
|
||||
|
||||
return ((IRB_WRITE_FIFO & ~IRB_MOD_ENABLE) | tb | delay);
|
||||
}
|
||||
|
||||
static void meson_irtx_send_buffer(struct meson_irtx *ir)
|
||||
{
|
||||
unsigned int nr = 0;
|
||||
unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD;
|
||||
|
||||
while (ir->buf_head < ir->buf_len && nr < max_fifo_level) {
|
||||
writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2);
|
||||
|
||||
ir->buf_head++;
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
|
||||
static bool meson_irtx_check_buf(struct meson_irtx *ir,
|
||||
unsigned int *buf, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
unsigned int max_tb_us;
|
||||
/*
|
||||
* Max space timebase is 100 us.
|
||||
* Pulse timebase equals to carrier period.
|
||||
*/
|
||||
if (i % 2 == 0)
|
||||
max_tb_us = USEC_PER_SEC / ir->carrier;
|
||||
else
|
||||
max_tb_us = 100;
|
||||
|
||||
if (buf[i] >= max_tb_us * IRB_MAX_DELAY)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf,
|
||||
unsigned int *src_buf, unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i % 2 == 0)
|
||||
dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]);
|
||||
else
|
||||
dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t meson_irtx_irqhandler(int irq, void *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct meson_irtx *ir = data;
|
||||
|
||||
writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING,
|
||||
ir->reg_base + IRB_ADDR3);
|
||||
|
||||
if (completion_done(&ir->completion))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
spin_lock_irqsave(&ir->lock, flags);
|
||||
if (ir->buf_head < ir->buf_len)
|
||||
meson_irtx_send_buffer(ir);
|
||||
else
|
||||
complete(&ir->completion);
|
||||
spin_unlock_irqrestore(&ir->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int meson_irtx_set_carrier(struct rc_dev *rc, u32 carrier)
|
||||
{
|
||||
struct meson_irtx *ir = rc->priv;
|
||||
|
||||
if (carrier == 0)
|
||||
return -EINVAL;
|
||||
|
||||
ir->carrier = carrier;
|
||||
meson_irtx_set_mod(ir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_irtx_set_duty_cycle(struct rc_dev *rc, u32 duty_cycle)
|
||||
{
|
||||
struct meson_irtx *ir = rc->priv;
|
||||
|
||||
ir->duty_cycle = duty_cycle;
|
||||
meson_irtx_set_mod(ir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf,
|
||||
unsigned int len, unsigned int head)
|
||||
{
|
||||
ir->buf = buf;
|
||||
ir->buf_len = len;
|
||||
ir->buf_head = head;
|
||||
}
|
||||
|
||||
static int meson_irtx_transmit(struct rc_dev *rc, unsigned int *buf,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct meson_irtx *ir = rc->priv;
|
||||
u32 *tx_buf;
|
||||
int ret = len;
|
||||
|
||||
if (!meson_irtx_check_buf(ir, buf, len))
|
||||
return -EINVAL;
|
||||
|
||||
tx_buf = kmalloc_array(len, sizeof(u32), GFP_KERNEL);
|
||||
if (!tx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
meson_irtx_fill_buf(ir, tx_buf, buf, len);
|
||||
dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len);
|
||||
|
||||
spin_lock_irqsave(&ir->lock, flags);
|
||||
meson_irtx_update_buf(ir, tx_buf, len, 0);
|
||||
reinit_completion(&ir->completion);
|
||||
meson_irtx_send_buffer(ir);
|
||||
spin_unlock_irqrestore(&ir->lock, flags);
|
||||
|
||||
if (!wait_for_completion_timeout(&ir->completion,
|
||||
usecs_to_jiffies(IR_MAX_DURATION)))
|
||||
ret = -ETIMEDOUT;
|
||||
|
||||
spin_lock_irqsave(&ir->lock, flags);
|
||||
kfree(ir->buf);
|
||||
meson_irtx_update_buf(ir, NULL, 0, 0);
|
||||
spin_unlock_irqrestore(&ir->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int meson_irtx_mod_clock_probe(struct meson_irtx *ir,
|
||||
unsigned int *clk_nr)
|
||||
{
|
||||
struct device_node *np = ir->dev->of_node;
|
||||
struct clk *clock;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
clock = devm_clk_get(ir->dev, "xtal");
|
||||
if (IS_ERR(clock) || clk_prepare_enable(clock))
|
||||
return -ENODEV;
|
||||
|
||||
*clk_nr = IRB_MOD_XTAL3_CLK;
|
||||
ir->clk_rate = clk_get_rate(clock) / 3;
|
||||
|
||||
if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) {
|
||||
*clk_nr = IRB_MOD_1US_CLK;
|
||||
ir->clk_rate = IRB_MOD_1US_CLK_RATE;
|
||||
}
|
||||
|
||||
dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init meson_irtx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct meson_irtx *ir;
|
||||
struct rc_dev *rc;
|
||||
int irq;
|
||||
unsigned int clk_nr;
|
||||
int ret;
|
||||
|
||||
ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL);
|
||||
if (!ir)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(ir->reg_base))
|
||||
return PTR_ERR(ir->reg_base);
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "no irq resource found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ir->dev = dev;
|
||||
ir->carrier = MIRTX_DEFAULT_CARRIER;
|
||||
ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE;
|
||||
init_completion(&ir->completion);
|
||||
spin_lock_init(&ir->lock);
|
||||
|
||||
ret = meson_irtx_mod_clock_probe(ir, &clk_nr);
|
||||
if (ret) {
|
||||
dev_err(dev, "modulator clock setup failed\n");
|
||||
return ret;
|
||||
}
|
||||
meson_irtx_setup(ir, clk_nr);
|
||||
|
||||
ret = devm_request_irq(dev, irq,
|
||||
meson_irtx_irqhandler,
|
||||
IRQF_TRIGGER_RISING,
|
||||
DRIVER_NAME, ir);
|
||||
if (ret) {
|
||||
dev_err(dev, "irq request failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
rc = rc_allocate_device(RC_DRIVER_IR_RAW_TX);
|
||||
if (!rc)
|
||||
return -ENOMEM;
|
||||
|
||||
rc->driver_name = DRIVER_NAME;
|
||||
rc->device_name = DEVICE_NAME;
|
||||
rc->priv = ir;
|
||||
|
||||
rc->tx_ir = meson_irtx_transmit;
|
||||
rc->s_tx_carrier = meson_irtx_set_carrier;
|
||||
rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle;
|
||||
|
||||
ret = rc_register_device(rc);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "rc_dev registration failed\n");
|
||||
rc_free_device(rc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int meson_irtx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rc_dev *rc = platform_get_drvdata(pdev);
|
||||
|
||||
rc_unregister_device(rc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id meson_irtx_dt_match[] = {
|
||||
{
|
||||
.compatible = "amlogic,meson-g12a-ir-tx",
|
||||
},
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
|
||||
|
||||
static struct platform_driver meson_irtx_pd = {
|
||||
.remove = meson_irtx_remove,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = meson_irtx_dt_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver_probe(meson_irtx_pd, meson_irtx_probe);
|
||||
|
||||
MODULE_DESCRIPTION("Meson IR TX driver");
|
||||
MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
|
||||
MODULE_LICENSE("GPL");
|
@ -15,12 +15,9 @@
|
||||
#include <linux/slab.h>
|
||||
#include <media/rc-core.h>
|
||||
|
||||
#define DRIVER_NAME "rc-loopback"
|
||||
#define dprintk(x...) if (debug) printk(KERN_INFO DRIVER_NAME ": " x)
|
||||
#define RXMASK_REGULAR 0x1
|
||||
#define RXMASK_LEARNING 0x2
|
||||
|
||||
static bool debug;
|
||||
#define DRIVER_NAME "rc-loopback"
|
||||
#define RXMASK_NARROWBAND 0x1
|
||||
#define RXMASK_WIDEBAND 0x2
|
||||
|
||||
struct loopback_dev {
|
||||
struct rc_dev *dev;
|
||||
@ -28,7 +25,7 @@ struct loopback_dev {
|
||||
u32 txcarrier;
|
||||
u32 txduty;
|
||||
bool idle;
|
||||
bool learning;
|
||||
bool wideband;
|
||||
bool carrierreport;
|
||||
u32 rxcarriermin;
|
||||
u32 rxcarriermax;
|
||||
@ -40,12 +37,12 @@ static int loop_set_tx_mask(struct rc_dev *dev, u32 mask)
|
||||
{
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
|
||||
dprintk("invalid tx mask: %u\n", mask);
|
||||
return -EINVAL;
|
||||
if ((mask & (RXMASK_NARROWBAND | RXMASK_WIDEBAND)) != mask) {
|
||||
dev_dbg(&dev->dev, "invalid tx mask: %u\n", mask);
|
||||
return 2;
|
||||
}
|
||||
|
||||
dprintk("setting tx mask: %u\n", mask);
|
||||
dev_dbg(&dev->dev, "setting tx mask: %u\n", mask);
|
||||
lodev->txmask = mask;
|
||||
return 0;
|
||||
}
|
||||
@ -54,7 +51,7 @@ static int loop_set_tx_carrier(struct rc_dev *dev, u32 carrier)
|
||||
{
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
dprintk("setting tx carrier: %u\n", carrier);
|
||||
dev_dbg(&dev->dev, "setting tx carrier: %u\n", carrier);
|
||||
lodev->txcarrier = carrier;
|
||||
return 0;
|
||||
}
|
||||
@ -64,11 +61,11 @@ static int loop_set_tx_duty_cycle(struct rc_dev *dev, u32 duty_cycle)
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if (duty_cycle < 1 || duty_cycle > 99) {
|
||||
dprintk("invalid duty cycle: %u\n", duty_cycle);
|
||||
dev_dbg(&dev->dev, "invalid duty cycle: %u\n", duty_cycle);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dprintk("setting duty cycle: %u\n", duty_cycle);
|
||||
dev_dbg(&dev->dev, "setting duty cycle: %u\n", duty_cycle);
|
||||
lodev->txduty = duty_cycle;
|
||||
return 0;
|
||||
}
|
||||
@ -78,11 +75,11 @@ static int loop_set_rx_carrier_range(struct rc_dev *dev, u32 min, u32 max)
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if (min < 1 || min > max) {
|
||||
dprintk("invalid rx carrier range %u to %u\n", min, max);
|
||||
dev_dbg(&dev->dev, "invalid rx carrier range %u to %u\n", min, max);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dprintk("setting rx carrier range %u to %u\n", min, max);
|
||||
dev_dbg(&dev->dev, "setting rx carrier range %u to %u\n", min, max);
|
||||
lodev->rxcarriermin = min;
|
||||
lodev->rxcarriermax = max;
|
||||
return 0;
|
||||
@ -97,25 +94,33 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
|
||||
|
||||
if (lodev->txcarrier < lodev->rxcarriermin ||
|
||||
lodev->txcarrier > lodev->rxcarriermax) {
|
||||
dprintk("ignoring tx, carrier out of range\n");
|
||||
dev_dbg(&dev->dev, "ignoring tx, carrier out of range\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lodev->learning)
|
||||
rxmask = RXMASK_LEARNING;
|
||||
if (lodev->wideband)
|
||||
rxmask = RXMASK_WIDEBAND;
|
||||
else
|
||||
rxmask = RXMASK_REGULAR;
|
||||
rxmask = RXMASK_NARROWBAND;
|
||||
|
||||
if (!(rxmask & lodev->txmask)) {
|
||||
dprintk("ignoring tx, rx mask mismatch\n");
|
||||
dev_dbg(&dev->dev, "ignoring tx, rx mask mismatch\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
rawir.pulse = i % 2 ? false : true;
|
||||
rawir.duration = txbuf[i];
|
||||
if (rawir.duration)
|
||||
ir_raw_event_store_with_filter(dev, &rawir);
|
||||
|
||||
ir_raw_event_store_with_filter(dev, &rawir);
|
||||
}
|
||||
|
||||
if (lodev->carrierreport) {
|
||||
rawir.pulse = false;
|
||||
rawir.carrier_report = true;
|
||||
rawir.carrier = lodev->txcarrier;
|
||||
|
||||
ir_raw_event_store(dev, &rawir);
|
||||
}
|
||||
|
||||
/* Fake a silence long enough to cause us to go idle */
|
||||
@ -134,18 +139,18 @@ static void loop_set_idle(struct rc_dev *dev, bool enable)
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if (lodev->idle != enable) {
|
||||
dprintk("%sing idle mode\n", enable ? "enter" : "exit");
|
||||
dev_dbg(&dev->dev, "%sing idle mode\n", enable ? "enter" : "exit");
|
||||
lodev->idle = enable;
|
||||
}
|
||||
}
|
||||
|
||||
static int loop_set_learning_mode(struct rc_dev *dev, int enable)
|
||||
static int loop_set_wideband_receiver(struct rc_dev *dev, int enable)
|
||||
{
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if (lodev->learning != enable) {
|
||||
dprintk("%sing learning mode\n", enable ? "enter" : "exit");
|
||||
lodev->learning = !!enable;
|
||||
if (lodev->wideband != enable) {
|
||||
dev_dbg(&dev->dev, "using %sband receiver\n", enable ? "wide" : "narrow");
|
||||
lodev->wideband = !!enable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -156,7 +161,7 @@ static int loop_set_carrier_report(struct rc_dev *dev, int enable)
|
||||
struct loopback_dev *lodev = dev->priv;
|
||||
|
||||
if (lodev->carrierreport != enable) {
|
||||
dprintk("%sabling carrier reports\n", enable ? "en" : "dis");
|
||||
dev_dbg(&dev->dev, "%sabling carrier reports\n", enable ? "en" : "dis");
|
||||
lodev->carrierreport = !!enable;
|
||||
}
|
||||
|
||||
@ -204,10 +209,8 @@ static int __init loop_init(void)
|
||||
int ret;
|
||||
|
||||
rc = rc_allocate_device(RC_DRIVER_IR_RAW);
|
||||
if (!rc) {
|
||||
printk(KERN_ERR DRIVER_NAME ": rc_dev allocation failed\n");
|
||||
if (!rc)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc->device_name = "rc-core loopback device";
|
||||
rc->input_phys = "rc-core/virtual";
|
||||
@ -219,9 +222,9 @@ static int __init loop_init(void)
|
||||
rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
|
||||
rc->allowed_wakeup_protocols = RC_PROTO_BIT_ALL_IR_ENCODER;
|
||||
rc->encode_wakeup = true;
|
||||
rc->timeout = MS_TO_US(100); /* 100 ms */
|
||||
rc->timeout = IR_DEFAULT_TIMEOUT;
|
||||
rc->min_timeout = 1;
|
||||
rc->max_timeout = UINT_MAX;
|
||||
rc->max_timeout = IR_MAX_TIMEOUT;
|
||||
rc->rx_resolution = 1;
|
||||
rc->tx_resolution = 1;
|
||||
rc->s_tx_mask = loop_set_tx_mask;
|
||||
@ -230,22 +233,22 @@ static int __init loop_init(void)
|
||||
rc->s_rx_carrier_range = loop_set_rx_carrier_range;
|
||||
rc->tx_ir = loop_tx_ir;
|
||||
rc->s_idle = loop_set_idle;
|
||||
rc->s_learning_mode = loop_set_learning_mode;
|
||||
rc->s_wideband_receiver = loop_set_wideband_receiver;
|
||||
rc->s_carrier_report = loop_set_carrier_report;
|
||||
rc->s_wakeup_filter = loop_set_wakeup_filter;
|
||||
|
||||
loopdev.txmask = RXMASK_REGULAR;
|
||||
loopdev.txmask = RXMASK_NARROWBAND;
|
||||
loopdev.txcarrier = 36000;
|
||||
loopdev.txduty = 50;
|
||||
loopdev.rxcarriermin = 1;
|
||||
loopdev.rxcarriermax = ~0;
|
||||
loopdev.idle = true;
|
||||
loopdev.learning = false;
|
||||
loopdev.wideband = false;
|
||||
loopdev.carrierreport = false;
|
||||
|
||||
ret = rc_register_device(rc);
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR DRIVER_NAME ": rc_dev registration failed\n");
|
||||
dev_err(&rc->dev, "rc_dev registration failed\n");
|
||||
rc_free_device(rc);
|
||||
return ret;
|
||||
}
|
||||
@ -262,9 +265,6 @@ static void __exit loop_exit(void)
|
||||
module_init(loop_init);
|
||||
module_exit(loop_exit);
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Enable debug messages");
|
||||
|
||||
MODULE_DESCRIPTION("Loopback device for rc-core debugging");
|
||||
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -1940,7 +1940,7 @@ int rc_register_device(struct rc_dev *dev)
|
||||
kfree(path);
|
||||
|
||||
/*
|
||||
* once the the input device is registered in rc_setup_rx_device,
|
||||
* once the input device is registered in rc_setup_rx_device,
|
||||
* userspace can open the input device and rc_open() will be called
|
||||
* as a result. This results in driver code being allowed to submit
|
||||
* keycodes with rc_keydown, so lirc must be registered first.
|
||||
|
@ -6,7 +6,7 @@
|
||||
* based heavily on the work of Stephen Cox, with additional
|
||||
* help from RedRat Ltd.
|
||||
*
|
||||
* This driver began life based an an old version of the first-generation
|
||||
* This driver began life based on an old version of the first-generation
|
||||
* lirc_mceusb driver from the lirc 0.7.2 distribution. It was then
|
||||
* significantly rewritten by Stephen Cox with the aid of RedRat Ltd's
|
||||
* Chris Dodge.
|
||||
|
@ -265,8 +265,6 @@ static void streamzap_callback(struct urb *urb)
|
||||
|
||||
ir_raw_event_handle(sz->rdev);
|
||||
usb_submit_urb(urb, GFP_ATOMIC);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct rc_dev *streamzap_init_rc_dev(struct streamzap_ir *sz)
|
||||
|
@ -524,13 +524,13 @@ cxd2880_spi_probe(struct spi_device *spi)
|
||||
if (IS_ERR(dvb_spi->vcc_supply)) {
|
||||
if (PTR_ERR(dvb_spi->vcc_supply) == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto fail_adapter;
|
||||
goto fail_regulator;
|
||||
}
|
||||
dvb_spi->vcc_supply = NULL;
|
||||
} else {
|
||||
ret = regulator_enable(dvb_spi->vcc_supply);
|
||||
if (ret)
|
||||
goto fail_adapter;
|
||||
goto fail_regulator;
|
||||
}
|
||||
|
||||
dvb_spi->spi = spi;
|
||||
@ -618,6 +618,9 @@ fail_frontend:
|
||||
fail_attach:
|
||||
dvb_unregister_adapter(&dvb_spi->adapter);
|
||||
fail_adapter:
|
||||
if (!dvb_spi->vcc_supply)
|
||||
regulator_disable(dvb_spi->vcc_supply);
|
||||
fail_regulator:
|
||||
kfree(dvb_spi);
|
||||
return ret;
|
||||
}
|
||||
|
@ -282,5 +282,5 @@ struct cec_adapter *vivid_cec_alloc_adap(struct vivid_dev *dev,
|
||||
snprintf(name, sizeof(name), "vivid-%03d-vid-%s%d",
|
||||
dev->inst, is_source ? "out" : "cap", idx);
|
||||
return cec_allocate_adapter(&vivid_cec_adap_ops, dev,
|
||||
name, caps, 1);
|
||||
name, caps, CEC_MAX_LOG_ADDRS);
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ config DVB_USB_AF9035
|
||||
tristate "Afatech AF9035 DVB-T USB2.0 support"
|
||||
depends on DVB_USB_V2
|
||||
select DVB_AF9033
|
||||
select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_TUA9001 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_FC0011 if MEDIA_SUBDRV_AUTOSELECT
|
||||
select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
|
||||
|
@ -210,6 +210,7 @@ static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
|
||||
/* register I2C device */
|
||||
client = i2c_new_client_device(adapter, &board_info);
|
||||
if (!i2c_client_has_driver(client)) {
|
||||
dev_err(&intf->dev, "failed to bind i2c device to %s driver\n", type);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
@ -541,7 +541,9 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
|
||||
si2168_config.i2c_adapter = &i2c_adapter;
|
||||
si2168_config.fe = &adap->fe[0];
|
||||
si2168_config.ts_mode = SI2168_TS_PARALLEL;
|
||||
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2)
|
||||
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2 ||
|
||||
le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230C2_LITE ||
|
||||
le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A)
|
||||
si2168_config.ts_mode |= SI2168_TS_CLK_MANUAL;
|
||||
si2168_config.ts_clock_inv = 1;
|
||||
|
||||
@ -577,15 +579,24 @@ static int dvbsky_mygica_t230c_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
|
||||
{
|
||||
dvbsky_gpio_ctrl(d, 0x04, 1);
|
||||
msleep(20);
|
||||
dvbsky_gpio_ctrl(d, 0x83, 0);
|
||||
dvbsky_gpio_ctrl(d, 0xc0, 1);
|
||||
msleep(100);
|
||||
dvbsky_gpio_ctrl(d, 0x83, 1);
|
||||
dvbsky_gpio_ctrl(d, 0xc0, 0);
|
||||
msleep(50);
|
||||
|
||||
if (le16_to_cpu(d->udev->descriptor.idProduct) == USB_PID_MYGICA_T230A) {
|
||||
dvbsky_gpio_ctrl(d, 0x87, 0);
|
||||
msleep(20);
|
||||
dvbsky_gpio_ctrl(d, 0x86, 1);
|
||||
dvbsky_gpio_ctrl(d, 0x80, 0);
|
||||
msleep(100);
|
||||
dvbsky_gpio_ctrl(d, 0x80, 1);
|
||||
msleep(50);
|
||||
} else {
|
||||
dvbsky_gpio_ctrl(d, 0x04, 1);
|
||||
msleep(20);
|
||||
dvbsky_gpio_ctrl(d, 0x83, 0);
|
||||
dvbsky_gpio_ctrl(d, 0xc0, 1);
|
||||
msleep(100);
|
||||
dvbsky_gpio_ctrl(d, 0x83, 1);
|
||||
dvbsky_gpio_ctrl(d, 0xc0, 0);
|
||||
msleep(50);
|
||||
}
|
||||
return WARM;
|
||||
}
|
||||
|
||||
@ -789,6 +800,12 @@ static const struct usb_device_id dvbsky_id_table[] = {
|
||||
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
|
||||
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2",
|
||||
RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
|
||||
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2_LITE,
|
||||
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230C v2 Lite",
|
||||
NULL) },
|
||||
{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230A,
|
||||
&mygica_t230c_props, "MyGica Mini DVB-(T/T2/C) USB Stick T230A",
|
||||
NULL) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
|
||||
|
@ -17,7 +17,8 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||
|
||||
if (d->props.i2c_algo == NULL) {
|
||||
err("no i2c algorithm specified");
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
|
||||
@ -27,11 +28,15 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||
|
||||
i2c_set_adapdata(&d->i2c_adap, d);
|
||||
|
||||
if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
|
||||
ret = i2c_add_adapter(&d->i2c_adap);
|
||||
if (ret < 0) {
|
||||
err("could not add i2c adapter");
|
||||
goto err;
|
||||
}
|
||||
|
||||
d->state |= DVB_USB_STATE_I2C;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,8 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
|
||||
|
||||
err_adapter_init:
|
||||
dvb_usb_adapter_exit(d);
|
||||
err_i2c_init:
|
||||
dvb_usb_i2c_exit(d);
|
||||
err_i2c_init:
|
||||
if (d->priv && d->props.priv_destroy)
|
||||
d->props.priv_destroy(d);
|
||||
err_priv_init:
|
||||
|
@ -130,7 +130,7 @@ ret:
|
||||
|
||||
static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
u8 b;
|
||||
|
||||
mac[0] = 0x00;
|
||||
@ -139,7 +139,9 @@ static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
|
||||
|
||||
/* this is a complete guess, but works for my box */
|
||||
for (i = 136; i < 139; i++) {
|
||||
dibusb_read_eeprom_byte(d,i, &b);
|
||||
ret = dibusb_read_eeprom_byte(d, i, &b);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mac[5 - (i - 136)] = b;
|
||||
}
|
||||
|
@ -291,16 +291,22 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
|
||||
{
|
||||
u8 i, *buf;
|
||||
int ret;
|
||||
struct vp702x_device_state *st = d->priv;
|
||||
|
||||
mutex_lock(&st->buf_mutex);
|
||||
buf = st->buf;
|
||||
for (i = 6; i < 12; i++)
|
||||
vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
|
||||
for (i = 6; i < 12; i++) {
|
||||
ret = vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1,
|
||||
&buf[i - 6], 1);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
memcpy(mac, buf, 6);
|
||||
err:
|
||||
mutex_unlock(&st->buf_mutex);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
@ -842,7 +842,6 @@ error:
|
||||
kfree(ir);
|
||||
ref_put:
|
||||
em28xx_shutdown_buttons(dev);
|
||||
kref_put(&dev->ref, em28xx_free_device);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -691,49 +691,23 @@ struct go7007 *go7007_alloc(const struct go7007_board_info *board,
|
||||
struct device *dev)
|
||||
{
|
||||
struct go7007 *go;
|
||||
int i;
|
||||
|
||||
go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
|
||||
if (go == NULL)
|
||||
return NULL;
|
||||
go->dev = dev;
|
||||
go->board_info = board;
|
||||
go->board_id = 0;
|
||||
go->tuner_type = -1;
|
||||
go->channel_number = 0;
|
||||
go->name[0] = 0;
|
||||
mutex_init(&go->hw_lock);
|
||||
init_waitqueue_head(&go->frame_waitq);
|
||||
spin_lock_init(&go->spinlock);
|
||||
go->status = STATUS_INIT;
|
||||
memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
|
||||
go->i2c_adapter_online = 0;
|
||||
go->interrupt_available = 0;
|
||||
init_waitqueue_head(&go->interrupt_waitq);
|
||||
go->input = 0;
|
||||
go7007_update_board(go);
|
||||
go->encoder_h_halve = 0;
|
||||
go->encoder_v_halve = 0;
|
||||
go->encoder_subsample = 0;
|
||||
go->format = V4L2_PIX_FMT_MJPEG;
|
||||
go->bitrate = 1500000;
|
||||
go->fps_scale = 1;
|
||||
go->pali = 0;
|
||||
go->aspect_ratio = GO7007_RATIO_1_1;
|
||||
go->gop_size = 0;
|
||||
go->ipb = 0;
|
||||
go->closed_gop = 0;
|
||||
go->repeat_seqhead = 0;
|
||||
go->seq_header_enable = 0;
|
||||
go->gop_header_enable = 0;
|
||||
go->dvd_mode = 0;
|
||||
go->interlace_coding = 0;
|
||||
for (i = 0; i < 4; ++i)
|
||||
go->modet[i].enable = 0;
|
||||
for (i = 0; i < 1624; ++i)
|
||||
go->modet_map[i] = 0;
|
||||
go->audio_deliver = NULL;
|
||||
go->audio_enabled = 0;
|
||||
|
||||
return go;
|
||||
}
|
||||
|
@ -1134,7 +1134,7 @@ static int go7007_usb_probe(struct usb_interface *intf,
|
||||
|
||||
ep = usb->usbdev->ep_in[4];
|
||||
if (!ep)
|
||||
return -ENODEV;
|
||||
goto allocfail;
|
||||
|
||||
/* Allocate the URB and buffer for receiving incoming interrupts */
|
||||
usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
|
@ -4,7 +4,6 @@ menuconfig USB_GSPCA
|
||||
depends on VIDEO_V4L2
|
||||
depends on INPUT || INPUT=n
|
||||
select VIDEOBUF2_VMALLOC
|
||||
default m
|
||||
help
|
||||
Say Y here if you want to enable selecting webcams based
|
||||
on the GSPCA framework.
|
||||
|
@ -1796,7 +1796,7 @@ static const u8 ov7660_60HZ[][4] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const u8 ov7660_NoFliker[][4] = {
|
||||
static const u8 ov7660_NoFlicker[][4] = {
|
||||
{0x00, 0x13, 0x87, 0xaa},
|
||||
{}
|
||||
};
|
||||
@ -3319,8 +3319,8 @@ static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
|
||||
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
struct sd *sd = (struct sd *) gspca_dev;
|
||||
static const u8 (*ov7660_freq_tb[3])[4] =
|
||||
{ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
|
||||
static const u8 (*ov7660_freq_tb[3])[4] = {
|
||||
ov7660_NoFlicker, ov7660_50HZ, ov7660_60HZ};
|
||||
|
||||
if (sd->sensor != SENSOR_OV7660)
|
||||
return;
|
||||
|
@ -323,7 +323,7 @@ static const struct usb_action adcm2700_60HZ[] = {
|
||||
{0xaa, 0x28, 0x0002}, /* 00,28,02,aa */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action adcm2700_NoFliker[] = {
|
||||
static const struct usb_action adcm2700_NoFlicker[] = {
|
||||
{0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
|
||||
{0xaa, 0xfe, 0x0002}, /* 00,fe,02,aa */
|
||||
{0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,0a,cc */
|
||||
@ -525,7 +525,7 @@ static const struct usb_action cs2102_60HZ[] = {
|
||||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action cs2102_NoFlikerScale[] = {
|
||||
static const struct usb_action cs2102_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xaa, 0x23, 0x0001},
|
||||
{0xaa, 0x24, 0x005f},
|
||||
@ -547,7 +547,7 @@ static const struct usb_action cs2102_NoFlikerScale[] = {
|
||||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action cs2102_NoFliker[] = {
|
||||
static const struct usb_action cs2102_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xaa, 0x23, 0x0000},
|
||||
{0xaa, 0x24, 0x00af},
|
||||
@ -1385,7 +1385,7 @@ static const struct usb_action gc0305_60HZ[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action gc0305_NoFliker[] = {
|
||||
static const struct usb_action gc0305_NoFlicker[] = {
|
||||
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
|
||||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||||
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
|
||||
@ -1710,7 +1710,7 @@ static const struct usb_action hdcs2020_60HZ[] = {
|
||||
{0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action hdcs2020_NoFliker[] = {
|
||||
static const struct usb_action hdcs2020_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0x13, 0x0010}, /* 00,13,10,aa */
|
||||
{0xaa, 0x14, 0x0001}, /* 00,14,01,aa */
|
||||
@ -1925,7 +1925,7 @@ static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
|
||||
{0xa0, 0x40, ZC3XX_R020_HSYNC_3}, /* 00,20,40,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
|
||||
static const struct usb_action hv7131b_NoFlicker[] = { /* 640x480*/
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
|
||||
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
|
||||
@ -1950,7 +1950,7 @@ static const struct usb_action hv7131b_NoFliker[] = { /* 640x480*/
|
||||
{0xa0, 0x03, ZC3XX_R020_HSYNC_3}, /* 00,20,03,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
|
||||
static const struct usb_action hv7131b_NoFlickerScale[] = { /* 320x240 */
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0x25, 0x0003}, /* 00,25,03,aa */
|
||||
{0xaa, 0x26, 0x0000}, /* 00,26,00,aa */
|
||||
@ -2141,7 +2141,7 @@ static const struct usb_action hv7131r_60HZScale[] = {
|
||||
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action hv7131r_NoFliker[] = {
|
||||
static const struct usb_action hv7131r_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
|
||||
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
|
||||
@ -2159,7 +2159,7 @@ static const struct usb_action hv7131r_NoFliker[] = {
|
||||
{0xa0, 0x08, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action hv7131r_NoFlikerScale[] = {
|
||||
static const struct usb_action hv7131r_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
|
||||
{0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
|
||||
@ -2662,7 +2662,7 @@ static const struct usb_action icm105a_60HZ[] = {
|
||||
{0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action icm105a_NoFlikerScale[] = {
|
||||
static const struct usb_action icm105a_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||||
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
|
||||
@ -2693,7 +2693,7 @@ static const struct usb_action icm105a_NoFlikerScale[] = {
|
||||
{0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action icm105a_NoFliker[] = {
|
||||
static const struct usb_action icm105a_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
|
||||
{0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
|
||||
@ -3009,7 +3009,7 @@ static const struct usb_action mc501cb_60HZScale[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action mc501cb_NoFliker[] = {
|
||||
static const struct usb_action mc501cb_NoFlicker[] = {
|
||||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||||
{0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
|
||||
@ -3021,7 +3021,7 @@ static const struct usb_action mc501cb_NoFliker[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action mc501cb_NoFlikerScale[] = {
|
||||
static const struct usb_action mc501cb_NoFlickerScale[] = {
|
||||
{0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
|
||||
{0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
|
||||
{0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
|
||||
@ -3211,7 +3211,7 @@ static const struct usb_action ov7620_60HZ[] = {
|
||||
{0xa1, 0x01, 0x0037}, */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action ov7620_NoFliker[] = {
|
||||
static const struct usb_action ov7620_NoFlicker[] = {
|
||||
{0xdd, 0x00, 0x0100}, /* 00,01,00,dd */
|
||||
{0xaa, 0x2b, 0x0000}, /* 00,2b,00,aa */
|
||||
/* disable 1/120s & 1/100s exposures for banding filter */
|
||||
@ -3827,7 +3827,7 @@ static const struct usb_action pas106b_60HZ[] = {
|
||||
{0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action pas106b_NoFliker[] = {
|
||||
static const struct usb_action pas106b_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
|
||||
{0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
|
||||
{0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
|
||||
@ -4051,7 +4051,7 @@ static const struct usb_action pas202b_60HZScale[] = {
|
||||
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action pas202b_NoFliker[] = {
|
||||
static const struct usb_action pas202b_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||||
@ -4080,7 +4080,7 @@ static const struct usb_action pas202b_NoFliker[] = {
|
||||
{0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW}, /* 00,88,0e,cc */
|
||||
{}
|
||||
};
|
||||
static const struct usb_action pas202b_NoFlikerScale[] = {
|
||||
static const struct usb_action pas202b_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xa0, 0x20, ZC3XX_R087_EXPTIMEMID}, /* 00,87,20,cc */
|
||||
{0xa0, 0x21, ZC3XX_R088_EXPTIMELOW}, /* 00,88,21,cc */
|
||||
@ -4309,7 +4309,7 @@ static const struct usb_action mt9v111_1_AE60HZScale[] = {
|
||||
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action mt9v111_1_AENoFliker[] = {
|
||||
static const struct usb_action mt9v111_1_AENoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xbb, 0x00, 0x0509},
|
||||
@ -4332,7 +4332,7 @@ static const struct usb_action mt9v111_1_AENoFliker[] = {
|
||||
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
|
||||
static const struct usb_action mt9v111_1_AENoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xbb, 0x00, 0x0534},
|
||||
@ -4554,7 +4554,7 @@ static const struct usb_action mt9v111_3_AE60HZScale[] = {
|
||||
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action mt9v111_3_AENoFliker[] = {
|
||||
static const struct usb_action mt9v111_3_AENoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xaa, 0x05, 0x0034},
|
||||
@ -4577,7 +4577,7 @@ static const struct usb_action mt9v111_3_AENoFliker[] = {
|
||||
{0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
|
||||
static const struct usb_action mt9v111_3_AENoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xaa, 0x05, 0x0034},
|
||||
@ -4787,7 +4787,7 @@ static const struct usb_action pb0330_60HZScale[] = {
|
||||
{0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action pb0330_NoFliker[] = {
|
||||
static const struct usb_action pb0330_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xbb, 0x00, 0x0509},
|
||||
{0xbb, 0x02, 0x0940},
|
||||
@ -4809,7 +4809,7 @@ static const struct usb_action pb0330_NoFliker[] = {
|
||||
{0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action pb0330_NoFlikerScale[] = {
|
||||
static const struct usb_action pb0330_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
|
||||
{0xbb, 0x00, 0x0535},
|
||||
{0xbb, 0x01, 0x0980},
|
||||
@ -5031,7 +5031,7 @@ static const struct usb_action po2030_60HZ[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action po2030_NoFliker[] = {
|
||||
static const struct usb_action po2030_NoFlicker[] = {
|
||||
{0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
|
||||
{0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
|
||||
{0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
|
||||
@ -5215,7 +5215,7 @@ static const struct usb_action tas5130c_60HZScale[] = {
|
||||
{0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
|
||||
{}
|
||||
};
|
||||
static const struct usb_action tas5130c_NoFliker[] = {
|
||||
static const struct usb_action tas5130c_NoFlicker[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
|
||||
{0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
|
||||
@ -5241,7 +5241,7 @@ static const struct usb_action tas5130c_NoFliker[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action tas5130c_NoFlikerScale[] = {
|
||||
static const struct usb_action tas5130c_NoFlickerScale[] = {
|
||||
{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
|
||||
{0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
|
||||
{0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
|
||||
@ -5482,7 +5482,7 @@ static const struct usb_action gc0303_60HZScale[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action gc0303_NoFliker[] = {
|
||||
static const struct usb_action gc0303_NoFlicker[] = {
|
||||
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
|
||||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||||
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
|
||||
@ -5504,7 +5504,7 @@ static const struct usb_action gc0303_NoFliker[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct usb_action gc0303_NoFlikerScale[] = {
|
||||
static const struct usb_action gc0303_NoFlickerScale[] = {
|
||||
{0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */
|
||||
{0xaa, 0x82, 0x0000}, /* 00,82,00,aa */
|
||||
{0xaa, 0x83, 0x0000}, /* 00,83,00,aa */
|
||||
@ -5806,7 +5806,7 @@ static void setquality(struct gspca_dev *gspca_dev)
|
||||
* Valid frequencies are:
|
||||
* 50Hz, for European and Asian lighting (default)
|
||||
* 60Hz, for American lighting
|
||||
* 0 = No Fliker (for outdoore usage)
|
||||
* 0 = No Flicker (for outdoor usage)
|
||||
*/
|
||||
static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
|
||||
{
|
||||
@ -5814,80 +5814,80 @@ static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
|
||||
int i, mode;
|
||||
const struct usb_action *zc3_freq;
|
||||
static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
|
||||
[SENSOR_ADCM2700] =
|
||||
{adcm2700_NoFliker, adcm2700_NoFliker,
|
||||
[SENSOR_ADCM2700] = {
|
||||
adcm2700_NoFlicker, adcm2700_NoFlicker,
|
||||
adcm2700_50HZ, adcm2700_50HZ,
|
||||
adcm2700_60HZ, adcm2700_60HZ},
|
||||
[SENSOR_CS2102] =
|
||||
{cs2102_NoFliker, cs2102_NoFlikerScale,
|
||||
[SENSOR_CS2102] = {
|
||||
cs2102_NoFlicker, cs2102_NoFlickerScale,
|
||||
cs2102_50HZ, cs2102_50HZScale,
|
||||
cs2102_60HZ, cs2102_60HZScale},
|
||||
[SENSOR_CS2102K] =
|
||||
{cs2102_NoFliker, cs2102_NoFlikerScale,
|
||||
[SENSOR_CS2102K] = {
|
||||
cs2102_NoFlicker, cs2102_NoFlickerScale,
|
||||
NULL, NULL, /* currently disabled */
|
||||
NULL, NULL},
|
||||
[SENSOR_GC0303] =
|
||||
{gc0303_NoFliker, gc0303_NoFlikerScale,
|
||||
[SENSOR_GC0303] = {
|
||||
gc0303_NoFlicker, gc0303_NoFlickerScale,
|
||||
gc0303_50HZ, gc0303_50HZScale,
|
||||
gc0303_60HZ, gc0303_60HZScale},
|
||||
[SENSOR_GC0305] =
|
||||
{gc0305_NoFliker, gc0305_NoFliker,
|
||||
[SENSOR_GC0305] = {
|
||||
gc0305_NoFlicker, gc0305_NoFlicker,
|
||||
gc0305_50HZ, gc0305_50HZ,
|
||||
gc0305_60HZ, gc0305_60HZ},
|
||||
[SENSOR_HDCS2020] =
|
||||
{hdcs2020_NoFliker, hdcs2020_NoFliker,
|
||||
[SENSOR_HDCS2020] = {
|
||||
hdcs2020_NoFlicker, hdcs2020_NoFlicker,
|
||||
hdcs2020_50HZ, hdcs2020_50HZ,
|
||||
hdcs2020_60HZ, hdcs2020_60HZ},
|
||||
[SENSOR_HV7131B] =
|
||||
{hv7131b_NoFliker, hv7131b_NoFlikerScale,
|
||||
[SENSOR_HV7131B] = {
|
||||
hv7131b_NoFlicker, hv7131b_NoFlickerScale,
|
||||
hv7131b_50HZ, hv7131b_50HZScale,
|
||||
hv7131b_60HZ, hv7131b_60HZScale},
|
||||
[SENSOR_HV7131R] =
|
||||
{hv7131r_NoFliker, hv7131r_NoFlikerScale,
|
||||
[SENSOR_HV7131R] = {
|
||||
hv7131r_NoFlicker, hv7131r_NoFlickerScale,
|
||||
hv7131r_50HZ, hv7131r_50HZScale,
|
||||
hv7131r_60HZ, hv7131r_60HZScale},
|
||||
[SENSOR_ICM105A] =
|
||||
{icm105a_NoFliker, icm105a_NoFlikerScale,
|
||||
[SENSOR_ICM105A] = {
|
||||
icm105a_NoFlicker, icm105a_NoFlickerScale,
|
||||
icm105a_50HZ, icm105a_50HZScale,
|
||||
icm105a_60HZ, icm105a_60HZScale},
|
||||
[SENSOR_MC501CB] =
|
||||
{mc501cb_NoFliker, mc501cb_NoFlikerScale,
|
||||
[SENSOR_MC501CB] = {
|
||||
mc501cb_NoFlicker, mc501cb_NoFlickerScale,
|
||||
mc501cb_50HZ, mc501cb_50HZScale,
|
||||
mc501cb_60HZ, mc501cb_60HZScale},
|
||||
[SENSOR_MT9V111_1] =
|
||||
{mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
|
||||
[SENSOR_MT9V111_1] = {
|
||||
mt9v111_1_AENoFlicker, mt9v111_1_AENoFlickerScale,
|
||||
mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
|
||||
mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
|
||||
[SENSOR_MT9V111_3] =
|
||||
{mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
|
||||
[SENSOR_MT9V111_3] = {
|
||||
mt9v111_3_AENoFlicker, mt9v111_3_AENoFlickerScale,
|
||||
mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
|
||||
mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
|
||||
[SENSOR_OV7620] =
|
||||
{ov7620_NoFliker, ov7620_NoFliker,
|
||||
[SENSOR_OV7620] = {
|
||||
ov7620_NoFlicker, ov7620_NoFlicker,
|
||||
ov7620_50HZ, ov7620_50HZ,
|
||||
ov7620_60HZ, ov7620_60HZ},
|
||||
[SENSOR_OV7630C] =
|
||||
{NULL, NULL,
|
||||
[SENSOR_OV7630C] = {
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL},
|
||||
[SENSOR_PAS106] =
|
||||
{pas106b_NoFliker, pas106b_NoFliker,
|
||||
[SENSOR_PAS106] = {
|
||||
pas106b_NoFlicker, pas106b_NoFlicker,
|
||||
pas106b_50HZ, pas106b_50HZ,
|
||||
pas106b_60HZ, pas106b_60HZ},
|
||||
[SENSOR_PAS202B] =
|
||||
{pas202b_NoFliker, pas202b_NoFlikerScale,
|
||||
[SENSOR_PAS202B] = {
|
||||
pas202b_NoFlicker, pas202b_NoFlickerScale,
|
||||
pas202b_50HZ, pas202b_50HZScale,
|
||||
pas202b_60HZ, pas202b_60HZScale},
|
||||
[SENSOR_PB0330] =
|
||||
{pb0330_NoFliker, pb0330_NoFlikerScale,
|
||||
[SENSOR_PB0330] = {
|
||||
pb0330_NoFlicker, pb0330_NoFlickerScale,
|
||||
pb0330_50HZ, pb0330_50HZScale,
|
||||
pb0330_60HZ, pb0330_60HZScale},
|
||||
[SENSOR_PO2030] =
|
||||
{po2030_NoFliker, po2030_NoFliker,
|
||||
[SENSOR_PO2030] = {
|
||||
po2030_NoFlicker, po2030_NoFlicker,
|
||||
po2030_50HZ, po2030_50HZ,
|
||||
po2030_60HZ, po2030_60HZ},
|
||||
[SENSOR_TAS5130C] =
|
||||
{tas5130c_NoFliker, tas5130c_NoFlikerScale,
|
||||
[SENSOR_TAS5130C] = {
|
||||
tas5130c_NoFlicker, tas5130c_NoFlickerScale,
|
||||
tas5130c_50HZ, tas5130c_50HZScale,
|
||||
tas5130c_60HZ, tas5130c_60HZScale},
|
||||
};
|
||||
|
@ -1346,7 +1346,7 @@ static int stk_camera_probe(struct usb_interface *interface,
|
||||
if (!dev->isoc_ep) {
|
||||
pr_err("Could not find isoc-in endpoint\n");
|
||||
err = -ENODEV;
|
||||
goto error;
|
||||
goto error_put;
|
||||
}
|
||||
dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
|
||||
dev->vsettings.mode = MODE_VGA;
|
||||
@ -1359,10 +1359,12 @@ static int stk_camera_probe(struct usb_interface *interface,
|
||||
|
||||
err = stk_register_video_device(dev);
|
||||
if (err)
|
||||
goto error;
|
||||
goto error_put;
|
||||
|
||||
return 0;
|
||||
|
||||
error_put:
|
||||
usb_put_intf(interface);
|
||||
error:
|
||||
v4l2_ctrl_handler_free(hdl);
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
|
@ -899,8 +899,8 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
|
||||
{
|
||||
struct uvc_fh *handle = fh;
|
||||
struct uvc_video_chain *chain = handle->chain;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
u8 i;
|
||||
|
||||
if (chain->selector == NULL ||
|
||||
(chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
|
||||
@ -908,22 +908,27 @@ static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = kmalloc(1, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
|
||||
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
|
||||
&i, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
buf, 1);
|
||||
if (!ret)
|
||||
*input = *buf - 1;
|
||||
|
||||
*input = i - 1;
|
||||
return 0;
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
|
||||
{
|
||||
struct uvc_fh *handle = fh;
|
||||
struct uvc_video_chain *chain = handle->chain;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
u32 i;
|
||||
|
||||
ret = uvc_acquire_privileges(handle);
|
||||
if (ret < 0)
|
||||
@ -939,10 +944,17 @@ static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
|
||||
if (input >= chain->selector->bNrInPins)
|
||||
return -EINVAL;
|
||||
|
||||
i = input + 1;
|
||||
return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
|
||||
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
|
||||
&i, 1);
|
||||
buf = kmalloc(1, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
*buf = input + 1;
|
||||
ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
|
||||
chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
|
||||
buf, 1);
|
||||
kfree(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uvc_ioctl_queryctrl(struct file *file, void *fh,
|
||||
|
@ -833,6 +833,7 @@ const char *v4l2_ctrl_get_name(u32 id)
|
||||
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE: return "Decoder Slice Interface";
|
||||
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER: return "MPEG4 Loop Filter Enable";
|
||||
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB: return "Number of Intra Refresh MBs";
|
||||
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD: return "Intra Refresh Period";
|
||||
case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE: return "Frame Level Rate Control Enable";
|
||||
case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE: return "H264 MB Level Rate Control";
|
||||
case V4L2_CID_MPEG_VIDEO_HEADER_MODE: return "Sequence Header Mode";
|
||||
@ -1258,6 +1259,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
|
||||
case V4L2_CID_MPEG_VIDEO_MV_H_SEARCH_RANGE:
|
||||
case V4L2_CID_MPEG_VIDEO_MV_V_SEARCH_RANGE:
|
||||
case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:
|
||||
case V4L2_CID_MPEG_VIDEO_INTRA_REFRESH_PERIOD:
|
||||
*type = V4L2_CTRL_TYPE_INTEGER;
|
||||
break;
|
||||
case V4L2_CID_MPEG_VIDEO_LTR_COUNT:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user