media updates for v4.12-rc1
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJZDHJ4AAoJEAhfPr2O5OEVdwAP/jAmT+Bu7gXfgcrrmHNpivx4 knyyGlmpoazPT4WbNvBkqCdYESXpJowQgzOMagRi2zSEqnylCgAFvZ/CF6imGJDd 0r1ahK6JE9sBSw2Y531h8t7IESmEFaDCOdg4W91lCMa76goZoSjWTDhv6xx1nQId d77lHhbAKctQI7VdBA1KlCdrvn5QKmNKsJHMGWJbXv/zNWube8Lk6ZAeqJ2Q2Efk yzrjQiXpYKVcG6tnI6BSp+rkzRYshO7vs+xw37RcCPfzf9YgHd9Olp9FDegzmRrd gJ1UudEpGPFZ6RIiOJLUkurPEdfAiSVMUG7jEimgRwsu0+QEURuVHF0HiTA2XjVX 5jKJSobOQQzc14b1d42eIMDBsqEP2/Bll4BBjy7VHzyAcxh3Jpo8Fqoe0Jq/gmio jP11RHt5XRrqPmyBoApigxffDSizqNhT+yoOr5G/2EJza/L7rH9SuGALa0OPql6o OVJyfSit02Eco7ccrcqxp2s6fqFGXBwso6U9aSKyiG2xqXLb/g1GkacOt1TjMCHU OnuWR/1RjizGyxoom5Y0WhnPcLEJ4x1cVtU8tuqAx2K4YhRFsH5e27gQCXPynm1Z 8yC2DA4+3w57U5uYAGUlZP6/Mo+KGVET83OtNHnmOZ8qH55CzFbp8TTF+iMMmLHm ZkXCS1/1Iwt+ykNymFLn =Snzj -----END PGP SIGNATURE----- Merge tag 'media/v4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: "Media updates for v4.12-rc1: - new driver to support mediatek jpeg in hardware codec - rc-lirc, s5p-cec and st-cec staging drivers got promoted - hardware histogram support for vsp1 driver - added Virtual Media Controller driver, to make easier to test the media controller - added a new CEC driver (rainshadow-cec) - removed two staging LIRC drivers for obscure hardware that are too obsolete - added support for Intel SR300 Depth camera - some improvements at CEC and RC core - lots of driver cleanups, improvements all over the tree With this series, we're finally getting rid of the LIRC staging driver. There's just one left (lirc_zilog), with require more care, as part of its functionality (IR RX) is already provided by another driver. Work in progress to convert it on the proper way" * tag 'media/v4.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (304 commits) [media] ov2640: print error if devm_*_optional*() fails [media] atmel-isc: Fix the static checker warning [media] ov2640: add support for MEDIA_BUS_FMT_YVYU8_2X8 and MEDIA_BUS_FMT_VYUY8_2X8 [media] ov2640: fix vflip control [media] ov2640: fix duplicate width+height returning from ov2640_select_win() [media] ov2640: add missing write to size change preamble [media] ov2640: add information about DSP register 0xc7 [media] ov2640: improve banding filter register definitions/documentation [media] ov2640: fix init sequence alignment [media] ov2640: make GPIOLIB an optional dependency [media] xc5000: fix spelling mistake: "calibration" [media] vidioc-queryctrl.rst: fix menu/int menu references [media] media-entity: only call dev_dbg_obj if mdev is not NULL [media] pixfmt-meta-vsp1-hgo.rst: remove spurious '-' [media] mtk-vcodec: avoid warnings because of empty macros [media] coda: bump maximum number of internal framebuffers to 17 [media] media: mtk-vcodec: remove informative log [media] subdev-formats.rst: remove spurious '-' [media] dw2102: limit messages to buffer size [media] ttusb2: limit messages to buffer size ...
This commit is contained in:
Коммит
e87d51ac61
|
@ -1,51 +1,66 @@
|
|||
Atmel Image Sensor Interface (ISI) SoC Camera Subsystem
|
||||
----------------------------------------------
|
||||
Atmel Image Sensor Interface (ISI)
|
||||
----------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "atmel,at91sam9g45-isi"
|
||||
- reg: physical base address and length of the registers set for the device;
|
||||
- interrupts: should contain IRQ line for the ISI;
|
||||
- clocks: list of clock specifiers, corresponding to entries in
|
||||
the clock-names property;
|
||||
- clock-names: must contain "isi_clk", which is the isi peripherial clock.
|
||||
Required properties for ISI:
|
||||
- compatible: must be "atmel,at91sam9g45-isi".
|
||||
- reg: physical base address and length of the registers set for the device.
|
||||
- interrupts: should contain IRQ line for the ISI.
|
||||
- clocks: list of clock specifiers, corresponding to entries in the clock-names
|
||||
property; please refer to clock-bindings.txt.
|
||||
- clock-names: required elements: "isi_clk".
|
||||
- pinctrl-names, pinctrl-0: please refer to pinctrl-bindings.txt.
|
||||
|
||||
ISI supports a single port node with parallel bus. It should contain one
|
||||
ISI supports a single port node with parallel bus. It shall contain one
|
||||
'port' child node with child 'endpoint' node. Please refer to the bindings
|
||||
defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
Endpoint node properties
|
||||
------------------------
|
||||
|
||||
- bus-width: <8> or <10> (mandatory)
|
||||
- hsync-active (default: active high)
|
||||
- vsync-active (default: active high)
|
||||
- pclk-sample (default: sample on falling edge)
|
||||
- remote-endpoint: A phandle to the bus receiver's endpoint node (mandatory).
|
||||
|
||||
Example:
|
||||
isi: isi@f0034000 {
|
||||
compatible = "atmel,at91sam9g45-isi";
|
||||
reg = <0xf0034000 0x4000>;
|
||||
interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
|
||||
clocks = <&isi_clk>;
|
||||
clock-names = "isi_clk";
|
||||
isi: isi@f0034000 {
|
||||
compatible = "atmel,at91sam9g45-isi";
|
||||
reg = <0xf0034000 0x4000>;
|
||||
interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_isi_data_0_7>;
|
||||
clocks = <&isi_clk>;
|
||||
clock-names = "isi_clk";
|
||||
port {
|
||||
isi_0: endpoint {
|
||||
remote-endpoint = <&ov2640_0>;
|
||||
bus-width = <8>;
|
||||
vsync-active = <1>;
|
||||
hsync-active = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c@f0018000 {
|
||||
ov2640: camera@30 {
|
||||
compatible = "ovti,ov2640";
|
||||
reg = <0x30>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_isi>;
|
||||
pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
|
||||
resetb-gpios = <&pioE 11 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&pioE 13 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "xvclk";
|
||||
assigned-clocks = <&pck0>;
|
||||
assigned-clock-rates = <25000000>;
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
isi_0: endpoint {
|
||||
remote-endpoint = <&ov2640_0>;
|
||||
ov2640_0: endpoint {
|
||||
remote-endpoint = <&isi_0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c@f0018000 {
|
||||
ov2640: camera@0x30 {
|
||||
compatible = "ovti,ov2640";
|
||||
reg = <0x30>;
|
||||
|
||||
port {
|
||||
ov2640_0: endpoint {
|
||||
remote-endpoint = <&isi_0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
* Omnivision OV2640 CMOS sensor
|
||||
|
||||
The Omnivision OV2640 sensor support multiple resolutions output, such as
|
||||
CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB
|
||||
output format.
|
||||
The Omnivision OV2640 sensor supports multiple resolutions output, such as
|
||||
CIF, SVGA, UXGA. It also can support the YUV422/420, RGB565/555 or raw RGB
|
||||
output formats.
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be "ovti,ov2640"
|
||||
|
@ -20,26 +20,21 @@ Documentation/devicetree/bindings/media/video-interfaces.txt.
|
|||
Example:
|
||||
|
||||
i2c1: i2c@f0018000 {
|
||||
ov2640: camera@0x30 {
|
||||
ov2640: camera@30 {
|
||||
compatible = "ovti,ov2640";
|
||||
reg = <0x30>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn &pinctrl_ov2640_resetb>;
|
||||
|
||||
resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
clocks = <&pck1>;
|
||||
pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
|
||||
resetb-gpios = <&pioE 11 GPIO_ACTIVE_LOW>;
|
||||
pwdn-gpios = <&pioE 13 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "xvclk";
|
||||
|
||||
assigned-clocks = <&pck1>;
|
||||
assigned-clocks = <&pck0>;
|
||||
assigned-clock-rates = <25000000>;
|
||||
|
||||
port {
|
||||
ov2640_0: endpoint {
|
||||
remote-endpoint = <&isi_0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
* Omnivision 1/4-Inch 5Mp CMOS Digital Image Sensor
|
||||
|
||||
The Omnivision OV5645 is a 1/4-Inch CMOS active pixel digital image sensor with
|
||||
an active array size of 2592H x 1944V. It is programmable through a serial I2C
|
||||
interface.
|
||||
|
||||
Required Properties:
|
||||
- compatible: Value should be "ovti,ov5645".
|
||||
- clocks: Reference to the xclk clock.
|
||||
- clock-names: Should be "xclk".
|
||||
- clock-frequency: Frequency of the xclk clock.
|
||||
- enable-gpios: Chip enable GPIO. Polarity is GPIO_ACTIVE_HIGH. This corresponds
|
||||
to the hardware pin PWDNB which is physically active low.
|
||||
- reset-gpios: Chip reset GPIO. Polarity is GPIO_ACTIVE_LOW. This corresponds to
|
||||
the hardware pin RESETB.
|
||||
- vdddo-supply: Chip digital IO regulator.
|
||||
- vdda-supply: Chip analog regulator.
|
||||
- vddd-supply: Chip digital core regulator.
|
||||
|
||||
The device node must contain one 'port' child node for its digital output
|
||||
video port, in accordance with the video interface bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
Example:
|
||||
|
||||
&i2c1 {
|
||||
...
|
||||
|
||||
ov5645: ov5645@78 {
|
||||
compatible = "ovti,ov5645";
|
||||
reg = <0x78>;
|
||||
|
||||
enable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
|
||||
reset-gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&camera_rear_default>;
|
||||
|
||||
clocks = <&clks 200>;
|
||||
clock-names = "xclk";
|
||||
clock-frequency = <23880000>;
|
||||
|
||||
vdddo-supply = <&camera_dovdd_1v8>;
|
||||
vdda-supply = <&camera_avdd_2v8>;
|
||||
vddd-supply = <&camera_dvdd_1v2>;
|
||||
|
||||
port {
|
||||
ov5645_ep: endpoint {
|
||||
clock-lanes = <1>;
|
||||
data-lanes = <0 2>;
|
||||
remote-endpoint = <&csi0_ep>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
Omnivision OV5647 raw image sensor
|
||||
---------------------------------
|
||||
|
||||
OV5647 is a raw image sensor with MIPI CSI-2 and CCP2 image data interfaces
|
||||
and CCI (I2C compatible) control bus.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "ovti,ov5647".
|
||||
- reg : I2C slave address of the sensor.
|
||||
- clocks : Reference to the xclk clock.
|
||||
|
||||
The common video interfaces bindings (see video-interfaces.txt) should be
|
||||
used to specify link to the image data receiver. The OV5647 device
|
||||
node should contain one 'port' child node with an 'endpoint' subnode.
|
||||
|
||||
Endpoint node mandatory properties:
|
||||
|
||||
- remote-endpoint: A phandle to the bus receiver's endpoint node.
|
||||
|
||||
Example:
|
||||
|
||||
i2c@2000 {
|
||||
...
|
||||
ov: camera@36 {
|
||||
compatible = "ovti,ov5647";
|
||||
reg = <0x36>;
|
||||
clocks = <&camera_clk>;
|
||||
port {
|
||||
camera_1: endpoint {
|
||||
remote-endpoint = <&csi1_ep1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
* Omnivision OV7670 CMOS sensor
|
||||
|
||||
The Omnivision OV7670 sensor supports multiple resolutions output, such as
|
||||
CIF, SVGA, UXGA. It also can support the YUV422/420, RGB565/555 or raw RGB
|
||||
output formats.
|
||||
|
||||
Required Properties:
|
||||
- compatible: should be "ovti,ov7670"
|
||||
- clocks: reference to the xclk input clock.
|
||||
- clock-names: should be "xclk".
|
||||
|
||||
Optional Properties:
|
||||
- reset-gpios: reference to the GPIO connected to the resetb pin, if any.
|
||||
Active is low.
|
||||
- powerdown-gpios: reference to the GPIO connected to the pwdn pin, if any.
|
||||
Active is high.
|
||||
|
||||
The device node must contain one 'port' child node for its digital output
|
||||
video port, in accordance with the video interface bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
Example:
|
||||
|
||||
i2c1: i2c@f0018000 {
|
||||
ov7670: camera@21 {
|
||||
compatible = "ovti,ov7670";
|
||||
reg = <0x21>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pck0_as_isi_mck &pinctrl_sensor_power &pinctrl_sensor_reset>;
|
||||
reset-gpios = <&pioE 11 GPIO_ACTIVE_LOW>;
|
||||
powerdown-gpios = <&pioE 13 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&pck0>;
|
||||
clock-names = "xclk";
|
||||
assigned-clocks = <&pck0>;
|
||||
assigned-clock-rates = <25000000>;
|
||||
|
||||
port {
|
||||
ov7670_0: endpoint {
|
||||
remote-endpoint = <&isi_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
* Mediatek JPEG Decoder
|
||||
|
||||
Mediatek JPEG Decoder is the JPEG decode hardware present in Mediatek SoCs
|
||||
|
||||
Required properties:
|
||||
- compatible : must be one of the following string:
|
||||
"mediatek,mt8173-jpgdec"
|
||||
"mediatek,mt2701-jpgdec"
|
||||
- reg : physical base address of the jpeg decoder registers and length of
|
||||
memory mapped region.
|
||||
- interrupts : interrupt number to the interrupt controller.
|
||||
- clocks: device clocks, see
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
|
||||
- clock-names: must contain "jpgdec-smi" and "jpgdec".
|
||||
- power-domains: a phandle to the power domain, see
|
||||
Documentation/devicetree/bindings/power/power_domain.txt for details.
|
||||
- mediatek,larb: must contain the local arbiters in the current Socs, see
|
||||
Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
|
||||
for details.
|
||||
- iommus: should point to the respective IOMMU block with master port as
|
||||
argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
|
||||
for details.
|
||||
|
||||
Example:
|
||||
jpegdec: jpegdec@15004000 {
|
||||
compatible = "mediatek,mt2701-jpgdec";
|
||||
reg = <0 0x15004000 0 0x1000>;
|
||||
interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_LOW>;
|
||||
clocks = <&imgsys CLK_IMG_JPGDEC_SMI>,
|
||||
<&imgsys CLK_IMG_JPGDEC>;
|
||||
clock-names = "jpgdec-smi",
|
||||
"jpgdec";
|
||||
power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>;
|
||||
mediatek,larb = <&larb2>;
|
||||
iommus = <&iommu MT2701_M4U_PORT_JPGDEC_WDMA>,
|
||||
<&iommu MT2701_M4U_PORT_JPGDEC_BSDMA>;
|
||||
};
|
|
@ -15,6 +15,7 @@ Required properties:
|
|||
- clock-names : from common clock binding: must contain "hdmicec",
|
||||
corresponding to entry in the clocks property.
|
||||
- samsung,syscon-phandle - phandle to the PMU system controller
|
||||
- hdmi-phandle - phandle to the HDMI controller
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -25,6 +26,7 @@ hdmicec: cec@100B0000 {
|
|||
clocks = <&clock CLK_HDMI_CEC>;
|
||||
clock-names = "hdmicec";
|
||||
samsung,syscon-phandle = <&pmu_system_controller>;
|
||||
hdmi-phandle = <&hdmi>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hdmi_cec>;
|
||||
status = "okay";
|
||||
|
|
|
@ -28,7 +28,7 @@ Optional properties:
|
|||
- memory-region : from reserved memory binding: phandles to two reserved
|
||||
memory regions, first is for "left" mfc memory bus interfaces,
|
||||
second if for the "right" mfc memory bus, used when no SYSMMU
|
||||
support is available
|
||||
support is available; used only by MFC v5 present in Exynos4 SoCs
|
||||
|
||||
Obsolete properties:
|
||||
- samsung,mfc-r, samsung,mfc-l : support removed, please use memory-region
|
||||
|
|
|
@ -9,6 +9,7 @@ Required properties:
|
|||
- pinctrl-names: Contains only one value - "default"
|
||||
- pinctrl-0: Specifies the pin control groups used for CEC hardware.
|
||||
- resets: Reference to a reset controller
|
||||
- hdmi-phandle: Phandle to the HDMI controller
|
||||
|
||||
Example for STIH407:
|
||||
|
||||
|
@ -22,4 +23,5 @@ sti-cec@094a087c {
|
|||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_cec0_default>;
|
||||
resets = <&softreset STIH407_LPM_SOFTRESET>;
|
||||
hdmi-phandle = <&hdmi>;
|
||||
};
|
||||
|
|
|
@ -16,8 +16,10 @@ Required properties:
|
|||
Video Capture:
|
||||
|
||||
VPIF has a 16-bit parallel bus input, supporting 2 8-bit channels or a
|
||||
single 16-bit channel. It should contain at least one port child node
|
||||
with child 'endpoint' node. Please refer to the bindings defined in
|
||||
single 16-bit channel. It should contain one or two port child nodes
|
||||
with child 'endpoint' node. If there are two ports then port@0 must
|
||||
describe the input and port@1 output channels. Please refer to the
|
||||
bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
Example using 2 8-bit input channels, one of which is connected to an
|
||||
|
@ -28,17 +30,24 @@ I2C-connected TVP5147 decoder:
|
|||
reg = <0x217000 0x1000>;
|
||||
interrupts = <92>;
|
||||
|
||||
port {
|
||||
vpif_ch0: endpoint@0 {
|
||||
reg = <0>;
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&composite>;
|
||||
port@0 {
|
||||
vpif_input_ch0: endpoint@0 {
|
||||
reg = <0>;
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&composite_in>;
|
||||
};
|
||||
|
||||
vpif_ch1: endpoint@1 {
|
||||
reg = <1>;
|
||||
bus-width = <8>;
|
||||
data-shift = <8>;
|
||||
vpif_input_ch1: endpoint@1 {
|
||||
reg = <1>;
|
||||
bus-width = <8>;
|
||||
data-shift = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
vpif_output_ch0: endpoint {
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&composite_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -53,13 +62,28 @@ I2C-connected TVP5147 decoder:
|
|||
status = "okay";
|
||||
|
||||
port {
|
||||
composite: endpoint {
|
||||
composite_in: endpoint {
|
||||
hsync-active = <1>;
|
||||
vsync-active = <1>;
|
||||
pclk-sample = <0>;
|
||||
|
||||
/* VPIF channel 0 (lower 8-bits) */
|
||||
remote-endpoint = <&vpif_ch0>;
|
||||
remote-endpoint = <&vpif_input_ch0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
adv7343@2a {
|
||||
compatible = "adi,adv7343";
|
||||
reg = <0x2a>;
|
||||
|
||||
port {
|
||||
composite_out: endpoint {
|
||||
adi,dac-enable = <1 1 1>;
|
||||
adi,sd-dac-enable = <1>;
|
||||
|
||||
remote-endpoint = <&vpif_output_ch0>;
|
||||
bus-width = <8>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -27,11 +27,8 @@ HDMI 1.3a specification is sufficient:
|
|||
http://www.microprocessor.org/HDMISpecification13a.pdf
|
||||
|
||||
|
||||
The Kernel Interface
|
||||
====================
|
||||
|
||||
CEC Adapter
|
||||
-----------
|
||||
CEC Adapter Interface
|
||||
---------------------
|
||||
|
||||
The struct cec_adapter represents the CEC adapter hardware. It is created by
|
||||
calling cec_allocate_adapter() and deleted by calling cec_delete_adapter():
|
||||
|
@ -51,6 +48,7 @@ ops:
|
|||
|
||||
priv:
|
||||
will be stored in adap->priv and can be used by the adapter ops.
|
||||
Use cec_get_drvdata(adap) to get the priv pointer.
|
||||
|
||||
name:
|
||||
the name of the CEC adapter. Note: this name will be copied.
|
||||
|
@ -65,6 +63,10 @@ available_las:
|
|||
the number of simultaneous logical addresses that this
|
||||
adapter can handle. Must be 1 <= available_las <= CEC_MAX_LOG_ADDRS.
|
||||
|
||||
To obtain the priv pointer use this helper function:
|
||||
|
||||
.. c:function::
|
||||
void *cec_get_drvdata(const struct cec_adapter *adap);
|
||||
|
||||
To register the /dev/cecX device node and the remote control device (if
|
||||
CEC_CAP_RC is set) you call:
|
||||
|
|
|
@ -45,10 +45,11 @@ where
|
|||
* - bits_per_sample
|
||||
- Number of bits per sample.
|
||||
|
||||
The transmitter drivers must configure the CSI-2 transmitter to *LP-11
|
||||
mode* whenever the transmitter is powered on but not active. Some
|
||||
transmitters do this automatically but some have to be explicitly
|
||||
programmed to do so.
|
||||
The transmitter drivers must, if possible, configure the CSI-2
|
||||
transmitter to *LP-11 mode* whenever the transmitter is powered on but
|
||||
not active. 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.
|
||||
|
||||
Receiver drivers
|
||||
----------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Video2Linux devices
|
||||
Video4Linux devices
|
||||
-------------------
|
||||
|
||||
.. toctree::
|
||||
|
|
|
@ -35,7 +35,6 @@ ignore define PULSE_MASK
|
|||
|
||||
ignore define LIRC_MODE2_SPACE
|
||||
ignore define LIRC_MODE2_PULSE
|
||||
ignore define LIRC_MODE2_TIMEOUT
|
||||
|
||||
ignore define LIRC_VALUE_MASK
|
||||
ignore define LIRC_MODE2_MASK
|
||||
|
|
|
@ -30,7 +30,7 @@ Arguments
|
|||
|
||||
``request``
|
||||
CEC ioctl request code as defined in the cec.h header file, for
|
||||
example :c:func:`CEC_ADAP_G_CAPS`.
|
||||
example :ref:`CEC_ADAP_G_CAPS <CEC_ADAP_G_CAPS>`.
|
||||
|
||||
``argp``
|
||||
Pointer to a request-specific structure.
|
||||
|
|
|
@ -33,7 +33,7 @@ Arguments
|
|||
Open flags. Access mode must be ``O_RDWR``.
|
||||
|
||||
When the ``O_NONBLOCK`` flag is given, the
|
||||
:ref:`CEC_RECEIVE <CEC_RECEIVE>` and :c:func:`CEC_DQEVENT` ioctls
|
||||
:ref:`CEC_RECEIVE <CEC_RECEIVE>` and :ref:`CEC_DQEVENT <CEC_DQEVENT>` ioctls
|
||||
will return the ``EAGAIN`` error code when no message or event is available, and
|
||||
ioctls :ref:`CEC_TRANSMIT <CEC_TRANSMIT>`,
|
||||
:ref:`CEC_ADAP_S_PHYS_ADDR <CEC_ADAP_S_PHYS_ADDR>` and
|
||||
|
|
|
@ -30,7 +30,7 @@ Arguments
|
|||
List of FD events to be watched
|
||||
|
||||
``nfds``
|
||||
Number of FD efents at the \*ufds array
|
||||
Number of FD events at the \*ufds array
|
||||
|
||||
``timeout``
|
||||
Timeout to wait for events
|
||||
|
@ -49,7 +49,7 @@ is non-zero). CEC devices set the ``POLLIN`` and ``POLLRDNORM`` flags in
|
|||
the ``revents`` field if there are messages in the receive queue. If the
|
||||
transmit queue has room for new messages, the ``POLLOUT`` and
|
||||
``POLLWRNORM`` flags are set. If there are events in the event queue,
|
||||
then the ``POLLPRI`` flag is set. When the function timed out it returns
|
||||
then the ``POLLPRI`` flag is set. When the function times out it returns
|
||||
a value of zero, on failure it returns -1 and the ``errno`` variable is
|
||||
set appropriately.
|
||||
|
||||
|
|
|
@ -351,3 +351,16 @@ On success 0 is returned, on error -1 and the ``errno`` variable is set
|
|||
appropriately. The generic error codes are described at the
|
||||
:ref:`Generic Error Codes <gen-errors>` chapter.
|
||||
|
||||
The :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>` can return the following
|
||||
error codes:
|
||||
|
||||
ENOTTY
|
||||
The ``CEC_CAP_LOG_ADDRS`` capability wasn't set, so this ioctl is not supported.
|
||||
|
||||
EBUSY
|
||||
The CEC adapter is currently configuring itself, or it is already configured and
|
||||
``num_log_addrs`` is non-zero, or another filehandle is in exclusive follower or
|
||||
initiator mode, or the filehandle is in mode ``CEC_MODE_NO_INITIATOR``.
|
||||
|
||||
EINVAL
|
||||
The contents of struct :c:type:`cec_log_addrs` is invalid.
|
||||
|
|
|
@ -78,3 +78,16 @@ Return Value
|
|||
On success 0 is returned, on error -1 and the ``errno`` variable is set
|
||||
appropriately. The generic error codes are described at the
|
||||
:ref:`Generic Error Codes <gen-errors>` chapter.
|
||||
|
||||
The :ref:`ioctl CEC_ADAP_S_PHYS_ADDR <CEC_ADAP_S_PHYS_ADDR>` can return the following
|
||||
error codes:
|
||||
|
||||
ENOTTY
|
||||
The ``CEC_CAP_PHYS_ADDR`` capability wasn't set, so this ioctl is not supported.
|
||||
|
||||
EBUSY
|
||||
Another filehandle is in exclusive follower or initiator mode, or the filehandle
|
||||
is in mode ``CEC_MODE_NO_INITIATOR``.
|
||||
|
||||
EINVAL
|
||||
The physical address is malformed.
|
||||
|
|
|
@ -56,7 +56,7 @@ it is guaranteed that the state did change in between the two events.
|
|||
* - __u16
|
||||
- ``phys_addr``
|
||||
- The current physical address. This is ``CEC_PHYS_ADDR_INVALID`` if no
|
||||
valid physical address is set.
|
||||
valid physical address is set.
|
||||
* - __u16
|
||||
- ``log_addr_mask``
|
||||
- The current set of claimed logical addresses. This is 0 if no logical
|
||||
|
@ -174,3 +174,14 @@ Return Value
|
|||
On success 0 is returned, on error -1 and the ``errno`` variable is set
|
||||
appropriately. The generic error codes are described at the
|
||||
:ref:`Generic Error Codes <gen-errors>` chapter.
|
||||
|
||||
The :ref:`ioctl CEC_DQEVENT <CEC_DQEVENT>` can return the following
|
||||
error codes:
|
||||
|
||||
EAGAIN
|
||||
This is returned when the filehandle is in non-blocking mode and there
|
||||
are no pending events.
|
||||
|
||||
ERESTARTSYS
|
||||
An interrupt (e.g. Ctrl-C) arrived while in blocking mode waiting for
|
||||
events to arrive.
|
||||
|
|
|
@ -249,3 +249,15 @@ Return Value
|
|||
On success 0 is returned, on error -1 and the ``errno`` variable is set
|
||||
appropriately. The generic error codes are described at the
|
||||
:ref:`Generic Error Codes <gen-errors>` chapter.
|
||||
|
||||
The :ref:`ioctl CEC_S_MODE <CEC_S_MODE>` can return the following
|
||||
error codes:
|
||||
|
||||
EINVAL
|
||||
The requested mode is invalid.
|
||||
|
||||
EPERM
|
||||
Monitor mode is requested without having root permissions
|
||||
|
||||
EBUSY
|
||||
Someone else is already an exclusive follower or initiator.
|
||||
|
|
|
@ -51,13 +51,13 @@ A received message can be:
|
|||
be non-zero).
|
||||
|
||||
To send a CEC message the application has to fill in the struct
|
||||
:c:type:` cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`.
|
||||
:c:type:`cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`.
|
||||
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is only available if
|
||||
``CEC_CAP_TRANSMIT`` is set. If there is no more room in the transmit
|
||||
queue, then it will return -1 and set errno to the ``EBUSY`` error code.
|
||||
The transmit queue has enough room for 18 messages (about 1 second worth
|
||||
of 2-byte messages). Note that the CEC kernel framework will also reply
|
||||
to core messages (see :ref:cec-core-processing), so it is not a good
|
||||
to core messages (see :ref:`cec-core-processing`), so it is not a good
|
||||
idea to fully fill up the transmit queue.
|
||||
|
||||
If the file descriptor is in non-blocking mode then the transmit will
|
||||
|
@ -69,6 +69,18 @@ The ``sequence`` field is filled in for every transmit and this can be
|
|||
checked against the received messages to find the corresponding transmit
|
||||
result.
|
||||
|
||||
Normally calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` when the physical
|
||||
address is invalid (due to e.g. a disconnect) will return ``ENONET``.
|
||||
|
||||
However, the CEC specification allows sending messages from 'Unregistered' to
|
||||
'TV' when the physical address is invalid since some TVs pull the hotplug detect
|
||||
pin of the HDMI connector low when they go into standby, or when switching to
|
||||
another input.
|
||||
|
||||
When the hotplug detect pin goes low the EDID disappears, and thus the
|
||||
physical address, but the cable is still connected and CEC still works.
|
||||
In order to detect/wake up the device it is allowed to send poll and 'Image/Text
|
||||
View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
|
||||
|
||||
.. tabularcolumns:: |p{1.0cm}|p{3.5cm}|p{13.0cm}|
|
||||
|
||||
|
@ -289,3 +301,42 @@ Return Value
|
|||
On success 0 is returned, on error -1 and the ``errno`` variable is set
|
||||
appropriately. The generic error codes are described at the
|
||||
:ref:`Generic Error Codes <gen-errors>` chapter.
|
||||
|
||||
The :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` can return the following
|
||||
error codes:
|
||||
|
||||
EAGAIN
|
||||
No messages are in the receive queue, and the filehandle is in non-blocking mode.
|
||||
|
||||
ETIMEDOUT
|
||||
The ``timeout`` was reached while waiting for a message.
|
||||
|
||||
ERESTARTSYS
|
||||
The wait for a message was interrupted (e.g. by Ctrl-C).
|
||||
|
||||
The :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` can return the following
|
||||
error codes:
|
||||
|
||||
ENOTTY
|
||||
The ``CEC_CAP_TRANSMIT`` capability wasn't set, so this ioctl is not supported.
|
||||
|
||||
EPERM
|
||||
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
|
||||
has never been called.
|
||||
|
||||
ENONET
|
||||
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
|
||||
was called, but the physical address is invalid so no logical address was claimed.
|
||||
An exception is made in this case for transmits from initiator 0xf ('Unregistered')
|
||||
to destination 0 ('TV'). In that case the transmit will proceed as usual.
|
||||
|
||||
EBUSY
|
||||
Another filehandle is in exclusive follower or initiator mode, or the filehandle
|
||||
is in mode ``CEC_MODE_NO_INITIATOR``. This is also returned if the transmit
|
||||
queue is full.
|
||||
|
||||
EINVAL
|
||||
The contents of struct :c:type:`cec_msg` is invalid.
|
||||
|
||||
ERESTARTSYS
|
||||
The wait for a successful transmit was interrupted (e.g. by Ctrl-C).
|
||||
|
|
|
@ -284,7 +284,8 @@ Types and flags used to represent the media graph elements
|
|||
supported scaling ratios is entity-specific and can differ
|
||||
between the horizontal and vertical directions (in particular
|
||||
scaling can be supported in one direction only). Binning and
|
||||
skipping are considered as scaling.
|
||||
sub-sampling (occasionally also referred to as skipping) are
|
||||
considered as scaling.
|
||||
|
||||
- .. row 28
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ What you should see for a chardev:
|
|||
$ ls -l /dev/lirc*
|
||||
crw-rw---- 1 root root 248, 0 Jul 2 22:20 /dev/lirc0
|
||||
|
||||
.. _lirc_modes:
|
||||
|
||||
**********
|
||||
LIRC modes
|
||||
**********
|
||||
|
@ -38,25 +40,62 @@ on the following table.
|
|||
|
||||
``LIRC_MODE_MODE2``
|
||||
|
||||
The driver returns a sequence of pulse and space codes to userspace.
|
||||
The driver returns a sequence of pulse and space codes to userspace,
|
||||
as a series of u32 values.
|
||||
|
||||
This mode is used only for IR receive.
|
||||
|
||||
The upper 8 bits determine the packet type, and the lower 24 bits
|
||||
the payload. Use ``LIRC_VALUE()`` macro to get the payload, and
|
||||
the macro ``LIRC_MODE2()`` will give you the type, which
|
||||
is one of:
|
||||
|
||||
``LIRC_MODE2_PULSE``
|
||||
|
||||
Signifies the presence of IR in microseconds.
|
||||
|
||||
``LIRC_MODE2_SPACE``
|
||||
|
||||
Signifies absence of IR in microseconds.
|
||||
|
||||
``LIRC_MODE2_FREQUENCY``
|
||||
|
||||
If measurement of the carrier frequency was enabled with
|
||||
:ref:`lirc_set_measure_carrier_mode` then this packet gives you
|
||||
the carrier frequency in Hertz.
|
||||
|
||||
``LIRC_MODE2_TIMEOUT``
|
||||
|
||||
If timeout reports are enabled with
|
||||
:ref:`lirc_set_rec_timeout_reports`, when the timeout set with
|
||||
:ref:`lirc_set_rec_timeout` expires due to no IR being detected,
|
||||
this packet will be sent, with the number of microseconds with
|
||||
no IR.
|
||||
|
||||
.. _lirc-mode-lirccode:
|
||||
|
||||
``LIRC_MODE_LIRCCODE``
|
||||
|
||||
The IR signal is decoded internally by the receiver. The LIRC interface
|
||||
returns the scancode as an integer value. This is the usual mode used
|
||||
by several TV media cards.
|
||||
This mode can be used for IR receive and send.
|
||||
|
||||
This mode is used only for IR receive.
|
||||
The IR signal is decoded internally by the receiver, or encoded by the
|
||||
transmitter. The LIRC interface represents the scancode as byte string,
|
||||
which might not be a u32, it can be any length. The value is entirely
|
||||
driver dependent. This mode is used by some older lirc drivers.
|
||||
|
||||
The length of each code depends on the driver, which can be retrieved
|
||||
with :ref:`lirc_get_length`. This length is used both
|
||||
for transmitting and receiving IR.
|
||||
|
||||
.. _lirc-mode-pulse:
|
||||
|
||||
``LIRC_MODE_PULSE``
|
||||
|
||||
On puse mode, a sequence of pulse/space integer values are written to the
|
||||
lirc device using :Ref:`lirc-write`.
|
||||
In pulse mode, a sequence of pulse/space integer values are written to the
|
||||
lirc device using :ref:`lirc-write`.
|
||||
|
||||
The values are alternating pulse and space lengths, in microseconds. The
|
||||
first and last entry must be a pulse, so there must be an odd number
|
||||
of entries.
|
||||
|
||||
This mode is used only for IR send.
|
||||
|
|
|
@ -48,8 +48,8 @@ LIRC features
|
|||
|
||||
``LIRC_CAN_REC_PULSE``
|
||||
|
||||
The driver is capable of receiving using
|
||||
:ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
|
||||
Unused. Kept just to avoid breaking uAPI.
|
||||
:ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` can only be used for transmitting.
|
||||
|
||||
.. _LIRC-CAN-REC-MODE2:
|
||||
|
||||
|
@ -156,19 +156,22 @@ LIRC features
|
|||
|
||||
``LIRC_CAN_SEND_PULSE``
|
||||
|
||||
The driver supports sending using :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
|
||||
The driver supports sending (also called as IR blasting or IR TX) using
|
||||
:ref:`LIRC_MODE_PULSE <lirc-mode-pulse>`.
|
||||
|
||||
.. _LIRC-CAN-SEND-MODE2:
|
||||
|
||||
``LIRC_CAN_SEND_MODE2``
|
||||
|
||||
The driver supports sending using :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`.
|
||||
Unused. Kept just to avoid breaking uAPI.
|
||||
:ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>` can only be used for receiving.
|
||||
|
||||
.. _LIRC-CAN-SEND-LIRCCODE:
|
||||
|
||||
``LIRC_CAN_SEND_LIRCCODE``
|
||||
|
||||
The driver supports sending codes (also called as IR blasting or IR TX).
|
||||
The driver supports sending (also called as IR blasting or IR TX) using
|
||||
:ref:`LIRC_MODE_LIRCCODE <lirc-mode-LIRCCODE>`.
|
||||
|
||||
|
||||
Return Value
|
||||
|
|
|
@ -30,7 +30,8 @@ Arguments
|
|||
Description
|
||||
===========
|
||||
|
||||
Retrieves the code length in bits (only for ``LIRC-MODE-LIRCCODE``).
|
||||
Retrieves the code length in bits (only for
|
||||
:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>`).
|
||||
Reads on the device must be done in blocks matching the bit count.
|
||||
The bit could should be rounded up so that it matches full bytes.
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ Description
|
|||
|
||||
Get/set supported receive modes. Only :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`
|
||||
and :ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` are supported for IR
|
||||
receive.
|
||||
|
||||
receive. Use :ref:`lirc_get_features` to find out which modes the driver
|
||||
supports.
|
||||
|
||||
Return Value
|
||||
============
|
||||
|
|
|
@ -34,9 +34,12 @@ Arguments
|
|||
Description
|
||||
===========
|
||||
|
||||
Get/set supported transmit mode.
|
||||
Get/set current transmit mode.
|
||||
|
||||
Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` is supported by for IR send.
|
||||
Only :ref:`LIRC_MODE_PULSE <lirc-mode-pulse>` and
|
||||
:ref:`LIRC_MODE_LIRCCODE <lirc-mode-lirccode>` is supported by for IR send,
|
||||
depending on the driver. Use :ref:`lirc_get_features` to find out which
|
||||
modes the driver supports.
|
||||
|
||||
Return Value
|
||||
============
|
||||
|
|
|
@ -44,17 +44,13 @@ descriptor ``fd`` into the buffer starting at ``buf``. If ``count`` is zero,
|
|||
:ref:`read() <lirc-read>` returns zero and has no other results. If ``count``
|
||||
is greater than ``SSIZE_MAX``, the result is unspecified.
|
||||
|
||||
The lircd userspace daemon reads raw IR data from the LIRC chardev. The
|
||||
exact format of the data depends on what modes a driver supports, and
|
||||
what mode has been selected. lircd obtains supported modes and sets the
|
||||
active mode via the ioctl interface, detailed at :ref:`lirc_func`.
|
||||
The generally preferred mode for receive is
|
||||
:ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`, in which packets containing an
|
||||
int value describing an IR signal are read from the chardev.
|
||||
The exact format of the data depends on what :ref:`lirc_modes` a driver
|
||||
uses. Use :ref:`lirc_get_features` to get the supported mode.
|
||||
|
||||
See also
|
||||
`http://www.lirc.org/html/technical.html <http://www.lirc.org/html/technical.html>`__
|
||||
for more info.
|
||||
The generally preferred mode for receive is
|
||||
:ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`,
|
||||
in which packets containing an int value describing an IR signal are
|
||||
read from the chardev.
|
||||
|
||||
Return Value
|
||||
============
|
||||
|
|
|
@ -9,7 +9,7 @@ ioctl LIRC_SET_REC_CARRIER_RANGE
|
|||
Name
|
||||
====
|
||||
|
||||
LIRC_SET_REC_CARRIER_RANGE - Set lower bond of the carrier used to modulate
|
||||
LIRC_SET_REC_CARRIER_RANGE - Set lower bound of the carrier used to modulate
|
||||
IR receive.
|
||||
|
||||
Synopsis
|
||||
|
|
|
@ -31,6 +31,8 @@ Arguments
|
|||
Description
|
||||
===========
|
||||
|
||||
.. _lirc-mode2-timeout:
|
||||
|
||||
Enable or disable timeout reports for IR receive. By default, timeout reports
|
||||
should be turned off.
|
||||
|
||||
|
|
|
@ -42,13 +42,16 @@ Description
|
|||
referenced by the file descriptor ``fd`` from the buffer starting at
|
||||
``buf``.
|
||||
|
||||
The data written to the chardev is a pulse/space sequence of integer
|
||||
values. Pulses and spaces are only marked implicitly by their position.
|
||||
The data must start and end with a pulse, therefore, the data must
|
||||
always include an uneven number of samples. The write function must
|
||||
block until the data has been transmitted by the hardware. If more data
|
||||
is provided than the hardware can send, the driver returns ``EINVAL``.
|
||||
The exact format of the data depends on what mode a driver uses, use
|
||||
:ref:`lirc_get_features` to get the supported mode.
|
||||
|
||||
When in :ref:`LIRC_MODE_PULSE <lirc-mode-PULSE>` mode, the data written to
|
||||
the chardev is a pulse/space sequence of integer values. Pulses and spaces
|
||||
are only marked implicitly by their position. The data must start and end
|
||||
with a pulse, therefore, the data must always include an uneven number of
|
||||
samples. The write function must block until the data has been transmitted
|
||||
by the hardware. If more data is provided than the hardware can send, the
|
||||
driver returns ``EINVAL``.
|
||||
|
||||
Return Value
|
||||
============
|
||||
|
|
|
@ -34,6 +34,125 @@ flags are copied from the OUTPUT video buffer to the CAPTURE video
|
|||
buffer.
|
||||
|
||||
|
||||
Interactions between formats, controls and buffers
|
||||
==================================================
|
||||
|
||||
V4L2 exposes parameters that influence the buffer size, or the way data is
|
||||
laid out in the buffer. Those parameters are exposed through both formats and
|
||||
controls. One example of such a control is the ``V4L2_CID_ROTATE`` control
|
||||
that modifies the direction in which pixels are stored in the buffer, as well
|
||||
as the buffer size when the selected format includes padding at the end of
|
||||
lines.
|
||||
|
||||
The set of information needed to interpret the content of a buffer (e.g. the
|
||||
pixel format, the line stride, the tiling orientation or the rotation) is
|
||||
collectively referred to in the rest of this section as the buffer layout.
|
||||
|
||||
Controls that can modify the buffer layout shall set the
|
||||
``V4L2_CTRL_FLAG_MODIFY_LAYOUT`` flag.
|
||||
|
||||
Modifying formats or controls that influence the buffer size or layout require
|
||||
the stream to be stopped. Any attempt at such a modification while the stream
|
||||
is active shall cause the ioctl setting the format or the control to return
|
||||
the ``EBUSY`` error code. In that case drivers shall also set the
|
||||
``V4L2_CTRL_FLAG_GRABBED`` flag when calling
|
||||
:c:func:`VIDIOC_QUERYCTRL` or :c:func:`VIDIOC_QUERY_EXT_CTRL` for such a
|
||||
control while the stream is active.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:func:`VIDIOC_S_SELECTION` ioctl can, depending on the hardware (for
|
||||
instance if the device doesn't include a scaler), modify the format in
|
||||
addition to the selection rectangle. Similarly, the
|
||||
:c:func:`VIDIOC_S_INPUT`, :c:func:`VIDIOC_S_OUTPUT`, :c:func:`VIDIOC_S_STD`
|
||||
and :c:func:`VIDIOC_S_DV_TIMINGS` ioctls can also modify the format and
|
||||
selection rectangles. When those ioctls result in a buffer size or layout
|
||||
change, drivers shall handle that condition as they would handle it in the
|
||||
:c:func:`VIDIOC_S_FMT` ioctl in all cases described in this section.
|
||||
|
||||
Controls that only influence the buffer layout can be modified at any time
|
||||
when the stream is stopped. As they don't influence the buffer size, no
|
||||
special handling is needed to synchronize those controls with buffer
|
||||
allocation and the ``V4L2_CTRL_FLAG_GRABBED`` flag is cleared once the
|
||||
stream is stopped.
|
||||
|
||||
Formats and controls that influence the buffer size interact with buffer
|
||||
allocation. The simplest way to handle this is for drivers to always require
|
||||
buffers to be reallocated in order to change those formats or controls. In
|
||||
that case, to perform such changes, userspace applications shall first stop
|
||||
the video stream with the :c:func:`VIDIOC_STREAMOFF` ioctl if it is running
|
||||
and free all buffers with the :c:func:`VIDIOC_REQBUFS` ioctl if they are
|
||||
allocated. After freeing all buffers the ``V4L2_CTRL_FLAG_GRABBED`` flag
|
||||
for controls is cleared. The format or controls can then be modified, and
|
||||
buffers shall then be reallocated and the stream restarted. A typical ioctl
|
||||
sequence is
|
||||
|
||||
#. VIDIOC_STREAMOFF
|
||||
#. VIDIOC_REQBUFS(0)
|
||||
#. VIDIOC_S_EXT_CTRLS
|
||||
#. VIDIOC_S_FMT
|
||||
#. VIDIOC_REQBUFS(n)
|
||||
#. VIDIOC_QBUF
|
||||
#. VIDIOC_STREAMON
|
||||
|
||||
The second :c:func:`VIDIOC_REQBUFS` call will take the new format and control
|
||||
value into account to compute the buffer size to allocate. Applications can
|
||||
also retrieve the size by calling the :c:func:`VIDIOC_G_FMT` ioctl if needed.
|
||||
|
||||
.. note::
|
||||
|
||||
The API doesn't mandate the above order for control (3.) and format (4.)
|
||||
changes. Format and controls can be set in a different order, or even
|
||||
interleaved, depending on the device and use case. For instance some
|
||||
controls might behave differently for different pixel formats, in which
|
||||
case the format might need to be set first.
|
||||
|
||||
When reallocation is required, any attempt to modify format or controls that
|
||||
influences the buffer size while buffers are allocated shall cause the format
|
||||
or control set ioctl to return the ``EBUSY`` error. Any attempt to queue a
|
||||
buffer too small for the current format or controls shall cause the
|
||||
:c:func:`VIDIOC_QBUF` ioctl to return a ``EINVAL`` error.
|
||||
|
||||
Buffer reallocation is an expensive operation. To avoid that cost, drivers can
|
||||
(and are encouraged to) allow format or controls that influence the buffer
|
||||
size to be changed with buffers allocated. In that case, a typical ioctl
|
||||
sequence to modify format and controls is
|
||||
|
||||
#. VIDIOC_STREAMOFF
|
||||
#. VIDIOC_S_EXT_CTRLS
|
||||
#. VIDIOC_S_FMT
|
||||
#. VIDIOC_QBUF
|
||||
#. VIDIOC_STREAMON
|
||||
|
||||
For this sequence to operate correctly, queued buffers need to be large enough
|
||||
for the new format or controls. Drivers shall return a ``ENOSPC`` error in
|
||||
response to format change (:c:func:`VIDIOC_S_FMT`) or control changes
|
||||
(:c:func:`VIDIOC_S_CTRL` or :c:func:`VIDIOC_S_EXT_CTRLS`) if buffers too small
|
||||
for the new format are currently queued. As a simplification, drivers are
|
||||
allowed to return a ``EBUSY`` error from these ioctls if any buffer is
|
||||
currently queued, without checking the queued buffers sizes.
|
||||
|
||||
Additionally, drivers shall return a ``EINVAL`` error from the
|
||||
:c:func:`VIDIOC_QBUF` ioctl if the buffer being queued is too small for the
|
||||
current format or controls. Together, these requirements ensure that queued
|
||||
buffers will always be large enough for the configured format and controls.
|
||||
|
||||
Userspace applications can query the buffer size required for a given format
|
||||
and controls by first setting the desired control values and then trying the
|
||||
desired format. The :c:func:`VIDIOC_TRY_FMT` ioctl will return the required
|
||||
buffer size.
|
||||
|
||||
#. VIDIOC_S_EXT_CTRLS(x)
|
||||
#. VIDIOC_TRY_FMT()
|
||||
#. VIDIOC_S_EXT_CTRLS(y)
|
||||
#. VIDIOC_TRY_FMT()
|
||||
|
||||
The :c:func:`VIDIOC_CREATE_BUFS` ioctl can then be used to allocate buffers
|
||||
based on the queried sizes (for instance by allocating a set of buffers large
|
||||
enough for all the desired formats and controls, or by allocating separate set
|
||||
of appropriately sized buffers for each use case).
|
||||
|
||||
|
||||
.. c:type:: v4l2_buffer
|
||||
|
||||
struct v4l2_buffer
|
||||
|
@ -330,6 +449,9 @@ enum v4l2_buf_type
|
|||
- 12
|
||||
- Buffer for Software Defined Radio (SDR) output stream, see
|
||||
:ref:`sdr`.
|
||||
* - ``V4L2_BUF_TYPE_META_CAPTURE``
|
||||
- 13
|
||||
- Buffer for metadata capture, see :ref:`metadata`.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -12,4 +12,5 @@ Depth data provides distance to points, mapped onto the image plane
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pixfmt-inzi
|
||||
pixfmt-z16
|
||||
|
|
|
@ -42,8 +42,8 @@ Video capture devices shall support :ref:`audio input <audio>`,
|
|||
:ref:`tuner`, :ref:`controls <control>`,
|
||||
:ref:`cropping and scaling <crop>` and
|
||||
:ref:`streaming parameter <streaming-par>` ioctls as needed. The
|
||||
:ref:`video input <video>` and :ref:`video standard <standard>`
|
||||
ioctls must be supported by all video capture devices.
|
||||
:ref:`video input <video>` ioctls must be supported by all video
|
||||
capture devices.
|
||||
|
||||
|
||||
Image Format Negotiation
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
.. -*- coding: utf-8; mode: rst -*-
|
||||
|
||||
.. _metadata:
|
||||
|
||||
******************
|
||||
Metadata Interface
|
||||
******************
|
||||
|
||||
Metadata refers to any non-image data that supplements video frames with
|
||||
additional information. This may include statistics computed over the image
|
||||
or frame capture parameters supplied by the image source. This interface is
|
||||
intended for transfer of metadata to userspace and control of that operation.
|
||||
|
||||
The metadata interface is implemented on video capture device nodes. The device
|
||||
can be dedicated to metadata or can implement both video and metadata capture
|
||||
as specified in its reported capabilities.
|
||||
|
||||
Querying Capabilities
|
||||
=====================
|
||||
|
||||
Device nodes supporting the metadata interface set the ``V4L2_CAP_META_CAPTURE``
|
||||
flag in the ``device_caps`` field of the
|
||||
:c:type:`v4l2_capability` structure returned by the :c:func:`VIDIOC_QUERYCAP`
|
||||
ioctl. That flag means the device can capture metadata to memory.
|
||||
|
||||
At least one of the read/write or streaming I/O methods must be supported.
|
||||
|
||||
|
||||
Data Format Negotiation
|
||||
=======================
|
||||
|
||||
The metadata device uses the :ref:`format` ioctls to select the capture format.
|
||||
The metadata buffer content format is bound to that selected format. In addition
|
||||
to the basic :ref:`format` ioctls, the :c:func:`VIDIOC_ENUM_FMT` ioctl must be
|
||||
supported as well.
|
||||
|
||||
To use the :ref:`format` ioctls applications set the ``type`` field of the
|
||||
:c:type:`v4l2_format` structure to ``V4L2_BUF_TYPE_META_CAPTURE`` and use the
|
||||
:c:type:`v4l2_meta_format` ``meta`` member of the ``fmt`` union as needed per
|
||||
the desired operation. Both drivers and applications must set the remainder of
|
||||
the :c:type:`v4l2_format` structure to 0.
|
||||
|
||||
.. _v4l2-meta-format:
|
||||
|
||||
.. flat-table:: struct v4l2_meta_format
|
||||
:header-rows: 0
|
||||
:stub-columns: 0
|
||||
:widths: 1 1 2
|
||||
|
||||
* - __u32
|
||||
- ``dataformat``
|
||||
- The data format, set by the application. This is a little endian
|
||||
:ref:`four character code <v4l2-fourcc>`. V4L2 defines metadata formats
|
||||
in :ref:`meta-formats`.
|
||||
* - __u32
|
||||
- ``buffersize``
|
||||
- Maximum buffer size in bytes required for data. The value is set by the
|
||||
driver.
|
|
@ -40,8 +40,8 @@ Video output devices shall support :ref:`audio output <audio>`,
|
|||
:ref:`modulator <tuner>`, :ref:`controls <control>`,
|
||||
:ref:`cropping and scaling <crop>` and
|
||||
:ref:`streaming parameter <streaming-par>` ioctls as needed. The
|
||||
:ref:`video output <video>` and :ref:`video standard <standard>`
|
||||
ioctls must be supported by all video output devices.
|
||||
:ref:`video output <video>` ioctls must be supported by all video
|
||||
output devices.
|
||||
|
||||
|
||||
Image Format Negotiation
|
||||
|
|
|
@ -25,3 +25,4 @@ Interfaces
|
|||
dev-touch
|
||||
dev-event
|
||||
dev-subdev
|
||||
dev-meta
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
.. -*- coding: utf-8; mode: rst -*-
|
||||
|
||||
.. _meta-formats:
|
||||
|
||||
****************
|
||||
Metadata Formats
|
||||
****************
|
||||
|
||||
These formats are used for the :ref:`metadata` interface only.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pixfmt-meta-vsp1-hgo
|
||||
pixfmt-meta-vsp1-hgt
|
|
@ -174,7 +174,7 @@ this colorspace:
|
|||
The xvYCC 709 encoding (``V4L2_YCBCR_ENC_XV709``, :ref:`xvycc`) is
|
||||
similar to the Rec. 709 encoding, but it allows for R', G' and B' values
|
||||
that are outside the range [0…1]. The resulting Y', Cb and Cr values are
|
||||
scaled and offset:
|
||||
scaled and offset according to the limited range formula:
|
||||
|
||||
.. math::
|
||||
|
||||
|
@ -187,7 +187,7 @@ scaled and offset:
|
|||
The xvYCC 601 encoding (``V4L2_YCBCR_ENC_XV601``, :ref:`xvycc`) is
|
||||
similar to the BT.601 encoding, but it allows for R', G' and B' values
|
||||
that are outside the range [0…1]. The resulting Y', Cb and Cr values are
|
||||
scaled and offset:
|
||||
scaled and offset according to the limited range formula:
|
||||
|
||||
.. math::
|
||||
|
||||
|
@ -198,9 +198,14 @@ scaled and offset:
|
|||
Cr = \frac{224}{256} * (0.5R' - 0.4187G' - 0.0813B')
|
||||
|
||||
Y' is clamped to the range [0…1] and Cb and Cr are clamped to the range
|
||||
[-0.5…0.5]. The non-standard xvYCC 709 or xvYCC 601 encodings can be
|
||||
[-0.5…0.5] and quantized without further scaling or offsets.
|
||||
The non-standard xvYCC 709 or xvYCC 601 encodings can be
|
||||
used by selecting ``V4L2_YCBCR_ENC_XV709`` or ``V4L2_YCBCR_ENC_XV601``.
|
||||
The xvYCC encodings always use full range quantization.
|
||||
As seen by the xvYCC formulas these encodings always use limited range quantization,
|
||||
there is no full range variant. The whole point of these extended gamut encodings
|
||||
is that values outside the limited range are still valid, although they
|
||||
map to R', G' and B' values outside the [0…1] range and are therefore outside
|
||||
the Rec. 709 colorspace gamut.
|
||||
|
||||
|
||||
.. _col-srgb:
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
.. -*- coding: utf-8; mode: rst -*-
|
||||
|
||||
.. _V4L2-PIX-FMT-INZI:
|
||||
|
||||
**************************
|
||||
V4L2_PIX_FMT_INZI ('INZI')
|
||||
**************************
|
||||
|
||||
Infrared 10-bit linked with Depth 16-bit images
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
Proprietary multi-planar format used by Intel SR300 Depth cameras, comprise of
|
||||
Infrared image followed by Depth data. The pixel definition is 32-bpp,
|
||||
with the Depth and Infrared Data split into separate continuous planes of
|
||||
identical dimensions.
|
||||
|
||||
|
||||
|
||||
The first plane - Infrared data - is stored according to
|
||||
:ref:`V4L2_PIX_FMT_Y10 <V4L2-PIX-FMT-Y10>` greyscale format.
|
||||
Each pixel is 16-bit cell, with actual data stored in the 10 LSBs
|
||||
with values in range 0 to 1023.
|
||||
The six remaining MSBs are padded with zeros.
|
||||
|
||||
|
||||
The second plane provides 16-bit per-pixel Depth data arranged in
|
||||
:ref:`V4L2-PIX-FMT-Z16 <V4L2-PIX-FMT-Z16>` format.
|
||||
|
||||
|
||||
**Frame Structure.**
|
||||
Each cell is a 16-bit word with more significant data stored at higher
|
||||
memory address (byte order is little-endian).
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\newline\newline\begin{adjustbox}{width=\columnwidth}
|
||||
|
||||
.. tabularcolumns:: |p{4.0cm}|p{4.0cm}|p{4.0cm}|p{4.0cm}|p{4.0cm}|p{4.0cm}|
|
||||
|
||||
.. flat-table::
|
||||
:header-rows: 0
|
||||
:stub-columns: 1
|
||||
:widths: 1 1 1 1 1 1
|
||||
|
||||
* - Ir\ :sub:`0,0`
|
||||
- Ir\ :sub:`0,1`
|
||||
- Ir\ :sub:`0,2`
|
||||
- ...
|
||||
- ...
|
||||
- ...
|
||||
* - :cspan:`5` ...
|
||||
* - :cspan:`5` Infrared Data
|
||||
* - :cspan:`5` ...
|
||||
* - ...
|
||||
- ...
|
||||
- ...
|
||||
- Ir\ :sub:`n-1,n-3`
|
||||
- Ir\ :sub:`n-1,n-2`
|
||||
- Ir\ :sub:`n-1,n-1`
|
||||
* - Depth\ :sub:`0,0`
|
||||
- Depth\ :sub:`0,1`
|
||||
- Depth\ :sub:`0,2`
|
||||
- ...
|
||||
- ...
|
||||
- ...
|
||||
* - :cspan:`5` ...
|
||||
* - :cspan:`5` Depth Data
|
||||
* - :cspan:`5` ...
|
||||
* - ...
|
||||
- ...
|
||||
- ...
|
||||
- Depth\ :sub:`n-1,n-3`
|
||||
- Depth\ :sub:`n-1,n-2`
|
||||
- Depth\ :sub:`n-1,n-1`
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\end{adjustbox}\newline\newline
|
|
@ -0,0 +1,168 @@
|
|||
.. -*- coding: utf-8; mode: rst -*-
|
||||
|
||||
.. _v4l2-meta-fmt-vsp1-hgo:
|
||||
|
||||
*******************************
|
||||
V4L2_META_FMT_VSP1_HGO ('VSPH')
|
||||
*******************************
|
||||
|
||||
Renesas R-Car VSP1 1-D Histogram Data
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
This format describes histogram data generated by the Renesas R-Car VSP1 1-D
|
||||
Histogram (HGO) engine.
|
||||
|
||||
The VSP1 HGO is a histogram computation engine that can operate on RGB, YCrCb
|
||||
or HSV data. It operates on a possibly cropped and subsampled input image and
|
||||
computes the minimum, maximum and sum of all pixels as well as per-channel
|
||||
histograms.
|
||||
|
||||
The HGO can compute histograms independently per channel, on the maximum of the
|
||||
three channels (RGB data only) or on the Y channel only (YCbCr only). It can
|
||||
additionally output the histogram with 64 or 256 bins, resulting in four
|
||||
possible modes of operation.
|
||||
|
||||
- In *64 bins normal mode*, the HGO operates on the three channels independently
|
||||
to compute three 64-bins histograms. RGB, YCbCr and HSV image formats are
|
||||
supported.
|
||||
- In *64 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
|
||||
channels to compute a single 64-bins histogram. Only the RGB image format is
|
||||
supported.
|
||||
- In *256 bins normal mode*, the HGO operates on the Y channel to compute a
|
||||
single 256-bins histogram. Only the YCbCr image format is supported.
|
||||
- In *256 bins maximum mode*, the HGO operates on the maximum of the (R, G, B)
|
||||
channels to compute a single 256-bins histogram. Only the RGB image format is
|
||||
supported.
|
||||
|
||||
**Byte Order.**
|
||||
All data is stored in memory in little endian format. Each cell in the tables
|
||||
contains one byte.
|
||||
|
||||
.. flat-table:: VSP1 HGO Data - 64 Bins, Normal Mode (792 bytes)
|
||||
:header-rows: 2
|
||||
:stub-columns: 0
|
||||
|
||||
* - Offset
|
||||
- :cspan:`4` Memory
|
||||
* -
|
||||
- [31:24]
|
||||
- [23:16]
|
||||
- [15:8]
|
||||
- [7:0]
|
||||
* - 0
|
||||
-
|
||||
- R/Cr/H max [7:0]
|
||||
-
|
||||
- R/Cr/H min [7:0]
|
||||
* - 4
|
||||
-
|
||||
- G/Y/S max [7:0]
|
||||
-
|
||||
- G/Y/S min [7:0]
|
||||
* - 8
|
||||
-
|
||||
- B/Cb/V max [7:0]
|
||||
-
|
||||
- B/Cb/V min [7:0]
|
||||
* - 12
|
||||
- :cspan:`4` R/Cr/H sum [31:0]
|
||||
* - 16
|
||||
- :cspan:`4` G/Y/S sum [31:0]
|
||||
* - 20
|
||||
- :cspan:`4` B/Cb/V sum [31:0]
|
||||
* - 24
|
||||
- :cspan:`4` R/Cr/H bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 276
|
||||
- :cspan:`4` R/Cr/H bin 63 [31:0]
|
||||
* - 280
|
||||
- :cspan:`4` G/Y/S bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 532
|
||||
- :cspan:`4` G/Y/S bin 63 [31:0]
|
||||
* - 536
|
||||
- :cspan:`4` B/Cb/V bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 788
|
||||
- :cspan:`4` B/Cb/V bin 63 [31:0]
|
||||
|
||||
.. flat-table:: VSP1 HGO Data - 64 Bins, Max Mode (264 bytes)
|
||||
:header-rows: 2
|
||||
:stub-columns: 0
|
||||
|
||||
* - Offset
|
||||
- :cspan:`4` Memory
|
||||
* -
|
||||
- [31:24]
|
||||
- [23:16]
|
||||
- [15:8]
|
||||
- [7:0]
|
||||
* - 0
|
||||
-
|
||||
- max(R,G,B) max [7:0]
|
||||
-
|
||||
- max(R,G,B) min [7:0]
|
||||
* - 4
|
||||
- :cspan:`4` max(R,G,B) sum [31:0]
|
||||
* - 8
|
||||
- :cspan:`4` max(R,G,B) bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 260
|
||||
- :cspan:`4` max(R,G,B) bin 63 [31:0]
|
||||
|
||||
.. flat-table:: VSP1 HGO Data - 256 Bins, Normal Mode (1032 bytes)
|
||||
:header-rows: 2
|
||||
:stub-columns: 0
|
||||
|
||||
* - Offset
|
||||
- :cspan:`4` Memory
|
||||
* -
|
||||
- [31:24]
|
||||
- [23:16]
|
||||
- [15:8]
|
||||
- [7:0]
|
||||
* - 0
|
||||
-
|
||||
- Y max [7:0]
|
||||
-
|
||||
- Y min [7:0]
|
||||
* - 4
|
||||
- :cspan:`4` Y sum [31:0]
|
||||
* - 8
|
||||
- :cspan:`4` Y bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 1028
|
||||
- :cspan:`4` Y bin 255 [31:0]
|
||||
|
||||
.. flat-table:: VSP1 HGO Data - 256 Bins, Max Mode (1032 bytes)
|
||||
:header-rows: 2
|
||||
:stub-columns: 0
|
||||
|
||||
* - Offset
|
||||
- :cspan:`4` Memory
|
||||
* -
|
||||
- [31:24]
|
||||
- [23:16]
|
||||
- [15:8]
|
||||
- [7:0]
|
||||
* - 0
|
||||
-
|
||||
- max(R,G,B) max [7:0]
|
||||
-
|
||||
- max(R,G,B) min [7:0]
|
||||
* - 4
|
||||
- :cspan:`4` max(R,G,B) sum [31:0]
|
||||
* - 8
|
||||
- :cspan:`4` max(R,G,B) bin 0 [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 1028
|
||||
- :cspan:`4` max(R,G,B) bin 255 [31:0]
|
|
@ -0,0 +1,120 @@
|
|||
.. -*- coding: utf-8; mode: rst -*-
|
||||
|
||||
.. _v4l2-meta-fmt-vsp1-hgt:
|
||||
|
||||
*******************************
|
||||
V4L2_META_FMT_VSP1_HGT ('VSPT')
|
||||
*******************************
|
||||
|
||||
Renesas R-Car VSP1 2-D Histogram Data
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
This format describes histogram data generated by the Renesas R-Car VSP1
|
||||
2-D Histogram (HGT) engine.
|
||||
|
||||
The VSP1 HGT is a histogram computation engine that operates on HSV
|
||||
data. It operates on a possibly cropped and subsampled input image and
|
||||
computes the sum, maximum and minimum of the S component as well as a
|
||||
weighted frequency histogram based on the H and S components.
|
||||
|
||||
The histogram is a matrix of 6 Hue and 32 Saturation buckets, 192 in
|
||||
total. Each HSV value is added to one or more buckets with a weight
|
||||
between 1 and 16 depending on the Hue areas configuration. Finding the
|
||||
corresponding buckets is done by inspecting the H and S value independently.
|
||||
|
||||
The Saturation position **n** (0 - 31) of the bucket in the matrix is
|
||||
found by the expression:
|
||||
|
||||
n = S / 8
|
||||
|
||||
The Hue position **m** (0 - 5) of the bucket in the matrix depends on
|
||||
how the HGT Hue areas are configured. There are 6 user configurable Hue
|
||||
Areas which can be configured to cover overlapping Hue values:
|
||||
|
||||
::
|
||||
|
||||
Area 0 Area 1 Area 2 Area 3 Area 4 Area 5
|
||||
________ ________ ________ ________ ________ ________
|
||||
\ /| |\ /| |\ /| |\ /| |\ /| |\ /| |\ /
|
||||
\ / | | \ / | | \ / | | \ / | | \ / | | \ / | | \ /
|
||||
X | | X | | X | | X | | X | | X | | X
|
||||
/ \ | | / \ | | / \ | | / \ | | / \ | | / \ | | / \
|
||||
/ \| |/ \| |/ \| |/ \| |/ \| |/ \| |/ \
|
||||
5U 0L 0U 1L 1U 2L 2U 3L 3U 4L 4U 5L 5U 0L
|
||||
<0..............................Hue Value............................255>
|
||||
|
||||
When two consecutive areas don't overlap (n+1L is equal to nU) the boundary
|
||||
value is considered as part of the lower area.
|
||||
|
||||
Pixels with a hue value included in the centre of an area (between nL and nU
|
||||
included) are attributed to that single area and given a weight of 16. Pixels
|
||||
with a hue value included in the overlapping region between two areas (between
|
||||
n+1L and nU excluded) are attributed to both areas and given a weight for each
|
||||
of these areas proportional to their position along the diagonal lines
|
||||
(rounded down).
|
||||
|
||||
The Hue area setup must match one of the following constrains:
|
||||
|
||||
::
|
||||
|
||||
0L <= 0U <= 1L <= 1U <= 2L <= 2U <= 3L <= 3U <= 4L <= 4U <= 5L <= 5U
|
||||
|
||||
::
|
||||
|
||||
0U <= 1L <= 1U <= 2L <= 2U <= 3L <= 3U <= 4L <= 4U <= 5L <= 5U <= 0L
|
||||
|
||||
**Byte Order.**
|
||||
All data is stored in memory in little endian format. Each cell in the tables
|
||||
contains one byte.
|
||||
|
||||
.. flat-table:: VSP1 HGT Data - (776 bytes)
|
||||
:header-rows: 2
|
||||
:stub-columns: 0
|
||||
|
||||
* - Offset
|
||||
- :cspan:`4` Memory
|
||||
* -
|
||||
- [31:24]
|
||||
- [23:16]
|
||||
- [15:8]
|
||||
- [7:0]
|
||||
* - 0
|
||||
- -
|
||||
- S max [7:0]
|
||||
- -
|
||||
- S min [7:0]
|
||||
* - 4
|
||||
- :cspan:`4` S sum [31:0]
|
||||
* - 8
|
||||
- :cspan:`4` Histogram bucket (m=0, n=0) [31:0]
|
||||
* - 12
|
||||
- :cspan:`4` Histogram bucket (m=0, n=1) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 132
|
||||
- :cspan:`4` Histogram bucket (m=0, n=31) [31:0]
|
||||
* - 136
|
||||
- :cspan:`4` Histogram bucket (m=1, n=0) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 264
|
||||
- :cspan:`4` Histogram bucket (m=2, n=0) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 392
|
||||
- :cspan:`4` Histogram bucket (m=3, n=0) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 520
|
||||
- :cspan:`4` Histogram bucket (m=4, n=0) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 648
|
||||
- :cspan:`4` Histogram bucket (m=5, n=0) [31:0]
|
||||
* -
|
||||
- :cspan:`4` ...
|
||||
* - 772
|
||||
- :cspan:`4` Histogram bucket (m=5, n=31) [31:0]
|
|
@ -34,4 +34,5 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`.)
|
|||
pixfmt-013
|
||||
sdr-formats
|
||||
tch-formats
|
||||
meta-formats
|
||||
pixfmt-reserved
|
||||
|
|
|
@ -1890,10 +1890,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- b\ :sub:`6`
|
||||
- b\ :sub:`5`
|
||||
|
@ -1911,10 +1911,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -1932,10 +1932,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -1953,10 +1953,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- r\ :sub:`7`
|
||||
- r\ :sub:`6`
|
||||
- r\ :sub:`5`
|
||||
|
@ -1974,10 +1974,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- b\ :sub:`6`
|
||||
- b\ :sub:`5`
|
||||
|
@ -1995,10 +1995,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -2016,10 +2016,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -2037,10 +2037,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- r\ :sub:`7`
|
||||
- r\ :sub:`6`
|
||||
- r\ :sub:`5`
|
||||
|
@ -2058,10 +2058,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- b\ :sub:`6`
|
||||
- b\ :sub:`5`
|
||||
|
@ -2079,10 +2079,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -2100,10 +2100,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`7`
|
||||
- g\ :sub:`6`
|
||||
- g\ :sub:`5`
|
||||
|
@ -2121,10 +2121,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- r\ :sub:`7`
|
||||
- r\ :sub:`6`
|
||||
- r\ :sub:`5`
|
||||
|
@ -2142,10 +2142,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
|
@ -2161,10 +2161,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- b\ :sub:`6`
|
||||
- b\ :sub:`5`
|
||||
|
@ -2182,10 +2182,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`7`
|
||||
- b\ :sub:`6`
|
||||
- b\ :sub:`5`
|
||||
|
@ -2201,10 +2201,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
|
@ -2222,10 +2222,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`9`
|
||||
- b\ :sub:`8`
|
||||
- b\ :sub:`7`
|
||||
|
@ -2241,10 +2241,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
- 0
|
||||
|
@ -2262,10 +2262,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`1`
|
||||
- b\ :sub:`0`
|
||||
- 0
|
||||
|
@ -2281,10 +2281,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`9`
|
||||
- b\ :sub:`8`
|
||||
- b\ :sub:`7`
|
||||
|
@ -2300,10 +2300,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`9`
|
||||
- b\ :sub:`8`
|
||||
- b\ :sub:`7`
|
||||
|
@ -2321,10 +2321,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`9`
|
||||
- g\ :sub:`8`
|
||||
- g\ :sub:`7`
|
||||
|
@ -2342,10 +2342,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`9`
|
||||
- g\ :sub:`8`
|
||||
- g\ :sub:`7`
|
||||
|
@ -2363,10 +2363,10 @@ organization is given as an example for the first pixel only.
|
|||
-
|
||||
-
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- r\ :sub:`9`
|
||||
- r\ :sub:`8`
|
||||
- r\ :sub:`7`
|
||||
|
@ -2382,10 +2382,10 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SBGGR12_1X12
|
||||
- 0x3008
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- b\ :sub:`11`
|
||||
- b\ :sub:`10`
|
||||
- b\ :sub:`9`
|
||||
|
@ -2403,10 +2403,10 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SGBRG12_1X12
|
||||
- 0x3010
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`11`
|
||||
- g\ :sub:`10`
|
||||
- g\ :sub:`9`
|
||||
|
@ -2424,10 +2424,10 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SGRBG12_1X12
|
||||
- 0x3011
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- g\ :sub:`11`
|
||||
- g\ :sub:`10`
|
||||
- g\ :sub:`9`
|
||||
|
@ -2445,10 +2445,10 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SRGGB12_1X12
|
||||
- 0x3012
|
||||
-
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
-
|
||||
-
|
||||
- r\ :sub:`11`
|
||||
- r\ :sub:`10`
|
||||
- r\ :sub:`9`
|
||||
|
@ -2466,8 +2466,8 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SBGGR14_1X14
|
||||
- 0x3019
|
||||
-
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
- b\ :sub:`13`
|
||||
- b\ :sub:`12`
|
||||
- b\ :sub:`11`
|
||||
|
@ -2487,8 +2487,8 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SGBRG14_1X14
|
||||
- 0x301a
|
||||
-
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
- g\ :sub:`13`
|
||||
- g\ :sub:`12`
|
||||
- g\ :sub:`11`
|
||||
|
@ -2508,8 +2508,8 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SGRBG14_1X14
|
||||
- 0x301b
|
||||
-
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
- g\ :sub:`13`
|
||||
- g\ :sub:`12`
|
||||
- g\ :sub:`11`
|
||||
|
@ -2529,8 +2529,8 @@ organization is given as an example for the first pixel only.
|
|||
- MEDIA_BUS_FMT_SRGGB14_1X14
|
||||
- 0x301c
|
||||
-
|
||||
- -
|
||||
- -
|
||||
-
|
||||
-
|
||||
- r\ :sub:`13`
|
||||
- r\ :sub:`12`
|
||||
- r\ :sub:`11`
|
||||
|
|
|
@ -8,9 +8,10 @@ Video Inputs and Outputs
|
|||
|
||||
Video inputs and outputs are physical connectors of a device. These can
|
||||
be for example RF connectors (antenna/cable), CVBS a.k.a. Composite
|
||||
Video, S-Video or RGB connectors. Video and VBI capture devices have
|
||||
inputs. Video and VBI output devices have outputs, at least one each.
|
||||
Radio devices have no video inputs or outputs.
|
||||
Video, S-Video and RGB connectors. Camera sensors are also considered to
|
||||
be a video input. Video and VBI capture devices have inputs. Video and
|
||||
VBI output devices have outputs, at least one each. Radio devices have
|
||||
no video inputs or outputs.
|
||||
|
||||
To learn about the number and attributes of the available inputs and
|
||||
outputs applications can enumerate them with the
|
||||
|
|
|
@ -33,7 +33,7 @@ Description
|
|||
|
||||
To query the attributes of a video input applications initialize the
|
||||
``index`` field of struct :c:type:`v4l2_input` and call the
|
||||
:ref:`VIDIOC_ENUMINPUT` ioctl with a pointer to this structure. Drivers
|
||||
:ref:`VIDIOC_ENUMINPUT` with a pointer to this structure. Drivers
|
||||
fill the rest of the structure or return an ``EINVAL`` error code when the
|
||||
index is out of bounds. To enumerate all inputs applications shall begin
|
||||
at index zero, incrementing by one until the driver returns ``EINVAL``.
|
||||
|
@ -117,8 +117,9 @@ at index zero, incrementing by one until the driver returns ``EINVAL``.
|
|||
- This input uses a tuner (RF demodulator).
|
||||
* - ``V4L2_INPUT_TYPE_CAMERA``
|
||||
- 2
|
||||
- Analog baseband input, for example CVBS / Composite Video,
|
||||
S-Video, RGB.
|
||||
- Any non-tuner video input, for example Composite Video,
|
||||
S-Video, HDMI, camera sensor. The naming as ``_TYPE_CAMERA`` is historical,
|
||||
today we would have called it ``_TYPE_VIDEO``.
|
||||
* - ``V4L2_INPUT_TYPE_TOUCH``
|
||||
- 3
|
||||
- This input is a touch device for capturing raw touch data.
|
||||
|
@ -209,11 +210,11 @@ at index zero, incrementing by one until the driver returns ``EINVAL``.
|
|||
* - ``V4L2_IN_CAP_DV_TIMINGS``
|
||||
- 0x00000002
|
||||
- This input supports setting video timings by using
|
||||
VIDIOC_S_DV_TIMINGS.
|
||||
``VIDIOC_S_DV_TIMINGS``.
|
||||
* - ``V4L2_IN_CAP_STD``
|
||||
- 0x00000004
|
||||
- This input supports setting the TV standard by using
|
||||
VIDIOC_S_STD.
|
||||
``VIDIOC_S_STD``.
|
||||
* - ``V4L2_IN_CAP_NATIVE_SIZE``
|
||||
- 0x00000008
|
||||
- This input supports setting the native size using the
|
||||
|
|
|
@ -33,11 +33,11 @@ Description
|
|||
|
||||
To query the attributes of a video outputs applications initialize the
|
||||
``index`` field of struct :c:type:`v4l2_output` and call
|
||||
the :ref:`VIDIOC_ENUMOUTPUT` ioctl with a pointer to this structure.
|
||||
the :ref:`VIDIOC_ENUMOUTPUT` with a pointer to this structure.
|
||||
Drivers fill the rest of the structure or return an ``EINVAL`` error code
|
||||
when the index is out of bounds. To enumerate all outputs applications
|
||||
shall begin at index zero, incrementing by one until the driver returns
|
||||
EINVAL.
|
||||
``EINVAL``.
|
||||
|
||||
|
||||
.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
|
||||
|
@ -112,11 +112,12 @@ EINVAL.
|
|||
- This output is an analog TV modulator.
|
||||
* - ``V4L2_OUTPUT_TYPE_ANALOG``
|
||||
- 2
|
||||
- Analog baseband output, for example Composite / CVBS, S-Video,
|
||||
RGB.
|
||||
- Any non-modulator video output, for example Composite Video,
|
||||
S-Video, HDMI. The naming as ``_TYPE_ANALOG`` is historical,
|
||||
today we would have called it ``_TYPE_VIDEO``.
|
||||
* - ``V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY``
|
||||
- 3
|
||||
- [?]
|
||||
- The video output will be copied to a :ref:`video overlay <overlay>`.
|
||||
|
||||
|
||||
|
||||
|
@ -132,11 +133,11 @@ EINVAL.
|
|||
* - ``V4L2_OUT_CAP_DV_TIMINGS``
|
||||
- 0x00000002
|
||||
- This output supports setting video timings by using
|
||||
VIDIOC_S_DV_TIMINGS.
|
||||
``VIDIOC_S_DV_TIMINGS``.
|
||||
* - ``V4L2_OUT_CAP_STD``
|
||||
- 0x00000004
|
||||
- This output supports setting the TV standard by using
|
||||
VIDIOC_S_STD.
|
||||
``VIDIOC_S_STD``.
|
||||
* - ``V4L2_OUT_CAP_NATIVE_SIZE``
|
||||
- 0x00000008
|
||||
- This output supports setting the native size using the
|
||||
|
|
|
@ -146,8 +146,20 @@ EBUSY
|
|||
- ``flags``
|
||||
- Several flags giving more information about the format. See
|
||||
:ref:`dv-bt-flags` for a description of the flags.
|
||||
* - __u32
|
||||
- ``reserved[14]``
|
||||
* - struct :c:type:`v4l2_fract`
|
||||
- ``picture_aspect``
|
||||
- The picture aspect if the pixels are not square. Only valid if the
|
||||
``V4L2_DV_FL_HAS_PICTURE_ASPECT`` flag is set.
|
||||
* - __u8
|
||||
- ``cea861_vic``
|
||||
- The Video Identification Code according to the CEA-861 standard.
|
||||
Only valid if the ``V4L2_DV_FL_HAS_CEA861_VIC`` flag is set.
|
||||
* - __u8
|
||||
- ``hdmi_vic``
|
||||
- The Video Identification Code according to the HDMI standard.
|
||||
Only valid if the ``V4L2_DV_FL_HAS_HDMI_VIC`` flag is set.
|
||||
* - __u8
|
||||
- ``reserved[46]``
|
||||
- Reserved for future extensions. Drivers and applications must set
|
||||
the array to zero.
|
||||
|
||||
|
|
|
@ -236,6 +236,9 @@ specification the ioctl returns an ``EINVAL`` error code.
|
|||
* - ``V4L2_CAP_SDR_OUTPUT``
|
||||
- 0x00400000
|
||||
- The device supports the :ref:`SDR Output <sdr>` interface.
|
||||
* - ``V4L2_CAP_META_CAPTURE``
|
||||
- 0x00800000
|
||||
- The device supports the :ref:`metadata` capture interface.
|
||||
* - ``V4L2_CAP_READWRITE``
|
||||
- 0x01000000
|
||||
- The device supports the :ref:`read() <rw>` and/or
|
||||
|
|
|
@ -301,12 +301,12 @@ See also the examples in :ref:`control`.
|
|||
- ``name``\ [32]
|
||||
- Name of the menu item, a NUL-terminated ASCII string. This
|
||||
information is intended for the user. This field is valid for
|
||||
``V4L2_CTRL_FLAG_MENU`` type controls.
|
||||
``V4L2_CTRL_TYPE_MENU`` type controls.
|
||||
* -
|
||||
- __s64
|
||||
- ``value``
|
||||
- Value of the integer menu item. This field is valid for
|
||||
``V4L2_CTRL_FLAG_INTEGER_MENU`` type controls.
|
||||
``V4L2_CTRL_TYPE_INTEGER_MENU`` type controls.
|
||||
* - __u32
|
||||
-
|
||||
- ``reserved``
|
||||
|
@ -507,6 +507,19 @@ See also the examples in :ref:`control`.
|
|||
represents an action on the hardware. For example: clearing an
|
||||
error flag or triggering the flash. All the controls of the type
|
||||
``V4L2_CTRL_TYPE_BUTTON`` have this flag set.
|
||||
* .. _FLAG_MODIFY_LAYOUT:
|
||||
|
||||
- ``V4L2_CTRL_FLAG_MODIFY_LAYOUT``
|
||||
- 0x0400
|
||||
- Changing this control value may modify the layout of the
|
||||
buffer (for video devices) or the media bus format (for sub-devices).
|
||||
|
||||
A typical example would be the ``V4L2_CID_ROTATE`` control.
|
||||
|
||||
Note that typically controls with this flag will also set the
|
||||
``V4L2_CTRL_FLAG_GRABBED`` flag when buffers are allocated or
|
||||
streaming is in progress since most drivers do not support changing
|
||||
the format in that case.
|
||||
|
||||
|
||||
Return Value
|
||||
|
|
|
@ -263,6 +263,14 @@ all configurable using the following module options:
|
|||
removed. Unless overridden by ccs_cap_mode and/or ccs_out_mode the
|
||||
will default to enabling crop, compose and scaling.
|
||||
|
||||
- allocators:
|
||||
|
||||
memory allocator selection, default is 0. It specifies the way buffers
|
||||
will be allocated.
|
||||
|
||||
- 0: vmalloc
|
||||
- 1: dma-contig
|
||||
|
||||
Taken together, all these module options allow you to precisely customize
|
||||
the driver behavior and test your application with all sorts of permutations.
|
||||
It is also very suitable to emulate hardware that is not yet available, e.g.
|
||||
|
|
|
@ -27,6 +27,7 @@ replace symbol V4L2_FIELD_SEQ_TB :c:type:`v4l2_field`
|
|||
replace symbol V4L2_FIELD_TOP :c:type:`v4l2_field`
|
||||
|
||||
# Documented enum v4l2_buf_type
|
||||
replace symbol V4L2_BUF_TYPE_META_CAPTURE :c:type:`v4l2_buf_type`
|
||||
replace symbol V4L2_BUF_TYPE_SDR_CAPTURE :c:type:`v4l2_buf_type`
|
||||
replace symbol V4L2_BUF_TYPE_SDR_OUTPUT :c:type:`v4l2_buf_type`
|
||||
replace symbol V4L2_BUF_TYPE_SLICED_VBI_CAPTURE :c:type:`v4l2_buf_type`
|
||||
|
@ -152,6 +153,7 @@ replace define V4L2_CAP_MODULATOR device-capabilities
|
|||
replace define V4L2_CAP_SDR_CAPTURE device-capabilities
|
||||
replace define V4L2_CAP_EXT_PIX_FORMAT device-capabilities
|
||||
replace define V4L2_CAP_SDR_OUTPUT device-capabilities
|
||||
replace define V4L2_CAP_META_CAPTURE device-capabilities
|
||||
replace define V4L2_CAP_READWRITE device-capabilities
|
||||
replace define V4L2_CAP_ASYNCIO device-capabilities
|
||||
replace define V4L2_CAP_STREAMING device-capabilities
|
||||
|
@ -339,6 +341,7 @@ replace define V4L2_CTRL_FLAG_WRITE_ONLY control-flags
|
|||
replace define V4L2_CTRL_FLAG_VOLATILE control-flags
|
||||
replace define V4L2_CTRL_FLAG_HAS_PAYLOAD control-flags
|
||||
replace define V4L2_CTRL_FLAG_EXECUTE_ON_WRITE control-flags
|
||||
replace define V4L2_CTRL_FLAG_MODIFY_LAYOUT control-flags
|
||||
|
||||
replace define V4L2_CTRL_FLAG_NEXT_CTRL control
|
||||
replace define V4L2_CTRL_FLAG_NEXT_COMPOUND control
|
||||
|
|
38
MAINTAINERS
38
MAINTAINERS
|
@ -2234,7 +2234,7 @@ ATMEL ISI DRIVER
|
|||
M: Ludovic Desroches <ludovic.desroches@microchip.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/media/platform/soc_camera/atmel-isi.c
|
||||
F: drivers/media/platform/atmel/atmel-isi.c
|
||||
F: include/media/atmel-isi.h
|
||||
|
||||
ATMEL LCDFB DRIVER
|
||||
|
@ -3100,7 +3100,7 @@ F: drivers/net/ieee802154/cc2520.c
|
|||
F: include/linux/spi/cc2520.h
|
||||
F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
|
||||
|
||||
CEC DRIVER
|
||||
CEC FRAMEWORK
|
||||
M: Hans Verkuil <hans.verkuil@cisco.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
|
@ -3109,10 +3109,9 @@ S: Supported
|
|||
F: Documentation/media/kapi/cec-core.rst
|
||||
F: Documentation/media/uapi/cec
|
||||
F: drivers/media/cec/
|
||||
F: drivers/media/cec-edid.c
|
||||
F: drivers/media/rc/keymaps/rc-cec.c
|
||||
F: include/media/cec.h
|
||||
F: include/media/cec-edid.h
|
||||
F: include/media/cec-notifier.h
|
||||
F: include/uapi/linux/cec.h
|
||||
F: include/uapi/linux/cec-funcs.h
|
||||
|
||||
|
@ -8173,6 +8172,7 @@ W: https://linuxtv.org
|
|||
Q: http://patchwork.kernel.org/project/linux-media/list/
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/
|
||||
F: Documentation/media/
|
||||
F: drivers/media/
|
||||
F: drivers/staging/media/
|
||||
|
@ -8193,6 +8193,13 @@ L: netdev@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/net/ethernet/mediatek/
|
||||
|
||||
MEDIATEK JPEG DRIVER
|
||||
M: Rick Chang <rick.chang@mediatek.com>
|
||||
M: Bin Liu <bin.liu@mediatek.com>
|
||||
S: Supported
|
||||
F: drivers/media/platform/mtk-jpeg/
|
||||
F: Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.txt
|
||||
|
||||
MEDIATEK MEDIA DRIVER
|
||||
M: Tiffany Lin <tiffany.lin@mediatek.com>
|
||||
M: Andrew-CT Chen <andrew-ct.chen@mediatek.com>
|
||||
|
@ -9367,12 +9374,20 @@ M: Harald Welte <laforge@gnumonks.org>
|
|||
S: Maintained
|
||||
F: drivers/char/pcmcia/cm4040_cs.*
|
||||
|
||||
OMNIVISION OV5647 SENSOR DRIVER
|
||||
M: Ramiro Oliveira <roliveir@synopsys.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/ov5647.c
|
||||
|
||||
OMNIVISION OV7670 SENSOR DRIVER
|
||||
M: Jonathan Corbet <corbet@lwn.net>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
S: Maintained
|
||||
F: drivers/media/i2c/ov7670.c
|
||||
F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
|
||||
|
||||
ONENAND FLASH DRIVER
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
|
@ -10559,6 +10574,13 @@ L: linux-fbdev@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/video/fbdev/aty/aty128fb.c
|
||||
|
||||
RAINSHADOW-CEC DRIVER
|
||||
M: Hans Verkuil <hverkuil@xs4all.nl>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
S: Maintained
|
||||
F: drivers/media/usb/rainshadow-cec/*
|
||||
|
||||
RALINK MIPS ARCHITECTURE
|
||||
M: John Crispin <john@phrozen.org>
|
||||
L: linux-mips@linux-mips.org
|
||||
|
@ -13555,6 +13577,14 @@ W: https://linuxtv.org
|
|||
S: Maintained
|
||||
F: drivers/media/platform/vivid/*
|
||||
|
||||
VIMC VIRTUAL MEDIA CONTROLLER DRIVER
|
||||
M: Helen Koike <helen.koike@collabora.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
W: https://linuxtv.org
|
||||
S: Maintained
|
||||
F: drivers/media/platform/vimc/*
|
||||
|
||||
VLYNQ BUS
|
||||
M: Florian Fainelli <f.fainelli@gmail.com>
|
||||
L: openwrt-devel@lists.openwrt.org (subscribers-only)
|
||||
|
|
|
@ -771,6 +771,7 @@
|
|||
clocks = <&clock CLK_HDMI_CEC>;
|
||||
clock-names = "hdmicec";
|
||||
samsung,syscon-phandle = <&pmu_system_controller>;
|
||||
hdmi-phandle = <&hdmi>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hdmi_cec>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -742,18 +742,6 @@
|
|||
<&clk_s_c0_flexgen CLK_ETH_PHY>;
|
||||
};
|
||||
|
||||
cec: sti-cec@094a087c {
|
||||
compatible = "st,stih-cec";
|
||||
reg = <0x94a087c 0x64>;
|
||||
clocks = <&clk_sysin>;
|
||||
clock-names = "cec-clk";
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "cec-irq";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_cec0_default>;
|
||||
resets = <&softreset STIH407_LPM_SOFTRESET>;
|
||||
};
|
||||
|
||||
rng10: rng@08a89000 {
|
||||
compatible = "st,rng";
|
||||
reg = <0x08a89000 0x1000>;
|
||||
|
|
|
@ -281,5 +281,18 @@
|
|||
<&clk_s_c0_flexgen CLK_ST231_DMU>,
|
||||
<&clk_s_c0_flexgen CLK_FLASH_PROMIP>;
|
||||
};
|
||||
|
||||
sti-cec@094a087c {
|
||||
compatible = "st,stih-cec";
|
||||
reg = <0x94a087c 0x64>;
|
||||
clocks = <&clk_sysin>;
|
||||
clock-names = "cec-clk";
|
||||
interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>;
|
||||
interrupt-names = "cec-irq";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_cec0_default>;
|
||||
resets = <&softreset STIH407_LPM_SOFTRESET>;
|
||||
hdmi-phandle = <&sti_hdmi>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1290,6 +1290,7 @@ static struct vpif_display_config da850_vpif_display_config = {
|
|||
.output_count = ARRAY_SIZE(da850_ch0_outputs),
|
||||
},
|
||||
.card_name = "DA850/OMAP-L138 Video Display",
|
||||
.i2c_adapter_id = 1,
|
||||
};
|
||||
|
||||
static __init void da850_vpif_init(void)
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
#include "exynos_drm_crtc.h"
|
||||
|
||||
#define HOTPLUG_DEBOUNCE_MS 1100
|
||||
|
@ -118,6 +120,7 @@ struct hdmi_context {
|
|||
bool dvi_mode;
|
||||
struct delayed_work hotplug_work;
|
||||
struct drm_display_mode current_mode;
|
||||
struct cec_notifier *notifier;
|
||||
const struct hdmi_driver_data *drv_data;
|
||||
|
||||
void __iomem *regs;
|
||||
|
@ -821,6 +824,7 @@ static enum drm_connector_status hdmi_detect(struct drm_connector *connector,
|
|||
if (gpiod_get_value(hdata->hpd_gpio))
|
||||
return connector_status_connected;
|
||||
|
||||
cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
|
@ -859,6 +863,7 @@ static int hdmi_get_modes(struct drm_connector *connector)
|
|||
edid->width_cm, edid->height_cm);
|
||||
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
cec_notifier_set_phys_addr_from_edid(hdata->notifier, edid);
|
||||
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
|
||||
|
@ -1501,6 +1506,7 @@ static void hdmi_disable(struct drm_encoder *encoder)
|
|||
if (funcs && funcs->disable)
|
||||
(*funcs->disable)(crtc);
|
||||
|
||||
cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
cancel_delayed_work(&hdata->hotplug_work);
|
||||
|
||||
hdmiphy_disable(hdata);
|
||||
|
@ -1880,15 +1886,22 @@ static int hdmi_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
hdata->notifier = cec_notifier_get(&pdev->dev);
|
||||
if (hdata->notifier == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_hdmiphy;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
ret = component_add(&pdev->dev, &hdmi_component_ops);
|
||||
if (ret)
|
||||
goto err_disable_pm_runtime;
|
||||
goto err_notifier_put;
|
||||
|
||||
return ret;
|
||||
|
||||
err_disable_pm_runtime:
|
||||
err_notifier_put:
|
||||
cec_notifier_put(hdata->notifier);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
err_hdmiphy:
|
||||
|
@ -1907,9 +1920,11 @@ static int hdmi_remove(struct platform_device *pdev)
|
|||
struct hdmi_context *hdata = platform_get_drvdata(pdev);
|
||||
|
||||
cancel_delayed_work_sync(&hdata->hotplug_work);
|
||||
cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
|
||||
component_del(&pdev->dev, &hdmi_component_ops);
|
||||
|
||||
cec_notifier_put(hdata->notifier);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
if (!IS_ERR(hdata->reg_hdmi_en))
|
||||
|
|
|
@ -771,6 +771,8 @@ static void sti_hdmi_disable(struct drm_bridge *bridge)
|
|||
clk_disable_unprepare(hdmi->clk_pix);
|
||||
|
||||
hdmi->enabled = false;
|
||||
|
||||
cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -973,6 +975,7 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
|
|||
DRM_DEBUG_KMS("%s : %dx%d cm\n",
|
||||
(hdmi->hdmi_monitor ? "hdmi monitor" : "dvi monitor"),
|
||||
edid->width_cm, edid->height_cm);
|
||||
cec_notifier_set_phys_addr_from_edid(hdmi->notifier, edid);
|
||||
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
drm_mode_connector_update_edid_property(connector, edid);
|
||||
|
@ -1035,6 +1038,7 @@ sti_hdmi_connector_detect(struct drm_connector *connector, bool force)
|
|||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("hdmi cable disconnected\n");
|
||||
cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
|
@ -1423,6 +1427,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
|
|||
goto release_adapter;
|
||||
}
|
||||
|
||||
hdmi->notifier = cec_notifier_get(&pdev->dev);
|
||||
if (!hdmi->notifier)
|
||||
goto release_adapter;
|
||||
|
||||
hdmi->reset = devm_reset_control_get(dev, "hdmi");
|
||||
/* Take hdmi out of reset */
|
||||
if (!IS_ERR(hdmi->reset))
|
||||
|
@ -1442,11 +1450,14 @@ static int sti_hdmi_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
cec_notifier_set_phys_addr(hdmi->notifier, CEC_PHYS_ADDR_INVALID);
|
||||
|
||||
i2c_put_adapter(hdmi->ddc_adapt);
|
||||
if (hdmi->audio_pdev)
|
||||
platform_device_unregister(hdmi->audio_pdev);
|
||||
component_del(&pdev->dev, &sti_hdmi_ops);
|
||||
|
||||
cec_notifier_put(hdmi->notifier);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
#define HDMI_STA 0x0010
|
||||
#define HDMI_STA_DLL_LCK BIT(5)
|
||||
|
@ -64,6 +65,7 @@ static const struct drm_prop_enum_list colorspace_mode_names[] = {
|
|||
* @audio_pdev: ASoC hdmi-codec platform device
|
||||
* @audio: hdmi audio parameters.
|
||||
* @drm_connector: hdmi connector
|
||||
* @notifier: hotplug detect notifier
|
||||
*/
|
||||
struct sti_hdmi {
|
||||
struct device dev;
|
||||
|
@ -89,6 +91,7 @@ struct sti_hdmi {
|
|||
struct platform_device *audio_pdev;
|
||||
struct hdmi_audio_params audio;
|
||||
struct drm_connector *drm_connector;
|
||||
struct cec_notifier *notifier;
|
||||
};
|
||||
|
||||
u32 hdmi_read(struct sti_hdmi *hdmi, int offset);
|
||||
|
|
|
@ -81,23 +81,15 @@ config MEDIA_RC_SUPPORT
|
|||
Say Y when you have a TV or an IR device.
|
||||
|
||||
config MEDIA_CEC_SUPPORT
|
||||
bool "HDMI CEC support"
|
||||
select MEDIA_CEC_EDID
|
||||
---help---
|
||||
Enable support for HDMI CEC (Consumer Electronics Control),
|
||||
which is an optional HDMI feature.
|
||||
bool "HDMI CEC support"
|
||||
---help---
|
||||
Enable support for HDMI CEC (Consumer Electronics Control),
|
||||
which is an optional HDMI feature.
|
||||
|
||||
Say Y when you have an HDMI receiver, transmitter or a USB CEC
|
||||
adapter that supports HDMI CEC.
|
||||
Say Y when you have an HDMI receiver, transmitter or a USB CEC
|
||||
adapter that supports HDMI CEC.
|
||||
|
||||
config MEDIA_CEC_DEBUG
|
||||
bool "HDMI CEC debugfs interface"
|
||||
depends on MEDIA_CEC_SUPPORT && DEBUG_FS
|
||||
---help---
|
||||
Turns on the DebugFS interface for CEC devices.
|
||||
|
||||
config MEDIA_CEC_EDID
|
||||
bool
|
||||
source "drivers/media/cec/Kconfig"
|
||||
|
||||
#
|
||||
# Media controller
|
||||
|
|
|
@ -2,16 +2,10 @@
|
|||
# Makefile for the kernel multimedia device drivers.
|
||||
#
|
||||
|
||||
ifeq ($(CONFIG_MEDIA_CEC_EDID),y)
|
||||
obj-$(CONFIG_MEDIA_SUPPORT) += cec-edid.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y)
|
||||
obj-$(CONFIG_MEDIA_SUPPORT) += cec/
|
||||
endif
|
||||
|
||||
media-objs := media-device.o media-devnode.o media-entity.o
|
||||
|
||||
obj-$(CONFIG_CEC_CORE) += cec/
|
||||
|
||||
#
|
||||
# I2C drivers should come before other drivers, otherwise they'll fail
|
||||
# when compiled as builtin drivers
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
config CEC_CORE
|
||||
tristate
|
||||
depends on MEDIA_CEC_SUPPORT
|
||||
default y
|
||||
|
||||
config MEDIA_CEC_NOTIFIER
|
||||
bool
|
||||
|
||||
config MEDIA_CEC_RC
|
||||
bool "HDMI CEC RC integration"
|
||||
depends on CEC_CORE && RC_CORE
|
||||
---help---
|
||||
Pass on CEC remote control messages to the RC framework.
|
||||
|
||||
config MEDIA_CEC_DEBUG
|
||||
bool "HDMI CEC debugfs interface"
|
||||
depends on CEC_CORE && DEBUG_FS
|
||||
---help---
|
||||
Turns on the DebugFS interface for CEC devices.
|
|
@ -1,5 +1,7 @@
|
|||
cec-objs := cec-core.o cec-adap.o cec-api.o
|
||||
cec-objs := cec-core.o cec-adap.o cec-api.o cec-edid.o
|
||||
|
||||
ifeq ($(CONFIG_MEDIA_CEC_SUPPORT),y)
|
||||
obj-$(CONFIG_MEDIA_SUPPORT) += cec.o
|
||||
ifeq ($(CONFIG_MEDIA_CEC_NOTIFIER),y)
|
||||
cec-objs += cec-notifier.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_CEC_CORE) += cec.o
|
||||
|
|
|
@ -299,6 +299,40 @@ static void cec_data_cancel(struct cec_data *data)
|
|||
cec_data_completed(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush all pending transmits and cancel any pending timeout work.
|
||||
*
|
||||
* This function is called with adap->lock held.
|
||||
*/
|
||||
static void cec_flush(struct cec_adapter *adap)
|
||||
{
|
||||
struct cec_data *data, *n;
|
||||
|
||||
/*
|
||||
* If the adapter is disabled, or we're asked to stop,
|
||||
* then cancel any pending transmits.
|
||||
*/
|
||||
while (!list_empty(&adap->transmit_queue)) {
|
||||
data = list_first_entry(&adap->transmit_queue,
|
||||
struct cec_data, list);
|
||||
cec_data_cancel(data);
|
||||
}
|
||||
if (adap->transmitting)
|
||||
cec_data_cancel(adap->transmitting);
|
||||
|
||||
/* Cancel the pending timeout work. */
|
||||
list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
|
||||
if (cancel_delayed_work(&data->work))
|
||||
cec_data_cancel(data);
|
||||
/*
|
||||
* If cancel_delayed_work returned false, then
|
||||
* the cec_wait_timeout function is running,
|
||||
* which will call cec_data_completed. So no
|
||||
* need to do anything special in that case.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Main CEC state machine
|
||||
*
|
||||
|
@ -333,7 +367,6 @@ int cec_thread_func(void *_adap)
|
|||
*/
|
||||
err = wait_event_interruptible_timeout(adap->kthread_waitq,
|
||||
kthread_should_stop() ||
|
||||
(!adap->is_configured && !adap->is_configuring) ||
|
||||
(!adap->transmitting &&
|
||||
!list_empty(&adap->transmit_queue)),
|
||||
msecs_to_jiffies(CEC_XFER_TIMEOUT_MS));
|
||||
|
@ -348,39 +381,8 @@ int cec_thread_func(void *_adap)
|
|||
|
||||
mutex_lock(&adap->lock);
|
||||
|
||||
if ((!adap->is_configured && !adap->is_configuring) ||
|
||||
kthread_should_stop()) {
|
||||
/*
|
||||
* If the adapter is disabled, or we're asked to stop,
|
||||
* then cancel any pending transmits.
|
||||
*/
|
||||
while (!list_empty(&adap->transmit_queue)) {
|
||||
data = list_first_entry(&adap->transmit_queue,
|
||||
struct cec_data, list);
|
||||
cec_data_cancel(data);
|
||||
}
|
||||
if (adap->transmitting)
|
||||
cec_data_cancel(adap->transmitting);
|
||||
|
||||
/*
|
||||
* Cancel the pending timeout work. We have to unlock
|
||||
* the mutex when flushing the work since
|
||||
* cec_wait_timeout() will take it. This is OK since
|
||||
* no new entries can be added to wait_queue as long
|
||||
* as adap->transmitting is NULL, which it is due to
|
||||
* the cec_data_cancel() above.
|
||||
*/
|
||||
while (!list_empty(&adap->wait_queue)) {
|
||||
data = list_first_entry(&adap->wait_queue,
|
||||
struct cec_data, list);
|
||||
|
||||
if (!cancel_delayed_work(&data->work)) {
|
||||
mutex_unlock(&adap->lock);
|
||||
flush_scheduled_work();
|
||||
mutex_lock(&adap->lock);
|
||||
}
|
||||
cec_data_cancel(data);
|
||||
}
|
||||
if (kthread_should_stop()) {
|
||||
cec_flush(adap);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
@ -410,6 +412,7 @@ int cec_thread_func(void *_adap)
|
|||
struct cec_data, list);
|
||||
list_del_init(&data->list);
|
||||
adap->transmit_queue_sz--;
|
||||
|
||||
/* Make this the current transmitting message */
|
||||
adap->transmitting = data;
|
||||
|
||||
|
@ -603,17 +606,17 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
|
||||
/* Sanity checks */
|
||||
if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
|
||||
dprintk(1, "cec_transmit_msg: invalid length %d\n", msg->len);
|
||||
dprintk(1, "%s: invalid length %d\n", __func__, msg->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (msg->timeout && msg->len == 1) {
|
||||
dprintk(1, "cec_transmit_msg: can't reply for poll msg\n");
|
||||
dprintk(1, "%s: can't reply for poll msg\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
|
||||
if (msg->len == 1) {
|
||||
if (cec_msg_destination(msg) == 0xf) {
|
||||
dprintk(1, "cec_transmit_msg: invalid poll message\n");
|
||||
dprintk(1, "%s: invalid poll message\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
||||
|
@ -634,20 +637,30 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
}
|
||||
if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
|
||||
cec_has_log_addr(adap, cec_msg_destination(msg))) {
|
||||
dprintk(1, "cec_transmit_msg: destination is the adapter itself\n");
|
||||
dprintk(1, "%s: destination is the adapter itself\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (msg->len > 1 && adap->is_configured &&
|
||||
!cec_has_log_addr(adap, cec_msg_initiator(msg))) {
|
||||
dprintk(1, "cec_transmit_msg: initiator has unknown logical address %d\n",
|
||||
cec_msg_initiator(msg));
|
||||
dprintk(1, "%s: initiator has unknown logical address %d\n",
|
||||
__func__, cec_msg_initiator(msg));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!adap->is_configured && !adap->is_configuring)
|
||||
return -ENONET;
|
||||
if (!adap->is_configured && !adap->is_configuring) {
|
||||
if (msg->msg[0] != 0xf0) {
|
||||
dprintk(1, "%s: adapter is unconfigured\n", __func__);
|
||||
return -ENONET;
|
||||
}
|
||||
if (msg->reply) {
|
||||
dprintk(1, "%s: invalid msg->reply\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ)
|
||||
if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) {
|
||||
dprintk(1, "%s: transmit queue full\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
|
@ -659,11 +672,11 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
}
|
||||
|
||||
if (msg->timeout)
|
||||
dprintk(2, "cec_transmit_msg: %*ph (wait for 0x%02x%s)\n",
|
||||
msg->len, msg->msg, msg->reply, !block ? ", nb" : "");
|
||||
dprintk(2, "%s: %*ph (wait for 0x%02x%s)\n",
|
||||
__func__, msg->len, msg->msg, msg->reply, !block ? ", nb" : "");
|
||||
else
|
||||
dprintk(2, "cec_transmit_msg: %*ph%s\n",
|
||||
msg->len, msg->msg, !block ? " (nb)" : "");
|
||||
dprintk(2, "%s: %*ph%s\n",
|
||||
__func__, msg->len, msg->msg, !block ? " (nb)" : "");
|
||||
|
||||
data->msg = *msg;
|
||||
data->fh = fh;
|
||||
|
@ -692,6 +705,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
|
||||
if (fh)
|
||||
list_add_tail(&data->xfer_list, &fh->xfer_list);
|
||||
|
||||
list_add_tail(&data->list, &adap->transmit_queue);
|
||||
adap->transmit_queue_sz++;
|
||||
if (!adap->transmitting)
|
||||
|
@ -1117,6 +1131,7 @@ static void cec_adap_unconfigure(struct cec_adapter *adap)
|
|||
adap->is_configuring = false;
|
||||
adap->is_configured = false;
|
||||
memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
|
||||
cec_flush(adap);
|
||||
wake_up_interruptible(&adap->kthread_waitq);
|
||||
cec_post_state_event(adap);
|
||||
}
|
||||
|
@ -1348,19 +1363,30 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
|
|||
/* Disabling monitor all mode should always succeed */
|
||||
if (adap->monitor_all_cnt)
|
||||
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
mutex_lock(&adap->devnode.lock);
|
||||
if (list_empty(&adap->devnode.fhs))
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
if (phys_addr == CEC_PHYS_ADDR_INVALID)
|
||||
return;
|
||||
}
|
||||
|
||||
if (adap->ops->adap_enable(adap, true))
|
||||
mutex_lock(&adap->devnode.lock);
|
||||
if (list_empty(&adap->devnode.fhs) &&
|
||||
adap->ops->adap_enable(adap, true)) {
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (adap->monitor_all_cnt &&
|
||||
call_op(adap, adap_monitor_all_enable, true)) {
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
if (list_empty(&adap->devnode.fhs))
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&adap->devnode.lock);
|
||||
|
||||
adap->phys_addr = phys_addr;
|
||||
cec_post_state_event(adap);
|
||||
if (adap->log_addrs.num_log_addrs)
|
||||
|
@ -1435,12 +1461,16 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
|||
* within the correct range.
|
||||
*/
|
||||
if (log_addrs->vendor_id != CEC_VENDOR_ID_NONE &&
|
||||
(log_addrs->vendor_id & 0xff000000) != 0)
|
||||
(log_addrs->vendor_id & 0xff000000) != 0) {
|
||||
dprintk(1, "invalid vendor ID\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (log_addrs->cec_version != CEC_OP_CEC_VERSION_1_4 &&
|
||||
log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0)
|
||||
log_addrs->cec_version != CEC_OP_CEC_VERSION_2_0) {
|
||||
dprintk(1, "invalid CEC version\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (log_addrs->num_log_addrs > 1)
|
||||
for (i = 0; i < log_addrs->num_log_addrs; i++)
|
||||
|
@ -1585,6 +1615,9 @@ static int cec_feature_abort_reason(struct cec_adapter *adap,
|
|||
*/
|
||||
if (msg->msg[1] == CEC_MSG_FEATURE_ABORT)
|
||||
return 0;
|
||||
/* Don't Feature Abort messages from 'Unregistered' */
|
||||
if (cec_msg_initiator(msg) == CEC_LOG_ADDR_UNREGISTERED)
|
||||
return 0;
|
||||
cec_msg_set_reply_to(&tx_msg, msg);
|
||||
cec_msg_feature_abort(&tx_msg, msg->msg[1], reason);
|
||||
return cec_transmit_msg(adap, &tx_msg, false);
|
||||
|
@ -1699,7 +1732,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
!(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU))
|
||||
break;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
switch (msg->msg[2]) {
|
||||
/*
|
||||
* Play function, this message can have variable length
|
||||
|
@ -1736,7 +1769,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg,
|
|||
if (!(adap->capabilities & CEC_CAP_RC) ||
|
||||
!(adap->log_addrs.flags & CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU))
|
||||
break;
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
rc_keyup(adap->rc);
|
||||
#endif
|
||||
break;
|
||||
|
|
|
@ -198,7 +198,11 @@ static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
|
|||
return -EINVAL;
|
||||
|
||||
mutex_lock(&adap->lock);
|
||||
if (!adap->is_configured)
|
||||
if (adap->log_addrs.num_log_addrs == 0)
|
||||
err = -EPERM;
|
||||
else if (adap->is_configuring)
|
||||
err = -ENONET;
|
||||
else if (!adap->is_configured && msg.msg[0] != 0xf0)
|
||||
err = -ENONET;
|
||||
else if (cec_is_busy(adap, fh))
|
||||
err = -EBUSY;
|
||||
|
@ -515,9 +519,18 @@ static int cec_open(struct inode *inode, struct file *filp)
|
|||
return err;
|
||||
}
|
||||
|
||||
mutex_lock(&devnode->lock);
|
||||
if (list_empty(&devnode->fhs) &&
|
||||
adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
||||
err = adap->ops->adap_enable(adap, true);
|
||||
if (err) {
|
||||
mutex_unlock(&devnode->lock);
|
||||
kfree(fh);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
filp->private_data = fh;
|
||||
|
||||
mutex_lock(&devnode->lock);
|
||||
/* Queue up initial state events */
|
||||
ev_state.state_change.phys_addr = adap->phys_addr;
|
||||
ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
|
||||
|
@ -551,6 +564,10 @@ static int cec_release(struct inode *inode, struct file *filp)
|
|||
|
||||
mutex_lock(&devnode->lock);
|
||||
list_del(&fh->list);
|
||||
if (list_empty(&devnode->fhs) &&
|
||||
adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
|
||||
WARN_ON(adap->ops->adap_enable(adap, false));
|
||||
}
|
||||
mutex_unlock(&devnode->lock);
|
||||
|
||||
/* Unhook pending transmits from this filehandle. */
|
||||
|
|
|
@ -187,6 +187,24 @@ static void cec_devnode_unregister(struct cec_devnode *devnode)
|
|||
put_device(&devnode->dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEDIA_CEC_NOTIFIER
|
||||
static void cec_cec_notify(struct cec_adapter *adap, u16 pa)
|
||||
{
|
||||
cec_s_phys_addr(adap, pa, false);
|
||||
}
|
||||
|
||||
void cec_register_cec_notifier(struct cec_adapter *adap,
|
||||
struct cec_notifier *notifier)
|
||||
{
|
||||
if (WARN_ON(!adap->devnode.registered))
|
||||
return;
|
||||
|
||||
adap->notifier = notifier;
|
||||
cec_notifier_register(adap->notifier, adap, cec_cec_notify);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_register_cec_notifier);
|
||||
#endif
|
||||
|
||||
struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
||||
void *priv, const char *name, u32 caps,
|
||||
u8 available_las)
|
||||
|
@ -194,6 +212,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
|||
struct cec_adapter *adap;
|
||||
int res;
|
||||
|
||||
#ifndef CONFIG_MEDIA_CEC_RC
|
||||
caps &= ~CEC_CAP_RC;
|
||||
#endif
|
||||
|
||||
if (WARN_ON(!caps))
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (WARN_ON(!ops))
|
||||
|
@ -226,10 +248,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
|||
return ERR_PTR(res);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
if (!(caps & CEC_CAP_RC))
|
||||
return adap;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
/* Prepare the RC input device */
|
||||
adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE);
|
||||
if (!adap->rc) {
|
||||
|
@ -256,8 +278,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
|
|||
adap->rc->priv = adap;
|
||||
adap->rc->map_name = RC_MAP_CEC;
|
||||
adap->rc->timeout = MS_TO_NS(100);
|
||||
#else
|
||||
adap->capabilities &= ~CEC_CAP_RC;
|
||||
#endif
|
||||
return adap;
|
||||
}
|
||||
|
@ -277,9 +297,9 @@ int cec_register_adapter(struct cec_adapter *adap,
|
|||
adap->owner = parent->driver->owner;
|
||||
adap->devnode.dev.parent = parent;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
adap->rc->dev.parent = parent;
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
if (adap->capabilities & CEC_CAP_RC) {
|
||||
adap->rc->dev.parent = parent;
|
||||
res = rc_register_device(adap->rc);
|
||||
|
||||
if (res) {
|
||||
|
@ -294,7 +314,7 @@ int cec_register_adapter(struct cec_adapter *adap,
|
|||
|
||||
res = cec_devnode_register(&adap->devnode, adap->owner);
|
||||
if (res) {
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
/* Note: rc_unregister also calls rc_free */
|
||||
rc_unregister_device(adap->rc);
|
||||
adap->rc = NULL;
|
||||
|
@ -329,12 +349,16 @@ void cec_unregister_adapter(struct cec_adapter *adap)
|
|||
if (IS_ERR_OR_NULL(adap))
|
||||
return;
|
||||
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
/* Note: rc_unregister also calls rc_free */
|
||||
rc_unregister_device(adap->rc);
|
||||
adap->rc = NULL;
|
||||
#endif
|
||||
debugfs_remove_recursive(adap->cec_dir);
|
||||
#ifdef CONFIG_MEDIA_CEC_NOTIFIER
|
||||
if (adap->notifier)
|
||||
cec_notifier_unregister(adap->notifier);
|
||||
#endif
|
||||
cec_devnode_unregister(&adap->devnode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_unregister_adapter);
|
||||
|
@ -349,7 +373,7 @@ void cec_delete_adapter(struct cec_adapter *adap)
|
|||
kthread_stop(adap->kthread);
|
||||
if (adap->kthread_config)
|
||||
kthread_stop(adap->kthread_config);
|
||||
#if IS_REACHABLE(CONFIG_RC_CORE)
|
||||
#ifdef CONFIG_MEDIA_CEC_RC
|
||||
rc_free_device(adap->rc);
|
||||
#endif
|
||||
kfree(adap);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <media/cec-edid.h>
|
||||
#include <media/cec.h>
|
||||
|
||||
/*
|
||||
* This EDID is expected to be a CEA-861 compliant, which means that there are
|
||||
|
@ -165,7 +165,3 @@ int cec_phys_addr_validate(u16 phys_addr, u16 *parent, u16 *port)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_phys_addr_validate);
|
||||
|
||||
MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
|
||||
MODULE_DESCRIPTION("CEC EDID helper functions");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* cec-notifier.c - notify CEC drivers of physical address changes
|
||||
*
|
||||
* Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
|
||||
* Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
|
||||
*
|
||||
* This program is free software; you may redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kref.h>
|
||||
|
||||
#include <media/cec.h>
|
||||
#include <media/cec-notifier.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
struct cec_notifier {
|
||||
struct mutex lock;
|
||||
struct list_head head;
|
||||
struct kref kref;
|
||||
struct device *dev;
|
||||
struct cec_adapter *cec_adap;
|
||||
void (*callback)(struct cec_adapter *adap, u16 pa);
|
||||
|
||||
u16 phys_addr;
|
||||
};
|
||||
|
||||
static LIST_HEAD(cec_notifiers);
|
||||
static DEFINE_MUTEX(cec_notifiers_lock);
|
||||
|
||||
struct cec_notifier *cec_notifier_get(struct device *dev)
|
||||
{
|
||||
struct cec_notifier *n;
|
||||
|
||||
mutex_lock(&cec_notifiers_lock);
|
||||
list_for_each_entry(n, &cec_notifiers, head) {
|
||||
if (n->dev == dev) {
|
||||
kref_get(&n->kref);
|
||||
mutex_unlock(&cec_notifiers_lock);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
n = kzalloc(sizeof(*n), GFP_KERNEL);
|
||||
if (!n)
|
||||
goto unlock;
|
||||
n->dev = dev;
|
||||
n->phys_addr = CEC_PHYS_ADDR_INVALID;
|
||||
mutex_init(&n->lock);
|
||||
kref_init(&n->kref);
|
||||
list_add_tail(&n->head, &cec_notifiers);
|
||||
unlock:
|
||||
mutex_unlock(&cec_notifiers_lock);
|
||||
return n;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_get);
|
||||
|
||||
static void cec_notifier_release(struct kref *kref)
|
||||
{
|
||||
struct cec_notifier *n =
|
||||
container_of(kref, struct cec_notifier, kref);
|
||||
|
||||
list_del(&n->head);
|
||||
kfree(n);
|
||||
}
|
||||
|
||||
void cec_notifier_put(struct cec_notifier *n)
|
||||
{
|
||||
mutex_lock(&cec_notifiers_lock);
|
||||
kref_put(&n->kref, cec_notifier_release);
|
||||
mutex_unlock(&cec_notifiers_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_put);
|
||||
|
||||
void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa)
|
||||
{
|
||||
mutex_lock(&n->lock);
|
||||
n->phys_addr = pa;
|
||||
if (n->callback)
|
||||
n->callback(n->cec_adap, n->phys_addr);
|
||||
mutex_unlock(&n->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr);
|
||||
|
||||
void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n,
|
||||
const struct edid *edid)
|
||||
{
|
||||
u16 pa = CEC_PHYS_ADDR_INVALID;
|
||||
|
||||
if (edid && edid->extensions)
|
||||
pa = cec_get_edid_phys_addr((const u8 *)edid,
|
||||
EDID_LENGTH * (edid->extensions + 1), NULL);
|
||||
cec_notifier_set_phys_addr(n, pa);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr_from_edid);
|
||||
|
||||
void cec_notifier_register(struct cec_notifier *n,
|
||||
struct cec_adapter *adap,
|
||||
void (*callback)(struct cec_adapter *adap, u16 pa))
|
||||
{
|
||||
kref_get(&n->kref);
|
||||
mutex_lock(&n->lock);
|
||||
n->cec_adap = adap;
|
||||
n->callback = callback;
|
||||
n->callback(adap, n->phys_addr);
|
||||
mutex_unlock(&n->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_register);
|
||||
|
||||
void cec_notifier_unregister(struct cec_notifier *n)
|
||||
{
|
||||
mutex_lock(&n->lock);
|
||||
n->callback = NULL;
|
||||
mutex_unlock(&n->lock);
|
||||
cec_notifier_put(n);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cec_notifier_unregister);
|
|
@ -473,7 +473,7 @@ static int airstar_atsc1_attach(struct flexcop_device *fc,
|
|||
|
||||
/* AirStar ATSC 2nd generation */
|
||||
#if FE_SUPPORTED(NXT200X) && FE_SUPPORTED(PLL)
|
||||
static struct nxt200x_config samsung_tbmv_config = {
|
||||
static const struct nxt200x_config samsung_tbmv_config = {
|
||||
.demod_address = 0x0a,
|
||||
};
|
||||
|
||||
|
|
|
@ -365,9 +365,8 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
|
||||
INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
|
||||
|
||||
init_timer(&vv->vbi_dmaq.timeout);
|
||||
vv->vbi_dmaq.timeout.function = saa7146_buffer_timeout;
|
||||
vv->vbi_dmaq.timeout.data = (unsigned long)(&vv->vbi_dmaq);
|
||||
setup_timer(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout,
|
||||
(unsigned long)(&vv->vbi_dmaq));
|
||||
vv->vbi_dmaq.dev = dev;
|
||||
|
||||
init_waitqueue_head(&vv->vbi_wq);
|
||||
|
|
|
@ -1201,9 +1201,8 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
{
|
||||
INIT_LIST_HEAD(&vv->video_dmaq.queue);
|
||||
|
||||
init_timer(&vv->video_dmaq.timeout);
|
||||
vv->video_dmaq.timeout.function = saa7146_buffer_timeout;
|
||||
vv->video_dmaq.timeout.data = (unsigned long)(&vv->video_dmaq);
|
||||
setup_timer(&vv->video_dmaq.timeout, saa7146_buffer_timeout,
|
||||
(unsigned long)(&vv->video_dmaq));
|
||||
vv->video_dmaq.dev = dev;
|
||||
|
||||
/* set some default values */
|
||||
|
|
|
@ -420,8 +420,8 @@ static int hasRadioTuner(int tunerType)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee,
|
||||
unsigned char *eeprom_data)
|
||||
void tveeprom_hauppauge_analog(struct tveeprom *tvee,
|
||||
unsigned char *eeprom_data)
|
||||
{
|
||||
/* ----------------------------------------------
|
||||
** The hauppauge eeprom format is tagged
|
||||
|
|
|
@ -927,7 +927,14 @@ static void precalculate_color(struct tpg_data *tpg, int k)
|
|||
y >>= 4;
|
||||
cb >>= 4;
|
||||
cr >>= 4;
|
||||
if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
|
||||
/*
|
||||
* XV601/709 use the header/footer margins to encode R', G'
|
||||
* and B' values outside the range [0-1]. So do not clamp
|
||||
* XV601/709 values.
|
||||
*/
|
||||
if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE &&
|
||||
tpg->real_ycbcr_enc != V4L2_YCBCR_ENC_XV601 &&
|
||||
tpg->real_ycbcr_enc != V4L2_YCBCR_ENC_XV709) {
|
||||
y = clamp(y, 16, 235);
|
||||
cb = clamp(cb, 16, 240);
|
||||
cr = clamp(cr, 16, 240);
|
||||
|
|
|
@ -785,6 +785,29 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * b
|
|||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* It may need some time for the CAM to settle down, or there might
|
||||
* be a race condition between the CAM, writing HC and our last
|
||||
* check for DA. This happens, if the CAM asserts DA, just after
|
||||
* checking DA before we are setting HC. In this case it might be
|
||||
* a bug in the CAM to keep the FR bit, the lower layer/HW
|
||||
* communication requires a longer timeout or the CAM needs more
|
||||
* time internally. But this happens in reality!
|
||||
* We need to read the status from the HW again and do the same
|
||||
* we did for the previous check for DA
|
||||
*/
|
||||
status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
|
||||
if (status < 0)
|
||||
goto exit;
|
||||
|
||||
if (status & (STATUSREG_DA | STATUSREG_RE)) {
|
||||
if (status & STATUSREG_DA)
|
||||
dvb_ca_en50221_thread_wakeup(ca);
|
||||
|
||||
status = -EAGAIN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* send the amount of data */
|
||||
if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
|
||||
goto exit;
|
||||
|
|
|
@ -643,6 +643,8 @@ struct dtv_frontend_properties {
|
|||
/**
|
||||
* struct dvb_frontend - Frontend structure to be used on drivers.
|
||||
*
|
||||
* @refcount: refcount to keep track of struct dvb_frontend
|
||||
* references
|
||||
* @ops: embedded struct dvb_frontend_ops
|
||||
* @dvb: pointer to struct dvb_adapter
|
||||
* @demodulator_priv: demod private data
|
||||
|
|
|
@ -3852,7 +3852,9 @@ static struct dvb_frontend_ops cxd2841er_t_c_ops = {
|
|||
FE_CAN_MUTE_TS |
|
||||
FE_CAN_2G_MODULATION,
|
||||
.frequency_min = 42000000,
|
||||
.frequency_max = 1002000000
|
||||
.frequency_max = 1002000000,
|
||||
.symbol_rate_min = 870000,
|
||||
.symbol_rate_max = 11700000
|
||||
},
|
||||
.init = cxd2841er_init_tc,
|
||||
.sleep = cxd2841er_sleep_tc,
|
||||
|
|
|
@ -1904,7 +1904,9 @@ static int get_lock_status(struct drxk_state *state, u32 *p_lock_status)
|
|||
status = get_dvbt_lock_status(state, p_lock_status);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
pr_debug("Unsupported operation mode %d in %s\n",
|
||||
state->m_operation_mode, __func__);
|
||||
return 0;
|
||||
}
|
||||
error:
|
||||
if (status < 0)
|
||||
|
|
|
@ -28,8 +28,9 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||
struct i2c_client *client = fe->demodulator_priv;
|
||||
struct mn88472_dev *dev = i2c_get_clientdata(client);
|
||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||
int ret;
|
||||
unsigned int utmp;
|
||||
int ret, i, stmp;
|
||||
unsigned int utmp, utmp1, utmp2;
|
||||
u8 buf[5];
|
||||
|
||||
if (!dev->active) {
|
||||
ret = -EAGAIN;
|
||||
|
@ -77,6 +78,127 @@ static int mn88472_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* Signal strength */
|
||||
if (*status & FE_HAS_SIGNAL) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
ret = regmap_bulk_read(dev->regmap[2], 0x8e + i,
|
||||
&buf[i], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
utmp1 = buf[0] << 8 | buf[1] << 0 | buf[0] >> 2;
|
||||
dev_dbg(&client->dev, "strength=%u\n", utmp1);
|
||||
|
||||
c->strength.stat[0].scale = FE_SCALE_RELATIVE;
|
||||
c->strength.stat[0].uvalue = utmp1;
|
||||
} else {
|
||||
c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* CNR */
|
||||
if (*status & FE_HAS_VITERBI && c->delivery_system == SYS_DVBT) {
|
||||
/* DVB-T CNR */
|
||||
ret = regmap_bulk_read(dev->regmap[0], 0x9c, buf, 2);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
utmp = buf[0] << 8 | buf[1] << 0;
|
||||
if (utmp) {
|
||||
/* CNR[dB]: 10 * log10(65536 / value) + 2 */
|
||||
/* log10(65536) = 80807124, 0.2 = 3355443 */
|
||||
stmp = ((u64)80807124 - intlog10(utmp) + 3355443)
|
||||
* 10000 >> 24;
|
||||
|
||||
dev_dbg(&client->dev, "cnr=%d value=%u\n", stmp, utmp);
|
||||
} else {
|
||||
stmp = 0;
|
||||
}
|
||||
|
||||
c->cnr.stat[0].svalue = stmp;
|
||||
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
} else if (*status & FE_HAS_VITERBI &&
|
||||
c->delivery_system == SYS_DVBT2) {
|
||||
/* DVB-T2 CNR */
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = regmap_bulk_read(dev->regmap[2], 0xbc + i,
|
||||
&buf[i], 1);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
utmp = buf[1] << 8 | buf[2] << 0;
|
||||
utmp1 = (buf[0] >> 2) & 0x01; /* 0=SISO, 1=MISO */
|
||||
if (utmp) {
|
||||
if (utmp1) {
|
||||
/* CNR[dB]: 10 * log10(16384 / value) - 6 */
|
||||
/* log10(16384) = 70706234, 0.6 = 10066330 */
|
||||
stmp = ((u64)70706234 - intlog10(utmp)
|
||||
- 10066330) * 10000 >> 24;
|
||||
dev_dbg(&client->dev, "cnr=%d value=%u MISO\n",
|
||||
stmp, utmp);
|
||||
} else {
|
||||
/* CNR[dB]: 10 * log10(65536 / value) + 2 */
|
||||
/* log10(65536) = 80807124, 0.2 = 3355443 */
|
||||
stmp = ((u64)80807124 - intlog10(utmp)
|
||||
+ 3355443) * 10000 >> 24;
|
||||
|
||||
dev_dbg(&client->dev, "cnr=%d value=%u SISO\n",
|
||||
stmp, utmp);
|
||||
}
|
||||
} else {
|
||||
stmp = 0;
|
||||
}
|
||||
|
||||
c->cnr.stat[0].svalue = stmp;
|
||||
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
} else if (*status & FE_HAS_VITERBI &&
|
||||
c->delivery_system == SYS_DVBC_ANNEX_A) {
|
||||
/* DVB-C CNR */
|
||||
ret = regmap_bulk_read(dev->regmap[1], 0xa1, buf, 4);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
utmp1 = buf[0] << 8 | buf[1] << 0; /* signal */
|
||||
utmp2 = buf[2] << 8 | buf[3] << 0; /* noise */
|
||||
if (utmp1 && utmp2) {
|
||||
/* CNR[dB]: 10 * log10(8 * (signal / noise)) */
|
||||
/* log10(8) = 15151336 */
|
||||
stmp = ((u64)15151336 + intlog10(utmp1)
|
||||
- intlog10(utmp2)) * 10000 >> 24;
|
||||
|
||||
dev_dbg(&client->dev, "cnr=%d signal=%u noise=%u\n",
|
||||
stmp, utmp1, utmp2);
|
||||
} else {
|
||||
stmp = 0;
|
||||
}
|
||||
|
||||
c->cnr.stat[0].svalue = stmp;
|
||||
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
|
||||
} else {
|
||||
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* PER */
|
||||
if (*status & FE_HAS_SYNC) {
|
||||
ret = regmap_bulk_read(dev->regmap[0], 0xe1, buf, 4);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
utmp1 = buf[0] << 8 | buf[1] << 0;
|
||||
utmp2 = buf[2] << 8 | buf[3] << 0;
|
||||
dev_dbg(&client->dev, "block_error=%u block_count=%u\n",
|
||||
utmp1, utmp2);
|
||||
|
||||
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_error.stat[0].uvalue += utmp1;
|
||||
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
|
||||
c->block_count.stat[0].uvalue += utmp2;
|
||||
} else {
|
||||
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dev_dbg(&client->dev, "failed=%d\n", ret);
|
||||
|
@ -462,6 +584,7 @@ static int mn88472_probe(struct i2c_client *client,
|
|||
{
|
||||
struct mn88472_config *pdata = client->dev.platform_data;
|
||||
struct mn88472_dev *dev;
|
||||
struct dtv_frontend_properties *c;
|
||||
int ret;
|
||||
unsigned int utmp;
|
||||
static const struct regmap_config regmap_config = {
|
||||
|
@ -547,6 +670,13 @@ static int mn88472_probe(struct i2c_client *client,
|
|||
*pdata->fe = &dev->fe;
|
||||
i2c_set_clientdata(client, dev);
|
||||
|
||||
/* Init stats to indicate which stats are supported */
|
||||
c = &dev->fe.dtv_property_cache;
|
||||
c->strength.len = 1;
|
||||
c->cnr.len = 1;
|
||||
c->block_error.len = 1;
|
||||
c->block_count.len = 1;
|
||||
|
||||
/* Setup callbacks */
|
||||
pdata->get_dvb_frontend = mn88472_get_dvb_frontend;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define MN88472_PRIV_H
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
#include "mn88472.h"
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/regmap.h>
|
||||
|
|
|
@ -740,6 +740,9 @@ static int si2168_probe(struct i2c_client *client,
|
|||
case SI2168_CHIP_ID_B40:
|
||||
dev->firmware_name = SI2168_B40_FIRMWARE;
|
||||
break;
|
||||
case SI2168_CHIP_ID_D60:
|
||||
dev->firmware_name = SI2168_D60_FIRMWARE;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(&client->dev, "unknown chip version Si21%d-%c%c%c\n",
|
||||
cmd.args[2], cmd.args[1], cmd.args[3], cmd.args[4]);
|
||||
|
@ -827,3 +830,4 @@ MODULE_LICENSE("GPL");
|
|||
MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_B40_FIRMWARE);
|
||||
MODULE_FIRMWARE(SI2168_D60_FIRMWARE);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw"
|
||||
#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
|
||||
#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
|
||||
#define SI2168_D60_FIRMWARE "dvb-demod-si2168-d60-01.fw"
|
||||
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
|
||||
|
||||
/* state struct */
|
||||
|
@ -38,6 +39,7 @@ struct si2168_dev {
|
|||
#define SI2168_CHIP_ID_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
|
||||
#define SI2168_CHIP_ID_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
|
||||
#define SI2168_CHIP_ID_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
|
||||
#define SI2168_CHIP_ID_D60 ('D' << 24 | 68 << 16 | '6' << 8 | '0' << 0)
|
||||
unsigned int chip_id;
|
||||
unsigned int version;
|
||||
const char *firmware_name;
|
||||
|
|
|
@ -209,7 +209,6 @@ config VIDEO_ADV7604
|
|||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
select HDMI
|
||||
select MEDIA_CEC_EDID
|
||||
---help---
|
||||
Support for the Analog Devices ADV7604 video decoder.
|
||||
|
||||
|
@ -221,7 +220,7 @@ config VIDEO_ADV7604
|
|||
|
||||
config VIDEO_ADV7604_CEC
|
||||
bool "Enable Analog Devices ADV7604 CEC support"
|
||||
depends on VIDEO_ADV7604 && MEDIA_CEC_SUPPORT
|
||||
depends on VIDEO_ADV7604 && CEC_CORE
|
||||
---help---
|
||||
When selected the adv7604 will support the optional
|
||||
HDMI CEC feature.
|
||||
|
@ -230,7 +229,6 @@ config VIDEO_ADV7842
|
|||
tristate "Analog Devices ADV7842 decoder"
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
select HDMI
|
||||
select MEDIA_CEC_EDID
|
||||
---help---
|
||||
Support for the Analog Devices ADV7842 video decoder.
|
||||
|
||||
|
@ -242,7 +240,7 @@ config VIDEO_ADV7842
|
|||
|
||||
config VIDEO_ADV7842_CEC
|
||||
bool "Enable Analog Devices ADV7842 CEC support"
|
||||
depends on VIDEO_ADV7842 && MEDIA_CEC_SUPPORT
|
||||
depends on VIDEO_ADV7842 && CEC_CORE
|
||||
---help---
|
||||
When selected the adv7842 will support the optional
|
||||
HDMI CEC feature.
|
||||
|
@ -470,7 +468,6 @@ config VIDEO_ADV7511
|
|||
tristate "Analog Devices ADV7511 encoder"
|
||||
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
|
||||
select HDMI
|
||||
select MEDIA_CEC_EDID
|
||||
---help---
|
||||
Support for the Analog Devices ADV7511 video encoder.
|
||||
|
||||
|
@ -481,7 +478,7 @@ config VIDEO_ADV7511
|
|||
|
||||
config VIDEO_ADV7511_CEC
|
||||
bool "Enable Analog Devices ADV7511 CEC support"
|
||||
depends on VIDEO_ADV7511 && MEDIA_CEC_SUPPORT
|
||||
depends on VIDEO_ADV7511 && CEC_CORE
|
||||
---help---
|
||||
When selected the adv7511 will support the optional
|
||||
HDMI CEC feature.
|
||||
|
@ -520,6 +517,17 @@ config VIDEO_APTINA_PLL
|
|||
config VIDEO_SMIAPP_PLL
|
||||
tristate
|
||||
|
||||
config VIDEO_OV2640
|
||||
tristate "OmniVision OV2640 sensor support"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
help
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV2640 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov2640.
|
||||
|
||||
config VIDEO_OV2659
|
||||
tristate "OmniVision OV2659 sensor support"
|
||||
depends on VIDEO_V4L2 && I2C
|
||||
|
@ -531,6 +539,29 @@ config VIDEO_OV2659
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov2659.
|
||||
|
||||
config VIDEO_OV5645
|
||||
tristate "OmniVision OV5645 sensor support"
|
||||
depends on OF
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV5645 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov5645.
|
||||
|
||||
config VIDEO_OV5647
|
||||
tristate "OmniVision OV5647 sensor support"
|
||||
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
depends on MEDIA_CAMERA_SUPPORT
|
||||
---help---
|
||||
This is a Video4Linux2 sensor-level driver for the OmniVision
|
||||
OV5647 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov5647.
|
||||
|
||||
config VIDEO_OV7640
|
||||
tristate "OmniVision OV7640 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
|
|
|
@ -57,6 +57,9 @@ obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
|
|||
obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
|
||||
obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
|
||||
obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
|
||||
obj-$(CONFIG_VIDEO_OV2640) += ov2640.o
|
||||
obj-$(CONFIG_VIDEO_OV5645) += ov5645.o
|
||||
obj-$(CONFIG_VIDEO_OV5647) += ov5647.o
|
||||
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
|
||||
|
|
|
@ -336,7 +336,7 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int __exit ad5820_remove(struct i2c_client *client)
|
||||
static int ad5820_remove(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
|
||||
struct ad5820_device *coil = to_ad5820_device(subdev);
|
||||
|
@ -362,7 +362,7 @@ static struct i2c_driver ad5820_i2c_driver = {
|
|||
.pm = &ad5820_pm,
|
||||
},
|
||||
.probe = ad5820_probe,
|
||||
.remove = __exit_p(ad5820_remove),
|
||||
.remove = ad5820_remove,
|
||||
.id_table = ad5820_id_table,
|
||||
};
|
||||
|
||||
|
|
|
@ -734,7 +734,7 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on)
|
|||
#if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
|
||||
static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
{
|
||||
struct adv7511_state *state = adap->priv;
|
||||
struct adv7511_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
|
||||
if (state->i2c_cec == NULL)
|
||||
|
@ -769,7 +769,7 @@ static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
|||
|
||||
static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
||||
{
|
||||
struct adv7511_state *state = adap->priv;
|
||||
struct adv7511_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
unsigned int i, free_idx = ADV7511_MAX_ADDRS;
|
||||
|
||||
|
@ -824,7 +824,7 @@ static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
|||
static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg)
|
||||
{
|
||||
struct adv7511_state *state = adap->priv;
|
||||
struct adv7511_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
u8 len = msg->len;
|
||||
unsigned int i;
|
||||
|
|
|
@ -2050,7 +2050,7 @@ static void adv76xx_cec_isr(struct v4l2_subdev *sd, bool *handled)
|
|||
|
||||
static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
{
|
||||
struct adv76xx_state *state = adap->priv;
|
||||
struct adv76xx_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
|
||||
if (!state->cec_enabled_adap && enable) {
|
||||
|
@ -2080,7 +2080,7 @@ static int adv76xx_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
|||
|
||||
static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
||||
{
|
||||
struct adv76xx_state *state = adap->priv;
|
||||
struct adv76xx_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
unsigned int i, free_idx = ADV76XX_MAX_ADDRS;
|
||||
|
||||
|
@ -2135,7 +2135,7 @@ static int adv76xx_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
|||
static int adv76xx_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg)
|
||||
{
|
||||
struct adv76xx_state *state = adap->priv;
|
||||
struct adv76xx_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
u8 len = msg->len;
|
||||
unsigned int i;
|
||||
|
|
|
@ -2250,7 +2250,7 @@ static void adv7842_cec_isr(struct v4l2_subdev *sd, bool *handled)
|
|||
|
||||
static int adv7842_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
||||
{
|
||||
struct adv7842_state *state = adap->priv;
|
||||
struct adv7842_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
|
||||
if (!state->cec_enabled_adap && enable) {
|
||||
|
@ -2279,7 +2279,7 @@ static int adv7842_cec_adap_enable(struct cec_adapter *adap, bool enable)
|
|||
|
||||
static int adv7842_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
||||
{
|
||||
struct adv7842_state *state = adap->priv;
|
||||
struct adv7842_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
unsigned int i, free_idx = ADV7842_MAX_ADDRS;
|
||||
|
||||
|
@ -2334,7 +2334,7 @@ static int adv7842_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
|
|||
static int adv7842_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
|
||||
u32 signal_free_time, struct cec_msg *msg)
|
||||
{
|
||||
struct adv7842_state *state = adap->priv;
|
||||
struct adv7842_state *state = cec_get_drvdata(adap);
|
||||
struct v4l2_subdev *sd = &state->sd;
|
||||
u8 len = msg->len;
|
||||
unsigned int i;
|
||||
|
|
|
@ -1485,6 +1485,7 @@ static const struct of_device_id et8ek8_of_table[] = {
|
|||
{ .compatible = "toshiba,et8ek8" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, et8ek8_of_table);
|
||||
|
||||
static const struct i2c_device_id et8ek8_id_table[] = {
|
||||
{ ET8EK8_NAME, 0 },
|
||||
|
@ -1495,6 +1496,7 @@ MODULE_DEVICE_TABLE(i2c, et8ek8_id_table);
|
|||
static const struct dev_pm_ops et8ek8_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(et8ek8_suspend, et8ek8_resume)
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, et8ek8_of_table);
|
||||
|
||||
static struct i2c_driver et8ek8_i2c_driver = {
|
||||
.driver = {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio.h>
|
||||
|
@ -24,8 +25,7 @@
|
|||
#include <linux/v4l2-mediabus.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/soc_camera.h>
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
|
@ -106,6 +106,10 @@
|
|||
#define CTRL1_AWB_GAIN 0x04
|
||||
#define CTRL1_LENC 0x02
|
||||
#define CTRL1_PRE 0x01
|
||||
/* REG 0xC7 (unknown name): affects Auto White Balance (AWB)
|
||||
* AWB_OFF 0x40
|
||||
* AWB_SIMPLE 0x10
|
||||
* AWB_ON 0x00 (Advanced AWB ?) */
|
||||
#define R_DVP_SP 0xD3 /* DVP output speed control */
|
||||
#define R_DVP_SP_AUTO_MODE 0x80
|
||||
#define R_DVP_SP_DVP_MASK 0x3F /* DVP PCLK = sysclk (48)/[6:0] (YUV0);
|
||||
|
@ -199,7 +203,7 @@
|
|||
#define COM7_ZOOM_EN 0x04 /* Enable Zoom mode */
|
||||
#define COM7_COLOR_BAR_TEST 0x02 /* Enable Color Bar Test Pattern */
|
||||
#define COM8 0x13 /* Common control 8 */
|
||||
#define COM8_DEF 0xC0 /* Banding filter ON/OFF */
|
||||
#define COM8_DEF 0xC0
|
||||
#define COM8_BNDF_EN 0x20 /* Banding filter ON/OFF */
|
||||
#define COM8_AGC_EN 0x04 /* AGC Auto/Manual control selection */
|
||||
#define COM8_AEC_EN 0x01 /* Auto/Manual Exposure control */
|
||||
|
@ -248,8 +252,19 @@
|
|||
#define ZOOMS 0x49 /* Zoom: Vertical start point */
|
||||
#define COM22 0x4B /* Flash light control */
|
||||
#define COM25 0x4E /* For Banding operations */
|
||||
#define COM25_50HZ_BANDING_AEC_MSBS_MASK 0xC0 /* 50Hz Bd. AEC 2 MSBs */
|
||||
#define COM25_60HZ_BANDING_AEC_MSBS_MASK 0x30 /* 60Hz Bd. AEC 2 MSBs */
|
||||
#define COM25_50HZ_BANDING_AEC_MSBS_SET(x) VAL_SET(x, 0x3, 8, 6)
|
||||
#define COM25_60HZ_BANDING_AEC_MSBS_SET(x) VAL_SET(x, 0x3, 8, 4)
|
||||
#define BD50 0x4F /* 50Hz Banding AEC 8 LSBs */
|
||||
#define BD50_50HZ_BANDING_AEC_LSBS_SET(x) VAL_SET(x, 0xFF, 0, 0)
|
||||
#define BD60 0x50 /* 60Hz Banding AEC 8 LSBs */
|
||||
#define BD60_60HZ_BANDING_AEC_LSBS_SET(x) VAL_SET(x, 0xFF, 0, 0)
|
||||
#define REG5A 0x5A /* 50/60Hz Banding Maximum AEC Step */
|
||||
#define BD50_MAX_AEC_STEP_MASK 0xF0 /* 50Hz Banding Max. AEC Step */
|
||||
#define BD60_MAX_AEC_STEP_MASK 0x0F /* 60Hz Banding Max. AEC Step */
|
||||
#define BD50_MAX_AEC_STEP_SET(x) VAL_SET((x - 1), 0x0F, 0, 4)
|
||||
#define BD60_MAX_AEC_STEP_SET(x) VAL_SET((x - 1), 0x0F, 0, 0)
|
||||
#define REG5D 0x5D /* AVGsel[7:0], 16-zone average weight option */
|
||||
#define REG5E 0x5E /* AVGsel[15:8], 16-zone average weight option */
|
||||
#define REG5F 0x5F /* AVGsel[23:16], 16-zone average weight option */
|
||||
|
@ -282,12 +297,14 @@ struct ov2640_win_size {
|
|||
|
||||
struct ov2640_priv {
|
||||
struct v4l2_subdev subdev;
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
struct media_pad pad;
|
||||
#endif
|
||||
struct v4l2_ctrl_handler hdl;
|
||||
u32 cfmt_code;
|
||||
struct v4l2_clk *clk;
|
||||
struct clk *clk;
|
||||
const struct ov2640_win_size *win;
|
||||
|
||||
struct soc_camera_subdev_desc ssdd_dt;
|
||||
struct gpio_desc *resetb_gpio;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
};
|
||||
|
@ -304,11 +321,11 @@ static const struct regval_list ov2640_init_regs[] = {
|
|||
{ 0x2e, 0xdf },
|
||||
{ BANK_SEL, BANK_SEL_SENS },
|
||||
{ 0x3c, 0x32 },
|
||||
{ CLKRC, CLKRC_DIV_SET(1) },
|
||||
{ COM2, COM2_OCAP_Nx_SET(3) },
|
||||
{ REG04, REG04_DEF | REG04_HREF_EN },
|
||||
{ COM8, COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN },
|
||||
{ COM9, COM9_AGC_GAIN_8x | 0x08},
|
||||
{ CLKRC, CLKRC_DIV_SET(1) },
|
||||
{ COM2, COM2_OCAP_Nx_SET(3) },
|
||||
{ REG04, REG04_DEF | REG04_HREF_EN },
|
||||
{ COM8, COM8_DEF | COM8_BNDF_EN | COM8_AGC_EN | COM8_AEC_EN },
|
||||
{ COM9, COM9_AGC_GAIN_8x | 0x08},
|
||||
{ 0x2c, 0x0c },
|
||||
{ 0x33, 0x78 },
|
||||
{ 0x3a, 0x33 },
|
||||
|
@ -353,25 +370,28 @@ static const struct regval_list ov2640_init_regs[] = {
|
|||
{ 0x71, 0x94 },
|
||||
{ 0x73, 0xc1 },
|
||||
{ 0x3d, 0x34 },
|
||||
{ COM7, COM7_RES_UXGA | COM7_ZOOM_EN },
|
||||
{ 0x5a, 0x57 },
|
||||
{ BD50, 0xbb },
|
||||
{ BD60, 0x9c },
|
||||
{ BANK_SEL, BANK_SEL_DSP },
|
||||
{ COM7, COM7_RES_UXGA | COM7_ZOOM_EN },
|
||||
{ REG5A, BD50_MAX_AEC_STEP_SET(6)
|
||||
| BD60_MAX_AEC_STEP_SET(8) }, /* 0x57 */
|
||||
{ COM25, COM25_50HZ_BANDING_AEC_MSBS_SET(0x0bb)
|
||||
| COM25_60HZ_BANDING_AEC_MSBS_SET(0x09c) }, /* 0x00 */
|
||||
{ BD50, BD50_50HZ_BANDING_AEC_LSBS_SET(0x0bb) }, /* 0xbb */
|
||||
{ BD60, BD60_60HZ_BANDING_AEC_LSBS_SET(0x09c) }, /* 0x9c */
|
||||
{ BANK_SEL, BANK_SEL_DSP },
|
||||
{ 0xe5, 0x7f },
|
||||
{ MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },
|
||||
{ MC_BIST, MC_BIST_RESET | MC_BIST_BOOT_ROM_SEL },
|
||||
{ 0x41, 0x24 },
|
||||
{ RESET, RESET_JPEG | RESET_DVP },
|
||||
{ RESET, RESET_JPEG | RESET_DVP },
|
||||
{ 0x76, 0xff },
|
||||
{ 0x33, 0xa0 },
|
||||
{ 0x42, 0x20 },
|
||||
{ 0x43, 0x18 },
|
||||
{ 0x4c, 0x00 },
|
||||
{ CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },
|
||||
{ CTRL3, CTRL3_BPC_EN | CTRL3_WPC_EN | 0x10 },
|
||||
{ 0x88, 0x3f },
|
||||
{ 0xd7, 0x03 },
|
||||
{ 0xd9, 0x10 },
|
||||
{ R_DVP_SP , R_DVP_SP_AUTO_MODE | 0x2 },
|
||||
{ R_DVP_SP, R_DVP_SP_AUTO_MODE | 0x2 },
|
||||
{ 0xc8, 0x08 },
|
||||
{ 0xc9, 0x80 },
|
||||
{ BPADDR, 0x00 },
|
||||
|
@ -433,7 +453,7 @@ static const struct regval_list ov2640_init_regs[] = {
|
|||
{ 0xc5, 0x11 },
|
||||
{ 0xc6, 0x51 },
|
||||
{ 0xbf, 0x80 },
|
||||
{ 0xc7, 0x10 },
|
||||
{ 0xc7, 0x10 }, /* simple AWB */
|
||||
{ 0xb6, 0x66 },
|
||||
{ 0xb8, 0xA5 },
|
||||
{ 0xb7, 0x64 },
|
||||
|
@ -480,6 +500,9 @@ static const struct regval_list ov2640_init_regs[] = {
|
|||
static const struct regval_list ov2640_size_change_preamble_regs[] = {
|
||||
{ BANK_SEL, BANK_SEL_DSP },
|
||||
{ RESET, RESET_DVP },
|
||||
{ SIZEL, SIZEL_HSIZE8_11_SET(UXGA_WIDTH) |
|
||||
SIZEL_HSIZE8_SET(UXGA_WIDTH) |
|
||||
SIZEL_VSIZE8_SET(UXGA_HEIGHT) },
|
||||
{ HSIZE8, HSIZE8_SET(UXGA_WIDTH) },
|
||||
{ VSIZE8, VSIZE8_SET(UXGA_HEIGHT) },
|
||||
{ CTRL2, CTRL2_DCW_EN | CTRL2_SDE_EN |
|
||||
|
@ -611,6 +634,8 @@ static const struct regval_list ov2640_rgb565_le_regs[] = {
|
|||
static u32 ov2640_codes[] = {
|
||||
MEDIA_BUS_FMT_YUYV8_2X8,
|
||||
MEDIA_BUS_FMT_UYVY8_2X8,
|
||||
MEDIA_BUS_FMT_YVYU8_2X8,
|
||||
MEDIA_BUS_FMT_VYUY8_2X8,
|
||||
MEDIA_BUS_FMT_RGB565_2X8_BE,
|
||||
MEDIA_BUS_FMT_RGB565_2X8_LE,
|
||||
};
|
||||
|
@ -677,13 +702,8 @@ err:
|
|||
}
|
||||
|
||||
/*
|
||||
* soc_camera_ops functions
|
||||
* functions
|
||||
*/
|
||||
static int ov2640_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct v4l2_subdev *sd =
|
||||
|
@ -698,8 +718,10 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_VFLIP:
|
||||
val = ctrl->val ? REG04_VFLIP_IMG : 0x00;
|
||||
return ov2640_mask_set(client, REG04, REG04_VFLIP_IMG, val);
|
||||
val = ctrl->val ? REG04_VFLIP_IMG | REG04_VREF_EN : 0x00;
|
||||
return ov2640_mask_set(client, REG04,
|
||||
REG04_VFLIP_IMG | REG04_VREF_EN, val);
|
||||
/* NOTE: REG04_VREF_EN: 1 line shift / even/odd line swap */
|
||||
case V4L2_CID_HFLIP:
|
||||
val = ctrl->val ? REG04_HFLIP_IMG : 0x00;
|
||||
return ov2640_mask_set(client, REG04, REG04_HFLIP_IMG, val);
|
||||
|
@ -743,41 +765,46 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
|
|||
|
||||
static int ov2640_s_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
|
||||
if (priv->pwdn_gpio)
|
||||
gpiod_direction_output(priv->pwdn_gpio, !on);
|
||||
if (on && priv->resetb_gpio) {
|
||||
/* Active the resetb pin to perform a reset pulse */
|
||||
gpiod_direction_output(priv->resetb_gpio, 1);
|
||||
usleep_range(3000, 5000);
|
||||
gpiod_set_value(priv->resetb_gpio, 0);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Select the nearest higher resolution for capture */
|
||||
static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
|
||||
static const struct ov2640_win_size *ov2640_select_win(u32 width, u32 height)
|
||||
{
|
||||
int i, default_size = ARRAY_SIZE(ov2640_supported_win_sizes) - 1;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ov2640_supported_win_sizes); i++) {
|
||||
if (ov2640_supported_win_sizes[i].width >= *width &&
|
||||
ov2640_supported_win_sizes[i].height >= *height) {
|
||||
*width = ov2640_supported_win_sizes[i].width;
|
||||
*height = ov2640_supported_win_sizes[i].height;
|
||||
if (ov2640_supported_win_sizes[i].width >= width &&
|
||||
ov2640_supported_win_sizes[i].height >= height)
|
||||
return &ov2640_supported_win_sizes[i];
|
||||
}
|
||||
}
|
||||
|
||||
*width = ov2640_supported_win_sizes[default_size].width;
|
||||
*height = ov2640_supported_win_sizes[default_size].height;
|
||||
return &ov2640_supported_win_sizes[default_size];
|
||||
}
|
||||
|
||||
static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
|
||||
u32 code)
|
||||
static int ov2640_set_params(struct i2c_client *client,
|
||||
const struct ov2640_win_size *win, u32 code)
|
||||
{
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
const struct regval_list *selected_cfmt_regs;
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
/* select win */
|
||||
priv->win = ov2640_select_win(width, height);
|
||||
priv->win = win;
|
||||
|
||||
/* select format */
|
||||
priv->cfmt_code = 0;
|
||||
|
@ -794,10 +821,19 @@ static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
|
|||
dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
|
||||
selected_cfmt_regs = ov2640_yuyv_regs;
|
||||
break;
|
||||
default:
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
default:
|
||||
dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
|
||||
selected_cfmt_regs = ov2640_uyvy_regs;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_YVYU8_2X8:
|
||||
dev_dbg(&client->dev, "%s: Selected cfmt YVYU", __func__);
|
||||
selected_cfmt_regs = ov2640_yuyv_regs;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_VYUY8_2X8:
|
||||
dev_dbg(&client->dev, "%s: Selected cfmt VYUY", __func__);
|
||||
selected_cfmt_regs = ov2640_uyvy_regs;
|
||||
break;
|
||||
}
|
||||
|
||||
/* reset hardware */
|
||||
|
@ -828,12 +864,15 @@ static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
|
|||
|
||||
/* set cfmt */
|
||||
ret = ov2640_write_array(client, selected_cfmt_regs);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
val = (code == MEDIA_BUS_FMT_YVYU8_2X8)
|
||||
|| (code == MEDIA_BUS_FMT_VYUY8_2X8) ? CTRL0_VFIRST : 0x00;
|
||||
ret = ov2640_mask_set(client, CTRL0, CTRL0_VFIRST, val);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
priv->cfmt_code = code;
|
||||
*width = priv->win->width;
|
||||
*height = priv->win->height;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -857,25 +896,14 @@ static int ov2640_get_fmt(struct v4l2_subdev *sd,
|
|||
return -EINVAL;
|
||||
|
||||
if (!priv->win) {
|
||||
u32 width = SVGA_WIDTH, height = SVGA_HEIGHT;
|
||||
priv->win = ov2640_select_win(&width, &height);
|
||||
priv->win = ov2640_select_win(SVGA_WIDTH, SVGA_HEIGHT);
|
||||
priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
|
||||
}
|
||||
|
||||
mf->width = priv->win->width;
|
||||
mf->height = priv->win->height;
|
||||
mf->code = priv->cfmt_code;
|
||||
|
||||
switch (mf->code) {
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_BE:
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_LE:
|
||||
mf->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
break;
|
||||
default:
|
||||
case MEDIA_BUS_FMT_YUYV8_2X8:
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
mf->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
}
|
||||
mf->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
mf->field = V4L2_FIELD_NONE;
|
||||
|
||||
return 0;
|
||||
|
@ -887,32 +915,34 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
|
|||
{
|
||||
struct v4l2_mbus_framefmt *mf = &format->format;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
const struct ov2640_win_size *win;
|
||||
|
||||
if (format->pad)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* select suitable win, but don't store it
|
||||
*/
|
||||
ov2640_select_win(&mf->width, &mf->height);
|
||||
/* select suitable win */
|
||||
win = ov2640_select_win(mf->width, mf->height);
|
||||
mf->width = win->width;
|
||||
mf->height = win->height;
|
||||
|
||||
mf->field = V4L2_FIELD_NONE;
|
||||
mf->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
|
||||
switch (mf->code) {
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_BE:
|
||||
case MEDIA_BUS_FMT_RGB565_2X8_LE:
|
||||
mf->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
case MEDIA_BUS_FMT_YUYV8_2X8:
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
case MEDIA_BUS_FMT_YVYU8_2X8:
|
||||
case MEDIA_BUS_FMT_VYUY8_2X8:
|
||||
break;
|
||||
default:
|
||||
mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
|
||||
case MEDIA_BUS_FMT_YUYV8_2X8:
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
mf->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
return ov2640_set_params(client, &mf->width,
|
||||
&mf->height, mf->code);
|
||||
return ov2640_set_params(client, win, mf->code);
|
||||
cfg->try_fmt = *mf;
|
||||
return 0;
|
||||
}
|
||||
|
@ -995,7 +1025,7 @@ static const struct v4l2_ctrl_ops ov2640_ctrl_ops = {
|
|||
.s_ctrl = ov2640_s_ctrl,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
|
||||
static const struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = ov2640_g_register,
|
||||
.s_register = ov2640_s_register,
|
||||
|
@ -1003,26 +1033,6 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
|
|||
.s_power = ov2640_s_power,
|
||||
};
|
||||
|
||||
static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
|
||||
struct v4l2_mbus_config *cfg)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
|
||||
|
||||
cfg->flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
|
||||
V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_HIGH |
|
||||
V4L2_MBUS_DATA_ACTIVE_HIGH;
|
||||
cfg->type = V4L2_MBUS_PARALLEL;
|
||||
cfg->flags = soc_camera_apply_board_flags(ssdd, cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
|
||||
.s_stream = ov2640_s_stream,
|
||||
.g_mbus_config = ov2640_g_mbus_config,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
|
||||
.enum_mbus_code = ov2640_enum_mbus_code,
|
||||
.get_selection = ov2640_get_selection,
|
||||
|
@ -1030,65 +1040,43 @@ static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
|
|||
.set_fmt = ov2640_set_fmt,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops ov2640_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops ov2640_subdev_ops = {
|
||||
.core = &ov2640_subdev_core_ops,
|
||||
.video = &ov2640_subdev_video_ops,
|
||||
.pad = &ov2640_subdev_pad_ops,
|
||||
};
|
||||
|
||||
/* OF probe functions */
|
||||
static int ov2640_hw_power(struct device *dev, int on)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
dev_dbg(&client->dev, "%s: %s the camera\n",
|
||||
__func__, on ? "ENABLE" : "DISABLE");
|
||||
|
||||
if (priv->pwdn_gpio)
|
||||
gpiod_direction_output(priv->pwdn_gpio, !on);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov2640_hw_reset(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
if (priv->resetb_gpio) {
|
||||
/* Active the resetb pin to perform a reset pulse */
|
||||
gpiod_direction_output(priv->resetb_gpio, 1);
|
||||
usleep_range(3000, 5000);
|
||||
gpiod_direction_output(priv->resetb_gpio, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov2640_probe_dt(struct i2c_client *client,
|
||||
struct ov2640_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Request the reset GPIO deasserted */
|
||||
priv->resetb_gpio = devm_gpiod_get_optional(&client->dev, "resetb",
|
||||
GPIOD_OUT_LOW);
|
||||
|
||||
if (!priv->resetb_gpio)
|
||||
dev_dbg(&client->dev, "resetb gpio is not assigned!\n");
|
||||
else if (IS_ERR(priv->resetb_gpio))
|
||||
return PTR_ERR(priv->resetb_gpio);
|
||||
|
||||
ret = PTR_ERR_OR_ZERO(priv->resetb_gpio);
|
||||
if (ret && ret != -ENOSYS) {
|
||||
dev_dbg(&client->dev,
|
||||
"Error %d while getting resetb gpio\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Request the power down GPIO asserted */
|
||||
priv->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "pwdn",
|
||||
GPIOD_OUT_HIGH);
|
||||
|
||||
if (!priv->pwdn_gpio)
|
||||
dev_dbg(&client->dev, "pwdn gpio is not assigned!\n");
|
||||
else if (IS_ERR(priv->pwdn_gpio))
|
||||
return PTR_ERR(priv->pwdn_gpio);
|
||||
|
||||
/* Initialize the soc_camera_subdev_desc */
|
||||
priv->ssdd_dt.power = ov2640_hw_power;
|
||||
priv->ssdd_dt.reset = ov2640_hw_reset;
|
||||
client->dev.platform_data = &priv->ssdd_dt;
|
||||
ret = PTR_ERR_OR_ZERO(priv->pwdn_gpio);
|
||||
if (ret && ret != -ENOSYS) {
|
||||
dev_dbg(&client->dev,
|
||||
"Error %d while getting pwdn gpio\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1100,7 +1088,6 @@ static int ov2640_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *did)
|
||||
{
|
||||
struct ov2640_priv *priv;
|
||||
struct soc_camera_subdev_desc *ssdd = soc_camera_i2c_to_desc(client);
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
int ret;
|
||||
|
||||
|
@ -1117,23 +1104,19 @@ static int ov2640_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->clk = v4l2_clk_get(&client->dev, "xvclk");
|
||||
if (IS_ERR(priv->clk))
|
||||
return -EPROBE_DEFER;
|
||||
if (client->dev.of_node) {
|
||||
priv->clk = devm_clk_get(&client->dev, "xvclk");
|
||||
if (IS_ERR(priv->clk))
|
||||
return -EPROBE_DEFER;
|
||||
clk_prepare_enable(priv->clk);
|
||||
}
|
||||
|
||||
if (!ssdd && !client->dev.of_node) {
|
||||
dev_err(&client->dev, "Missing platform_data for driver\n");
|
||||
ret = -EINVAL;
|
||||
ret = ov2640_probe_dt(client, priv);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
if (!ssdd) {
|
||||
ret = ov2640_probe_dt(client, priv);
|
||||
if (ret)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
|
||||
priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
v4l2_ctrl_handler_init(&priv->hdl, 2);
|
||||
v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
|
||||
V4L2_CID_VFLIP, 0, 1, 1, 0);
|
||||
|
@ -1142,8 +1125,15 @@ static int ov2640_probe(struct i2c_client *client,
|
|||
priv->subdev.ctrl_handler = &priv->hdl;
|
||||
if (priv->hdl.error) {
|
||||
ret = priv->hdl.error;
|
||||
goto err_clk;
|
||||
goto err_hdl;
|
||||
}
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
priv->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
priv->subdev.entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
ret = media_entity_pads_init(&priv->subdev.entity, 1, &priv->pad);
|
||||
if (ret < 0)
|
||||
goto err_hdl;
|
||||
#endif
|
||||
|
||||
ret = ov2640_video_probe(client);
|
||||
if (ret < 0)
|
||||
|
@ -1158,9 +1148,13 @@ static int ov2640_probe(struct i2c_client *client,
|
|||
return 0;
|
||||
|
||||
err_videoprobe:
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
media_entity_cleanup(&priv->subdev.entity);
|
||||
#endif
|
||||
err_hdl:
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
err_clk:
|
||||
v4l2_clk_put(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1169,9 +1163,12 @@ static int ov2640_remove(struct i2c_client *client)
|
|||
struct ov2640_priv *priv = to_ov2640(client);
|
||||
|
||||
v4l2_async_unregister_subdev(&priv->subdev);
|
||||
v4l2_clk_put(priv->clk);
|
||||
v4l2_device_unregister_subdev(&priv->subdev);
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
media_entity_cleanup(&priv->subdev.entity);
|
||||
#endif
|
||||
v4l2_device_unregister_subdev(&priv->subdev);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1199,6 +1196,6 @@ static struct i2c_driver ov2640_i2c_driver = {
|
|||
|
||||
module_i2c_driver(ov2640_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SoC Camera driver for Omni Vision 2640 sensor");
|
||||
MODULE_DESCRIPTION("Driver for Omni Vision 2640 sensor");
|
||||
MODULE_AUTHOR("Alberto Panizzo");
|
||||
MODULE_LICENSE("GPL v2");
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,634 @@
|
|||
/*
|
||||
* A V4L2 driver for OmniVision OV5647 cameras.
|
||||
*
|
||||
* Based on Samsung S5K6AAFX SXGA 1/6" 1.3M CMOS Image Sensor driver
|
||||
* Copyright (C) 2011 Sylwester Nawrocki <s.nawrocki@samsung.com>
|
||||
*
|
||||
* Based on Omnivision OV7670 Camera Driver
|
||||
* Copyright (C) 2006-7 Jonathan Corbet <corbet@lwn.net>
|
||||
*
|
||||
* Copyright (C) 2016, Synopsys, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed .as is. WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-image-sizes.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
#include <media/v4l2-of.h>
|
||||
|
||||
#define SENSOR_NAME "ov5647"
|
||||
|
||||
#define OV5647_SW_RESET 0x0103
|
||||
#define OV5647_REG_CHIPID_H 0x300A
|
||||
#define OV5647_REG_CHIPID_L 0x300B
|
||||
|
||||
#define REG_TERM 0xfffe
|
||||
#define VAL_TERM 0xfe
|
||||
#define REG_DLY 0xffff
|
||||
|
||||
#define OV5647_ROW_START 0x01
|
||||
#define OV5647_ROW_START_MIN 0
|
||||
#define OV5647_ROW_START_MAX 2004
|
||||
#define OV5647_ROW_START_DEF 54
|
||||
|
||||
#define OV5647_COLUMN_START 0x02
|
||||
#define OV5647_COLUMN_START_MIN 0
|
||||
#define OV5647_COLUMN_START_MAX 2750
|
||||
#define OV5647_COLUMN_START_DEF 16
|
||||
|
||||
#define OV5647_WINDOW_HEIGHT 0x03
|
||||
#define OV5647_WINDOW_HEIGHT_MIN 2
|
||||
#define OV5647_WINDOW_HEIGHT_MAX 2006
|
||||
#define OV5647_WINDOW_HEIGHT_DEF 1944
|
||||
|
||||
#define OV5647_WINDOW_WIDTH 0x04
|
||||
#define OV5647_WINDOW_WIDTH_MIN 2
|
||||
#define OV5647_WINDOW_WIDTH_MAX 2752
|
||||
#define OV5647_WINDOW_WIDTH_DEF 2592
|
||||
|
||||
struct regval_list {
|
||||
u16 addr;
|
||||
u8 data;
|
||||
};
|
||||
|
||||
struct ov5647 {
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
struct mutex lock;
|
||||
struct v4l2_mbus_framefmt format;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
int power_count;
|
||||
struct clk *xclk;
|
||||
};
|
||||
|
||||
static inline struct ov5647 *to_state(struct v4l2_subdev *sd)
|
||||
{
|
||||
return container_of(sd, struct ov5647, sd);
|
||||
}
|
||||
|
||||
static struct regval_list sensor_oe_disable_regs[] = {
|
||||
{0x3000, 0x00},
|
||||
{0x3001, 0x00},
|
||||
{0x3002, 0x00},
|
||||
};
|
||||
|
||||
static struct regval_list sensor_oe_enable_regs[] = {
|
||||
{0x3000, 0x0f},
|
||||
{0x3001, 0xff},
|
||||
{0x3002, 0xe4},
|
||||
};
|
||||
|
||||
static struct regval_list ov5647_640x480[] = {
|
||||
{0x0100, 0x00},
|
||||
{0x0103, 0x01},
|
||||
{0x3034, 0x08},
|
||||
{0x3035, 0x21},
|
||||
{0x3036, 0x46},
|
||||
{0x303c, 0x11},
|
||||
{0x3106, 0xf5},
|
||||
{0x3821, 0x07},
|
||||
{0x3820, 0x41},
|
||||
{0x3827, 0xec},
|
||||
{0x370c, 0x0f},
|
||||
{0x3612, 0x59},
|
||||
{0x3618, 0x00},
|
||||
{0x5000, 0x06},
|
||||
{0x5001, 0x01},
|
||||
{0x5002, 0x41},
|
||||
{0x5003, 0x08},
|
||||
{0x5a00, 0x08},
|
||||
{0x3000, 0x00},
|
||||
{0x3001, 0x00},
|
||||
{0x3002, 0x00},
|
||||
{0x3016, 0x08},
|
||||
{0x3017, 0xe0},
|
||||
{0x3018, 0x44},
|
||||
{0x301c, 0xf8},
|
||||
{0x301d, 0xf0},
|
||||
{0x3a18, 0x00},
|
||||
{0x3a19, 0xf8},
|
||||
{0x3c01, 0x80},
|
||||
{0x3b07, 0x0c},
|
||||
{0x380c, 0x07},
|
||||
{0x380d, 0x68},
|
||||
{0x380e, 0x03},
|
||||
{0x380f, 0xd8},
|
||||
{0x3814, 0x31},
|
||||
{0x3815, 0x31},
|
||||
{0x3708, 0x64},
|
||||
{0x3709, 0x52},
|
||||
{0x3808, 0x02},
|
||||
{0x3809, 0x80},
|
||||
{0x380a, 0x01},
|
||||
{0x380b, 0xE0},
|
||||
{0x3801, 0x00},
|
||||
{0x3802, 0x00},
|
||||
{0x3803, 0x00},
|
||||
{0x3804, 0x0a},
|
||||
{0x3805, 0x3f},
|
||||
{0x3806, 0x07},
|
||||
{0x3807, 0xa1},
|
||||
{0x3811, 0x08},
|
||||
{0x3813, 0x02},
|
||||
{0x3630, 0x2e},
|
||||
{0x3632, 0xe2},
|
||||
{0x3633, 0x23},
|
||||
{0x3634, 0x44},
|
||||
{0x3636, 0x06},
|
||||
{0x3620, 0x64},
|
||||
{0x3621, 0xe0},
|
||||
{0x3600, 0x37},
|
||||
{0x3704, 0xa0},
|
||||
{0x3703, 0x5a},
|
||||
{0x3715, 0x78},
|
||||
{0x3717, 0x01},
|
||||
{0x3731, 0x02},
|
||||
{0x370b, 0x60},
|
||||
{0x3705, 0x1a},
|
||||
{0x3f05, 0x02},
|
||||
{0x3f06, 0x10},
|
||||
{0x3f01, 0x0a},
|
||||
{0x3a08, 0x01},
|
||||
{0x3a09, 0x27},
|
||||
{0x3a0a, 0x00},
|
||||
{0x3a0b, 0xf6},
|
||||
{0x3a0d, 0x04},
|
||||
{0x3a0e, 0x03},
|
||||
{0x3a0f, 0x58},
|
||||
{0x3a10, 0x50},
|
||||
{0x3a1b, 0x58},
|
||||
{0x3a1e, 0x50},
|
||||
{0x3a11, 0x60},
|
||||
{0x3a1f, 0x28},
|
||||
{0x4001, 0x02},
|
||||
{0x4004, 0x02},
|
||||
{0x4000, 0x09},
|
||||
{0x4837, 0x24},
|
||||
{0x4050, 0x6e},
|
||||
{0x4051, 0x8f},
|
||||
{0x0100, 0x01},
|
||||
};
|
||||
|
||||
static int ov5647_write(struct v4l2_subdev *sd, u16 reg, u8 val)
|
||||
{
|
||||
int ret;
|
||||
unsigned char data[3] = { reg >> 8, reg & 0xff, val};
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
ret = i2c_master_send(client, data, 3);
|
||||
if (ret < 0)
|
||||
dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
|
||||
__func__, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov5647_read(struct v4l2_subdev *sd, u16 reg, u8 *val)
|
||||
{
|
||||
int ret;
|
||||
unsigned char data_w[2] = { reg >> 8, reg & 0xff };
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
ret = i2c_master_send(client, data_w, 2);
|
||||
if (ret < 0) {
|
||||
dev_dbg(&client->dev, "%s: i2c write error, reg: %x\n",
|
||||
__func__, reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = i2c_master_recv(client, val, 1);
|
||||
if (ret < 0)
|
||||
dev_dbg(&client->dev, "%s: i2c read error, reg: %x\n",
|
||||
__func__, reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov5647_write_array(struct v4l2_subdev *sd,
|
||||
struct regval_list *regs, int array_size)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < array_size; i++) {
|
||||
ret = ov5647_write(sd, regs[i].addr, regs[i].data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov5647_set_virtual_channel(struct v4l2_subdev *sd, int channel)
|
||||
{
|
||||
u8 channel_id;
|
||||
int ret;
|
||||
|
||||
ret = ov5647_read(sd, 0x4814, &channel_id);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
channel_id &= ~(3 << 6);
|
||||
return ov5647_write(sd, 0x4814, channel_id | (channel << 6));
|
||||
}
|
||||
|
||||
static int ov5647_stream_on(struct v4l2_subdev *sd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov5647_write(sd, 0x4202, 0x00);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ov5647_write(sd, 0x300D, 0x00);
|
||||
}
|
||||
|
||||
static int ov5647_stream_off(struct v4l2_subdev *sd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov5647_write(sd, 0x4202, 0x0f);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ov5647_write(sd, 0x300D, 0x01);
|
||||
}
|
||||
|
||||
static int set_sw_standby(struct v4l2_subdev *sd, bool standby)
|
||||
{
|
||||
int ret;
|
||||
u8 rdval;
|
||||
|
||||
ret = ov5647_read(sd, 0x0100, &rdval);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (standby)
|
||||
rdval &= ~0x01;
|
||||
else
|
||||
rdval |= 0x01;
|
||||
|
||||
return ov5647_write(sd, 0x0100, rdval);
|
||||
}
|
||||
|
||||
static int __sensor_init(struct v4l2_subdev *sd)
|
||||
{
|
||||
int ret;
|
||||
u8 resetval, rdval;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
ret = ov5647_read(sd, 0x0100, &rdval);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5647_write_array(sd, ov5647_640x480,
|
||||
ARRAY_SIZE(ov5647_640x480));
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "write sensor default regs error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ov5647_set_virtual_channel(sd, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5647_read(sd, 0x0100, &resetval);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(resetval & 0x01)) {
|
||||
dev_err(&client->dev, "Device was in SW standby");
|
||||
ret = ov5647_write(sd, 0x0100, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ov5647_write(sd, 0x4800, 0x04);
|
||||
}
|
||||
|
||||
static int ov5647_sensor_power(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ov5647 *ov5647 = to_state(sd);
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
mutex_lock(&ov5647->lock);
|
||||
|
||||
if (on && !ov5647->power_count) {
|
||||
dev_dbg(&client->dev, "OV5647 power on\n");
|
||||
|
||||
ret = clk_prepare_enable(ov5647->xclk);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "clk prepare enable failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ov5647_write_array(sd, sensor_oe_enable_regs,
|
||||
ARRAY_SIZE(sensor_oe_enable_regs));
|
||||
if (ret < 0) {
|
||||
clk_disable_unprepare(ov5647->xclk);
|
||||
dev_err(&client->dev,
|
||||
"write sensor_oe_enable_regs error\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __sensor_init(sd);
|
||||
if (ret < 0) {
|
||||
clk_disable_unprepare(ov5647->xclk);
|
||||
dev_err(&client->dev,
|
||||
"Camera not available, check Power\n");
|
||||
goto out;
|
||||
}
|
||||
} else if (!on && ov5647->power_count == 1) {
|
||||
dev_dbg(&client->dev, "OV5647 power off\n");
|
||||
|
||||
ret = ov5647_write_array(sd, sensor_oe_disable_regs,
|
||||
ARRAY_SIZE(sensor_oe_disable_regs));
|
||||
|
||||
if (ret < 0)
|
||||
dev_dbg(&client->dev, "disable oe failed\n");
|
||||
|
||||
ret = set_sw_standby(sd, true);
|
||||
|
||||
if (ret < 0)
|
||||
dev_dbg(&client->dev, "soft stby failed\n");
|
||||
|
||||
clk_disable_unprepare(ov5647->xclk);
|
||||
}
|
||||
|
||||
/* Update the power count. */
|
||||
ov5647->power_count += on ? 1 : -1;
|
||||
WARN_ON(ov5647->power_count < 0);
|
||||
|
||||
out:
|
||||
mutex_unlock(&ov5647->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
static int ov5647_sensor_get_register(struct v4l2_subdev *sd,
|
||||
struct v4l2_dbg_register *reg)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
|
||||
ret = ov5647_read(sd, reg->reg & 0xff, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reg->val = val;
|
||||
reg->size = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov5647_sensor_set_register(struct v4l2_subdev *sd,
|
||||
const struct v4l2_dbg_register *reg)
|
||||
{
|
||||
return ov5647_write(sd, reg->reg & 0xff, reg->val & 0xff);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @short Subdev core operations registration
|
||||
*/
|
||||
static const struct v4l2_subdev_core_ops ov5647_subdev_core_ops = {
|
||||
.s_power = ov5647_sensor_power,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = ov5647_sensor_get_register,
|
||||
.s_register = ov5647_sensor_set_register,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ov5647_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
if (enable)
|
||||
return ov5647_stream_on(sd);
|
||||
else
|
||||
return ov5647_stream_off(sd);
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_video_ops ov5647_subdev_video_ops = {
|
||||
.s_stream = ov5647_s_stream,
|
||||
};
|
||||
|
||||
static int ov5647_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
if (code->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
code->code = MEDIA_BUS_FMT_SBGGR8_1X8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_pad_ops ov5647_subdev_pad_ops = {
|
||||
.enum_mbus_code = ov5647_enum_mbus_code,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops ov5647_subdev_ops = {
|
||||
.core = &ov5647_subdev_core_ops,
|
||||
.video = &ov5647_subdev_video_ops,
|
||||
.pad = &ov5647_subdev_pad_ops,
|
||||
};
|
||||
|
||||
static int ov5647_detect(struct v4l2_subdev *sd)
|
||||
{
|
||||
u8 read;
|
||||
int ret;
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
||||
ret = ov5647_write(sd, OV5647_SW_RESET, 0x01);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ov5647_read(sd, OV5647_REG_CHIPID_H, &read);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (read != 0x56) {
|
||||
dev_err(&client->dev, "ID High expected 0x56 got %x", read);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = ov5647_read(sd, OV5647_REG_CHIPID_L, &read);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (read != 0x47) {
|
||||
dev_err(&client->dev, "ID Low expected 0x47 got %x", read);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return ov5647_write(sd, OV5647_SW_RESET, 0x00);
|
||||
}
|
||||
|
||||
static int ov5647_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *format =
|
||||
v4l2_subdev_get_try_format(sd, fh->pad, 0);
|
||||
struct v4l2_rect *crop =
|
||||
v4l2_subdev_get_try_crop(sd, fh->pad, 0);
|
||||
|
||||
crop->left = OV5647_COLUMN_START_DEF;
|
||||
crop->top = OV5647_ROW_START_DEF;
|
||||
crop->width = OV5647_WINDOW_WIDTH_DEF;
|
||||
crop->height = OV5647_WINDOW_HEIGHT_DEF;
|
||||
|
||||
format->code = MEDIA_BUS_FMT_SBGGR8_1X8;
|
||||
|
||||
format->width = OV5647_WINDOW_WIDTH_DEF;
|
||||
format->height = OV5647_WINDOW_HEIGHT_DEF;
|
||||
format->field = V4L2_FIELD_NONE;
|
||||
format->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
|
||||
.open = ov5647_open,
|
||||
};
|
||||
|
||||
static int ov5647_parse_dt(struct device_node *np)
|
||||
{
|
||||
struct v4l2_of_endpoint bus_cfg;
|
||||
struct device_node *ep;
|
||||
|
||||
int ret;
|
||||
|
||||
ep = of_graph_get_next_endpoint(np, NULL);
|
||||
if (!ep)
|
||||
return -EINVAL;
|
||||
|
||||
ret = v4l2_of_parse_endpoint(ep, &bus_cfg);
|
||||
|
||||
of_node_put(ep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov5647_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct ov5647 *sensor;
|
||||
int ret;
|
||||
struct v4l2_subdev *sd;
|
||||
struct device_node *np = client->dev.of_node;
|
||||
u32 xclk_freq;
|
||||
|
||||
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
|
||||
if (!sensor)
|
||||
return -ENOMEM;
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF) && np) {
|
||||
ret = ov5647_parse_dt(np);
|
||||
if (ret) {
|
||||
dev_err(dev, "DT parsing error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* get system clock (xclk) */
|
||||
sensor->xclk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(sensor->xclk)) {
|
||||
dev_err(dev, "could not get xclk");
|
||||
return PTR_ERR(sensor->xclk);
|
||||
}
|
||||
|
||||
xclk_freq = clk_get_rate(sensor->xclk);
|
||||
if (xclk_freq != 25000000) {
|
||||
dev_err(dev, "Unsupported clock frequency: %u\n", xclk_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_init(&sensor->lock);
|
||||
|
||||
sd = &sensor->sd;
|
||||
v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops);
|
||||
sensor->sd.internal_ops = &ov5647_subdev_internal_ops;
|
||||
sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
|
||||
sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
|
||||
ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad);
|
||||
if (ret < 0)
|
||||
goto mutex_remove;
|
||||
|
||||
ret = ov5647_detect(sd);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = v4l2_async_register_subdev(sd);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
dev_dbg(dev, "OmniVision OV5647 camera driver probed\n");
|
||||
return 0;
|
||||
error:
|
||||
media_entity_cleanup(&sd->entity);
|
||||
mutex_remove:
|
||||
mutex_destroy(&sensor->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ov5647_remove(struct i2c_client *client)
|
||||
{
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct ov5647 *ov5647 = to_state(sd);
|
||||
|
||||
v4l2_async_unregister_subdev(&ov5647->sd);
|
||||
media_entity_cleanup(&ov5647->sd.entity);
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
mutex_destroy(&ov5647->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id ov5647_id[] = {
|
||||
{ "ov5647", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ov5647_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id ov5647_of_match[] = {
|
||||
{ .compatible = "ovti,ov5647" },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ov5647_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver ov5647_driver = {
|
||||
.driver = {
|
||||
.of_match_table = of_match_ptr(ov5647_of_match),
|
||||
.name = SENSOR_NAME,
|
||||
},
|
||||
.probe = ov5647_probe,
|
||||
.remove = ov5647_remove,
|
||||
.id_table = ov5647_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(ov5647_driver);
|
||||
|
||||
MODULE_AUTHOR("Ramiro Oliveira <roliveir@synopsys.com>");
|
||||
MODULE_DESCRIPTION("A low-level driver for OmniVision ov5647 sensors");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -10,12 +10,15 @@
|
|||
* This file may be distributed under the terms of the GNU General
|
||||
* Public License, version 2.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-mediabus.h>
|
||||
|
@ -227,6 +230,9 @@ struct ov7670_info {
|
|||
struct v4l2_ctrl *hue;
|
||||
};
|
||||
struct ov7670_format_struct *fmt; /* Current format */
|
||||
struct clk *clk;
|
||||
struct gpio_desc *resetb_gpio;
|
||||
struct gpio_desc *pwdn_gpio;
|
||||
int min_width; /* Filter out smaller sizes */
|
||||
int min_height; /* Filter out smaller sizes */
|
||||
int clock_speed; /* External clock speed (MHz) */
|
||||
|
@ -589,8 +595,6 @@ static int ov7670_init(struct v4l2_subdev *sd, u32 val)
|
|||
return ov7670_write_array(sd, ov7670_default_regs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ov7670_detect(struct v4l2_subdev *sd)
|
||||
{
|
||||
unsigned char v;
|
||||
|
@ -1046,7 +1050,6 @@ static int ov7670_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
|
|||
if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
|
||||
memset(cp, 0, sizeof(struct v4l2_captureparm));
|
||||
cp->capability = V4L2_CAP_TIMEPERFRAME;
|
||||
info->devtype->get_framerate(sd, &cp->timeperframe);
|
||||
|
||||
|
@ -1061,9 +1064,8 @@ static int ov7670_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
|
|||
|
||||
if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
if (cp->extendedmode != 0)
|
||||
return -EINVAL;
|
||||
|
||||
cp->capability = V4L2_CAP_TIMEPERFRAME;
|
||||
return info->devtype->set_framerate(sd, tpf);
|
||||
}
|
||||
|
||||
|
@ -1549,6 +1551,27 @@ static const struct ov7670_devtype ov7670_devdata[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static int ov7670_init_gpio(struct i2c_client *client, struct ov7670_info *info)
|
||||
{
|
||||
info->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(info->pwdn_gpio)) {
|
||||
dev_info(&client->dev, "can't get %s GPIO\n", "powerdown");
|
||||
return PTR_ERR(info->pwdn_gpio);
|
||||
}
|
||||
|
||||
info->resetb_gpio = devm_gpiod_get_optional(&client->dev, "reset",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(info->resetb_gpio)) {
|
||||
dev_info(&client->dev, "can't get %s GPIO\n", "reset");
|
||||
return PTR_ERR(info->resetb_gpio);
|
||||
}
|
||||
|
||||
usleep_range(3000, 5000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov7670_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -1589,13 +1612,28 @@ static int ov7670_probe(struct i2c_client *client,
|
|||
info->pclk_hb_disable = true;
|
||||
}
|
||||
|
||||
info->clk = devm_clk_get(&client->dev, "xclk");
|
||||
if (IS_ERR(info->clk))
|
||||
return -EPROBE_DEFER;
|
||||
clk_prepare_enable(info->clk);
|
||||
|
||||
ret = ov7670_init_gpio(client, info);
|
||||
if (ret)
|
||||
goto clk_disable;
|
||||
|
||||
info->clock_speed = clk_get_rate(info->clk) / 1000000;
|
||||
if (info->clock_speed < 10 || info->clock_speed > 48) {
|
||||
ret = -EINVAL;
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
/* Make sure it's an ov7670 */
|
||||
ret = ov7670_detect(sd);
|
||||
if (ret) {
|
||||
v4l_dbg(1, debug, client,
|
||||
"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
|
||||
client->addr << 1, client->adapter->name);
|
||||
return ret;
|
||||
goto clk_disable;
|
||||
}
|
||||
v4l_info(client, "chip found @ 0x%02x (%s)\n",
|
||||
client->addr << 1, client->adapter->name);
|
||||
|
@ -1636,10 +1674,9 @@ static int ov7670_probe(struct i2c_client *client,
|
|||
V4L2_EXPOSURE_AUTO);
|
||||
sd->ctrl_handler = &info->hdl;
|
||||
if (info->hdl.error) {
|
||||
int err = info->hdl.error;
|
||||
ret = info->hdl.error;
|
||||
|
||||
v4l2_ctrl_handler_free(&info->hdl);
|
||||
return err;
|
||||
goto hdl_free;
|
||||
}
|
||||
/*
|
||||
* We have checked empirically that hw allows to read back the gain
|
||||
|
@ -1651,7 +1688,17 @@ static int ov7670_probe(struct i2c_client *client,
|
|||
v4l2_ctrl_cluster(2, &info->saturation);
|
||||
v4l2_ctrl_handler_setup(&info->hdl);
|
||||
|
||||
ret = v4l2_async_register_subdev(&info->sd);
|
||||
if (ret < 0)
|
||||
goto hdl_free;
|
||||
|
||||
return 0;
|
||||
|
||||
hdl_free:
|
||||
v4l2_ctrl_handler_free(&info->hdl);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(info->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1662,6 +1709,7 @@ static int ov7670_remove(struct i2c_client *client)
|
|||
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
v4l2_ctrl_handler_free(&info->hdl);
|
||||
clk_disable_unprepare(info->clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1672,9 +1720,18 @@ static const struct i2c_device_id ov7670_id[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ov7670_id);
|
||||
|
||||
#if IS_ENABLED(CONFIG_OF)
|
||||
static const struct of_device_id ov7670_of_match[] = {
|
||||
{ .compatible = "ovti,ov7670", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ov7670_of_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver ov7670_driver = {
|
||||
.driver = {
|
||||
.name = "ov7670",
|
||||
.of_match_table = of_match_ptr(ov7670_of_match),
|
||||
},
|
||||
.probe = ov7670_probe,
|
||||
.remove = ov7670_remove,
|
||||
|
|
|
@ -41,12 +41,6 @@ config SOC_CAMERA_MT9V022
|
|||
help
|
||||
This driver supports MT9V022 cameras from Micron
|
||||
|
||||
config SOC_CAMERA_OV2640
|
||||
tristate "ov2640 camera support"
|
||||
depends on SOC_CAMERA && I2C
|
||||
help
|
||||
This is a ov2640 camera driver
|
||||
|
||||
config SOC_CAMERA_OV5642
|
||||
tristate "ov5642 camera support"
|
||||
depends on SOC_CAMERA && I2C
|
||||
|
|
|
@ -3,7 +3,6 @@ obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
|
|||
obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9T112) += mt9t112.o
|
||||
obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV2640) += ov2640.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV5642) += ov5642.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV6650) += ov6650.o
|
||||
obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
|
||||
|
|
|
@ -180,7 +180,7 @@ static int imx074_set_fmt(struct v4l2_subdev *sd,
|
|||
mf->field = V4L2_FIELD_NONE;
|
||||
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
priv->fmt = imx074_find_datafmt(mf->code);
|
||||
priv->fmt = fmt;
|
||||
else
|
||||
cfg->try_fmt = *mf;
|
||||
|
||||
|
@ -271,12 +271,12 @@ static int imx074_g_mbus_config(struct v4l2_subdev *sd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
|
||||
static const struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
|
||||
.s_stream = imx074_s_stream,
|
||||
.g_mbus_config = imx074_g_mbus_config,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
|
||||
static const struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
|
||||
.s_power = imx074_s_power,
|
||||
};
|
||||
|
||||
|
@ -287,7 +287,7 @@ static const struct v4l2_subdev_pad_ops imx074_subdev_pad_ops = {
|
|||
.set_fmt = imx074_set_fmt,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops imx074_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops imx074_subdev_ops = {
|
||||
.core = &imx074_subdev_core_ops,
|
||||
.video = &imx074_subdev_video_ops,
|
||||
.pad = &imx074_subdev_pad_ops,
|
||||
|
|
|
@ -278,6 +278,7 @@ static int mt9m001_get_fmt(struct v4l2_subdev *sd,
|
|||
}
|
||||
|
||||
static int mt9m001_s_fmt(struct v4l2_subdev *sd,
|
||||
const struct mt9m001_datafmt *fmt,
|
||||
struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
|
@ -297,9 +298,8 @@ static int mt9m001_s_fmt(struct v4l2_subdev *sd,
|
|||
if (!ret) {
|
||||
mf->width = mt9m001->rect.width;
|
||||
mf->height = mt9m001->rect.height;
|
||||
mt9m001->fmt = mt9m001_find_datafmt(mf->code,
|
||||
mt9m001->fmts, mt9m001->num_fmts);
|
||||
mf->colorspace = mt9m001->fmt->colorspace;
|
||||
mt9m001->fmt = fmt;
|
||||
mf->colorspace = fmt->colorspace;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -335,7 +335,7 @@ static int mt9m001_set_fmt(struct v4l2_subdev *sd,
|
|||
mf->colorspace = fmt->colorspace;
|
||||
|
||||
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
|
||||
return mt9m001_s_fmt(sd, mf);
|
||||
return mt9m001_s_fmt(sd, fmt, mf);
|
||||
cfg->try_fmt = *mf;
|
||||
return 0;
|
||||
}
|
||||
|
@ -574,7 +574,7 @@ static const struct v4l2_ctrl_ops mt9m001_ctrl_ops = {
|
|||
.s_ctrl = mt9m001_s_ctrl,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
|
||||
static const struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = mt9m001_g_register,
|
||||
.s_register = mt9m001_s_register,
|
||||
|
@ -630,7 +630,7 @@ static int mt9m001_s_mbus_config(struct v4l2_subdev *sd,
|
|||
return bps == 10 ? 0 : -EINVAL;
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
|
||||
static const struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
|
||||
.s_stream = mt9m001_s_stream,
|
||||
.g_mbus_config = mt9m001_g_mbus_config,
|
||||
.s_mbus_config = mt9m001_s_mbus_config,
|
||||
|
@ -648,7 +648,7 @@ static const struct v4l2_subdev_pad_ops mt9m001_subdev_pad_ops = {
|
|||
.set_fmt = mt9m001_set_fmt,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops mt9m001_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops mt9m001_subdev_ops = {
|
||||
.core = &mt9m001_subdev_core_ops,
|
||||
.video = &mt9m001_subdev_video_ops,
|
||||
.sensor = &mt9m001_subdev_sensor_ops,
|
||||
|
|
|
@ -679,7 +679,7 @@ static const struct v4l2_ctrl_ops mt9t031_ctrl_ops = {
|
|||
.s_ctrl = mt9t031_s_ctrl,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
|
||||
static const struct v4l2_subdev_core_ops mt9t031_subdev_core_ops = {
|
||||
.s_power = mt9t031_s_power,
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = mt9t031_g_register,
|
||||
|
@ -726,7 +726,7 @@ static int mt9t031_s_mbus_config(struct v4l2_subdev *sd,
|
|||
return reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
|
||||
static const struct v4l2_subdev_video_ops mt9t031_subdev_video_ops = {
|
||||
.s_stream = mt9t031_s_stream,
|
||||
.g_mbus_config = mt9t031_g_mbus_config,
|
||||
.s_mbus_config = mt9t031_s_mbus_config,
|
||||
|
@ -744,7 +744,7 @@ static const struct v4l2_subdev_pad_ops mt9t031_subdev_pad_ops = {
|
|||
.set_fmt = mt9t031_set_fmt,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops mt9t031_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops mt9t031_subdev_ops = {
|
||||
.core = &mt9t031_subdev_core_ops,
|
||||
.video = &mt9t031_subdev_video_ops,
|
||||
.sensor = &mt9t031_subdev_sensor_ops,
|
||||
|
|
|
@ -773,7 +773,7 @@ static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
|
|||
return soc_camera_set_power(&client->dev, ssdd, priv->clk, on);
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
|
||||
static const struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
|
||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||
.g_register = mt9t112_g_register,
|
||||
.s_register = mt9t112_s_register,
|
||||
|
@ -1031,7 +1031,7 @@ static int mt9t112_s_mbus_config(struct v4l2_subdev *sd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
|
||||
static const struct v4l2_subdev_video_ops mt9t112_subdev_video_ops = {
|
||||
.s_stream = mt9t112_s_stream,
|
||||
.g_mbus_config = mt9t112_g_mbus_config,
|
||||
.s_mbus_config = mt9t112_s_mbus_config,
|
||||
|
@ -1048,7 +1048,7 @@ static const struct v4l2_subdev_pad_ops mt9t112_subdev_pad_ops = {
|
|||
/************************************************************************
|
||||
i2c driver
|
||||
************************************************************************/
|
||||
static struct v4l2_subdev_ops mt9t112_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops mt9t112_subdev_ops = {
|
||||
.core = &mt9t112_subdev_core_ops,
|
||||
.video = &mt9t112_subdev_video_ops,
|
||||
.pad = &mt9t112_subdev_pad_ops,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче