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:
Linus Torvalds 2017-05-05 17:34:57 -07:00
commit e87d51ac61
352 changed files with 14997 additions and 5234 deletions

View file

@ -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>;
};
};
};
};
};

View file

@ -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>;
};
};
};

View file

@ -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>;
};
};
};
};

View file

@ -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>;
};
};
};
};

View file

@ -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>;
};
};
};
};

View file

@ -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>;
};

View file

@ -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";

View file

@ -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

View file

@ -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>;
};

View file

@ -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>;
};
};

View file

@ -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:

View file

@ -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
----------------

View file

@ -1,4 +1,4 @@
Video2Linux devices
Video4Linux devices
-------------------
.. toctree::

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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).

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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
============

View file

@ -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
============

View file

@ -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
============

View file

@ -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

View file

@ -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.

View file

@ -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
============

View file

@ -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`.

View file

@ -12,4 +12,5 @@ Depth data provides distance to points, mapped onto the image plane
.. toctree::
:maxdepth: 1
pixfmt-inzi
pixfmt-z16

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -25,3 +25,4 @@ Interfaces
dev-touch
dev-event
dev-subdev
dev-meta

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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]

View file

@ -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]

View file

@ -34,4 +34,5 @@ see also :ref:`VIDIOC_G_FBUF <VIDIOC_G_FBUF>`.)
pixfmt-013
sdr-formats
tch-formats
meta-formats
pixfmt-reserved

View file

@ -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`

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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)

View file

@ -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";

View file

@ -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>;

View file

@ -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>;
};
};
};

View file

@ -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)

View file

@ -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))

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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

19
drivers/media/cec/Kconfig Normal file
View file

@ -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.

View file

@ -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

View file

@ -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;

View file

@ -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. */

View file

@ -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);

View file

@ -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");

View file

@ -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);

View file

@ -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,
};

View file

@ -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);

View file

@ -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 */

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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,

View file

@ -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)

View file

@ -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;

View file

@ -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>

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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,
};

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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 = {

View file

@ -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");

1345
drivers/media/i2c/ov5645.c Normal file

File diff suppressed because it is too large Load diff

634
drivers/media/i2c/ov5647.c Normal file
View file

@ -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");

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

Some files were not shown because too many files have changed in this diff Show more