media updates for v4.18-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJbGDjcAAoJEAhfPr2O5OEV1KwP/Am2n5Ehc2W0/DLD3K7LlwgN
 8JnMPWNQTCreLRgJD0/KX+HH1M+yBJ05KF/Glm7fcOKpOhWqrUbPgtiQT0GyHHBB
 uvmQfGJrRvCrP+1S1SeWtNhItsyWvCfDaorzsTWJYEF/F9Wtj/Sj92DC1y/BKQaR
 Rcs4yeCqlFEp3rjbXExanFhA3/XeMzK2sby8c51cILTZPkWI64qrHcZRWOW7+zZ6
 fKEVDNOKxa7sfg8I9yaI73lBGXBpCJxLROloJ3jEtuH5gY3nR6PZdXunBC5K0+pX
 UH1vUeBcS/3ExQWL0zmCqHz1aYb6kzTSbIPs+NktxyzTTb8FDjT9JhV/9AxhEQfK
 iIxv81LRBdbEoPxbvx88sj5VVvlRla/NRv03WsXhhVDqx2SZJuNgSXw3XJtGDx3j
 AuUur0AQH4KMNNmwxmyn6wbhm7N63AaGbmYE2sRmaL7lk6b48BSbsUpOM5AMWzZe
 ZsESSsoqjRR86zFtVVzI7ZImCk16D6mNRP94Z0DQReWAJ6zS57/EYfKZ+pEQ6mww
 IyoJalD+pBe160fqsSo59F4k2fqzsqP4p8m29OQWFvyl7+UboMBz7FscWfyT98+R
 MbJolZ8QJNlOVaOusxPYLfdfjVmkHCt4E0cBZVFYIvliTGd5QiKqHAW+kTYQH0No
 Y0nHm4bShsUY8I9YCgsk
 =r/WP
 -----END PGP SIGNATURE-----

Merge tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - remove of atomisp driver from staging, as nobody would have time to
   dedicate huge efforts to fix all the problems there. Also, we have a
   feeling that the driver may not even run the way it is.

 - move Zoran driver to staging, in order to be either fixed to use VB2
   and the proper media kAPIs or to be removed

 - remove videobuf-dvb driver, with is unused for a while

 - some V4L2 documentation fixes/improvements

 - new sensor drivers: imx258 and ov7251

 - a new driver was added to allow using I2C transparent drivers

 - several improvements at the ddbridge driver

 - several improvements at the ISDB pt1 driver, making it more coherent
   with the DVB framework

 - added a new platform driver for MIPI CSI-2 RX: cadence

 - now, all media drivers can be compiled on x86 with COMPILE_TEST

 - almost all media drivers now build on non-x86 architectures with
   COMPILE_TEST

 - lots of other random stuff: cleanups, support for new board models,
   bug fixes, etc

* tag 'media/v4.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (464 commits)
  media: omap2: fix compile-testing with FB_OMAP2=m
  media: media/radio/Kconfig: add back RADIO_ISA
  media: v4l2-ioctl.c: fix missing unlock in __video_do_ioctl()
  media: pxa_camera: ignore -ENOIOCTLCMD from v4l2_subdev_call for s_power
  media: arch: sh: migor: Fix TW9910 PDN gpio
  media: staging: tegra-vde: Reset VDE regardless of memory client resetting failure
  media: marvel-ccic: mmp: select VIDEOBUF2_VMALLOC/DMA_CONTIG
  media: marvel-ccic: allow ccic and mmp drivers to coexist
  media: uvcvideo: Prevent setting unavailable flags
  media: ddbridge: conditionally enable fast TS for stv0910-equipped bridges
  media: dvb-frontends/stv0910: make TS speed configurable
  media: ddbridge/mci: add identifiers to function definition arguments
  media: ddbridge/mci: protect against out-of-bounds array access in stop()
  media: rc: ensure input/lirc device can be opened after register
  media: rc: nuvoton: Keep device enabled during reg init
  media: rc: nuvoton: Keep track of users on CIR enable/disable
  media: rc: nuvoton: Tweak the interrupt enabling dance
  media: uvcvideo: Support realtek's UVC 1.5 device
  media: uvcvideo: Fix driver reference counting
  media: gspca_zc3xx: Enable short exposure times for OV7648
  ...
This commit is contained in:
Linus Torvalds 2018-06-07 12:34:37 -07:00
commit 3036bc4536
1168 changed files with 16826 additions and 176711 deletions

View File

@ -1,7 +1,7 @@
What: /sys/class/rc/
Date: Apr 2010
KernelVersion: 2.6.35
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
The rc/ class sub-directory belongs to the Remote Controller
core and provides a sysfs interface for configuring infrared
@ -10,7 +10,7 @@ Description:
What: /sys/class/rc/rcN/
Date: Apr 2010
KernelVersion: 2.6.35
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
A /sys/class/rc/rcN directory is created for each remote
control receiver device where N is the number of the receiver.
@ -18,7 +18,7 @@ Description:
What: /sys/class/rc/rcN/protocols
Date: Jun 2010
KernelVersion: 2.6.36
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Reading this file returns a list of available protocols,
something like:
@ -36,7 +36,7 @@ Description:
What: /sys/class/rc/rcN/filter
Date: Jan 2014
KernelVersion: 3.15
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Sets the scancode filter expected value.
Use in combination with /sys/class/rc/rcN/filter_mask to set the
@ -49,7 +49,7 @@ Description:
What: /sys/class/rc/rcN/filter_mask
Date: Jan 2014
KernelVersion: 3.15
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Sets the scancode filter mask of bits to compare.
Use in combination with /sys/class/rc/rcN/filter to set the bits
@ -64,7 +64,7 @@ Description:
What: /sys/class/rc/rcN/wakeup_protocols
Date: Feb 2017
KernelVersion: 4.11
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Reading this file returns a list of available protocols to use
for the wakeup filter, something like:
@ -83,7 +83,7 @@ Description:
What: /sys/class/rc/rcN/wakeup_filter
Date: Jan 2014
KernelVersion: 3.15
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Sets the scancode wakeup filter expected value.
Use in combination with /sys/class/rc/rcN/wakeup_filter_mask to
@ -98,7 +98,7 @@ Description:
What: /sys/class/rc/rcN/wakeup_filter_mask
Date: Jan 2014
KernelVersion: 3.15
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Sets the scancode wakeup filter mask of bits to compare.
Use in combination with /sys/class/rc/rcN/wakeup_filter to set

View File

@ -1,7 +1,7 @@
What: /sys/class/rc/rcN/wakeup_data
Date: Mar 2016
KernelVersion: 4.6
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Description:
Reading this file returns the stored CIR wakeup sequence.
It starts with a pulse, followed by a space, pulse etc.

View File

@ -77,7 +77,7 @@ Description: Read/Write attribute file that controls memory scrubbing.
What: /sys/devices/system/edac/mc/mc*/max_location
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file displays the information about the last
available memory slot in this memory controller. It is used by
@ -85,7 +85,7 @@ Description: This attribute file displays the information about the last
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/size
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file will display the size of dimm or rank.
For dimm*/size, this is the size, in MB of the DIMM memory
@ -96,14 +96,14 @@ Description: This attribute file will display the size of dimm or rank.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_dev_type
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of DRAM device is
being utilized on this DIMM (x1, x2, x4, x8, ...).
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_edac_mode
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of Error detection
and correction is being utilized. For example: S4ECD4ED would
@ -111,7 +111,7 @@ Description: This attribute file will display what type of Error detection
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_label
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This control file allows this DIMM to have a label assigned
to it. With this label in the module, when errors occur
@ -126,14 +126,14 @@ Description: This control file allows this DIMM to have a label assigned
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_location
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file will display the location (csrow/channel,
branch/channel/slot or channel/slot) of the dimm or rank.
What: /sys/devices/system/edac/mc/mc*/(dimm|rank)*/dimm_mem_type
Date: April 2012
Contact: Mauro Carvalho Chehab <m.chehab@samsung.com>
Contact: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
linux-edac@vger.kernel.org
Description: This attribute file will display what type of memory is
currently on this csrow. Normally, either buffered or

View File

@ -0,0 +1,100 @@
Cadence MIPI-CSI2 RX controller
===============================
The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
lanes in input, and 4 different pixel streams in output.
Required properties:
- compatible: must be set to "cdns,csi2rx" and an SoC-specific compatible
- reg: base address and size of the memory mapped region
- clocks: phandles to the clocks driving the controller
- clock-names: must contain:
* sys_clk: main clock
* p_clk: register bank clock
* pixel_if[0-3]_clk: pixel stream output clock, one for each stream
implemented in hardware, between 0 and 3
Optional properties:
- phys: phandle to the external D-PHY, phy-names must be provided
- phy-names: must contain "dphy", if the implementation uses an
external D-PHY
Required subnodes:
- ports: A ports node with one port child node per device input and output
port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
port nodes are numbered as follows:
Port Description
-----------------------------
0 CSI-2 input
1 Stream 0 output
2 Stream 1 output
3 Stream 2 output
4 Stream 3 output
The stream output port nodes are optional if they are not
connected to anything at the hardware level or implemented
in the design.Since there is only one endpoint per port,
the endpoints are not numbered.
Example:
csi2rx: csi-bridge@0d060000 {
compatible = "cdns,csi2rx";
reg = <0x0d060000 0x1000>;
clocks = <&byteclock>, <&byteclock>
<&coreclock>, <&coreclock>,
<&coreclock>, <&coreclock>;
clock-names = "sys_clk", "p_clk",
"pixel_if0_clk", "pixel_if1_clk",
"pixel_if2_clk", "pixel_if3_clk";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2rx_in_sensor: endpoint {
remote-endpoint = <&sensor_out_csi2rx>;
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
csi2rx_out_grabber0: endpoint {
remote-endpoint = <&grabber0_in_csi2rx>;
};
};
port@2 {
reg = <2>;
csi2rx_out_grabber1: endpoint {
remote-endpoint = <&grabber1_in_csi2rx>;
};
};
port@3 {
reg = <3>;
csi2rx_out_grabber2: endpoint {
remote-endpoint = <&grabber2_in_csi2rx>;
};
};
port@4 {
reg = <4>;
csi2rx_out_grabber3: endpoint {
remote-endpoint = <&grabber3_in_csi2rx>;
};
};
};
};

View File

@ -0,0 +1,98 @@
Cadence MIPI-CSI2 TX controller
===============================
The Cadence MIPI-CSI2 TX controller is a CSI-2 bridge supporting up to
4 CSI lanes in output, and up to 4 different pixel streams in input.
Required properties:
- compatible: must be set to "cdns,csi2tx"
- reg: base address and size of the memory mapped region
- clocks: phandles to the clocks driving the controller
- clock-names: must contain:
* esc_clk: escape mode clock
* p_clk: register bank clock
* pixel_if[0-3]_clk: pixel stream output clock, one for each stream
implemented in hardware, between 0 and 3
Optional properties
- phys: phandle to the D-PHY. If it is set, phy-names need to be set
- phy-names: must contain "dphy"
Required subnodes:
- ports: A ports node with one port child node per device input and output
port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
port nodes are numbered as follows.
Port Description
-----------------------------
0 CSI-2 output
1 Stream 0 input
2 Stream 1 input
3 Stream 2 input
4 Stream 3 input
The stream input port nodes are optional if they are not
connected to anything at the hardware level or implemented
in the design. Since there is only one endpoint per port,
the endpoints are not numbered.
Example:
csi2tx: csi-bridge@0d0e1000 {
compatible = "cdns,csi2tx";
reg = <0x0d0e1000 0x1000>;
clocks = <&byteclock>, <&byteclock>,
<&coreclock>, <&coreclock>,
<&coreclock>, <&coreclock>;
clock-names = "p_clk", "esc_clk",
"pixel_if0_clk", "pixel_if1_clk",
"pixel_if2_clk", "pixel_if3_clk";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2tx_out: endpoint {
remote-endpoint = <&remote_in>;
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
csi2tx_in_stream0: endpoint {
remote-endpoint = <&stream0_out>;
};
};
port@2 {
reg = <2>;
csi2tx_in_stream1: endpoint {
remote-endpoint = <&stream1_out>;
};
};
port@3 {
reg = <3>;
csi2tx_in_stream2: endpoint {
remote-endpoint = <&stream2_out>;
};
};
port@4 {
reg = <4>;
csi2tx_in_stream3: endpoint {
remote-endpoint = <&stream3_out>;
};
};
};
};

View File

@ -0,0 +1,52 @@
* Omnivision 1/7.5-Inch B&W VGA CMOS Digital Image Sensor
The Omnivision OV7251 is a 1/7.5-Inch CMOS active pixel digital image sensor
with an active array size of 640H x 480V. It is programmable through a serial
I2C interface.
Required Properties:
- compatible: Value should be "ovti,ov7251".
- 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 XSHUTDOWN which is physically active low.
- vdddo-supply: Chip digital IO regulator.
- vdda-supply: Chip analog regulator.
- vddd-supply: Chip digital core regulator.
The device node shall contain one 'port' child node with a single 'endpoint'
subnode for its digital output video port, in accordance with the video
interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Example:
&i2c1 {
...
ov7251: camera-sensor@60 {
compatible = "ovti,ov7251";
reg = <0x60>;
enable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&camera_bw_default>;
clocks = <&clks 200>;
clock-names = "xclk";
clock-frequency = <24000000>;
vdddo-supply = <&camera_dovdd_1v8>;
vdda-supply = <&camera_avdd_2v8>;
vddd-supply = <&camera_dvdd_1v2>;
port {
ov7251_ep: endpoint {
clock-lanes = <1>;
data-lanes = <0>;
remote-endpoint = <&csi0_ep>;
};
};
};
};

View File

@ -0,0 +1,40 @@
* Omnivision OV7720/OV7725 CMOS sensor
The Omnivision OV7720/OV7725 sensor supports multiple resolutions output,
such as VGA, QVGA, and any size scaling down from CIF to 40x30. It also can
support the YUV422, RGB565/555/444, GRB422 or raw RGB output formats.
Required Properties:
- compatible: shall be one of
"ovti,ov7720"
"ovti,ov7725"
- clocks: reference to the xclk input clock.
Optional Properties:
- reset-gpios: reference to the GPIO connected to the RSTB pin which is
active low, if any.
- powerdown-gpios: reference to the GPIO connected to the PWDN pin which is
active high, if any.
The device node shall contain one 'port' child node with one child 'endpoint'
subnode for its digital output video port, in accordance with the video
interface bindings defined in Documentation/devicetree/bindings/media/
video-interfaces.txt.
Example:
&i2c0 {
ov772x: camera@21 {
compatible = "ovti,ov7725";
reg = <0x21>;
reset-gpios = <&axi_gpio_0 0 GPIO_ACTIVE_LOW>;
powerdown-gpios = <&axi_gpio_0 1 GPIO_ACTIVE_LOW>;
clocks = <&xclk>;
port {
ov772x_0: endpoint {
remote-endpoint = <&vcap1_in0>;
};
};
};
};

View File

@ -0,0 +1,19 @@
* Panasonic AMG88xx
The Panasonic family of AMG88xx Grid-Eye sensors allow recording
8x8 10Hz video which consists of thermal datapoints
Required Properties:
- compatible : Must be "panasonic,amg88xx"
- reg : i2c address of the device
Example:
i2c0@1c22000 {
...
amg88xx@69 {
compatible = "panasonic,amg88xx";
reg = <0x69>;
};
...
};

View File

@ -2,20 +2,28 @@ Renesas R-Car Video Input driver (rcar_vin)
-------------------------------------------
The rcar_vin device provides video input capabilities for the Renesas R-Car
family of devices. The current blocks are always slaves and suppot one input
channel which can be either RGB, YUYV or BT656.
family of devices.
Each VIN instance has a single parallel input that supports RGB and YUV video,
with both external synchronization and BT.656 synchronization for the latter.
Depending on the instance the VIN input is connected to external SoC pins, or
on Gen3 platforms to a CSI-2 receiver.
- compatible: Must be one or more of the following
- "renesas,vin-r8a7795" for the R8A7795 device
- "renesas,vin-r8a7794" for the R8A7794 device
- "renesas,vin-r8a7793" for the R8A7793 device
- "renesas,vin-r8a7792" for the R8A7792 device
- "renesas,vin-r8a7791" for the R8A7791 device
- "renesas,vin-r8a7790" for the R8A7790 device
- "renesas,vin-r8a7779" for the R8A7779 device
- "renesas,vin-r8a7743" for the R8A7743 device
- "renesas,vin-r8a7745" for the R8A7745 device
- "renesas,vin-r8a7778" for the R8A7778 device
- "renesas,rcar-gen2-vin" for a generic R-Car Gen2 compatible device.
- "renesas,rcar-gen3-vin" for a generic R-Car Gen3 compatible device.
- "renesas,vin-r8a7779" for the R8A7779 device
- "renesas,vin-r8a7790" for the R8A7790 device
- "renesas,vin-r8a7791" for the R8A7791 device
- "renesas,vin-r8a7792" for the R8A7792 device
- "renesas,vin-r8a7793" for the R8A7793 device
- "renesas,vin-r8a7794" for the R8A7794 device
- "renesas,vin-r8a7795" for the R8A7795 device
- "renesas,vin-r8a7796" for the R8A7796 device
- "renesas,vin-r8a77970" for the R8A77970 device
- "renesas,rcar-gen2-vin" for a generic R-Car Gen2 or RZ/G1 compatible
device.
When compatible with the generic version nodes must list the
SoC-specific version corresponding to the platform first
@ -28,21 +36,38 @@ channel which can be either RGB, YUYV or BT656.
Additionally, an alias named vinX will need to be created to specify
which video input device this is.
The per-board settings:
The per-board settings Gen2 platforms:
- port sub-node describing a single endpoint connected to the vin
as described in video-interfaces.txt[1]. Only the first one will
be considered as each vin interface has one input port.
These settings are used to work out video input format and widths
into the system.
The per-board settings Gen3 platforms:
Gen3 platforms can support both a single connected parallel input source
from external SoC pins (port0) and/or multiple parallel input sources
from local SoC CSI-2 receivers (port1) depending on SoC.
Device node example
-------------------
- renesas,id - ID number of the VIN, VINx in the documentation.
- ports
- port 0 - sub-node describing a single endpoint connected to the VIN
from external SoC pins described in video-interfaces.txt[1].
Describing more then one endpoint in port 0 is invalid. Only VIN
instances that are connected to external pins should have port 0.
- port 1 - sub-nodes describing one or more endpoints connected to
the VIN from local SoC CSI-2 receivers. The endpoint numbers must
use the following schema.
aliases {
vin0 = &vin0;
};
- Endpoint 0 - sub-node describing the endpoint connected to CSI20
- Endpoint 1 - sub-node describing the endpoint connected to CSI21
- Endpoint 2 - sub-node describing the endpoint connected to CSI40
- Endpoint 3 - sub-node describing the endpoint connected to CSI41
Device node example for Gen2 platforms
--------------------------------------
aliases {
vin0 = &vin0;
};
vin0: vin@e6ef0000 {
compatible = "renesas,vin-r8a7790", "renesas,rcar-gen2-vin";
@ -52,8 +77,8 @@ Device node example
status = "disabled";
};
Board setup example (vin1 composite video input)
------------------------------------------------
Board setup example for Gen2 platforms (vin1 composite video input)
-------------------------------------------------------------------
&i2c2 {
status = "okay";
@ -92,6 +117,77 @@ Board setup example (vin1 composite video input)
};
};
Device node example for Gen3 platforms
--------------------------------------
vin0: video@e6ef0000 {
compatible = "renesas,vin-r8a7795";
reg = <0 0xe6ef0000 0 0x1000>;
interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 811>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 811>;
renesas,id = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
vin0csi20: endpoint@0 {
reg = <0>;
remote-endpoint= <&csi20vin0>;
};
vin0csi21: endpoint@1 {
reg = <1>;
remote-endpoint= <&csi21vin0>;
};
vin0csi40: endpoint@2 {
reg = <2>;
remote-endpoint= <&csi40vin0>;
};
};
};
};
csi20: csi2@fea80000 {
compatible = "renesas,r8a7795-csi2";
reg = <0 0xfea80000 0 0x10000>;
interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 714>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 714>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi20_in: endpoint {
clock-lanes = <0>;
data-lanes = <1>;
remote-endpoint = <&adv7482_txb>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
csi20vin0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vin0csi20>;
};
};
};
};
[1] video-interfaces.txt common video media interface

View File

@ -2,14 +2,15 @@ Renesas Capture Engine Unit (CEU)
----------------------------------------------
The Capture Engine Unit is the image capture interface found in the Renesas
SH Mobile and RZ SoCs.
SH Mobile, R-Mobile and RZ SoCs.
The interface supports a single parallel input with data bus width of 8 or 16
bits.
Required properties:
- compatible: Shall be "renesas,r7s72100-ceu" for CEU units found in RZ/A1H
and RZ/A1M SoCs.
- compatible: Shall be one of the following values:
"renesas,r7s72100-ceu" for CEU units found in RZ/A1H and RZ/A1M SoCs
"renesas,r8a7740-ceu" for CEU units found in R-Mobile A1 R8A7740 SoCs
- reg: Registers address base and size.
- interrupts: The interrupt specifier.

View File

@ -0,0 +1,101 @@
Renesas R-Car MIPI CSI-2
------------------------
The R-Car CSI-2 receiver device provides MIPI CSI-2 capabilities for the
Renesas R-Car family of devices. It is used in conjunction with the
R-Car VIN module, which provides the video capture capabilities.
Mandatory properties
--------------------
- compatible: Must be one or more of the following
- "renesas,r8a7795-csi2" for the R8A7795 device.
- "renesas,r8a7796-csi2" for the R8A7796 device.
- "renesas,r8a77965-csi2" for the R8A77965 device.
- "renesas,r8a77970-csi2" for the R8A77970 device.
- reg: the register base and size for the device registers
- interrupts: the interrupt for the device
- clocks: reference to the parent clock
The device node shall contain two 'port' child nodes according to the
bindings defined in Documentation/devicetree/bindings/media/
video-interfaces.txt. port@0 shall connect to the CSI-2 source. port@1
shall connect to all the R-Car VIN modules that have a hardware
connection to the CSI-2 receiver.
- port@0- Video source (mandatory)
- endpoint@0 - sub-node describing the endpoint that is the video source
- port@1 - VIN instances (optional)
- One endpoint sub-node for every R-Car VIN instance which is connected
to the R-Car CSI-2 receiver.
Example:
csi20: csi2@fea80000 {
compatible = "renesas,r8a7796-csi2";
reg = <0 0xfea80000 0 0x10000>;
interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 714>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
resets = <&cpg 714>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
csi20_in: endpoint@0 {
reg = <0>;
clock-lanes = <0>;
data-lanes = <1>;
remote-endpoint = <&adv7482_txb>;
};
};
port@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
csi20vin0: endpoint@0 {
reg = <0>;
remote-endpoint = <&vin0csi20>;
};
csi20vin1: endpoint@1 {
reg = <1>;
remote-endpoint = <&vin1csi20>;
};
csi20vin2: endpoint@2 {
reg = <2>;
remote-endpoint = <&vin2csi20>;
};
csi20vin3: endpoint@3 {
reg = <3>;
remote-endpoint = <&vin3csi20>;
};
csi20vin4: endpoint@4 {
reg = <4>;
remote-endpoint = <&vin4csi20>;
};
csi20vin5: endpoint@5 {
reg = <5>;
remote-endpoint = <&vin5csi20>;
};
csi20vin6: endpoint@6 {
reg = <6>;
remote-endpoint = <&vin6csi20>;
};
csi20vin7: endpoint@7 {
reg = <7>;
remote-endpoint = <&vin7csi20>;
};
};
};
};

View File

@ -246,7 +246,10 @@ CEC_TX_STATUS_LOW_DRIVE:
CEC_TX_STATUS_ERROR:
some unspecified error occurred: this can be one of ARB_LOST
or LOW_DRIVE if the hardware cannot differentiate or something
else entirely.
else entirely. Some hardware only supports OK and FAIL as the
result of a transmit, i.e. there is no way to differentiate
between the different possible errors. In that case map FAIL
to CEC_TX_STATUS_NACK and not to CEC_TX_STATUS_ERROR.
CEC_TX_STATUS_MAX_RETRIES:
could not transmit the message after trying multiple times.

View File

@ -231,26 +231,32 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
- ``CEC_TX_STATUS_OK``
- 0x01
- The message was transmitted successfully. This is mutually
exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`. Other bits can still
be set if earlier attempts met with failure before the transmit
was eventually successful.
exclusive with :ref:`CEC_TX_STATUS_MAX_RETRIES <CEC-TX-STATUS-MAX-RETRIES>`.
Other bits can still be set if earlier attempts met with failure before
the transmit was eventually successful.
* .. _`CEC-TX-STATUS-ARB-LOST`:
- ``CEC_TX_STATUS_ARB_LOST``
- 0x02
- CEC line arbitration was lost.
- CEC line arbitration was lost, i.e. another transmit started at the
same time with a higher priority. Optional status, not all hardware
can detect this error condition.
* .. _`CEC-TX-STATUS-NACK`:
- ``CEC_TX_STATUS_NACK``
- 0x04
- Message was not acknowledged.
- Message was not acknowledged. Note that some hardware cannot tell apart
a 'Not Acknowledged' status from other error conditions, i.e. the result
of a transmit is just OK or FAIL. In that case this status will be
returned when the transmit failed.
* .. _`CEC-TX-STATUS-LOW-DRIVE`:
- ``CEC_TX_STATUS_LOW_DRIVE``
- 0x08
- Low drive was detected on the CEC bus. This indicates that a
follower detected an error on the bus and requests a
retransmission.
retransmission. Optional status, not all hardware can detect this
error condition.
* .. _`CEC-TX-STATUS-ERROR`:
- ``CEC_TX_STATUS_ERROR``
@ -258,14 +264,14 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
- Some error occurred. This is used for any errors that do not fit
``CEC_TX_STATUS_ARB_LOST`` or ``CEC_TX_STATUS_LOW_DRIVE``, either because
the hardware could not tell which error occurred, or because the hardware
tested for other conditions besides those two.
tested for other conditions besides those two. Optional status.
* .. _`CEC-TX-STATUS-MAX-RETRIES`:
- ``CEC_TX_STATUS_MAX_RETRIES``
- 0x20
- The transmit failed after one or more retries. This status bit is
mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`. Other bits can still
be set to explain which failures were seen.
mutually exclusive with :ref:`CEC_TX_STATUS_OK <CEC-TX-STATUS-OK>`.
Other bits can still be set to explain which failures were seen.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|

View File

@ -62,7 +62,7 @@ Authors:
- Original author of the Digital TV API documentation.
- Carvalho Chehab, Mauro <m.chehab@kernel.org>
- Carvalho Chehab, Mauro <mchehab+samsung@kernel.org>
- Ported document to Docbook XML, addition of DVBv5 API, documentation gaps fix.

View File

@ -18,7 +18,7 @@ Example dmesg output upon a driver registering w/LIRC:
.. code-block:: none
$ dmesg |grep lirc_dev
rc rc0: lirc_dev: driver mceusb registered at minor = 0
rc rc0: lirc_dev: driver mceusb registered at minor = 0, raw IR receiver, raw IR transmitter
What you should see for a chardev:

View File

@ -1,19 +1,23 @@
.. -*- coding: utf-8; mode: rst -*-
.. _lirc_set_rec_timeout:
.. _lirc_get_rec_timeout:
**************************
ioctl LIRC_SET_REC_TIMEOUT
**************************
***************************************************
ioctl LIRC_GET_REC_TIMEOUT and LIRC_SET_REC_TIMEOUT
***************************************************
Name
====
LIRC_SET_REC_TIMEOUT - sets the integer value for IR inactivity timeout.
LIRC_GET_REC_TIMEOUT/LIRC_SET_REC_TIMEOUT - Get/set the integer value for IR inactivity timeout.
Synopsis
========
.. c:function:: int ioctl( int fd, LIRC_GET_REC_TIMEOUT, __u32 *timeout )
:name: LIRC_GET_REC_TIMEOUT
.. c:function:: int ioctl( int fd, LIRC_SET_REC_TIMEOUT, __u32 *timeout )
:name: LIRC_SET_REC_TIMEOUT
@ -30,7 +34,7 @@ Arguments
Description
===========
Sets the integer value for IR inactivity timeout.
Get and set the integer value for IR inactivity timeout.
If supported by the hardware, setting it to 0 disables all hardware timeouts
and data should be reported as soon as possible. If the exact value

View File

@ -41,6 +41,6 @@ applicable to all devices.
extended-controls
format
planar-apis
crop
selection-api
crop
streaming-par

View File

@ -2,9 +2,18 @@
.. _crop:
*************************************
Image Cropping, Insertion and Scaling
*************************************
*****************************************************
Image Cropping, Insertion and Scaling -- the CROP API
*****************************************************
.. note::
The CROP API is mostly superseded by the newer :ref:`SELECTION API
<selection-api>`. The new API should be preferred in most cases,
with the exception of pixel aspect ratio detection, which is
implemented by :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` and has no
equivalent in the SELECTION API. See :ref:`selection-vs-crop` for a
comparison of the two APIs.
Some video capture devices can sample a subsection of the picture and
shrink or enlarge it to an image of arbitrary size. We call these
@ -42,10 +51,9 @@ where applicable) will be fixed in this case.
.. note::
All capture and output devices must support the
:ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>` ioctl such that applications
can determine if scaling takes place.
All capture and output devices that support the CROP or SELECTION
API will also support the :ref:`VIDIOC_CROPCAP <VIDIOC_CROPCAP>`
ioctl.
Cropping Structures
===================

View File

@ -1,34 +0,0 @@
.. -*- coding: utf-8; mode: rst -*-
********************************
Comparison with old cropping API
********************************
The selection API was introduced to cope with deficiencies of previous
:ref:`API <crop>`, that was designed to control simple capture
devices. Later the cropping API was adopted by video output drivers. The
ioctls are used to select a part of the display were the video signal is
inserted. It should be considered as an API abuse because the described
operation is actually the composing. The selection API makes a clear
distinction between composing and cropping operations by setting the
appropriate targets. The V4L2 API lacks any support for composing to and
cropping from an image inside a memory buffer. The application could
configure a capture device to fill only a part of an image by abusing
V4L2 API. Cropping a smaller image from a larger one is achieved by
setting the field ``bytesperline`` at struct
:c:type:`v4l2_pix_format`.
Introducing an image offsets could be done by modifying field ``m_userptr``
at struct
:c:type:`v4l2_buffer` before calling
:ref:`VIDIOC_QBUF`. Those operations should be avoided because they are not
portable (endianness), and do not work for macroblock and Bayer formats
and mmap buffers. The selection API deals with configuration of buffer
cropping/composing in a clear, intuitive and portable way. Next, with
the selection API the concepts of the padded target and constraints
flags are introduced. Finally, struct :c:type:`v4l2_crop`
and struct :c:type:`v4l2_cropcap` have no reserved
fields. Therefore there is no way to extend their functionality. The new
struct :c:type:`v4l2_selection` provides a lot of place
for future extensions. Driver developers are encouraged to implement
only selection API. The former cropping API would be simulated using the
new one.

View File

@ -41,7 +41,7 @@ The driver may further adjust the requested size and/or position
according to hardware limitations.
Each capture device has a default source rectangle, given by the
``V4L2_SEL_TGT_CROP_DEFAULT`` target. This rectangle shall over what the
``V4L2_SEL_TGT_CROP_DEFAULT`` target. This rectangle shall cover what the
driver writer considers the complete picture. Drivers shall set the
active crop rectangle to the default when the driver is first loaded,
but not later.

View File

@ -0,0 +1,39 @@
.. -*- coding: utf-8; mode: rst -*-
.. _selection-vs-crop:
********************************
Comparison with old cropping API
********************************
The selection API was introduced to cope with deficiencies of the
older :ref:`CROP API <crop>`, that was designed to control simple
capture devices. Later the cropping API was adopted by video output
drivers. The ioctls are used to select a part of the display were the
video signal is inserted. It should be considered as an API abuse
because the described operation is actually the composing. The
selection API makes a clear distinction between composing and cropping
operations by setting the appropriate targets.
The CROP API lacks any support for composing to and cropping from an
image inside a memory buffer. The application could configure a
capture device to fill only a part of an image by abusing V4L2
API. Cropping a smaller image from a larger one is achieved by setting
the field ``bytesperline`` at struct :c:type:`v4l2_pix_format`.
Introducing an image offsets could be done by modifying field
``m_userptr`` at struct :c:type:`v4l2_buffer` before calling
:ref:`VIDIOC_QBUF <VIDIOC_QBUF>`. Those operations should be avoided
because they are not portable (endianness), and do not work for
macroblock and Bayer formats and mmap buffers.
The selection API deals with configuration of buffer
cropping/composing in a clear, intuitive and portable way. Next, with
the selection API the concepts of the padded target and constraints
flags are introduced. Finally, struct :c:type:`v4l2_crop` and struct
:c:type:`v4l2_cropcap` have no reserved fields. Therefore there is no
way to extend their functionality. The new struct
:c:type:`v4l2_selection` provides a lot of place for future
extensions.
Driver developers are encouraged to implement only selection API. The
former cropping API would be simulated using the new one.

View File

@ -2,15 +2,15 @@
.. _selection-api:
API for cropping, composing and scaling
=======================================
Cropping, composing and scaling -- the SELECTION API
====================================================
.. toctree::
:maxdepth: 1
selection-api-002
selection-api-003
selection-api-004
selection-api-005
selection-api-006
selection-api-intro.rst
selection-api-targets.rst
selection-api-configuration.rst
selection-api-vs-crop-api.rst
selection-api-examples.rst

View File

@ -1128,11 +1128,11 @@
</text>
</g>
<text transform="matrix(.96106 0 0 1.0405 48.571 195.53)" x="2438.062" y="1368.429" enable-background="new" font-size="50" style="line-height:125%">
<tspan x="2438.062" y="1368.429">COMPOSE_BONDS</tspan>
<tspan x="2438.062" y="1368.429">COMPOSE_BOUNDS</tspan>
</text>
<g font-size="40">
<text transform="translate(48.571 195.53)" x="8.082" y="1438.896" enable-background="new" style="line-height:125%">
<tspan x="8.082" y="1438.896" font-size="50">CROP_BONDS</tspan>
<tspan x="8.082" y="1438.896" font-size="50">CROP_BOUNDS</tspan>
</text>
<text transform="translate(48.571 195.53)" x="1455.443" y="-26.808" enable-background="new" style="line-height:125%">
<tspan x="1455.443" y="-26.808" font-size="50">overscan area</tspan>

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

@ -45,7 +45,7 @@ Authors, in alphabetical order:
- Subdev selections API.
- Carvalho Chehab, Mauro <m.chehab@kernel.org>
- Carvalho Chehab, Mauro <mchehab+samsung@kernel.org>
- Documented libv4l, designed and added v4l2grab example, Remote Controller chapter.

View File

@ -186,7 +186,7 @@ cx23885 cards list
* - 43
- Hauppauge ImpactVCB-e
- 0070:7133
- 0070:7133, 0070:7137
* - 44
- DViCO FusionHDTV DVB-T Dual Express2
@ -243,3 +243,19 @@ cx23885 cards list
* - 57
- Hauppauge WinTV-QuadHD-ATSC
- 0070:6a18, 0070:6b18
* - 58
- Hauppauge WinTV-HVR-1265(161111)
- 0070:2a18
* - 59
- Hauppauge WinTV-Starburst2
- 0070:f02a
* - 60
- Hauppauge WinTV-QuadHD-DVB(885)
-
* - 61
- Hauppauge WinTV-QuadHD-ATSC(885)
-

View File

@ -391,7 +391,7 @@ EM28xx cards list
* - 94
- PCTV tripleStick (292e)
- em28178
- 2013:025f, 2040:0264
- 2013:025f, 2013:0264, 2040:0264, 2040:8264, 2040:8268, 2040:8268
* - 95
- Leadtek VC100
- em2861
@ -411,12 +411,16 @@ EM28xx cards list
* - 99
- Hauppauge WinTV-dualHD DVB
- em28174
- 2040:0265
- 2040:0265, 2040:8265
* - 100
- Hauppauge WinTV-dualHD 01595 ATSC/QAM
- em28174
- 2040:026d
- 2040:026d, 2040:826d
* - 101
- Terratec Cinergy H6 rev. 2
- em2884
- 0ccd:10b2
* - 102
- :ZOLID HYBRID TV STICK
- em2882
-

View File

@ -3147,6 +3147,13 @@ S: Supported
F: Documentation/filesystems/caching/cachefiles.txt
F: fs/cachefiles/
CADENCE MIPI-CSI2 BRIDGES
M: Maxime Ripard <maxime.ripard@bootlin.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/cdns,*.txt
F: drivers/media/platform/cadence/cdns-csi2*
CADET FM/AM RADIO RECEIVER DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
@ -8894,6 +8901,7 @@ L: linux-media@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Supported
F: Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
F: Documentation/devicetree/bindings/media/rcar_vin.txt
F: drivers/media/platform/rcar-vin/
@ -10450,6 +10458,7 @@ T: git git://linuxtv.org/media_tree.git
S: Odd fixes
F: drivers/media/i2c/ov772x.c
F: include/media/i2c/ov772x.h
F: Documentation/devicetree/bindings/media/i2c/ov772x.txt
OMNIVISION OV7740 SENSOR DRIVER
M: Wenyou Yang <wenyou.yang@microchip.com>
@ -13163,6 +13172,13 @@ S: Maintained
F: drivers/ssb/
F: include/linux/ssb/
SONY IMX258 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/imx258.c
SONY IMX274 SENSOR DRIVER
M: Leon Luo <leonl@leopardimaging.com>
L: linux-media@vger.kernel.org
@ -13379,13 +13395,6 @@ L: stable@vger.kernel.org
S: Supported
F: Documentation/process/stable-kernel-rules.rst
STAGING - ATOMISP DRIVER
M: Alan Cox <alan@linux.intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/atomisp/
STAGING - COMEDI
M: Ian Abbott <abbotti@mev.co.uk>
M: H Hartley Sweeten <hsweeten@visionengravers.com>
@ -15048,6 +15057,12 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/platform/video-mux.c
VIDEO I2C POLLING DRIVER
M: Matt Ranostay <matt.ranostay@konsulko.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/video-i2c.c
VIDEOBUF2 FRAMEWORK
M: Pawel Osciak <pawel@osciak.com>
M: Marek Szyprowski <m.szyprowski@samsung.com>
@ -15745,7 +15760,7 @@ L: linux-media@vger.kernel.org
W: http://mjpeg.sourceforge.net/driver-zoran/
T: hg https://linuxtv.org/hg/v4l-dvb
S: Odd Fixes
F: drivers/media/pci/zoran/
F: drivers/staging/media/zoran/
ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
M: Minchan Kim <minchan@kernel.org>

View File

@ -359,7 +359,7 @@ static struct gpiod_lookup_table ov7725_gpios = {
static struct gpiod_lookup_table tw9910_gpios = {
.dev_id = "0-0045",
.table = {
GPIO_LOOKUP("sh7722_pfc", GPIO_PTT2, "pdn", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("sh7722_pfc", GPIO_PTT2, "pdn", GPIO_ACTIVE_LOW),
GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
},
};

View File

@ -691,6 +691,52 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
.atomic_disable = rcar_du_crtc_atomic_disable,
};
static struct drm_crtc_state *
rcar_du_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
{
struct rcar_du_crtc_state *state;
struct rcar_du_crtc_state *copy;
if (WARN_ON(!crtc->state))
return NULL;
state = to_rcar_crtc_state(crtc->state);
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (copy == NULL)
return NULL;
__drm_atomic_helper_crtc_duplicate_state(crtc, &copy->state);
return &copy->state;
}
static void rcar_du_crtc_atomic_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
__drm_atomic_helper_crtc_destroy_state(state);
kfree(to_rcar_crtc_state(state));
}
static void rcar_du_crtc_reset(struct drm_crtc *crtc)
{
struct rcar_du_crtc_state *state;
if (crtc->state) {
rcar_du_crtc_atomic_destroy_state(crtc, crtc->state);
crtc->state = NULL;
}
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL)
return;
state->crc.source = VSP1_DU_CRC_NONE;
state->crc.index = 0;
crtc->state = &state->state;
crtc->state->crtc = crtc;
}
static int rcar_du_crtc_enable_vblank(struct drm_crtc *crtc)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@ -710,17 +756,113 @@ static void rcar_du_crtc_disable_vblank(struct drm_crtc *crtc)
rcrtc->vblank_enable = false;
}
static const struct drm_crtc_funcs crtc_funcs = {
.reset = drm_atomic_helper_crtc_reset,
static int rcar_du_crtc_set_crc_source(struct drm_crtc *crtc,
const char *source_name,
size_t *values_cnt)
{
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct drm_modeset_acquire_ctx ctx;
struct drm_crtc_state *crtc_state;
struct drm_atomic_state *state;
enum vsp1_du_crc_source source;
unsigned int index = 0;
unsigned int i;
int ret;
/*
* Parse the source name. Supported values are "plane%u" to compute the
* CRC on an input plane (%u is the plane ID), and "auto" to compute the
* CRC on the composer (VSP) output.
*/
if (!source_name) {
source = VSP1_DU_CRC_NONE;
} else if (!strcmp(source_name, "auto")) {
source = VSP1_DU_CRC_OUTPUT;
} else if (strstarts(source_name, "plane")) {
source = VSP1_DU_CRC_PLANE;
ret = kstrtouint(source_name + strlen("plane"), 10, &index);
if (ret < 0)
return ret;
for (i = 0; i < rcrtc->vsp->num_planes; ++i) {
if (index == rcrtc->vsp->planes[i].plane.base.id) {
index = i;
break;
}
}
if (i >= rcrtc->vsp->num_planes)
return -EINVAL;
} else {
return -EINVAL;
}
*values_cnt = 1;
/* Perform an atomic commit to set the CRC source. */
drm_modeset_acquire_init(&ctx, 0);
state = drm_atomic_state_alloc(crtc->dev);
if (!state) {
ret = -ENOMEM;
goto unlock;
}
state->acquire_ctx = &ctx;
retry:
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (!IS_ERR(crtc_state)) {
struct rcar_du_crtc_state *rcrtc_state;
rcrtc_state = to_rcar_crtc_state(crtc_state);
rcrtc_state->crc.source = source;
rcrtc_state->crc.index = index;
ret = drm_atomic_commit(state);
} else {
ret = PTR_ERR(crtc_state);
}
if (ret == -EDEADLK) {
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
goto retry;
}
drm_atomic_state_put(state);
unlock:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
return 0;
}
static const struct drm_crtc_funcs crtc_funcs_gen2 = {
.reset = rcar_du_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
.atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
.enable_vblank = rcar_du_crtc_enable_vblank,
.disable_vblank = rcar_du_crtc_disable_vblank,
};
static const struct drm_crtc_funcs crtc_funcs_gen3 = {
.reset = rcar_du_crtc_reset,
.destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.atomic_duplicate_state = rcar_du_crtc_atomic_duplicate_state,
.atomic_destroy_state = rcar_du_crtc_atomic_destroy_state,
.enable_vblank = rcar_du_crtc_enable_vblank,
.disable_vblank = rcar_du_crtc_disable_vblank,
.set_crc_source = rcar_du_crtc_set_crc_source,
};
/* -----------------------------------------------------------------------------
* Interrupt Handling
*/
@ -822,8 +964,10 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
else
primary = &rgrp->planes[swindex % 2].plane;
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
NULL, &crtc_funcs, NULL);
ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, NULL,
rcdu->info->gen <= 2 ?
&crtc_funcs_gen2 : &crtc_funcs_gen3,
NULL);
if (ret < 0)
return ret;

View File

@ -21,6 +21,8 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <media/vsp1.h>
struct rcar_du_group;
struct rcar_du_vsp;
@ -69,6 +71,19 @@ struct rcar_du_crtc {
#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
/**
* struct rcar_du_crtc_state - Driver-specific CRTC state
* @state: base DRM CRTC state
* @crc: CRC computation configuration
*/
struct rcar_du_crtc_state {
struct drm_crtc_state state;
struct vsp1_du_crc_config crc;
};
#define to_rcar_crtc_state(s) container_of(s, struct rcar_du_crtc_state, state)
enum rcar_du_output {
RCAR_DU_OUTPUT_DPAD0,
RCAR_DU_OUTPUT_DPAD1,

View File

@ -32,7 +32,7 @@
#include "rcar_du_kms.h"
#include "rcar_du_vsp.h"
static void rcar_du_vsp_complete(void *private, bool completed)
static void rcar_du_vsp_complete(void *private, bool completed, u32 crc)
{
struct rcar_du_crtc *crtc = private;
@ -41,6 +41,8 @@ static void rcar_du_vsp_complete(void *private, bool completed)
if (completed)
rcar_du_crtc_finish_page_flip(crtc);
drm_crtc_add_crc_entry(&crtc->crtc, false, 0, &crc);
}
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
@ -103,7 +105,13 @@ void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc)
void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc)
{
vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe);
struct vsp1_du_atomic_pipe_config cfg = { { 0, } };
struct rcar_du_crtc_state *state;
state = to_rcar_crtc_state(crtc->crtc.state);
cfg.crc = state->crc;
vsp1_du_atomic_flush(crtc->vsp->vsp, crtc->vsp_pipe, &cfg);
}
/* Keep the two tables in sync. */

View File

@ -78,13 +78,13 @@ config MEDIA_SDR_SUPPORT
Say Y when you have a software defined radio device.
config MEDIA_CEC_SUPPORT
bool "HDMI CEC support"
---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.
source "drivers/media/cec/Kconfig"

View File

@ -339,12 +339,19 @@ static void cec_data_cancel(struct cec_data *data)
data->adap->transmit_queue_sz--;
}
/* Mark it as an error */
data->msg.tx_ts = ktime_get_ns();
data->msg.tx_status |= CEC_TX_STATUS_ERROR |
CEC_TX_STATUS_MAX_RETRIES;
data->msg.tx_error_cnt++;
data->attempts = 0;
if (data->msg.tx_status & CEC_TX_STATUS_OK) {
/* Mark the canceled RX as a timeout */
data->msg.rx_ts = ktime_get_ns();
data->msg.rx_status = CEC_RX_STATUS_TIMEOUT;
} else {
/* Mark the canceled TX as an error */
data->msg.tx_ts = ktime_get_ns();
data->msg.tx_status |= CEC_TX_STATUS_ERROR |
CEC_TX_STATUS_MAX_RETRIES;
data->msg.tx_error_cnt++;
data->attempts = 0;
}
/* Queue transmitted message for monitoring purposes */
cec_queue_msg_monitor(data->adap, &data->msg, 1);

View File

@ -322,7 +322,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
adap->rc->allowed_protocols = RC_PROTO_BIT_CEC;
adap->rc->priv = adap;
adap->rc->map_name = RC_MAP_CEC;
adap->rc->timeout = MS_TO_NS(100);
adap->rc->timeout = MS_TO_NS(550);
#endif
return adap;
}

View File

@ -81,10 +81,9 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
u64 *error;
u8 *args;
bool has_op;
u32 op;
u8 op;
u8 mode;
u8 pos;
u8 v;
p = skip_spaces(p);
token = strsep(&p, delims);
@ -146,12 +145,18 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
comma = strchr(token, ',');
if (comma)
*comma++ = '\0';
if (!strcmp(token, "any"))
op = CEC_ERROR_INJ_OP_ANY;
else if (!kstrtou8(token, 0, &v))
op = v;
else
if (!strcmp(token, "any")) {
has_op = false;
error = pin->error_inj + CEC_ERROR_INJ_OP_ANY;
args = pin->error_inj_args[CEC_ERROR_INJ_OP_ANY];
} else if (!kstrtou8(token, 0, &op)) {
has_op = true;
error = pin->error_inj + op;
args = pin->error_inj_args[op];
} else {
return false;
}
mode = CEC_ERROR_INJ_MODE_ONCE;
if (comma) {
if (!strcmp(comma, "off"))
@ -166,10 +171,6 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
return false;
}
error = pin->error_inj + op;
args = pin->error_inj_args[op];
has_op = op <= 0xff;
token = strsep(&p, delims);
if (p) {
p = skip_spaces(p);
@ -203,16 +204,18 @@ bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
mode_mask = CEC_ERROR_INJ_MODE_MASK << mode_offset;
arg_idx = cec_error_inj_cmds[i].arg_idx;
if (mode_offset == CEC_ERROR_INJ_RX_ARB_LOST_OFFSET ||
mode_offset == CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET)
is_bit_pos = false;
if (mode_offset == CEC_ERROR_INJ_RX_ARB_LOST_OFFSET) {
if (has_op)
return false;
if (!has_pos)
pos = 0x0f;
is_bit_pos = false;
} else if (mode_offset == CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET) {
if (!has_pos || !pos)
return false;
is_bit_pos = false;
}
if (arg_idx >= 0 && is_bit_pos) {
if (!has_pos || pos >= 160)
return false;

View File

@ -119,7 +119,7 @@ static void cec_pin_update(struct cec_pin *pin, bool v, bool force)
if (pin->work_pin_events_dropped) {
pin->work_pin_events_dropped = false;
v |= CEC_PIN_EVENT_FL_DROPPED;
ev |= CEC_PIN_EVENT_FL_DROPPED;
}
pin->work_pin_events[pin->work_pin_events_wr] = ev;
pin->work_pin_ts[pin->work_pin_events_wr] = ktime_get();

View File

@ -495,7 +495,6 @@ static int airstar_atsc2_attach(struct flexcop_device *fc,
/* AirStar ATSC 3rd generation */
#if FE_SUPPORTED(LGDT330X)
static struct lgdt330x_config air2pc_atsc_hd5000_config = {
.demod_address = 0x59,
.demod_chip = LGDT3303,
.serial_mpeg = 0x04,
.clock_polarity_flip = 1,
@ -504,7 +503,8 @@ static struct lgdt330x_config air2pc_atsc_hd5000_config = {
static int airstar_atsc3_attach(struct flexcop_device *fc,
struct i2c_adapter *i2c)
{
fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, i2c);
fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config,
0x59, i2c);
if (!fc->fe)
return 0;

View File

@ -105,40 +105,36 @@ static int flexcop_i2c_write4(struct flexcop_device *fc,
}
int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
flexcop_access_op_t op, u8 chipaddr, u8 addr, u8 *buf, u16 len)
flexcop_access_op_t op, u8 chipaddr,
u8 start_addr, u8 *buf, u16 size)
{
int ret;
#ifdef DUMP_I2C_MESSAGES
int i;
#endif
int len = size;
u8 *p;
u8 addr = start_addr;
u16 bytes_to_transfer;
flexcop_ibi_value r100;
deb_i2c("op = %d\n",op);
deb_i2c("port %d %s(%02x): register %02x, size: %d\n",
i2c->port,
op == FC_READ ? "rd" : "wr",
chipaddr, start_addr, size);
r100.raw = 0;
r100.tw_sm_c_100.chipaddr = chipaddr;
r100.tw_sm_c_100.twoWS_rw = op;
r100.tw_sm_c_100.twoWS_port_reg = i2c->port;
#ifdef DUMP_I2C_MESSAGES
printk(KERN_DEBUG "%d ", i2c->port);
if (op == FC_READ)
printk(KERN_CONT "rd(");
else
printk(KERN_CONT "wr(");
printk(KERN_CONT "%02x): %02x ", chipaddr, addr);
#endif
/* in that case addr is the only value ->
* we write it twice as baseaddr and val0
* BBTI is doing it like that for ISL6421 at least */
if (i2c->no_base_addr && len == 0 && op == FC_WRITE) {
buf = &addr;
buf = &start_addr;
len = 1;
}
p = buf;
while (len != 0) {
bytes_to_transfer = len > 4 ? 4 : len;
@ -146,26 +142,21 @@ int flexcop_i2c_request(struct flexcop_i2c_adapter *i2c,
r100.tw_sm_c_100.baseaddr = addr;
if (op == FC_READ)
ret = flexcop_i2c_read4(i2c, r100, buf);
ret = flexcop_i2c_read4(i2c, r100, p);
else
ret = flexcop_i2c_write4(i2c->fc, r100, buf);
#ifdef DUMP_I2C_MESSAGES
for (i = 0; i < bytes_to_transfer; i++)
printk(KERN_CONT "%02x ", buf[i]);
#endif
ret = flexcop_i2c_write4(i2c->fc, r100, p);
if (ret < 0)
return ret;
buf += bytes_to_transfer;
p += bytes_to_transfer;
addr += bytes_to_transfer;
len -= bytes_to_transfer;
}
#ifdef DUMP_I2C_MESSAGES
printk(KERN_CONT "\n");
#endif
deb_i2c_dump("port %d %s(%02x): register %02x: %*ph\n",
i2c->port,
op == FC_READ ? "rd" : "wr",
chipaddr, start_addr, size, buf);
return 0;
}

View File

@ -42,7 +42,7 @@ int b2c2_flexcop_debug;
EXPORT_SYMBOL_GPL(b2c2_flexcop_debug);
module_param_named(debug, b2c2_flexcop_debug, int, 0644);
MODULE_PARM_DESC(debug,
"set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg (|-able))."
"set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram,32=reg,64=i2cdump (|-able))."
DEBSTATUS);
#undef DEBSTATUS

View File

@ -26,5 +26,6 @@ extern int b2c2_flexcop_debug;
#define deb_ts(args...) dprintk(0x08, args)
#define deb_sram(args...) dprintk(0x10, args)
#define deb_rdump(args...) dprintk(0x20, args)
#define deb_i2c_dump(args...) dprintk(0x40, args)
#endif

View File

@ -308,7 +308,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* prepare the message(s), get number of u32s to transfer */
count = saa7146_i2c_msg_prepare(msgs, num, buffer);
if ( 0 > count ) {
err = -1;
err = -EIO;
goto out;
}
@ -360,7 +360,7 @@ static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *m
/* if any things had to be read, get the results */
if ( 0 != saa7146_i2c_msg_cleanup(msgs, num, buffer)) {
DEB_I2C("could not cleanup i2c-message\n");
err = -1;
err = -EIO;
goto out;
}

View File

@ -415,8 +415,8 @@ EXPORT_SYMBOL_GPL(smscore_get_board_id);
struct smscore_registry_entry_t {
struct list_head entry;
char devpath[32];
int mode;
char devpath[32];
int mode;
enum sms_device_type_st type;
};
@ -442,7 +442,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
next != &g_smscore_registry;
next = next->next) {
entry = (struct smscore_registry_entry_t *) next;
if (!strcmp(entry->devpath, devpath)) {
if (!strncmp(entry->devpath, devpath, sizeof(entry->devpath))) {
kmutex_unlock(&g_smscore_registrylock);
return entry;
}
@ -450,7 +450,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (entry) {
entry->mode = default_mode;
strcpy(entry->devpath, devpath);
strlcpy(entry->devpath, devpath, sizeof(entry->devpath));
list_add(&entry->entry, &g_smscore_registry);
} else
pr_err("failed to create smscore_registry.\n");
@ -649,6 +649,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
*/
int smscore_register_device(struct smsdevice_params_t *params,
struct smscore_device_t **coredev,
gfp_t gfp_buf_flags,
void *mdev)
{
struct smscore_device_t *dev;
@ -661,6 +662,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
dev->media_dev = mdev;
#endif
dev->gfp_buf_flags = gfp_buf_flags;
/* init list entry so it could be safe in smscore_unregister_device */
INIT_LIST_HEAD(&dev->entry);
@ -697,7 +699,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
buffer = dma_alloc_coherent(params->device,
dev->common_buffer_size,
&dev->common_buffer_phys,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | dev->gfp_buf_flags);
if (!buffer) {
smscore_unregister_device(dev);
return -ENOMEM;
@ -733,7 +735,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
dev->postload_handler = params->postload_handler;
dev->device_flags = params->flags;
strcpy(dev->devpath, params->devpath);
strlcpy(dev->devpath, params->devpath, sizeof(dev->devpath));
smscore_registry_settype(dev->devpath, params->device_type);
@ -792,7 +794,7 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
else {
buffer = kmalloc(sizeof(struct sms_msg_data2) +
SMS_DMA_ALIGNMENT,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | coredev->gfp_buf_flags);
if (buffer) {
struct sms_msg_data2 *msg =
(struct sms_msg_data2 *)
@ -933,7 +935,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
}
/* PAGE_SIZE buffer shall be enough and dma aligned */
msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
msg = kmalloc(PAGE_SIZE, GFP_KERNEL | coredev->gfp_buf_flags);
if (!msg)
return -ENOMEM;
@ -1168,7 +1170,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
}
pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
fw_buf = kmalloc(ALIGN(fw->size + sizeof(struct sms_firmware),
SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
SMS_ALLOC_ALIGNMENT), GFP_KERNEL | coredev->gfp_buf_flags);
if (!fw_buf) {
pr_err("failed to allocate firmware buffer\n");
rc = -ENOMEM;
@ -1260,7 +1262,7 @@ EXPORT_SYMBOL_GPL(smscore_unregister_device);
static int smscore_detect_mode(struct smscore_device_t *coredev)
{
void *buffer = kmalloc(sizeof(struct sms_msg_hdr) + SMS_DMA_ALIGNMENT,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | coredev->gfp_buf_flags);
struct sms_msg_hdr *msg =
(struct sms_msg_hdr *) SMS_ALIGN_ADDRESS(buffer);
int rc;
@ -1309,7 +1311,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode)
int rc = 0;
buffer = kmalloc(sizeof(struct sms_msg_data) +
SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
SMS_DMA_ALIGNMENT, GFP_KERNEL | coredev->gfp_buf_flags);
if (!buffer)
return -ENOMEM;
@ -1398,7 +1400,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
buffer = kmalloc(sizeof(struct sms_msg_data) +
SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
SMS_DMA_ALIGNMENT, GFP_KERNEL | coredev->gfp_buf_flags);
if (buffer) {
struct sms_msg_data *msg = (struct sms_msg_data *) SMS_ALIGN_ADDRESS(buffer);
@ -1971,7 +1973,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);
buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | coredev->gfp_buf_flags);
if (!buffer)
return -ENOMEM;
@ -2043,7 +2045,7 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
(3 * sizeof(u32)); /* keep it 3 ! */
buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | coredev->gfp_buf_flags);
if (!buffer)
return -ENOMEM;
@ -2091,7 +2093,7 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
total_len = sizeof(struct sms_msg_hdr) + (2 * sizeof(u32));
buffer = kmalloc(total_len + SMS_DMA_ALIGNMENT,
GFP_KERNEL | GFP_DMA);
GFP_KERNEL | coredev->gfp_buf_flags);
if (!buffer)
return -ENOMEM;

View File

@ -190,6 +190,8 @@ struct smscore_device_t {
int mode, modes_supported;
gfp_t gfp_buf_flags;
/* host <--> device messages */
struct completion version_ex_done, data_download_done, trigger_done;
struct completion data_validity_done, device_ready_done;
@ -1125,6 +1127,7 @@ extern void smscore_unregister_hotplug(hotplug_t hotplug);
extern int smscore_register_device(struct smsdevice_params_t *params,
struct smscore_device_t **coredev,
gfp_t gfp_buf_flags,
void *mdev);
extern void smscore_unregister_device(struct smscore_device_t *coredev);

View File

@ -35,7 +35,7 @@ void smsendian_handle_tx_message(void *buffer)
switch (msg->x_msg_header.msg_type) {
case MSG_SMS_DATA_DOWNLOAD_REQ:
{
msg->msg_data[0] = le32_to_cpu(msg->msg_data[0]);
msg->msg_data[0] = le32_to_cpu((__force __le32)(msg->msg_data[0]));
break;
}
@ -44,7 +44,7 @@ void smsendian_handle_tx_message(void *buffer)
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
break;
}
@ -64,7 +64,7 @@ void smsendian_handle_rx_message(void *buffer)
{
struct sms_version_res *ver =
(struct sms_version_res *) msg;
ver->chip_model = le16_to_cpu(ver->chip_model);
ver->chip_model = le16_to_cpu((__force __le16)ver->chip_model);
break;
}
@ -81,7 +81,7 @@ void smsendian_handle_rx_message(void *buffer)
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]);
break;
}
@ -95,9 +95,9 @@ void smsendian_handle_message_header(void *msg)
#ifdef __BIG_ENDIAN
struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)msg;
phdr->msg_type = le16_to_cpu(phdr->msg_type);
phdr->msg_length = le16_to_cpu(phdr->msg_length);
phdr->msg_flags = le16_to_cpu(phdr->msg_flags);
phdr->msg_type = le16_to_cpu((__force __le16)phdr->msg_type);
phdr->msg_length = le16_to_cpu((__force __le16)phdr->msg_length);
phdr->msg_flags = le16_to_cpu((__force __le16)phdr->msg_flags);
#endif /* __BIG_ENDIAN */
}
EXPORT_SYMBOL_GPL(smsendian_handle_message_header);

View File

@ -12,7 +12,6 @@ config VIDEOBUF2_MEMOPS
config VIDEOBUF2_DMA_CONTIG
tristate
depends on HAS_DMA
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
select DMA_SHARED_BUFFER
@ -25,7 +24,6 @@ config VIDEOBUF2_VMALLOC
config VIDEOBUF2_DMA_SG
tristate
depends on HAS_DMA
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS

View File

@ -916,9 +916,12 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
dprintk(4, "done processing on buffer %d, state: %d\n",
vb->index, state);
/* sync buffers */
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
if (state != VB2_BUF_STATE_QUEUED &&
state != VB2_BUF_STATE_REQUEUEING) {
/* sync buffers */
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
}
spin_lock_irqsave(&q->done_lock, flags);
if (state == VB2_BUF_STATE_QUEUED ||

View File

@ -622,7 +622,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
struct dmxdev_filter *filter,
struct dmxdev_feed *feed)
{
ktime_t timeout = 0;
ktime_t timeout = ktime_set(0, 0);
struct dmx_pes_filter_params *para = &filter->params.pes;
enum dmx_output otype;
int ret;

View File

@ -31,6 +31,7 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/nospec.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
@ -1476,6 +1477,7 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
if (slot >= ca->slot_count)
return -EINVAL;
slot = array_index_nospec(slot, ca->slot_count);
sl = &ca->slot_info[slot];
/* check if the slot is actually running */

View File

@ -190,7 +190,7 @@ dtv_property_legacy_params_sync(struct dvb_frontend *fe,
static bool has_get_frontend(struct dvb_frontend *fe)
{
return fe->ops.get_frontend != NULL;
return fe->ops.get_frontend;
}
/*
@ -272,11 +272,23 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe,
mutex_unlock(&events->mtx);
wake_up_interruptible (&events->wait_queue);
wake_up_interruptible(&events->wait_queue);
}
static int dvb_frontend_test_event(struct dvb_frontend_private *fepriv,
struct dvb_fe_events *events)
{
int ret;
up(&fepriv->sem);
ret = events->eventw != events->eventr;
down(&fepriv->sem);
return ret;
}
static int dvb_frontend_get_event(struct dvb_frontend *fe,
struct dvb_frontend_event *event, int flags)
struct dvb_frontend_event *event, int flags)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_fe_events *events = &fepriv->events;
@ -294,13 +306,8 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
if (flags & O_NONBLOCK)
return -EWOULDBLOCK;
up(&fepriv->sem);
ret = wait_event_interruptible (events->wait_queue,
events->eventw != events->eventr);
if (down_interruptible (&fepriv->sem))
return -ERESTARTSYS;
ret = wait_event_interruptible(events->wait_queue,
dvb_frontend_test_event(fepriv, events));
if (ret < 0)
return ret;
@ -327,8 +334,8 @@ static void dvb_frontend_clear_events(struct dvb_frontend *fe)
static void dvb_frontend_init(struct dvb_frontend *fe)
{
dev_dbg(fe->dvb->device,
"%s: initialising adapter %i frontend %i (%s)...\n",
__func__, fe->dvb->num, fe->id, fe->ops.info.name);
"%s: initialising adapter %i frontend %i (%s)...\n",
__func__, fe->dvb->num, fe->id, fe->ops.info.name);
if (fe->ops.init)
fe->ops.init(fe);
@ -358,14 +365,14 @@ static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepr
dev_dbg(fe->dvb->device, "%s:\n", __func__);
if (locked)
(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
(fepriv->quality) = (fepriv->quality * 220 + 36 * 256) / 256;
else
(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
q2 = fepriv->quality - 128;
q2 *= q2;
fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
fepriv->delay = fepriv->min_delay + q2 * HZ / (128 * 128);
}
/**
@ -393,7 +400,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
(c->inversion == INVERSION_AUTO));
/* setup parameters correctly */
while(!ready) {
while (!ready) {
/* calculate the lnb_drift */
fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size;
@ -405,7 +412,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
}
/* perform inversion and +/- zigzag */
switch(fepriv->auto_sub_step) {
switch (fepriv->auto_sub_step) {
case 0:
/* try with the current inversion and current drift setting */
ready = 1;
@ -450,11 +457,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
return 1;
}
dev_dbg(fe->dvb->device, "%s: drift:%i inversion:%i auto_step:%i " \
"auto_sub_step:%i started_auto_step:%i\n",
__func__, fepriv->lnb_drift, fepriv->inversion,
fepriv->auto_step, fepriv->auto_sub_step,
fepriv->started_auto_step);
dev_dbg(fe->dvb->device,
"%s: drift:%i inversion:%i auto_step:%i auto_sub_step:%i started_auto_step:%i\n",
__func__, fepriv->lnb_drift, fepriv->inversion,
fepriv->auto_step, fepriv->auto_sub_step,
fepriv->started_auto_step);
/* set the frontend itself */
c->frequency += fepriv->lnb_drift;
@ -485,7 +492,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
/* if we've got no parameters, just keep idling */
if (fepriv->state & FESTATE_IDLE) {
fepriv->delay = 3*HZ;
fepriv->delay = 3 * HZ;
fepriv->quality = 0;
return;
}
@ -502,7 +509,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
else
fepriv->state = FESTATE_TUNED;
}
fepriv->delay = 3*HZ;
fepriv->delay = 3 * HZ;
fepriv->quality = 0;
return;
}
@ -591,7 +598,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
}
fepriv->check_wrapped = 1;
/* if we've just retuned, enter the ZIGZAG_FAST state.
/* if we've just re-tuned, enter the ZIGZAG_FAST state.
* This ensures we cannot return from an
* FE_SET_FRONTEND ioctl before the first frontend tune
* occurs */
@ -658,7 +665,7 @@ static int dvb_frontend_thread(void *data)
fepriv->check_wrapped = 0;
fepriv->quality = 0;
fepriv->delay = 3*HZ;
fepriv->delay = 3 * HZ;
fepriv->status = 0;
fepriv->wakeup = 0;
fepriv->reinitialise = 0;
@ -670,8 +677,9 @@ static int dvb_frontend_thread(void *data)
up(&fepriv->sem); /* is locked when we enter the thread... */
restart:
wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe) || kthread_should_stop()
|| freezing(current),
dvb_frontend_should_wakeup(fe) ||
kthread_should_stop() ||
freezing(current),
fepriv->delay);
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
@ -820,8 +828,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
/* paranoia check in case a signal arrived */
if (fepriv->thread)
dev_warn(fe->dvb->device,
"dvb_frontend_stop: warning: thread %p won't exit\n",
fepriv->thread);
"dvb_frontend_stop: warning: thread %p won't exit\n",
fepriv->thread);
}
/*
@ -858,12 +866,12 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
if (fe->exit == DVB_FE_NO_EXIT)
return 0;
else
dvb_frontend_stop (fe);
dvb_frontend_stop(fe);
}
if (signal_pending(current))
return -EINTR;
if (down_interruptible (&fepriv->sem))
if (down_interruptible(&fepriv->sem))
return -EINTR;
fepriv->state = FESTATE_IDLE;
@ -872,12 +880,12 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
mb();
fe_thread = kthread_run(dvb_frontend_thread, fe,
"kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
"kdvb-ad-%i-fe-%i", fe->dvb->num, fe->id);
if (IS_ERR(fe_thread)) {
ret = PTR_ERR(fe_thread);
dev_warn(fe->dvb->device,
"dvb_frontend_start: failed to start kthread (%d)\n",
ret);
"dvb_frontend_start: failed to start kthread (%d)\n",
ret);
up(&fepriv->sem);
return ret;
}
@ -886,7 +894,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
}
static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
u32 *freq_min, u32 *freq_max)
u32 *freq_min, u32 *freq_max)
{
*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
@ -898,8 +906,9 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
*freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
if (*freq_min == 0 || *freq_max == 0)
dev_warn(fe->dvb->device, "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
fe->dvb->num, fe->id);
dev_warn(fe->dvb->device,
"DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
fe->dvb->num, fe->id);
}
static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
@ -913,8 +922,8 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
if ((freq_min && c->frequency < freq_min) ||
(freq_max && c->frequency > freq_max)) {
dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
fe->dvb->num, fe->id, c->frequency,
freq_min, freq_max);
fe->dvb->num, fe->id, c->frequency,
freq_min, freq_max);
return -EINVAL;
}
@ -930,9 +939,9 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
(fe->ops.info.symbol_rate_max &&
c->symbol_rate > fe->ops.info.symbol_rate_max)) {
dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
fe->dvb->num, fe->id, c->symbol_rate,
fe->ops.info.symbol_rate_min,
fe->ops.info.symbol_rate_max);
fe->dvb->num, fe->id, c->symbol_rate,
fe->ops.info.symbol_rate_min,
fe->ops.info.symbol_rate_max);
return -EINVAL;
}
default:
@ -953,7 +962,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
c->delivery_system = delsys;
dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n",
__func__, c->delivery_system);
__func__, c->delivery_system);
c->transmission_mode = TRANSMISSION_MODE_AUTO;
c->bandwidth_hz = 0; /* AUTO */
@ -973,7 +982,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
c->isdbt_sb_subchannel = 0;
c->isdbt_sb_segment_idx = 0;
c->isdbt_sb_segment_count = 0;
c->isdbt_layer_enabled = 0;
c->isdbt_layer_enabled = 7; /* All layers (A,B,C) */
for (i = 0; i < 3; i++) {
c->layer[i].fec = FEC_AUTO;
c->layer[i].modulation = QAM_AUTO;
@ -1178,8 +1187,8 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
break;
case DVBV3_UNKNOWN:
dev_err(fe->dvb->device,
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
return -EINVAL;
}
@ -1200,8 +1209,8 @@ dtv_property_legacy_params_sync(struct dvb_frontend *fe,
switch (dvbv3_type(c->delivery_system)) {
case DVBV3_UNKNOWN:
dev_err(fe->dvb->device,
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
return -EINVAL;
case DVBV3_QPSK:
dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
@ -1293,7 +1302,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
{
int ncaps;
switch(tvp->cmd) {
switch (tvp->cmd) {
case DTV_ENUM_DELSYS:
ncaps = 0;
while (ncaps < MAX_DELSYS && fe->ops.delsys[ncaps]) {
@ -1622,8 +1631,8 @@ static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
if (fe->ops.delsys[ncaps] == desired_system) {
c->delivery_system = desired_system;
dev_dbg(fe->dvb->device,
"%s: Changing delivery system to %d\n",
__func__, desired_system);
"%s: Changing delivery system to %d\n",
__func__, desired_system);
return 0;
}
ncaps++;
@ -1715,8 +1724,8 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
*/
if (is_dvbv3_delsys(c->delivery_system)) {
dev_dbg(fe->dvb->device,
"%s: Using delivery system to %d\n",
__func__, c->delivery_system);
"%s: Using delivery system to %d\n",
__func__, c->delivery_system);
return 0;
}
@ -1756,8 +1765,8 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
* Zero on success, negative errno on failure.
*/
static int dtv_property_process_set(struct dvb_frontend *fe,
struct file *file,
u32 cmd, u32 data)
struct file *file,
u32 cmd, u32 data)
{
int r = 0;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@ -1765,11 +1774,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
/** Dump DTV command name and value*/
if (!cmd || cmd > DTV_MAX_COMMAND)
dev_warn(fe->dvb->device, "%s: SET cmd 0x%08x undefined\n",
__func__, cmd);
__func__, cmd);
else
dev_dbg(fe->dvb->device,
"%s: SET cmd 0x%08x (%s) to 0x%08x\n",
__func__, cmd, dtv_cmds[cmd].name, data);
"%s: SET cmd 0x%08x (%s) to 0x%08x\n",
__func__, cmd, dtv_cmds[cmd].name, data);
switch (cmd) {
case DTV_CLEAR:
/*
@ -1819,12 +1828,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
case DTV_VOLTAGE:
c->voltage = data;
r = dvb_frontend_handle_ioctl(file, FE_SET_VOLTAGE,
(void *)c->voltage);
(void *)c->voltage);
break;
case DTV_TONE:
c->sectone = data;
r = dvb_frontend_handle_ioctl(file, FE_SET_TONE,
(void *)c->sectone);
(void *)c->sectone);
break;
case DTV_CODE_RATE_HP:
c->code_rate_HP = data;
@ -2045,8 +2054,8 @@ static int dvb_frontend_handle_compat_ioctl(struct file *file, unsigned int cmd,
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_set(fe, file,
(tvp + i)->cmd,
(tvp + i)->u.data);
(tvp + i)->cmd,
(tvp + i)->u.data);
if (err < 0) {
kfree(tvp);
return err;
@ -2265,7 +2274,6 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
return 0;
}
static int dvb_frontend_handle_ioctl(struct file *file,
unsigned int cmd, void *parg)
{
@ -2300,8 +2308,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_set(fe, file,
(tvp + i)->cmd,
(tvp + i)->u.data);
(tvp + i)->cmd,
(tvp + i)->u.data);
if (err < 0) {
kfree(tvp);
return err;
@ -2365,7 +2373,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
}
case FE_GET_INFO: {
struct dvb_frontend_info* info = parg;
struct dvb_frontend_info *info = parg;
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
@ -2396,12 +2404,12 @@ static int dvb_frontend_handle_ioctl(struct file *file,
break;
default:
dev_err(fe->dvb->device,
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
"%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
__func__, c->delivery_system);
fe->ops.info.type = FE_OFDM;
}
dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
__func__, c->delivery_system, fe->ops.info.type);
__func__, c->delivery_system, fe->ops.info.type);
/* Set CAN_INVERSION_AUTO bit on in other than oneshot mode */
if (!(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT))
@ -2417,7 +2425,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
* that user get signal state from previous tuning */
if (fepriv->state == FESTATE_RETUNE ||
fepriv->state == FESTATE_ERROR) {
err=0;
err = 0;
*status = 0;
break;
}
@ -2485,11 +2493,11 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_ENABLE_HIGH_LNB_VOLTAGE:
if (fe->ops.enable_high_lnb_voltage)
err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
err = fe->ops.enable_high_lnb_voltage(fe, (long)parg);
break;
case FE_SET_FRONTEND_TUNE_MODE:
fepriv->tune_mode_flags = (unsigned long) parg;
fepriv->tune_mode_flags = (unsigned long)parg;
err = 0;
break;
@ -2518,11 +2526,12 @@ static int dvb_frontend_handle_ioctl(struct file *file,
* initialization, so parg is 8 bits and does not
* include the initialization or start bit
*/
unsigned long swcmd = ((unsigned long) parg) << 1;
unsigned long swcmd = ((unsigned long)parg) << 1;
ktime_t nexttime;
ktime_t tv[10];
int i;
u8 last = 1;
if (dvb_frontend_debug)
dprintk("%s switch command: 0x%04lx\n",
__func__, swcmd);
@ -2537,7 +2546,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
for (i = 0; i < 9; i++) {
if (dvb_frontend_debug)
tv[i+1] = ktime_get_boottime();
tv[i + 1] = ktime_get_boottime();
if ((swcmd & 0x01) != last) {
/* set voltage to (last ? 13V : 18V) */
fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
@ -2552,7 +2561,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
__func__, fe->dvb->num);
for (i = 1; i < 10; i++)
pr_info("%d: %d\n", i,
(int) ktime_us_delta(tv[i], tv[i-1]));
(int)ktime_us_delta(tv[i], tv[i - 1]));
}
err = 0;
fepriv->state = FESTATE_DISEQC;
@ -2611,7 +2620,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
err = dtv_set_frontend(fe);
break;
case FE_GET_EVENT:
err = dvb_frontend_get_event (fe, parg, file->f_flags);
err = dvb_frontend_get_event(fe, parg, file->f_flags);
break;
case FE_GET_FRONTEND: {
@ -2634,7 +2643,6 @@ static int dvb_frontend_handle_ioctl(struct file *file,
return err;
}
static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
{
struct dvb_device *dvbdev = file->private_data;
@ -2643,7 +2651,7 @@ static __poll_t dvb_frontend_poll(struct file *file, struct poll_table_struct *w
dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__);
poll_wait (file, &fepriv->events.wait_queue, wait);
poll_wait(file, &fepriv->events.wait_queue, wait);
if (fepriv->events.eventw != fepriv->events.eventr)
return (EPOLLIN | EPOLLRDNORM | EPOLLPRI);
@ -2664,9 +2672,9 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
return -ENODEV;
if (adapter->mfe_shared) {
mutex_lock (&adapter->mfe_lock);
mutex_lock(&adapter->mfe_lock);
if (adapter->mfe_dvbdev == NULL)
if (!adapter->mfe_dvbdev)
adapter->mfe_dvbdev = dvbdev;
else if (adapter->mfe_dvbdev != dvbdev) {
@ -2678,23 +2686,23 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
*mfepriv = mfe->frontend_priv;
int mferetry = (dvb_mfe_wait_time << 1);
mutex_unlock (&adapter->mfe_lock);
mutex_unlock(&adapter->mfe_lock);
while (mferetry-- && (mfedev->users != -1 ||
mfepriv->thread != NULL)) {
if(msleep_interruptible(500)) {
if(signal_pending(current))
mfepriv->thread)) {
if (msleep_interruptible(500)) {
if (signal_pending(current))
return -EINTR;
}
}
mutex_lock (&adapter->mfe_lock);
if(adapter->mfe_dvbdev != dvbdev) {
mutex_lock(&adapter->mfe_lock);
if (adapter->mfe_dvbdev != dvbdev) {
mfedev = adapter->mfe_dvbdev;
mfe = mfedev->priv;
mfepriv = mfe->frontend_priv;
if (mfedev->users != -1 ||
mfepriv->thread != NULL) {
mutex_unlock (&adapter->mfe_lock);
mfepriv->thread) {
mutex_unlock(&adapter->mfe_lock);
return -EBUSY;
}
adapter->mfe_dvbdev = dvbdev;
@ -2715,7 +2723,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
fepriv->reinitialise = 1;
}
if ((ret = dvb_generic_open (inode, file)) < 0)
if ((ret = dvb_generic_open(inode, file)) < 0)
goto err1;
if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
@ -2725,6 +2733,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
fepriv->voltage = -1;
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_lock(&fe->dvb->mdev_lock);
if (fe->dvb->mdev) {
mutex_lock(&fe->dvb->mdev->graph_mutex);
if (fe->dvb->mdev->enable_source)
@ -2733,13 +2742,15 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
&fepriv->pipe);
mutex_unlock(&fe->dvb->mdev->graph_mutex);
if (ret) {
mutex_unlock(&fe->dvb->mdev_lock);
dev_err(fe->dvb->device,
"Tuner is busy. Error %d\n", ret);
goto err2;
}
}
mutex_unlock(&fe->dvb->mdev_lock);
#endif
ret = dvb_frontend_start (fe);
ret = dvb_frontend_start(fe);
if (ret)
goto err3;
@ -2750,17 +2761,19 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
dvb_frontend_get(fe);
if (adapter->mfe_shared)
mutex_unlock (&adapter->mfe_lock);
mutex_unlock(&adapter->mfe_lock);
return ret;
err3:
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_lock(&fe->dvb->mdev_lock);
if (fe->dvb->mdev) {
mutex_lock(&fe->dvb->mdev->graph_mutex);
if (fe->dvb->mdev->disable_source)
fe->dvb->mdev->disable_source(dvbdev->entity);
mutex_unlock(&fe->dvb->mdev->graph_mutex);
}
mutex_unlock(&fe->dvb->mdev_lock);
err2:
#endif
dvb_generic_release(inode, file);
@ -2769,7 +2782,7 @@ err1:
fe->ops.ts_bus_ctrl(fe, 0);
err0:
if (adapter->mfe_shared)
mutex_unlock (&adapter->mfe_lock);
mutex_unlock(&adapter->mfe_lock);
return ret;
}
@ -2787,17 +2800,19 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
mb();
}
ret = dvb_generic_release (inode, file);
ret = dvb_generic_release(inode, file);
if (dvbdev->users == -1) {
wake_up(&fepriv->wait_queue);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_lock(&fe->dvb->mdev_lock);
if (fe->dvb->mdev) {
mutex_lock(&fe->dvb->mdev->graph_mutex);
if (fe->dvb->mdev->disable_source)
fe->dvb->mdev->disable_source(dvbdev->entity);
mutex_unlock(&fe->dvb->mdev->graph_mutex);
}
mutex_unlock(&fe->dvb->mdev_lock);
#endif
if (fe->exit != DVB_FE_NO_EXIT)
wake_up(&dvbdev->wait_queue);
@ -2827,7 +2842,7 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
int ret = 0;
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
fe->id);
if (fe->ops.tuner_ops.suspend)
ret = fe->ops.tuner_ops.suspend(fe);
@ -2847,7 +2862,7 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
int ret = 0;
dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
fe->id);
fe->id);
fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init)
@ -2871,14 +2886,14 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
}
EXPORT_SYMBOL(dvb_frontend_resume);
int dvb_register_frontend(struct dvb_adapter* dvb,
struct dvb_frontend* fe)
int dvb_register_frontend(struct dvb_adapter *dvb,
struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv;
const struct dvb_device dvbdev_template = {
.users = ~0,
.writers = 1,
.readers = (~0)-1,
.readers = (~0) - 1,
.fops = &dvb_frontend_fops,
#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
.name = fe->ops.info.name,
@ -2891,7 +2906,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
return -ERESTARTSYS;
fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
if (fe->frontend_priv == NULL) {
if (!fe->frontend_priv) {
mutex_unlock(&frontend_mutex);
return -ENOMEM;
}
@ -2907,18 +2922,18 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
dvb_frontend_get(fe);
sema_init(&fepriv->sem, 1);
init_waitqueue_head (&fepriv->wait_queue);
init_waitqueue_head (&fepriv->events.wait_queue);
init_waitqueue_head(&fepriv->wait_queue);
init_waitqueue_head(&fepriv->events.wait_queue);
mutex_init(&fepriv->events.mtx);
fe->dvb = dvb;
fepriv->inversion = INVERSION_OFF;
dev_info(fe->dvb->device,
"DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num, fe->id, fe->ops.info.name);
"DVB: registering adapter %i frontend %i (%s)...\n",
fe->dvb->num, fe->id, fe->ops.info.name);
dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
fe, DVB_DEVICE_FRONTEND, 0);
/*
* Initialize the cache to the proper values according with the
@ -2933,9 +2948,10 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
}
EXPORT_SYMBOL(dvb_register_frontend);
int dvb_unregister_frontend(struct dvb_frontend* fe)
int dvb_unregister_frontend(struct dvb_frontend *fe)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
dev_dbg(fe->dvb->device, "%s:\n", __func__);
mutex_lock(&frontend_mutex);
@ -2960,7 +2976,7 @@ static void dvb_frontend_invoke_release(struct dvb_frontend *fe,
}
}
void dvb_frontend_detach(struct dvb_frontend* fe)
void dvb_frontend_detach(struct dvb_frontend *fe)
{
dvb_frontend_invoke_release(fe, fe->ops.release_sec);
dvb_frontend_invoke_release(fe, fe->ops.tuner_ops.release);

View File

@ -1005,7 +1005,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
return 0;
}
static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t dvb_net_tx(struct sk_buff *skb, struct net_device *dev)
{
dev_kfree_skb(skb);
return NETDEV_TX_OK;

View File

@ -859,6 +859,10 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
adap->mfe_dvbdev = NULL;
mutex_init (&adap->mfe_lock);
#ifdef CONFIG_MEDIA_CONTROLLER_DVB
mutex_init(&adap->mdev_lock);
#endif
list_add_tail (&adap->list_head, &dvb_adapter_list);
mutex_unlock(&dvbdev_register_lock);

View File

@ -903,7 +903,7 @@ comment "Common Interface (EN50221) controller drivers"
depends on DVB_CORE
config DVB_CXD2099
tristate "CXD2099AR Common Interface driver"
tristate "Sony CXD2099AR Common Interface driver"
depends on DVB_CORE && I2C
select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT

View File

@ -1,6 +1,6 @@
/*
* Abilis Systems Single DVB-T Receiver
* Copyright (C) 2014 Mauro Carvalho Chehab <m.chehab@samsung.com>
* Copyright (C) 2014 Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
*
* 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

View File

@ -280,14 +280,12 @@ static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
AU8522_TOREGAAGC_REG0E5H_CVBS);
au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
if (is_svideo) {
/* Despite what the table says, for the HVR-950q we still need
to be in CVBS mode for the S-Video input (reason unknown). */
/* filter_coef_type = 3; */
filter_coef_type = 5;
} else {
filter_coef_type = 5;
}
/*
* Despite what the table says, for the HVR-950q we still need
* to be in CVBS mode for the S-Video input (reason unknown).
*/
/* filter_coef_type = 3; */
filter_coef_type = 5;
/* Load the Video Decoder Filter Coefficients */
for (i = 0; i < NUM_FILTER_COEF; i++) {

View File

@ -1456,7 +1456,7 @@ static int cx24116_tune(struct dvb_frontend *fe, bool re_tune,
return cx24116_read_status(fe, status);
}
static int cx24116_get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo cx24116_get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -1555,7 +1555,7 @@ static int cx24117_tune(struct dvb_frontend *fe, bool re_tune,
return cx24117_read_status(fe, status);
}
static int cx24117_get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo cx24117_get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -1491,7 +1491,7 @@ static int cx24120_tune(struct dvb_frontend *fe, bool re_tune,
return cx24120_read_status(fe, status);
}
static int cx24120_get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo cx24120_get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -1005,7 +1005,7 @@ static int cx24123_tune(struct dvb_frontend *fe,
return retval;
}
static int cx24123_get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo cx24123_get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -1,5 +1,5 @@
/*
* cxd2099.c: Driver for the CXD2099AR Common Interface Controller
* cxd2099.c: Driver for the Sony CXD2099AR Common Interface Controller
*
* Copyright (C) 2010-2013 Digital Devices GmbH
*
@ -699,6 +699,6 @@ static struct i2c_driver cxd2099_driver = {
module_i2c_driver(cxd2099_driver);
MODULE_DESCRIPTION("CXD2099AR Common Interface controller driver");
MODULE_DESCRIPTION("Sony CXD2099AR Common Interface controller driver");
MODULE_AUTHOR("Ralph Metzler");
MODULE_LICENSE("GPL");

View File

@ -1,5 +1,5 @@
/*
* cxd2099.h: Driver for the CXD2099AR Common Interface Controller
* cxd2099.h: Driver for the Sony CXD2099AR Common Interface Controller
*
* Copyright (C) 2010-2011 Digital Devices GmbH
*

View File

@ -403,7 +403,7 @@ error:
return DVBFE_ALGO_SEARCH_ERROR;
}
static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
static enum dvbfe_algo cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_CUSTOM;
}

View File

@ -7,6 +7,6 @@
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#define CXD2880_TNRDMD_DRIVER_VERSION "1.4.1 - 1.0.4"
#define CXD2880_TNRDMD_DRIVER_VERSION "1.4.1 - 1.0.5"
#define CXD2880_TNRDMD_DRIVER_RELEASE_DATE "2018-01-17"
#define CXD2880_TNRDMD_DRIVER_RELEASE_DATE "2018-04-25"

View File

@ -520,6 +520,15 @@ static int cxd2880_init(struct dvb_frontend *fe)
pr_err("cxd2880 integ init failed %d\n", ret);
return ret;
}
ret = cxd2880_tnrdmd_set_cfg(&priv->tnrdmd,
CXD2880_TNRDMD_CFG_TSPIN_CURRENT,
0x00);
if (ret) {
mutex_unlock(priv->spi_mutex);
pr_err("cxd2880 set config failed %d\n", ret);
return ret;
}
mutex_unlock(priv->spi_mutex);
pr_debug("OK.\n");
@ -1126,7 +1135,7 @@ static int cxd2880_get_stats(struct dvb_frontend *fe,
priv = fe->demodulator_priv;
c = &fe->dtv_property_cache;
if (!(status & FE_HAS_LOCK)) {
if (!(status & FE_HAS_LOCK) || !(status & FE_HAS_CARRIER)) {
c->pre_bit_error.len = 1;
c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.len = 1;
@ -1345,7 +1354,8 @@ static int cxd2880_read_status(struct dvb_frontend *fe,
pr_debug("status %d\n", *status);
if (priv->s == 0 && (*status & FE_HAS_LOCK)) {
if (priv->s == 0 && (*status & FE_HAS_LOCK) &&
(*status & FE_HAS_CARRIER)) {
mutex_lock(priv->spi_mutex);
if (c->delivery_system == SYS_DVBT) {
ret = cxd2880_set_ber_per_period_t(fe);

View File

@ -533,6 +533,45 @@ static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
}
};
/* Infineon TUA6034 ISDB-T, used in Friio */
/* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */
static const struct dvb_pll_desc dvb_pll_tua6034_friio = {
.name = "Infineon TUA6034 ISDB-T (Friio)",
.min = 90000000,
.max = 770000000,
.iffreq = 57000000,
.initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },
.sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b },
.count = 3,
.entries = {
{ 170000000, 142857, 0xba, 0x09 },
{ 470000000, 142857, 0xba, 0x0a },
{ 770000000, 142857, 0xb2, 0x08 },
}
};
/* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */
static const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = {
.name = "Philips TDA6651 ISDB-T (EarthSoft PT1)",
.min = 90000000,
.max = 770000000,
.iffreq = 57000000,
.initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 },
.count = 10,
.entries = {
{ 140000000, 142857, 0xc1, 0x81 },
{ 170000000, 142857, 0xc1, 0xa1 },
{ 220000000, 142857, 0xc1, 0x62 },
{ 330000000, 142857, 0xc1, 0xa2 },
{ 402000000, 142857, 0xc1, 0xe2 },
{ 450000000, 142857, 0xc1, 0x64 },
{ 550000000, 142857, 0xc1, 0x84 },
{ 600000000, 142857, 0xc1, 0xa4 },
{ 700000000, 142857, 0xc1, 0xc4 },
{ 770000000, 142857, 0xc1, 0xe4 },
}
};
/* ----------------------------------------------------------- */
static const struct dvb_pll_desc *pll_list[] = {
@ -556,6 +595,8 @@ static const struct dvb_pll_desc *pll_list[] = {
[DVB_PLL_SAMSUNG_TDTC9251DH0] = &dvb_pll_samsung_tdtc9251dh0,
[DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132,
[DVB_PLL_SAMSUNG_TBMU24112] = &dvb_pll_samsung_tbmu24112,
[DVB_PLL_TUA6034_FRIIO] = &dvb_pll_tua6034_friio,
[DVB_PLL_TDA665X_EARTH_PT1] = &dvb_pll_tda665x_earth_pt1,
};
/* ----------------------------------------------------------- */
@ -827,6 +868,75 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
}
EXPORT_SYMBOL(dvb_pll_attach);
static int
dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct dvb_pll_config *cfg;
struct dvb_frontend *fe;
unsigned int desc_id;
cfg = client->dev.platform_data;
fe = cfg->fe;
i2c_set_clientdata(client, fe);
desc_id = (unsigned int) id->driver_data;
if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
return -ENOMEM;
dev_info(&client->dev, "DVB Simple Tuner attached.\n");
return 0;
}
static int dvb_pll_remove(struct i2c_client *client)
{
struct dvb_frontend *fe;
fe = i2c_get_clientdata(client);
dvb_pll_release(fe);
return 0;
}
static const struct i2c_device_id dvb_pll_id[] = {
{"dtt7579", DVB_PLL_THOMSON_DTT7579},
{"dtt759x", DVB_PLL_THOMSON_DTT759X},
{"z201", DVB_PLL_LG_Z201},
{"unknown_1", DVB_PLL_UNKNOWN_1},
{"tua6010xs", DVB_PLL_TUA6010XS},
{"env57h1xd5", DVB_PLL_ENV57H1XD5},
{"tua6034", DVB_PLL_TUA6034},
{"tda665x", DVB_PLL_TDA665X},
{"tded4", DVB_PLL_TDED4},
{"tdhu2", DVB_PLL_TDHU2},
{"tbmv", DVB_PLL_SAMSUNG_TBMV},
{"sd1878_tda8261", DVB_PLL_PHILIPS_SD1878_TDA8261},
{"opera1", DVB_PLL_OPERA1},
{"dtos403ih102a", DVB_PLL_SAMSUNG_DTOS403IH102A},
{"tdtc9251dh0", DVB_PLL_SAMSUNG_TDTC9251DH0},
{"tbdu18132", DVB_PLL_SAMSUNG_TBDU18132},
{"tbmu24112", DVB_PLL_SAMSUNG_TBMU24112},
{"tdee4", DVB_PLL_TDEE4},
{"dtt7520x", DVB_PLL_THOMSON_DTT7520X},
{"tua6034_friio", DVB_PLL_TUA6034_FRIIO},
{"tda665x_earthpt1", DVB_PLL_TDA665X_EARTH_PT1},
{}
};
MODULE_DEVICE_TABLE(i2c, dvb_pll_id);
static struct i2c_driver dvb_pll_driver = {
.driver = {
.name = "dvb_pll",
},
.probe = dvb_pll_probe,
.remove = dvb_pll_remove,
.id_table = dvb_pll_id,
};
module_i2c_driver(dvb_pll_driver);
MODULE_DESCRIPTION("dvb pll library");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");

View File

@ -29,6 +29,12 @@
#define DVB_PLL_SAMSUNG_TBMU24112 17
#define DVB_PLL_TDEE4 18
#define DVB_PLL_THOMSON_DTT7520X 19
#define DVB_PLL_TUA6034_FRIIO 20
#define DVB_PLL_TDA665X_EARTH_PT1 21
struct dvb_pll_config {
struct dvb_frontend *fe;
};
#if IS_REACHABLE(CONFIG_DVB_PLL)
/**

View File

@ -546,7 +546,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
/* Responds to all reads with 0 */
if (l64781_readreg(state, 0x1a) != 0) {
dprintk("Read 1 returned unexpcted value\n");
dprintk("Read 1 returned unexpected value\n");
goto error;
}
@ -555,7 +555,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
/* Responds with register default value */
if (l64781_readreg(state, 0x1a) != 0xa1) {
dprintk("Read 2 returned unexpcted value\n");
dprintk("Read 2 returned unexpected value\n");
goto error;
}

View File

@ -1784,7 +1784,7 @@ static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
return 0;
}
static int lgdt3306a_search(struct dvb_frontend *fe)
static enum dvbfe_search lgdt3306a_search(struct dvb_frontend *fe)
{
enum fe_status status = 0;
int ret;

File diff suppressed because it is too large Load Diff

View File

@ -26,34 +26,41 @@ typedef enum lg_chip_t {
LGDT3303
}lg_chip_type;
/**
* struct lgdt330x_config - contains lgdt330x configuration
*
* @demod_chip: LG demodulator chip LGDT3302 or LGDT3303
* @serial_mpeg: MPEG hardware interface - 0:parallel 1:serial
* @pll_rf_set: Callback function to set PLL interface
* @set_ts_params: Callback function to set device param for start_dma
* @clock_polarity_flip:
* Flip the polarity of the mpeg data transfer clock using alternate
* init data.
* This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled
* @get_dvb_frontend:
* returns the frontend associated with this I2C client.
* Filled by the driver.
*/
struct lgdt330x_config
{
/* The demodulator's i2c address */
u8 demod_address;
/* LG demodulator chip LGDT3302 or LGDT3303 */
lg_chip_type demod_chip;
/* MPEG hardware interface - 0:parallel 1:serial */
int serial_mpeg;
/* PLL interface */
int (*pll_rf_set) (struct dvb_frontend* fe, int index);
/* Need to set device param for start_dma */
int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
/* Flip the polarity of the mpeg data transfer clock using alternate init data
* This option applies ONLY to LGDT3303 - 0:disabled (default) 1:enabled */
int clock_polarity_flip;
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
};
#if IS_REACHABLE(CONFIG_DVB_LGDT330X)
extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c);
struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *config,
u8 demod_address,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
struct i2c_adapter* i2c)
static inline
struct dvb_frontend *lgdt330x_attach(const struct lgdt330x_config *config,
u8 demod_address,
struct i2c_adapter *i2c)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;

View File

@ -2055,7 +2055,7 @@ static void mb86a20s_release(struct dvb_frontend *fe)
kfree(state);
}
static int mb86a20s_get_frontend_algo(struct dvb_frontend *fe)
static enum dvbfe_algo mb86a20s_get_frontend_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -375,7 +375,7 @@ static void release(struct dvb_frontend *fe)
kfree(state);
}
static int get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -464,7 +464,7 @@ static int s921_tune(struct dvb_frontend *fe,
return rc;
}
static int s921_get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo s921_get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}

View File

@ -1200,7 +1200,6 @@ static int probe(struct stv *state)
write_reg(state, RSTV0910_P1_TSCFGM, 0xC0); /* Manual speed */
write_reg(state, RSTV0910_P1_TSCFGL, 0x20);
/* Speed = 67.5 MHz */
write_reg(state, RSTV0910_P1_TSSPEED, state->tsspeed);
write_reg(state, RSTV0910_P2_TSCFGH, state->tscfgh | 0x01);
@ -1208,7 +1207,6 @@ static int probe(struct stv *state)
write_reg(state, RSTV0910_P2_TSCFGM, 0xC0); /* Manual speed */
write_reg(state, RSTV0910_P2_TSCFGL, 0x20);
/* Speed = 67.5 MHz */
write_reg(state, RSTV0910_P2_TSSPEED, state->tsspeed);
/* Reset stream merger */
@ -1220,6 +1218,12 @@ static int probe(struct stv *state)
write_reg(state, RSTV0910_P1_I2CRPT, state->i2crpt);
write_reg(state, RSTV0910_P2_I2CRPT, state->i2crpt);
write_reg(state, RSTV0910_P1_TSINSDELM, 0x17);
write_reg(state, RSTV0910_P1_TSINSDELL, 0xff);
write_reg(state, RSTV0910_P2_TSINSDELM, 0x17);
write_reg(state, RSTV0910_P2_TSINSDELL, 0xff);
init_diseqc(state);
return 0;
}
@ -1320,7 +1324,7 @@ static int read_snr(struct dvb_frontend *fe)
if (!get_signal_to_noise(state, &snrval)) {
p->cnr.stat[0].scale = FE_SCALE_DECIBEL;
p->cnr.stat[0].uvalue = 100 * snrval; /* fix scale */
p->cnr.stat[0].svalue = 100 * snrval; /* fix scale */
} else {
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
@ -1633,7 +1637,7 @@ static int tune(struct dvb_frontend *fe, bool re_tune,
return 0;
}
static int get_algo(struct dvb_frontend *fe)
static enum dvbfe_algo get_algo(struct dvb_frontend *fe)
{
return DVBFE_ALGO_HW;
}
@ -1784,7 +1788,8 @@ struct dvb_frontend *stv0910_attach(struct i2c_adapter *i2c,
state->tscfgh = 0x20 | (cfg->parallel ? 0 : 0x40);
state->tsgeneral = (cfg->parallel == 2) ? 0x02 : 0x00;
state->i2crpt = 0x0A | ((cfg->rptlvl & 0x07) << 4);
state->tsspeed = 0x28;
/* use safe tsspeed value if unspecified through stv0910_cfg */
state->tsspeed = (cfg->tsspeed ? cfg->tsspeed : 0x28);
state->nr = nr;
state->regoff = state->nr ? 0 : 0x200;
state->search_range = 16000000;

View File

@ -10,6 +10,7 @@ struct stv0910_cfg {
u8 parallel;
u8 rptlvl;
u8 single;
u8 tsspeed;
};
#if IS_REACHABLE(CONFIG_DVB_STV0910)

View File

@ -1,17 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Toshiba TC90522 Demodulator
*
* Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
*
* 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 in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
@ -352,7 +343,7 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe,
mode = 1;
ret = reg_read(state, 0xb0, val, 1);
if (ret == 0) {
mode = (val[0] & 0xc0) >> 2;
mode = (val[0] & 0xc0) >> 6;
c->transmission_mode = tm_conv[mode];
c->guard_interval = (val[0] & 0x30) >> 4;
}
@ -379,7 +370,7 @@ static int tc90522t_get_frontend(struct dvb_frontend *fe,
}
/* layer B */
v = (val[3] & 0x03) << 1 | (val[4] & 0xc0) >> 6;
v = (val[3] & 0x03) << 2 | (val[4] & 0xc0) >> 6;
if (v == 0x0f)
c->layer[1].segment_count = 0;
else {

View File

@ -1,17 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Toshiba TC90522 Demodulator
*
* Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com>
*
* 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 in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*

View File

@ -575,6 +575,17 @@ config VIDEO_APTINA_PLL
config VIDEO_SMIAPP_PLL
tristate
config VIDEO_IMX258
tristate "Sony IMX258 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 Sony
IMX258 camera.
To compile this driver as a module, choose M here: the
module will be called imx258.
config VIDEO_IMX274
tristate "Sony IMX274 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@ -688,6 +699,18 @@ config VIDEO_OV5695
To compile this driver as a module, choose M here: the
module will be called ov5695.
config VIDEO_OV7251
tristate "OmniVision OV7251 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
select V4L2_FWNODE
help
This is a Video4Linux2 sensor-level driver for the OmniVision
OV7251 camera.
To compile this driver as a module, choose M here: the
module will be called ov7251.
config VIDEO_OV772X
tristate "OmniVision OV772x sensor support"
depends on I2C && VIDEO_V4L2
@ -974,6 +997,19 @@ config VIDEO_M52790
To compile this driver as a module, choose M here: the
module will be called m52790.
config VIDEO_I2C
tristate "I2C transport video support"
depends on VIDEO_V4L2 && I2C
select VIDEOBUF2_VMALLOC
---help---
Enable the I2C transport video support which supports the
following:
* Panasonic AMG88xx Grid-Eye Sensors
To compile this driver as a module, choose M here: the
module will be called video-i2c
endmenu
menu "Sensors used on soc_camera driver"

View File

@ -70,6 +70,7 @@ obj-$(CONFIG_VIDEO_OV5647) += ov5647.o
obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
obj-$(CONFIG_VIDEO_OV5695) += ov5695.o
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
obj-$(CONFIG_VIDEO_OV7251) += ov7251.o
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
@ -96,9 +97,11 @@ obj-$(CONFIG_VIDEO_LM3646) += lm3646.o
obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
obj-$(CONFIG_VIDEO_AK881X) += ak881x.o
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_I2C) += video-i2c.o
obj-$(CONFIG_VIDEO_ML86V7667) += ml86v7667.o
obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
obj-$(CONFIG_VIDEO_TC358743) += tc358743.o
obj-$(CONFIG_VIDEO_IMX258) += imx258.o
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_SDR_MAX2175) += max2175.o

View File

@ -321,17 +321,17 @@ static const struct v4l2_subdev_video_ops adv748x_afe_video_ops = {
static int adv748x_afe_propagate_pixelrate(struct adv748x_afe *afe)
{
struct v4l2_subdev *tx;
unsigned int width, height, fps;
tx = adv748x_get_remote_sd(&afe->pads[ADV748X_AFE_SOURCE]);
if (!tx)
return -ENOLINK;
width = 720;
height = afe->curr_norm & V4L2_STD_525_60 ? 480 : 576;
fps = afe->curr_norm & V4L2_STD_525_60 ? 30 : 25;
return adv748x_csi2_set_pixelrate(tx, width * height * fps);
/*
* The ADV748x ADC sampling frequency is twice the externally supplied
* clock whose frequency is required to be 28.63636 MHz. It oversamples
* with a factor of 4 resulting in a pixel rate of 14.3180180 MHz.
*/
return adv748x_csi2_set_pixelrate(tx, 14318180);
}
static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd,

View File

@ -402,8 +402,6 @@ static int adv748x_hdmi_propagate_pixelrate(struct adv748x_hdmi *hdmi)
{
struct v4l2_subdev *tx;
struct v4l2_dv_timings timings;
struct v4l2_bt_timings *bt = &timings.bt;
unsigned int fps;
tx = adv748x_get_remote_sd(&hdmi->pads[ADV748X_HDMI_SOURCE]);
if (!tx)
@ -411,11 +409,7 @@ static int adv748x_hdmi_propagate_pixelrate(struct adv748x_hdmi *hdmi)
adv748x_hdmi_query_dv_timings(&hdmi->sd, &timings);
fps = DIV_ROUND_CLOSEST_ULL(bt->pixelclock,
V4L2_DV_BT_FRAME_WIDTH(bt) *
V4L2_DV_BT_FRAME_HEIGHT(bt));
return adv748x_csi2_set_pixelrate(tx, bt->width * bt->height * fps);
return adv748x_csi2_set_pixelrate(tx, timings.bt.pixelclock);
}
static int adv748x_hdmi_enum_mbus_code(struct v4l2_subdev *sd,

View File

@ -732,8 +732,8 @@ static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
/* power up cec section */
adv7511_cec_write_and_or(sd, 0x4e, 0xfc, 0x01);
/* legacy mode and clear all rx buffers */
adv7511_cec_write(sd, 0x4a, 0x00);
adv7511_cec_write(sd, 0x4a, 0x07);
adv7511_cec_write(sd, 0x4a, 0);
adv7511_cec_write_and_or(sd, 0x11, 0xfe, 0); /* initially disable tx */
/* enabled irqs: */
/* tx: ready */
@ -831,8 +831,8 @@ static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
*/
adv7511_cec_write_and_or(sd, 0x12, ~0x70, max(1, attempts - 1) << 4);
/* blocking, clear cec tx irq status */
adv7511_wr_and_or(sd, 0x97, 0xc7, 0x38);
/* clear cec tx irq status */
adv7511_wr(sd, 0x97, 0x38);
/* write data */
for (i = 0; i < len; i++)
@ -917,9 +917,6 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
else if (adv7511_have_hotplug(sd))
irqs |= MASK_ADV7511_EDID_RDY_INT;
adv7511_wr_and_or(sd, 0x95, 0xc0,
(state->cec_enabled_adap && enable) ? 0x39 : 0x00);
/*
* This i2c write can fail (approx. 1 in 1000 writes). But it
* is essential that this register is correct, so retry it
@ -933,9 +930,11 @@ static void adv7511_set_isr(struct v4l2_subdev *sd, bool enable)
irqs_rd = adv7511_rd(sd, 0x94);
} while (retries-- && irqs_rd != irqs);
if (irqs_rd == irqs)
return;
v4l2_err(sd, "Could not set interrupts: hw failure?\n");
if (irqs_rd != irqs)
v4l2_err(sd, "Could not set interrupts: hw failure?\n");
adv7511_wr_and_or(sd, 0x95, 0xc0,
(state->cec_enabled_adap && enable) ? 0x39 : 0x00);
}
/* Interrupt handler */
@ -982,8 +981,8 @@ static int adv7511_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
for (i = 0; i < msg.len; i++)
msg.msg[i] = adv7511_cec_read(sd, i + 0x15);
adv7511_cec_write(sd, 0x4a, 1); /* toggle to re-enable rx 1 */
adv7511_cec_write(sd, 0x4a, 0);
adv7511_cec_write(sd, 0x4a, 0); /* toggle to re-enable rx 1 */
adv7511_cec_write(sd, 0x4a, 1);
cec_received_msg(state->cec_adap, &msg);
}
}
@ -1778,6 +1777,7 @@ static void adv7511_init_setup(struct v4l2_subdev *sd)
/* legacy mode */
adv7511_cec_write(sd, 0x4a, 0x00);
adv7511_cec_write(sd, 0x4a, 0x07);
if (cec_clk % 750000 != 0)
v4l2_err(sd, "%s: cec_clk %d, not multiple of 750 Khz\n",

1318
drivers/media/i2c/imx258.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -87,7 +87,7 @@
#define IMX274_SHR_LIMIT_CONST (4)
/*
* Constants for sensor reset delay
* Min and max sensor reset delay (microseconds)
*/
#define IMX274_RESET_DELAY1 (2000)
#define IMX274_RESET_DELAY2 (2200)
@ -107,15 +107,15 @@
/*
* IMX274 register definitions
*/
#define IMX274_FRAME_LENGTH_ADDR_1 0x30FA /* VMAX, MSB */
#define IMX274_FRAME_LENGTH_ADDR_2 0x30F9 /* VMAX */
#define IMX274_FRAME_LENGTH_ADDR_3 0x30F8 /* VMAX, LSB */
#define IMX274_SHR_REG_MSB 0x300D /* SHR */
#define IMX274_SHR_REG_LSB 0x300C /* SHR */
#define IMX274_SVR_REG_MSB 0x300F /* SVR */
#define IMX274_SVR_REG_LSB 0x300E /* SVR */
#define IMX274_VMAX_REG_1 0x30FA /* VMAX, MSB */
#define IMX274_VMAX_REG_2 0x30F9 /* VMAX */
#define IMX274_VMAX_REG_3 0x30F8 /* VMAX, LSB */
#define IMX274_HMAX_REG_MSB 0x30F7 /* HMAX */
#define IMX274_HMAX_REG_LSB 0x30F6 /* HMAX */
#define IMX274_COARSE_TIME_ADDR_MSB 0x300D /* SHR */
#define IMX274_COARSE_TIME_ADDR_LSB 0x300C /* SHR */
#define IMX274_ANALOG_GAIN_ADDR_LSB 0x300A /* ANALOG GAIN LSB */
#define IMX274_ANALOG_GAIN_ADDR_MSB 0x300B /* ANALOG GAIN MSB */
#define IMX274_DIGITAL_GAIN_REG 0x3012 /* Digital Gain */
@ -144,22 +144,13 @@ enum imx274_mode {
IMX274_MODE_3840X2160,
IMX274_MODE_1920X1080,
IMX274_MODE_1280X720,
IMX274_MODE_START_STREAM_1,
IMX274_MODE_START_STREAM_2,
IMX274_MODE_START_STREAM_3,
IMX274_MODE_START_STREAM_4,
IMX274_MODE_STOP_STREAM
};
/*
* imx274 format related structure
*/
struct imx274_frmfmt {
u32 mbus_code;
enum v4l2_colorspace colorspace;
struct v4l2_frmsize_discrete size;
enum imx274_mode mode;
};
/*
@ -489,24 +480,15 @@ static const struct reg_8 *mode_table[] = {
[IMX274_MODE_3840X2160] = imx274_mode1_3840x2160_raw10,
[IMX274_MODE_1920X1080] = imx274_mode3_1920x1080_raw10,
[IMX274_MODE_1280X720] = imx274_mode5_1280x720_raw10,
[IMX274_MODE_START_STREAM_1] = imx274_start_1,
[IMX274_MODE_START_STREAM_2] = imx274_start_2,
[IMX274_MODE_START_STREAM_3] = imx274_start_3,
[IMX274_MODE_START_STREAM_4] = imx274_start_4,
[IMX274_MODE_STOP_STREAM] = imx274_stop,
};
/*
* imx274 format related structure
*/
static const struct imx274_frmfmt imx274_formats[] = {
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {3840, 2160},
IMX274_MODE_3840X2160},
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1920, 1080},
IMX274_MODE_1920X1080},
{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1280, 720},
IMX274_MODE_1280X720},
{ {3840, 2160} },
{ {1920, 1080} },
{ {1280, 720} },
};
/*
@ -737,11 +719,11 @@ static int imx274_mode_regs(struct stimx274 *priv, int mode)
{
int err = 0;
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_1]);
err = imx274_write_table(priv, imx274_start_1);
if (err)
return err;
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_2]);
err = imx274_write_table(priv, imx274_start_2);
if (err)
return err;
@ -766,7 +748,7 @@ static int imx274_start_stream(struct stimx274 *priv)
* give it 1 extra ms for margin
*/
msleep_range(11);
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_3]);
err = imx274_write_table(priv, imx274_start_3);
if (err)
return err;
@ -776,7 +758,7 @@ static int imx274_start_stream(struct stimx274 *priv)
* give it 1 extra ms for margin
*/
msleep_range(8);
err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_4]);
err = imx274_write_table(priv, imx274_start_4);
if (err)
return err;
@ -890,9 +872,8 @@ static int imx274_set_fmt(struct v4l2_subdev *sd,
int index;
dev_dbg(&client->dev,
"%s: width = %d height = %d code = %d mbus_code = %d\n",
__func__, fmt->width, fmt->height, fmt->code,
imx274_formats[imx274->mode_index].mbus_code);
"%s: width = %d height = %d code = %d\n",
__func__, fmt->width, fmt->height, fmt->code);
mutex_lock(&imx274->lock);
@ -971,7 +952,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
if (!ret) {
/*
* exposure time range is decided by frame interval
* need to update it after frame interal changes
* need to update it after frame interval changes
*/
min = IMX274_MIN_EXPOSURE_TIME;
max = fi->interval.numerator * 1000000
@ -984,7 +965,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
}
/* update exposure time accordingly */
imx274_set_exposure(imx274, imx274->ctrls.exposure->val);
imx274_set_exposure(imx274, ctrl->val);
dev_dbg(&imx274->client->dev, "set frame interval to %uus\n",
fi->interval.numerator * 1000000
@ -1088,8 +1069,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
goto fail;
} else {
/* stop stream */
ret = imx274_write_table(imx274,
mode_table[IMX274_MODE_STOP_STREAM]);
ret = imx274_write_table(imx274, imx274_stop);
if (ret)
goto fail;
}
@ -1133,15 +1113,15 @@ static int imx274_get_frame_length(struct stimx274 *priv, u32 *val)
svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
/* vmax */
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_3, &reg_val[0]);
err = imx274_read_reg(priv, IMX274_VMAX_REG_3, &reg_val[0]);
if (err)
goto fail;
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_2, &reg_val[1]);
err = imx274_read_reg(priv, IMX274_VMAX_REG_2, &reg_val[1]);
if (err)
goto fail;
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_1, &reg_val[2]);
err = imx274_read_reg(priv, IMX274_VMAX_REG_1, &reg_val[2]);
if (err)
goto fail;
@ -1300,10 +1280,10 @@ fail:
static inline void imx274_calculate_coarse_time_regs(struct reg_8 regs[2],
u32 coarse_time)
{
regs->addr = IMX274_COARSE_TIME_ADDR_MSB;
regs->addr = IMX274_SHR_REG_MSB;
regs->val = (coarse_time >> IMX274_SHIFT_8_BITS)
& IMX274_MASK_LSB_8_BITS;
(regs + 1)->addr = IMX274_COARSE_TIME_ADDR_LSB;
(regs + 1)->addr = IMX274_SHR_REG_LSB;
(regs + 1)->val = (coarse_time) & IMX274_MASK_LSB_8_BITS;
}
@ -1471,13 +1451,13 @@ static int imx274_set_test_pattern(struct stimx274 *priv, int val)
static inline void imx274_calculate_frame_length_regs(struct reg_8 regs[3],
u32 frame_length)
{
regs->addr = IMX274_FRAME_LENGTH_ADDR_1;
regs->addr = IMX274_VMAX_REG_1;
regs->val = (frame_length >> IMX274_SHIFT_16_BITS)
& IMX274_MASK_LSB_4_BITS;
(regs + 1)->addr = IMX274_FRAME_LENGTH_ADDR_2;
(regs + 1)->addr = IMX274_VMAX_REG_2;
(regs + 1)->val = (frame_length >> IMX274_SHIFT_8_BITS)
& IMX274_MASK_LSB_8_BITS;
(regs + 2)->addr = IMX274_FRAME_LENGTH_ADDR_3;
(regs + 2)->addr = IMX274_VMAX_REG_3;
(regs + 2)->val = (frame_length) & IMX274_MASK_LSB_8_BITS;
}
@ -1786,7 +1766,7 @@ static int imx274_remove(struct i2c_client *client)
struct stimx274 *imx274 = to_imx274(sd);
/* stop stream */
imx274_write_table(imx274, mode_table[IMX274_MODE_STOP_STREAM]);
imx274_write_table(imx274, imx274_stop);
v4l2_async_unregister_subdev(sd);
v4l2_ctrl_handler_free(&imx274->ctrls.handler);

View File

@ -739,6 +739,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
struct rc_dev *rc = NULL;
struct i2c_adapter *adap = client->adapter;
unsigned short addr = client->addr;
bool probe_tx = (id->driver_data & FLAG_TX) != 0;
int err;
if ((id->driver_data & FLAG_HDPVR) && !enable_hdpvr) {
@ -800,6 +801,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
rc_proto = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
RC_PROTO_BIT_RC6_6A_32;
ir_codes = RC_MAP_HAUPPAUGE;
probe_tx = true;
break;
}
@ -892,7 +894,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
INIT_DELAYED_WORK(&ir->work, ir_work);
if (id->driver_data & FLAG_TX) {
if (probe_tx) {
ir->tx_c = i2c_new_dummy(client->adapter, 0x70);
if (!ir->tx_c) {
dev_err(&client->dev, "failed to setup tx i2c address");

View File

@ -1796,7 +1796,6 @@ MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids);
static struct i2c_driver ov13858_i2c_driver = {
.driver = {
.name = "ov13858",
.owner = THIS_MODULE,
.pm = &ov13858_pm_ops,
.acpi_match_table = ACPI_PTR(ov13858_acpi_ids),
},

View File

@ -307,6 +307,10 @@ struct ov2640_priv {
struct gpio_desc *resetb_gpio;
struct gpio_desc *pwdn_gpio;
struct mutex lock; /* lock to protect streaming and power_count */
bool streaming;
int power_count;
};
/*
@ -709,9 +713,20 @@ static int ov2640_s_ctrl(struct v4l2_ctrl *ctrl)
struct v4l2_subdev *sd =
&container_of(ctrl->handler, struct ov2640_priv, hdl)->subdev;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
u8 val;
int ret;
/* v4l2_ctrl_lock() locks our own mutex */
/*
* If the device is not powered up by the host driver, do not apply any
* controls to H/W at this time. Instead the controls will be restored
* when the streaming is started.
*/
if (!priv->power_count)
return 0;
ret = i2c_smbus_write_byte_data(client, BANK_SEL, BANK_SEL_SENS);
if (ret < 0)
return ret;
@ -763,12 +778,9 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
}
#endif
static int ov2640_s_power(struct v4l2_subdev *sd, int on)
static void ov2640_set_power(struct ov2640_priv *priv, int on)
{
#ifdef CONFIG_GPIOLIB
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
if (priv->pwdn_gpio)
gpiod_direction_output(priv->pwdn_gpio, !on);
if (on && priv->resetb_gpio) {
@ -778,6 +790,25 @@ static int ov2640_s_power(struct v4l2_subdev *sd, int on)
gpiod_set_value(priv->resetb_gpio, 0);
}
#endif
}
static int ov2640_s_power(struct v4l2_subdev *sd, int on)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
mutex_lock(&priv->lock);
/*
* If the power count is modified from 0 to != 0 or from != 0 to 0,
* update the power state.
*/
if (priv->power_count == !on)
ov2640_set_power(priv, on);
priv->power_count += on ? 1 : -1;
WARN_ON(priv->power_count < 0);
mutex_unlock(&priv->lock);
return 0;
}
@ -798,16 +829,13 @@ static const struct ov2640_win_size *ov2640_select_win(u32 width, u32 height)
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 = win;
if (!win)
return -EINVAL;
/* select format */
priv->cfmt_code = 0;
switch (code) {
case MEDIA_BUS_FMT_RGB565_2X8_BE:
dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
@ -846,13 +874,13 @@ static int ov2640_set_params(struct i2c_client *client,
goto err;
/* select preamble */
dev_dbg(&client->dev, "%s: Set size to %s", __func__, priv->win->name);
dev_dbg(&client->dev, "%s: Set size to %s", __func__, win->name);
ret = ov2640_write_array(client, ov2640_size_change_preamble_regs);
if (ret < 0)
goto err;
/* set size win */
ret = ov2640_write_array(client, priv->win->regs);
ret = ov2640_write_array(client, win->regs);
if (ret < 0)
goto err;
@ -872,14 +900,11 @@ static int ov2640_set_params(struct i2c_client *client,
if (ret < 0)
goto err;
priv->cfmt_code = code;
return 0;
err:
dev_err(&client->dev, "%s: Error %d", __func__, ret);
ov2640_reset(client);
priv->win = NULL;
return ret;
}
@ -915,11 +940,15 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
{
struct v4l2_mbus_framefmt *mf = &format->format;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
const struct ov2640_win_size *win;
int ret = 0;
if (format->pad)
return -EINVAL;
mutex_lock(&priv->lock);
/* select suitable win */
win = ov2640_select_win(mf->width, mf->height);
mf->width = win->width;
@ -941,10 +970,24 @@ static int ov2640_set_fmt(struct v4l2_subdev *sd,
break;
}
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
return ov2640_set_params(client, win, mf->code);
cfg->try_fmt = *mf;
return 0;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
struct ov2640_priv *priv = to_ov2640(client);
if (priv->streaming) {
ret = -EBUSY;
goto out;
}
/* select win */
priv->win = win;
/* select format */
priv->cfmt_code = mf->code;
} else {
cfg->try_fmt = *mf;
}
out:
mutex_unlock(&priv->lock);
return ret;
}
static int ov2640_enum_mbus_code(struct v4l2_subdev *sd,
@ -979,6 +1022,28 @@ static int ov2640_get_selection(struct v4l2_subdev *sd,
}
}
static int ov2640_s_stream(struct v4l2_subdev *sd, int on)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov2640_priv *priv = to_ov2640(client);
int ret = 0;
mutex_lock(&priv->lock);
if (priv->streaming == !on) {
if (on) {
ret = ov2640_set_params(client, priv->win,
priv->cfmt_code);
if (!ret)
ret = __v4l2_ctrl_handler_setup(&priv->hdl);
}
}
if (!ret)
priv->streaming = on;
mutex_unlock(&priv->lock);
return ret;
}
static int ov2640_video_probe(struct i2c_client *client)
{
struct ov2640_priv *priv = to_ov2640(client);
@ -1014,8 +1079,6 @@ static int ov2640_video_probe(struct i2c_client *client)
"%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
devname, pid, ver, midh, midl);
ret = v4l2_ctrl_handler_setup(&priv->hdl);
done:
ov2640_s_power(&priv->subdev, 0);
return ret;
@ -1040,9 +1103,14 @@ static const struct v4l2_subdev_pad_ops ov2640_subdev_pad_ops = {
.set_fmt = ov2640_set_fmt,
};
static const struct v4l2_subdev_video_ops ov2640_subdev_video_ops = {
.s_stream = ov2640_s_stream,
};
static const struct v4l2_subdev_ops ov2640_subdev_ops = {
.core = &ov2640_subdev_core_ops,
.pad = &ov2640_subdev_pad_ops,
.video = &ov2640_subdev_video_ops,
};
static int ov2640_probe_dt(struct i2c_client *client,
@ -1116,7 +1184,9 @@ static int ov2640_probe(struct i2c_client *client,
v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
mutex_init(&priv->lock);
v4l2_ctrl_handler_init(&priv->hdl, 2);
priv->hdl.lock = &priv->lock;
v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
@ -1150,6 +1220,7 @@ err_videoprobe:
media_entity_cleanup(&priv->subdev.entity);
err_hdl:
v4l2_ctrl_handler_free(&priv->hdl);
mutex_destroy(&priv->lock);
err_clk:
clk_disable_unprepare(priv->clk);
return ret;
@ -1161,6 +1232,7 @@ static int ov2640_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(&priv->subdev);
v4l2_ctrl_handler_free(&priv->hdl);
mutex_destroy(&priv->lock);
media_entity_cleanup(&priv->subdev.entity);
v4l2_device_unregister_subdev(&priv->subdev);
clk_disable_unprepare(priv->clk);

View File

@ -60,6 +60,8 @@
#define OV5640_REG_AEC_PK_MANUAL 0x3503
#define OV5640_REG_AEC_PK_REAL_GAIN 0x350a
#define OV5640_REG_AEC_PK_VTS 0x350c
#define OV5640_REG_TIMING_DVPHO 0x3808
#define OV5640_REG_TIMING_DVPVO 0x380a
#define OV5640_REG_TIMING_HTS 0x380c
#define OV5640_REG_TIMING_VTS 0x380e
#define OV5640_REG_TIMING_TC_REG21 0x3821
@ -91,6 +93,9 @@
#define OV5640_REG_SDE_CTRL5 0x5585
#define OV5640_REG_AVG_READOUT 0x56a1
#define OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT 1
#define OV5640_SCLK_ROOT_DIVIDER_DEFAULT 2
enum ov5640_mode_id {
OV5640_MODE_QCIF_176_144 = 0,
OV5640_MODE_QVGA_320_240,
@ -165,8 +170,10 @@ struct reg_value {
struct ov5640_mode_info {
enum ov5640_mode_id id;
enum ov5640_downsize_mode dn_mode;
u32 width;
u32 height;
u32 hact;
u32 htot;
u32 vact;
u32 vtot;
const struct reg_value *reg_data;
u32 reg_data_size;
};
@ -187,6 +194,7 @@ struct ov5640_ctrls {
struct v4l2_ctrl *gain;
};
struct v4l2_ctrl *brightness;
struct v4l2_ctrl *light_freq;
struct v4l2_ctrl *saturation;
struct v4l2_ctrl *contrast;
struct v4l2_ctrl *hue;
@ -248,7 +256,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
{0x3034, 0x18, 0, 0}, {0x3035, 0x14, 0, 0}, {0x3036, 0x38, 0, 0},
{0x3037, 0x13, 0, 0}, {0x3108, 0x01, 0, 0}, {0x3630, 0x36, 0, 0},
{0x3037, 0x13, 0, 0}, {0x3630, 0x36, 0, 0},
{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
@ -265,9 +273,7 @@ static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -339,9 +345,7 @@ static const struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -360,9 +364,7 @@ static const struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -381,9 +383,7 @@ static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x04, 0, 0}, {0x380f, 0x38, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -393,8 +393,7 @@ static const struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
{0x3808, 0x04, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0},
{0x380b, 0x00, 0, 0}, {0x3035, 0x12, 0, 0},
{0x3035, 0x12, 0, 0},
};
static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
@ -404,9 +403,7 @@ static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0x80, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -415,8 +412,7 @@ static const struct reg_value ov5640_setting_15fps_XGA_1024_768[] = {
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3808, 0x04, 0, 0},
{0x3809, 0x00, 0, 0}, {0x380a, 0x03, 0, 0}, {0x380b, 0x00, 0, 0},
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
};
static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
@ -426,9 +422,7 @@ static const struct reg_value ov5640_setting_30fps_QVGA_320_240[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -447,9 +441,7 @@ static const struct reg_value ov5640_setting_15fps_QVGA_320_240[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x01, 0, 0}, {0x3809, 0x40, 0, 0}, {0x380a, 0x00, 0, 0},
{0x380b, 0xf0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -468,9 +460,7 @@ static const struct reg_value ov5640_setting_30fps_QCIF_176_144[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -489,9 +479,7 @@ static const struct reg_value ov5640_setting_15fps_QCIF_176_144[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x00, 0, 0}, {0x3809, 0xb0, 0, 0}, {0x380a, 0x00, 0, 0},
{0x380b, 0x90, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -510,9 +498,7 @@ static const struct reg_value ov5640_setting_30fps_NTSC_720_480[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -531,9 +517,7 @@ static const struct reg_value ov5640_setting_15fps_NTSC_720_480[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x01, 0, 0},
{0x380b, 0xe0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x3c, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -552,9 +536,7 @@ static const struct reg_value ov5640_setting_30fps_PAL_720_576[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -573,9 +555,7 @@ static const struct reg_value ov5640_setting_15fps_PAL_720_576[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x04, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9b, 0, 0},
{0x3808, 0x02, 0, 0}, {0x3809, 0xd0, 0, 0}, {0x380a, 0x02, 0, 0},
{0x380b, 0x40, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x68, 0, 0},
{0x380e, 0x03, 0, 0}, {0x380f, 0xd8, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x38, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x06, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -595,9 +575,7 @@ static const struct reg_value ov5640_setting_30fps_720P_1280_720[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
@ -617,9 +595,7 @@ static const struct reg_value ov5640_setting_15fps_720P_1280_720[] = {
{0x3815, 0x31, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0xfa, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x06, 0, 0}, {0x3807, 0xa9, 0, 0},
{0x3808, 0x05, 0, 0}, {0x3809, 0x00, 0, 0}, {0x380a, 0x02, 0, 0},
{0x380b, 0xd0, 0, 0}, {0x380c, 0x07, 0, 0}, {0x380d, 0x64, 0, 0},
{0x380e, 0x02, 0, 0}, {0x380f, 0xe4, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
{0x3618, 0x00, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3709, 0x52, 0, 0}, {0x370c, 0x03, 0, 0}, {0x3a02, 0x02, 0, 0},
@ -639,9 +615,7 @@ static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -655,10 +629,8 @@ static const struct reg_value ov5640_setting_30fps_1080P_1920_1080[] = {
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
@ -676,9 +648,7 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -692,10 +662,8 @@ static const struct reg_value ov5640_setting_15fps_1080P_1920_1080[] = {
{0x3c09, 0x1c, 0, 0}, {0x3c0a, 0x9c, 0, 0}, {0x3c0b, 0x40, 0, 0},
{0x3800, 0x01, 0, 0}, {0x3801, 0x50, 0, 0}, {0x3802, 0x01, 0, 0},
{0x3803, 0xb2, 0, 0}, {0x3804, 0x08, 0, 0}, {0x3805, 0xef, 0, 0},
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0}, {0x3808, 0x07, 0, 0},
{0x3809, 0x80, 0, 0}, {0x380a, 0x04, 0, 0}, {0x380b, 0x38, 0, 0},
{0x380c, 0x09, 0, 0}, {0x380d, 0xc4, 0, 0}, {0x380e, 0x04, 0, 0},
{0x380f, 0x60, 0, 0}, {0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3806, 0x05, 0, 0}, {0x3807, 0xf1, 0, 0},
{0x3612, 0x2b, 0, 0}, {0x3708, 0x64, 0, 0},
{0x3a02, 0x04, 0, 0}, {0x3a03, 0x60, 0, 0}, {0x3a08, 0x01, 0, 0},
{0x3a09, 0x50, 0, 0}, {0x3a0a, 0x01, 0, 0}, {0x3a0b, 0x18, 0, 0},
{0x3a0e, 0x03, 0, 0}, {0x3a0d, 0x04, 0, 0}, {0x3a14, 0x04, 0, 0},
@ -712,9 +680,7 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
{0x3815, 0x11, 0, 0}, {0x3800, 0x00, 0, 0}, {0x3801, 0x00, 0, 0},
{0x3802, 0x00, 0, 0}, {0x3803, 0x00, 0, 0}, {0x3804, 0x0a, 0, 0},
{0x3805, 0x3f, 0, 0}, {0x3806, 0x07, 0, 0}, {0x3807, 0x9f, 0, 0},
{0x3808, 0x0a, 0, 0}, {0x3809, 0x20, 0, 0}, {0x380a, 0x07, 0, 0},
{0x380b, 0x98, 0, 0}, {0x380c, 0x0b, 0, 0}, {0x380d, 0x1c, 0, 0},
{0x380e, 0x07, 0, 0}, {0x380f, 0xb0, 0, 0}, {0x3810, 0x00, 0, 0},
{0x3810, 0x00, 0, 0},
{0x3811, 0x10, 0, 0}, {0x3812, 0x00, 0, 0}, {0x3813, 0x04, 0, 0},
{0x3618, 0x04, 0, 0}, {0x3612, 0x29, 0, 0}, {0x3708, 0x21, 0, 0},
{0x3709, 0x12, 0, 0}, {0x370c, 0x00, 0, 0}, {0x3a02, 0x03, 0, 0},
@ -728,66 +694,84 @@ static const struct reg_value ov5640_setting_15fps_QSXGA_2592_1944[] = {
/* power-on sensor init reg table */
static const struct ov5640_mode_info ov5640_mode_init_data = {
0, SUBSAMPLING, 640, 480, ov5640_init_setting_30fps_VGA,
0, SUBSAMPLING, 640, 1896, 480, 984,
ov5640_init_setting_30fps_VGA,
ARRAY_SIZE(ov5640_init_setting_30fps_VGA),
};
static const struct ov5640_mode_info
ov5640_mode_data[OV5640_NUM_FRAMERATES][OV5640_NUM_MODES] = {
{
{OV5640_MODE_QCIF_176_144, SUBSAMPLING, 176, 144,
{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
176, 1896, 144, 984,
ov5640_setting_15fps_QCIF_176_144,
ARRAY_SIZE(ov5640_setting_15fps_QCIF_176_144)},
{OV5640_MODE_QVGA_320_240, SUBSAMPLING, 320, 240,
{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
320, 1896, 240, 984,
ov5640_setting_15fps_QVGA_320_240,
ARRAY_SIZE(ov5640_setting_15fps_QVGA_320_240)},
{OV5640_MODE_VGA_640_480, SUBSAMPLING, 640, 480,
{OV5640_MODE_VGA_640_480, SUBSAMPLING,
640, 1896, 480, 1080,
ov5640_setting_15fps_VGA_640_480,
ARRAY_SIZE(ov5640_setting_15fps_VGA_640_480)},
{OV5640_MODE_NTSC_720_480, SUBSAMPLING, 720, 480,
{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
720, 1896, 480, 984,
ov5640_setting_15fps_NTSC_720_480,
ARRAY_SIZE(ov5640_setting_15fps_NTSC_720_480)},
{OV5640_MODE_PAL_720_576, SUBSAMPLING, 720, 576,
{OV5640_MODE_PAL_720_576, SUBSAMPLING,
720, 1896, 576, 984,
ov5640_setting_15fps_PAL_720_576,
ARRAY_SIZE(ov5640_setting_15fps_PAL_720_576)},
{OV5640_MODE_XGA_1024_768, SUBSAMPLING, 1024, 768,
{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
1024, 1896, 768, 1080,
ov5640_setting_15fps_XGA_1024_768,
ARRAY_SIZE(ov5640_setting_15fps_XGA_1024_768)},
{OV5640_MODE_720P_1280_720, SUBSAMPLING, 1280, 720,
{OV5640_MODE_720P_1280_720, SUBSAMPLING,
1280, 1892, 720, 740,
ov5640_setting_15fps_720P_1280_720,
ARRAY_SIZE(ov5640_setting_15fps_720P_1280_720)},
{OV5640_MODE_1080P_1920_1080, SCALING, 1920, 1080,
{OV5640_MODE_1080P_1920_1080, SCALING,
1920, 2500, 1080, 1120,
ov5640_setting_15fps_1080P_1920_1080,
ARRAY_SIZE(ov5640_setting_15fps_1080P_1920_1080)},
{OV5640_MODE_QSXGA_2592_1944, SCALING, 2592, 1944,
{OV5640_MODE_QSXGA_2592_1944, SCALING,
2592, 2844, 1944, 1968,
ov5640_setting_15fps_QSXGA_2592_1944,
ARRAY_SIZE(ov5640_setting_15fps_QSXGA_2592_1944)},
}, {
{OV5640_MODE_QCIF_176_144, SUBSAMPLING, 176, 144,
{OV5640_MODE_QCIF_176_144, SUBSAMPLING,
176, 1896, 144, 984,
ov5640_setting_30fps_QCIF_176_144,
ARRAY_SIZE(ov5640_setting_30fps_QCIF_176_144)},
{OV5640_MODE_QVGA_320_240, SUBSAMPLING, 320, 240,
{OV5640_MODE_QVGA_320_240, SUBSAMPLING,
320, 1896, 240, 984,
ov5640_setting_30fps_QVGA_320_240,
ARRAY_SIZE(ov5640_setting_30fps_QVGA_320_240)},
{OV5640_MODE_VGA_640_480, SUBSAMPLING, 640, 480,
{OV5640_MODE_VGA_640_480, SUBSAMPLING,
640, 1896, 480, 1080,
ov5640_setting_30fps_VGA_640_480,
ARRAY_SIZE(ov5640_setting_30fps_VGA_640_480)},
{OV5640_MODE_NTSC_720_480, SUBSAMPLING, 720, 480,
{OV5640_MODE_NTSC_720_480, SUBSAMPLING,
720, 1896, 480, 984,
ov5640_setting_30fps_NTSC_720_480,
ARRAY_SIZE(ov5640_setting_30fps_NTSC_720_480)},
{OV5640_MODE_PAL_720_576, SUBSAMPLING, 720, 576,
{OV5640_MODE_PAL_720_576, SUBSAMPLING,
720, 1896, 576, 984,
ov5640_setting_30fps_PAL_720_576,
ARRAY_SIZE(ov5640_setting_30fps_PAL_720_576)},
{OV5640_MODE_XGA_1024_768, SUBSAMPLING, 1024, 768,
{OV5640_MODE_XGA_1024_768, SUBSAMPLING,
1024, 1896, 768, 1080,
ov5640_setting_30fps_XGA_1024_768,
ARRAY_SIZE(ov5640_setting_30fps_XGA_1024_768)},
{OV5640_MODE_720P_1280_720, SUBSAMPLING, 1280, 720,
{OV5640_MODE_720P_1280_720, SUBSAMPLING,
1280, 1892, 720, 740,
ov5640_setting_30fps_720P_1280_720,
ARRAY_SIZE(ov5640_setting_30fps_720P_1280_720)},
{OV5640_MODE_1080P_1920_1080, SCALING, 1920, 1080,
{OV5640_MODE_1080P_1920_1080, SCALING,
1920, 2500, 1080, 1120,
ov5640_setting_30fps_1080P_1920_1080,
ARRAY_SIZE(ov5640_setting_30fps_1080P_1920_1080)},
{OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, NULL, 0},
{OV5640_MODE_QSXGA_2592_1944, -1, 0, 0, 0, 0, NULL, 0},
},
};
@ -1377,6 +1361,30 @@ static int ov5640_set_virtual_channel(struct ov5640_dev *sensor)
return ov5640_write_reg(sensor, OV5640_REG_DEBUG_MODE, temp);
}
static int ov5640_set_timings(struct ov5640_dev *sensor,
const struct ov5640_mode_info *mode)
{
int ret;
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPHO, mode->hact);
if (ret < 0)
return ret;
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_DVPVO, mode->vact);
if (ret < 0)
return ret;
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_HTS, mode->htot);
if (ret < 0)
return ret;
ret = ov5640_write_reg16(sensor, OV5640_REG_TIMING_VTS, mode->vtot);
if (ret < 0)
return ret;
return 0;
}
static const struct ov5640_mode_info *
ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
int width, int height, bool nearest)
@ -1390,10 +1398,10 @@ ov5640_find_mode(struct ov5640_dev *sensor, enum ov5640_frame_rate fr,
if (!mode->reg_data)
continue;
if ((nearest && mode->width <= width &&
mode->height <= height) ||
(!nearest && mode->width == width &&
mode->height == height))
if ((nearest && mode->hact <= width &&
mode->vact <= height) ||
(!nearest && mode->hact == width &&
mode->vact == height))
break;
}
@ -1568,7 +1576,8 @@ static int ov5640_set_mode_exposure_calc(struct ov5640_dev *sensor,
* change mode directly
*/
static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
const struct ov5640_mode_info *mode)
const struct ov5640_mode_info *mode,
s32 exposure)
{
int ret;
@ -1584,7 +1593,8 @@ static int ov5640_set_mode_direct(struct ov5640_dev *sensor,
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 1);
if (ret)
return ret;
return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, V4L2_EXPOSURE_AUTO);
return __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, exposure);
}
static int ov5640_set_mode(struct ov5640_dev *sensor,
@ -1592,6 +1602,7 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
{
const struct ov5640_mode_info *mode = sensor->current_mode;
enum ov5640_downsize_mode dn_mode, orig_dn_mode;
s32 exposure;
int ret;
dn_mode = mode->dn_mode;
@ -1601,7 +1612,9 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_gain, 0);
if (ret)
return ret;
ret = __v4l2_ctrl_s_ctrl(sensor->ctrls.auto_exp, V4L2_EXPOSURE_MANUAL);
exposure = sensor->ctrls.auto_exp->val;
ret = ov5640_set_exposure(sensor, V4L2_EXPOSURE_MANUAL);
if (ret)
return ret;
@ -1617,9 +1630,13 @@ static int ov5640_set_mode(struct ov5640_dev *sensor,
* change inside subsampling or scaling
* download firmware directly
*/
ret = ov5640_set_mode_direct(sensor, mode);
ret = ov5640_set_mode_direct(sensor, mode, exposure);
}
if (ret < 0)
return ret;
ret = ov5640_set_timings(sensor, mode);
if (ret < 0)
return ret;
@ -1654,6 +1671,12 @@ static int ov5640_restore_mode(struct ov5640_dev *sensor)
if (ret < 0)
return ret;
ret = ov5640_mod_reg(sensor, OV5640_REG_SYS_ROOT_DIVIDER, 0x3f,
(ilog2(OV5640_SCLK2X_ROOT_DIVIDER_DEFAULT) << 2) |
ilog2(OV5640_SCLK_ROOT_DIVIDER_DEFAULT));
if (ret)
return ret;
/* now restore the last capture mode */
ret = ov5640_set_mode(sensor, &ov5640_mode_init_data);
if (ret < 0)
@ -1871,8 +1894,8 @@ static int ov5640_try_fmt_internal(struct v4l2_subdev *sd,
mode = ov5640_find_mode(sensor, fr, fmt->width, fmt->height, true);
if (!mode)
return -EINVAL;
fmt->width = mode->width;
fmt->height = mode->height;
fmt->width = mode->hact;
fmt->height = mode->vact;
if (new_mode)
*new_mode = mode;
@ -2155,6 +2178,21 @@ static int ov5640_set_ctrl_test_pattern(struct ov5640_dev *sensor, int value)
0xa4, value ? 0xa4 : 0);
}
static int ov5640_set_ctrl_light_freq(struct ov5640_dev *sensor, int value)
{
int ret;
ret = ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL01, BIT(7),
(value == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) ?
0 : BIT(7));
if (ret)
return ret;
return ov5640_mod_reg(sensor, OV5640_REG_HZ5060_CTRL00, BIT(2),
(value == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) ?
BIT(2) : 0);
}
static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{
struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
@ -2223,6 +2261,9 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_TEST_PATTERN:
ret = ov5640_set_ctrl_test_pattern(sensor, ctrl->val);
break;
case V4L2_CID_POWER_LINE_FREQUENCY:
ret = ov5640_set_ctrl_light_freq(sensor, ctrl->val);
break;
default:
ret = -EINVAL;
break;
@ -2285,6 +2326,12 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
ARRAY_SIZE(test_pattern_menu) - 1,
0, 0, test_pattern_menu);
ctrls->light_freq =
v4l2_ctrl_new_std_menu(hdl, ops,
V4L2_CID_POWER_LINE_FREQUENCY,
V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
if (hdl->error) {
ret = hdl->error;
goto free_ctrls;
@ -2315,10 +2362,10 @@ static int ov5640_enum_frame_size(struct v4l2_subdev *sd,
return -EINVAL;
fse->min_width =
ov5640_mode_data[0][fse->index].width;
ov5640_mode_data[0][fse->index].hact;
fse->max_width = fse->min_width;
fse->min_height =
ov5640_mode_data[0][fse->index].height;
ov5640_mode_data[0][fse->index].vact;
fse->max_height = fse->min_height;
return 0;
@ -2382,14 +2429,14 @@ static int ov5640_s_frame_interval(struct v4l2_subdev *sd,
mode = sensor->current_mode;
frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
mode->width, mode->height);
mode->hact, mode->vact);
if (frame_rate < 0)
frame_rate = OV5640_15_FPS;
sensor->current_fr = frame_rate;
sensor->frame_interval = fi->interval;
sensor->current_mode = ov5640_find_mode(sensor, frame_rate, mode->width,
mode->height, true);
sensor->current_mode = ov5640_find_mode(sensor, frame_rate, mode->hact,
mode->vact, true);
sensor->pending_mode_change = true;
out:
mutex_unlock(&sensor->lock);
@ -2536,8 +2583,8 @@ static int ov5640_probe(struct i2c_client *client,
sensor->ae_target = 52;
endpoint = fwnode_graph_get_next_endpoint(
of_fwnode_handle(client->dev.of_node), NULL);
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev),
NULL);
if (!endpoint) {
dev_err(dev, "endpoint node not found\n");
return -EINVAL;

View File

@ -600,11 +600,13 @@ static int ov5645_write_reg(struct ov5645 *ov5645, u16 reg, u8 val)
regbuf[2] = val;
ret = i2c_master_send(ov5645->i2c_client, regbuf, 3);
if (ret < 0)
if (ret < 0) {
dev_err(ov5645->dev, "%s: write reg error %d: reg=%x, val=%x\n",
__func__, ret, reg, val);
return ret;
}
return ret;
return 0;
}
static int ov5645_read_reg(struct ov5645 *ov5645, u16 reg, u8 *val)

View File

@ -1385,7 +1385,6 @@ MODULE_DEVICE_TABLE(of, ov5695_of_match);
static struct i2c_driver ov5695_i2c_driver = {
.driver = {
.name = "ov5695",
.owner = THIS_MODULE,
.pm = &ov5695_pm_ops,
.of_match_table = of_match_ptr(ov5695_of_match),
},

1503
drivers/media/i2c/ov7251.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1035,7 +1035,7 @@ static int ov772x_set_params(struct ov772x_priv *priv,
/* Set COM8. */
if (priv->band_filter) {
ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1);
ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, BNDF_ON_OFF);
if (!ret)
ret = ov772x_mask_set(client, BDBASE,
0xff, 256 - priv->band_filter);

View File

@ -953,7 +953,7 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
struct v4l2_ctrl_handler *ctrl_hdlr = &ov7740->ctrl_handler;
int ret;
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 2);
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
if (ret < 0)
return ret;
@ -980,27 +980,39 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
V4L2_CID_HFLIP, 0, 1, 1, 0);
ov7740->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_GAIN, 0, 1023, 1, 500);
if (ov7740->gain)
ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
ov7740->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_EXPOSURE, 0, 65535, 1, 500);
if (ov7740->exposure)
ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
ov7740->auto_exposure = v4l2_ctrl_new_std_menu(ctrl_hdlr,
&ov7740_ctrl_ops,
V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_MANUAL, 0,
V4L2_EXPOSURE_AUTO);
ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
ov7740->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
v4l2_ctrl_auto_cluster(3, &ov7740->auto_wb, 0, false);
v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
V4L2_EXPOSURE_MANUAL, false);
v4l2_ctrl_cluster(2, &ov7740->hflip);
if (ctrl_hdlr->error) {
ret = ctrl_hdlr->error;
dev_err(&client->dev, "controls initialisation failed (%d)\n",
ret);
goto error;
}
ret = v4l2_ctrl_handler_setup(ctrl_hdlr);
if (ret) {
dev_err(&client->dev, "%s control init failed (%d)\n",
@ -1074,7 +1086,7 @@ static int ov7740_probe(struct i2c_client *client,
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
sd->internal_ops = &ov7740_subdev_internal_ops;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
#endif
#if defined(CONFIG_MEDIA_CONTROLLER)

View File

@ -1001,7 +1001,7 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor,
if (rval)
goto out;
for (i = 0; i < 1000; i++) {
for (i = 1000; i > 0; i--) {
rval = smiapp_read(
sensor,
SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS, &s);
@ -1012,11 +1012,10 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor,
if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY)
break;
if (--i == 0) {
rval = -ETIMEDOUT;
goto out;
}
}
if (!i) {
rval = -ETIMEDOUT;
goto out;
}
for (i = 0; i < SMIAPP_NVM_PAGE_SIZE; i++) {

View File

@ -2569,7 +2569,7 @@ static int tda1997x_probe(struct i2c_client *client,
snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
id->name, i2c_adapter_id(client->adapter),
client->addr);
sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
sd->entity.function = MEDIA_ENT_F_DTV_DECODER;
sd->entity.ops = &tda1997x_media_ops;
@ -2723,7 +2723,7 @@ static int tda1997x_probe(struct i2c_client *client,
state->pads);
if (ret) {
v4l_err(client, "failed entity_init: %d", ret);
goto err_free_mutex;
goto err_free_handler;
}
ret = v4l2_async_register_subdev(sd);

View File

@ -319,136 +319,136 @@ struct i2c_reg_value {
/* Default values as sugested at TVP5150AM1 datasheet */
static const struct i2c_reg_value tvp5150_init_default[] = {
{ /* 0x00 */
TVP5150_VD_IN_SRC_SEL_1,0x00
TVP5150_VD_IN_SRC_SEL_1, 0x00
},
{ /* 0x01 */
TVP5150_ANAL_CHL_CTL,0x15
TVP5150_ANAL_CHL_CTL, 0x15
},
{ /* 0x02 */
TVP5150_OP_MODE_CTL,0x00
TVP5150_OP_MODE_CTL, 0x00
},
{ /* 0x03 */
TVP5150_MISC_CTL,0x01
TVP5150_MISC_CTL, 0x01
},
{ /* 0x06 */
TVP5150_COLOR_KIL_THSH_CTL,0x10
TVP5150_COLOR_KIL_THSH_CTL, 0x10
},
{ /* 0x07 */
TVP5150_LUMA_PROC_CTL_1,0x60
TVP5150_LUMA_PROC_CTL_1, 0x60
},
{ /* 0x08 */
TVP5150_LUMA_PROC_CTL_2,0x00
TVP5150_LUMA_PROC_CTL_2, 0x00
},
{ /* 0x09 */
TVP5150_BRIGHT_CTL,0x80
TVP5150_BRIGHT_CTL, 0x80
},
{ /* 0x0a */
TVP5150_SATURATION_CTL,0x80
TVP5150_SATURATION_CTL, 0x80
},
{ /* 0x0b */
TVP5150_HUE_CTL,0x00
TVP5150_HUE_CTL, 0x00
},
{ /* 0x0c */
TVP5150_CONTRAST_CTL,0x80
TVP5150_CONTRAST_CTL, 0x80
},
{ /* 0x0d */
TVP5150_DATA_RATE_SEL,0x47
TVP5150_DATA_RATE_SEL, 0x47
},
{ /* 0x0e */
TVP5150_LUMA_PROC_CTL_3,0x00
TVP5150_LUMA_PROC_CTL_3, 0x00
},
{ /* 0x0f */
TVP5150_CONF_SHARED_PIN,0x08
TVP5150_CONF_SHARED_PIN, 0x08
},
{ /* 0x11 */
TVP5150_ACT_VD_CROP_ST_MSB,0x00
TVP5150_ACT_VD_CROP_ST_MSB, 0x00
},
{ /* 0x12 */
TVP5150_ACT_VD_CROP_ST_LSB,0x00
TVP5150_ACT_VD_CROP_ST_LSB, 0x00
},
{ /* 0x13 */
TVP5150_ACT_VD_CROP_STP_MSB,0x00
TVP5150_ACT_VD_CROP_STP_MSB, 0x00
},
{ /* 0x14 */
TVP5150_ACT_VD_CROP_STP_LSB,0x00
TVP5150_ACT_VD_CROP_STP_LSB, 0x00
},
{ /* 0x15 */
TVP5150_GENLOCK,0x01
TVP5150_GENLOCK, 0x01
},
{ /* 0x16 */
TVP5150_HORIZ_SYNC_START,0x80
TVP5150_HORIZ_SYNC_START, 0x80
},
{ /* 0x18 */
TVP5150_VERT_BLANKING_START,0x00
TVP5150_VERT_BLANKING_START, 0x00
},
{ /* 0x19 */
TVP5150_VERT_BLANKING_STOP,0x00
TVP5150_VERT_BLANKING_STOP, 0x00
},
{ /* 0x1a */
TVP5150_CHROMA_PROC_CTL_1,0x0c
TVP5150_CHROMA_PROC_CTL_1, 0x0c
},
{ /* 0x1b */
TVP5150_CHROMA_PROC_CTL_2,0x14
TVP5150_CHROMA_PROC_CTL_2, 0x14
},
{ /* 0x1c */
TVP5150_INT_RESET_REG_B,0x00
TVP5150_INT_RESET_REG_B, 0x00
},
{ /* 0x1d */
TVP5150_INT_ENABLE_REG_B,0x00
TVP5150_INT_ENABLE_REG_B, 0x00
},
{ /* 0x1e */
TVP5150_INTT_CONFIG_REG_B,0x00
TVP5150_INTT_CONFIG_REG_B, 0x00
},
{ /* 0x28 */
TVP5150_VIDEO_STD,0x00
TVP5150_VIDEO_STD, 0x00
},
{ /* 0x2e */
TVP5150_MACROVISION_ON_CTR,0x0f
TVP5150_MACROVISION_ON_CTR, 0x0f
},
{ /* 0x2f */
TVP5150_MACROVISION_OFF_CTR,0x01
TVP5150_MACROVISION_OFF_CTR, 0x01
},
{ /* 0xbb */
TVP5150_TELETEXT_FIL_ENA,0x00
TVP5150_TELETEXT_FIL_ENA, 0x00
},
{ /* 0xc0 */
TVP5150_INT_STATUS_REG_A,0x00
TVP5150_INT_STATUS_REG_A, 0x00
},
{ /* 0xc1 */
TVP5150_INT_ENABLE_REG_A,0x00
TVP5150_INT_ENABLE_REG_A, 0x00
},
{ /* 0xc2 */
TVP5150_INT_CONF,0x04
TVP5150_INT_CONF, 0x04
},
{ /* 0xc8 */
TVP5150_FIFO_INT_THRESHOLD,0x80
TVP5150_FIFO_INT_THRESHOLD, 0x80
},
{ /* 0xc9 */
TVP5150_FIFO_RESET,0x00
TVP5150_FIFO_RESET, 0x00
},
{ /* 0xca */
TVP5150_LINE_NUMBER_INT,0x00
TVP5150_LINE_NUMBER_INT, 0x00
},
{ /* 0xcb */
TVP5150_PIX_ALIGN_REG_LOW,0x4e
TVP5150_PIX_ALIGN_REG_LOW, 0x4e
},
{ /* 0xcc */
TVP5150_PIX_ALIGN_REG_HIGH,0x00
TVP5150_PIX_ALIGN_REG_HIGH, 0x00
},
{ /* 0xcd */
TVP5150_FIFO_OUT_CTRL,0x01
TVP5150_FIFO_OUT_CTRL, 0x01
},
{ /* 0xcf */
TVP5150_FULL_FIELD_ENA,0x00
TVP5150_FULL_FIELD_ENA, 0x00
},
{ /* 0xd0 */
TVP5150_LINE_MODE_INI,0x00
TVP5150_LINE_MODE_INI, 0x00
},
{ /* 0xfc */
TVP5150_FULL_FIELD_MODE_REG,0x7f
TVP5150_FULL_FIELD_MODE_REG, 0x7f
},
{ /* end of data */
0xff,0xff
0xff, 0xff
}
};
@ -456,27 +456,27 @@ static const struct i2c_reg_value tvp5150_init_default[] = {
static const struct i2c_reg_value tvp5150_init_enable[] = {
{
TVP5150_CONF_SHARED_PIN, 2
},{ /* Automatic offset and AGC enabled */
}, { /* Automatic offset and AGC enabled */
TVP5150_ANAL_CHL_CTL, 0x15
},{ /* Activate YCrCb output 0x9 or 0xd ? */
}, { /* Activate YCrCb output 0x9 or 0xd ? */
TVP5150_MISC_CTL, TVP5150_MISC_CTL_GPCL |
TVP5150_MISC_CTL_INTREQ_OE |
TVP5150_MISC_CTL_YCBCR_OE |
TVP5150_MISC_CTL_SYNC_OE |
TVP5150_MISC_CTL_VBLANK |
TVP5150_MISC_CTL_CLOCK_OE,
},{ /* Activates video std autodetection for all standards */
}, { /* Activates video std autodetection for all standards */
TVP5150_AUTOSW_MSK, 0x0
},{ /* Default format: 0x47. For 4:2:2: 0x40 */
}, { /* Default format: 0x47. For 4:2:2: 0x40 */
TVP5150_DATA_RATE_SEL, 0x47
},{
}, {
TVP5150_CHROMA_PROC_CTL_1, 0x0c
},{
}, {
TVP5150_CHROMA_PROC_CTL_2, 0x54
},{ /* Non documented, but initialized on WinTV USB2 */
}, { /* Non documented, but initialized on WinTV USB2 */
0x27, 0x20
},{
0xff,0xff
}, {
0xff, 0xff
}
};
@ -500,78 +500,80 @@ struct i2c_vbi_ram_value {
* and so on. There are 16 possible locations from 0 to 15.
*/
static struct i2c_vbi_ram_value vbi_ram_default[] =
{
/* FIXME: Current api doesn't handle all VBI types, those not
yet supported are placed under #if 0 */
static struct i2c_vbi_ram_value vbi_ram_default[] = {
/*
* FIXME: Current api doesn't handle all VBI types, those not
* yet supported are placed under #if 0
*/
#if 0
[0] = {0x010, /* Teletext, SECAM, WST System A */
{V4L2_SLICED_TELETEXT_SECAM,6,23,1},
{V4L2_SLICED_TELETEXT_SECAM, 6, 23, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x26,
0xe6, 0xb4, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
#endif
[1] = {0x030, /* Teletext, PAL, WST System B */
{V4L2_SLICED_TELETEXT_B,6,22,1},
{V4L2_SLICED_TELETEXT_B, 6, 22, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x2b,
0xa6, 0x72, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
#if 0
[2] = {0x050, /* Teletext, PAL, WST System C */
{V4L2_SLICED_TELETEXT_PAL_C,6,22,1},
{V4L2_SLICED_TELETEXT_PAL_C, 6, 22, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
0xa6, 0x98, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
[3] = {0x070, /* Teletext, NTSC, WST System B */
{V4L2_SLICED_TELETEXT_NTSC_B,10,21,1},
{V4L2_SLICED_TELETEXT_NTSC_B, 10, 21, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0x27, 0x2e, 0x20, 0x23,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
[4] = {0x090, /* Tetetext, NTSC NABTS System C */
{V4L2_SLICED_TELETEXT_NTSC_C,10,21,1},
{V4L2_SLICED_TELETEXT_NTSC_C, 10, 21, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xe7, 0x2e, 0x20, 0x22,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x15, 0x00 }
},
[5] = {0x0b0, /* Teletext, NTSC-J, NABTS System D */
{V4L2_SLICED_TELETEXT_NTSC_D,10,21,1},
{V4L2_SLICED_TELETEXT_NTSC_D, 10, 21, 1},
{ 0xaa, 0xaa, 0xff, 0xff, 0xa7, 0x2e, 0x20, 0x23,
0x69, 0x93, 0x0d, 0x00, 0x00, 0x00, 0x10, 0x00 }
},
[6] = {0x0d0, /* Closed Caption, PAL/SECAM */
{V4L2_SLICED_CAPTION_625,22,22,1},
{V4L2_SLICED_CAPTION_625, 22, 22, 1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0xa6, 0x7b, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
},
#endif
[7] = {0x0f0, /* Closed Caption, NTSC */
{V4L2_SLICED_CAPTION_525,21,21,1},
{V4L2_SLICED_CAPTION_525, 21, 21, 1},
{ 0xaa, 0x2a, 0xff, 0x3f, 0x04, 0x51, 0x6e, 0x02,
0x69, 0x8c, 0x09, 0x00, 0x00, 0x00, 0x27, 0x00 }
},
[8] = {0x110, /* Wide Screen Signal, PAL/SECAM */
{V4L2_SLICED_WSS_625,23,23,1},
{V4L2_SLICED_WSS_625, 23, 23, 1},
{ 0x5b, 0x55, 0xc5, 0xff, 0x00, 0x71, 0x6e, 0x42,
0xa6, 0xcd, 0x0f, 0x00, 0x00, 0x00, 0x3a, 0x00 }
},
#if 0
[9] = {0x130, /* Wide Screen Signal, NTSC C */
{V4L2_SLICED_WSS_525,20,20,1},
{V4L2_SLICED_WSS_525, 20, 20, 1},
{ 0x38, 0x00, 0x3f, 0x00, 0x00, 0x71, 0x6e, 0x43,
0x69, 0x7c, 0x08, 0x00, 0x00, 0x00, 0x39, 0x00 }
},
[10] = {0x150, /* Vertical Interval Timecode (VITC), PAL/SECAM */
{V4l2_SLICED_VITC_625,6,22,0},
{V4l2_SLICED_VITC_625, 6, 22, 0},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0xa6, 0x85, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
},
[11] = {0x170, /* Vertical Interval Timecode (VITC), NTSC */
{V4l2_SLICED_VITC_525,10,20,0},
{V4l2_SLICED_VITC_525, 10, 20, 0},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x6d, 0x49,
0x69, 0x94, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00 }
},
#endif
[12] = {0x190, /* Video Program System (VPS), PAL */
{V4L2_SLICED_VPS,16,16,0},
{V4L2_SLICED_VPS, 16, 16, 0},
{ 0xaa, 0xaa, 0xff, 0xff, 0xba, 0xce, 0x2b, 0x0d,
0xa6, 0xda, 0x0b, 0x00, 0x00, 0x00, 0x60, 0x00 }
},
@ -623,7 +625,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
int line, i;
dev_dbg_lvl(sd->dev, 1, debug, "g_sliced_vbi_cap\n");
memset(cap, 0, sizeof *cap);
memset(cap, 0, sizeof(*cap));
for (i = 0; i < ARRAY_SIZE(vbi_ram_default); i++) {
const struct i2c_vbi_ram_value *regs = &vbi_ram_default[i];
@ -655,7 +657,7 @@ static int tvp5150_g_sliced_vbi_cap(struct v4l2_subdev *sd,
* MSB = field2
*/
static int tvp5150_set_vbi(struct v4l2_subdev *sd,
unsigned int type,u8 flags, int line,
unsigned int type, u8 flags, int line,
const int fields)
{
struct tvp5150 *decoder = to_tvp5150(sd);
@ -1101,11 +1103,14 @@ static int tvp5150_s_routing(struct v4l2_subdev *sd,
static int tvp5150_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
{
/* this is for capturing 36 raw vbi lines
if there's a way to cut off the beginning 2 vbi lines
with the tvp5150 then the vbi line count could be lowered
to 17 lines/field again, although I couldn't find a register
which could do that cropping */
/*
* this is for capturing 36 raw vbi lines
* if there's a way to cut off the beginning 2 vbi lines
* with the tvp5150 then the vbi line count could be lowered
* to 17 lines/field again, although I couldn't find a register
* which could do that cropping
*/
if (fmt->sample_format == V4L2_PIX_FMT_GREY)
tvp5150_write(sd, TVP5150_LUMA_PROC_CTL_1, 0x70);
if (fmt->count[0] == 18 && fmt->count[1] == 18) {

View File

@ -0,0 +1,564 @@
// SPDX-License-Identifier: GPL-2.0
/*
* video-i2c.c - Support for I2C transport video devices
*
* Copyright (C) 2018 Matt Ranostay <matt.ranostay@konsulko.com>
*
* Supported:
* - Panasonic AMG88xx Grid-Eye Sensors
*/
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
#include <linux/i2c.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-vmalloc.h>
#define VIDEO_I2C_DRIVER "video-i2c"
struct video_i2c_chip;
struct video_i2c_buffer {
struct vb2_v4l2_buffer vb;
struct list_head list;
};
struct video_i2c_data {
struct i2c_client *client;
const struct video_i2c_chip *chip;
struct mutex lock;
spinlock_t slock;
unsigned int sequence;
struct mutex queue_lock;
struct v4l2_device v4l2_dev;
struct video_device vdev;
struct vb2_queue vb_vidq;
struct task_struct *kthread_vid_cap;
struct list_head vid_cap_active;
};
static const struct v4l2_fmtdesc amg88xx_format = {
.pixelformat = V4L2_PIX_FMT_Y12,
};
static const struct v4l2_frmsize_discrete amg88xx_size = {
.width = 8,
.height = 8,
};
struct video_i2c_chip {
/* video dimensions */
const struct v4l2_fmtdesc *format;
const struct v4l2_frmsize_discrete *size;
/* max frames per second */
unsigned int max_fps;
/* pixel buffer size */
unsigned int buffer_size;
/* pixel size in bits */
unsigned int bpp;
/* xfer function */
int (*xfer)(struct video_i2c_data *data, char *buf);
};
static int amg88xx_xfer(struct video_i2c_data *data, char *buf)
{
struct i2c_client *client = data->client;
struct i2c_msg msg[2];
u8 reg = 0x80;
int ret;
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = (char *)&reg;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = data->chip->buffer_size;
msg[1].buf = (char *)buf;
ret = i2c_transfer(client->adapter, msg, 2);
return (ret == 2) ? 0 : -EIO;
}
#define AMG88XX 0
static const struct video_i2c_chip video_i2c_chip[] = {
[AMG88XX] = {
.size = &amg88xx_size,
.format = &amg88xx_format,
.max_fps = 10,
.buffer_size = 128,
.bpp = 16,
.xfer = &amg88xx_xfer,
},
};
static const struct v4l2_file_operations video_i2c_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
.release = vb2_fop_release,
.poll = vb2_fop_poll,
.read = vb2_fop_read,
.mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
};
static int queue_setup(struct vb2_queue *vq,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], struct device *alloc_devs[])
{
struct video_i2c_data *data = vb2_get_drv_priv(vq);
unsigned int size = data->chip->buffer_size;
if (vq->num_buffers + *nbuffers < 2)
*nbuffers = 2;
if (*nplanes)
return sizes[0] < size ? -EINVAL : 0;
*nplanes = 1;
sizes[0] = size;
return 0;
}
static int buffer_prepare(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue);
unsigned int size = data->chip->buffer_size;
if (vb2_plane_size(vb, 0) < size)
return -EINVAL;
vbuf->field = V4L2_FIELD_NONE;
vb2_set_plane_payload(vb, 0, size);
return 0;
}
static void buffer_queue(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct video_i2c_data *data = vb2_get_drv_priv(vb->vb2_queue);
struct video_i2c_buffer *buf =
container_of(vbuf, struct video_i2c_buffer, vb);
spin_lock(&data->slock);
list_add_tail(&buf->list, &data->vid_cap_active);
spin_unlock(&data->slock);
}
static int video_i2c_thread_vid_cap(void *priv)
{
struct video_i2c_data *data = priv;
unsigned int delay = msecs_to_jiffies(1000 / data->chip->max_fps);
set_freezable();
do {
unsigned long start_jiffies = jiffies;
struct video_i2c_buffer *vid_cap_buf = NULL;
int schedule_delay;
try_to_freeze();
spin_lock(&data->slock);
if (!list_empty(&data->vid_cap_active)) {
vid_cap_buf = list_last_entry(&data->vid_cap_active,
struct video_i2c_buffer, list);
list_del(&vid_cap_buf->list);
}
spin_unlock(&data->slock);
if (vid_cap_buf) {
struct vb2_buffer *vb2_buf = &vid_cap_buf->vb.vb2_buf;
void *vbuf = vb2_plane_vaddr(vb2_buf, 0);
int ret;
ret = data->chip->xfer(data, vbuf);
vb2_buf->timestamp = ktime_get_ns();
vid_cap_buf->vb.sequence = data->sequence++;
vb2_buffer_done(vb2_buf, ret ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
}
schedule_delay = delay - (jiffies - start_jiffies);
if (time_after(jiffies, start_jiffies + delay))
schedule_delay = delay;
schedule_timeout_interruptible(schedule_delay);
} while (!kthread_should_stop());
return 0;
}
static void video_i2c_del_list(struct vb2_queue *vq, enum vb2_buffer_state state)
{
struct video_i2c_data *data = vb2_get_drv_priv(vq);
struct video_i2c_buffer *buf, *tmp;
spin_lock(&data->slock);
list_for_each_entry_safe(buf, tmp, &data->vid_cap_active, list) {
list_del(&buf->list);
vb2_buffer_done(&buf->vb.vb2_buf, state);
}
spin_unlock(&data->slock);
}
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct video_i2c_data *data = vb2_get_drv_priv(vq);
if (data->kthread_vid_cap)
return 0;
data->sequence = 0;
data->kthread_vid_cap = kthread_run(video_i2c_thread_vid_cap, data,
"%s-vid-cap", data->v4l2_dev.name);
if (!IS_ERR(data->kthread_vid_cap))
return 0;
video_i2c_del_list(vq, VB2_BUF_STATE_QUEUED);
return PTR_ERR(data->kthread_vid_cap);
}
static void stop_streaming(struct vb2_queue *vq)
{
struct video_i2c_data *data = vb2_get_drv_priv(vq);
if (data->kthread_vid_cap == NULL)
return;
kthread_stop(data->kthread_vid_cap);
data->kthread_vid_cap = NULL;
video_i2c_del_list(vq, VB2_BUF_STATE_ERROR);
}
static struct vb2_ops video_i2c_video_qops = {
.queue_setup = queue_setup,
.buf_prepare = buffer_prepare,
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
static int video_i2c_querycap(struct file *file, void *priv,
struct v4l2_capability *vcap)
{
struct video_i2c_data *data = video_drvdata(file);
struct i2c_client *client = data->client;
strlcpy(vcap->driver, data->v4l2_dev.name, sizeof(vcap->driver));
strlcpy(vcap->card, data->vdev.name, sizeof(vcap->card));
sprintf(vcap->bus_info, "I2C:%d-%d", client->adapter->nr, client->addr);
return 0;
}
static int video_i2c_g_input(struct file *file, void *fh, unsigned int *inp)
{
*inp = 0;
return 0;
}
static int video_i2c_s_input(struct file *file, void *fh, unsigned int inp)
{
return (inp > 0) ? -EINVAL : 0;
}
static int video_i2c_enum_input(struct file *file, void *fh,
struct v4l2_input *vin)
{
if (vin->index > 0)
return -EINVAL;
strlcpy(vin->name, "Camera", sizeof(vin->name));
vin->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
static int video_i2c_enum_fmt_vid_cap(struct file *file, void *fh,
struct v4l2_fmtdesc *fmt)
{
struct video_i2c_data *data = video_drvdata(file);
enum v4l2_buf_type type = fmt->type;
if (fmt->index > 0)
return -EINVAL;
*fmt = *data->chip->format;
fmt->type = type;
return 0;
}
static int video_i2c_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
const struct video_i2c_data *data = video_drvdata(file);
const struct v4l2_frmsize_discrete *size = data->chip->size;
/* currently only one frame size is allowed */
if (fsize->index > 0)
return -EINVAL;
if (fsize->pixel_format != data->chip->format->pixelformat)
return -EINVAL;
fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
fsize->discrete.width = size->width;
fsize->discrete.height = size->height;
return 0;
}
static int video_i2c_enum_frameintervals(struct file *file, void *priv,
struct v4l2_frmivalenum *fe)
{
const struct video_i2c_data *data = video_drvdata(file);
const struct v4l2_frmsize_discrete *size = data->chip->size;
if (fe->index > 0)
return -EINVAL;
if (fe->width != size->width || fe->height != size->height)
return -EINVAL;
fe->type = V4L2_FRMIVAL_TYPE_DISCRETE;
fe->discrete.numerator = 1;
fe->discrete.denominator = data->chip->max_fps;
return 0;
}
static int video_i2c_try_fmt_vid_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
const struct video_i2c_data *data = video_drvdata(file);
const struct v4l2_frmsize_discrete *size = data->chip->size;
struct v4l2_pix_format *pix = &fmt->fmt.pix;
unsigned int bpp = data->chip->bpp / 8;
pix->width = size->width;
pix->height = size->height;
pix->pixelformat = data->chip->format->pixelformat;
pix->field = V4L2_FIELD_NONE;
pix->bytesperline = pix->width * bpp;
pix->sizeimage = pix->bytesperline * pix->height;
pix->colorspace = V4L2_COLORSPACE_RAW;
return 0;
}
static int video_i2c_s_fmt_vid_cap(struct file *file, void *fh,
struct v4l2_format *fmt)
{
struct video_i2c_data *data = video_drvdata(file);
if (vb2_is_busy(&data->vb_vidq))
return -EBUSY;
return video_i2c_try_fmt_vid_cap(file, fh, fmt);
}
static int video_i2c_g_parm(struct file *filp, void *priv,
struct v4l2_streamparm *parm)
{
struct video_i2c_data *data = video_drvdata(filp);
if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
parm->parm.capture.readbuffers = 1;
parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
parm->parm.capture.timeperframe.numerator = 1;
parm->parm.capture.timeperframe.denominator = data->chip->max_fps;
return 0;
}
static const struct v4l2_ioctl_ops video_i2c_ioctl_ops = {
.vidioc_querycap = video_i2c_querycap,
.vidioc_g_input = video_i2c_g_input,
.vidioc_s_input = video_i2c_s_input,
.vidioc_enum_input = video_i2c_enum_input,
.vidioc_enum_fmt_vid_cap = video_i2c_enum_fmt_vid_cap,
.vidioc_enum_framesizes = video_i2c_enum_framesizes,
.vidioc_enum_frameintervals = video_i2c_enum_frameintervals,
.vidioc_g_fmt_vid_cap = video_i2c_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = video_i2c_s_fmt_vid_cap,
.vidioc_g_parm = video_i2c_g_parm,
.vidioc_s_parm = video_i2c_g_parm,
.vidioc_try_fmt_vid_cap = video_i2c_try_fmt_vid_cap,
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
};
static void video_i2c_release(struct video_device *vdev)
{
kfree(video_get_drvdata(vdev));
}
static int video_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct video_i2c_data *data;
struct v4l2_device *v4l2_dev;
struct vb2_queue *queue;
int ret = -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
if (dev_fwnode(&client->dev))
data->chip = device_get_match_data(&client->dev);
else if (id)
data->chip = &video_i2c_chip[id->driver_data];
else
goto error_free_device;
data->client = client;
v4l2_dev = &data->v4l2_dev;
strlcpy(v4l2_dev->name, VIDEO_I2C_DRIVER, sizeof(v4l2_dev->name));
ret = v4l2_device_register(&client->dev, v4l2_dev);
if (ret < 0)
goto error_free_device;
mutex_init(&data->lock);
mutex_init(&data->queue_lock);
queue = &data->vb_vidq;
queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
queue->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR | VB2_READ;
queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
queue->drv_priv = data;
queue->buf_struct_size = sizeof(struct video_i2c_buffer);
queue->min_buffers_needed = 1;
queue->ops = &video_i2c_video_qops;
queue->mem_ops = &vb2_vmalloc_memops;
ret = vb2_queue_init(queue);
if (ret < 0)
goto error_unregister_device;
data->vdev.queue = queue;
data->vdev.queue->lock = &data->queue_lock;
snprintf(data->vdev.name, sizeof(data->vdev.name),
"I2C %d-%d Transport Video",
client->adapter->nr, client->addr);
data->vdev.v4l2_dev = v4l2_dev;
data->vdev.fops = &video_i2c_fops;
data->vdev.lock = &data->lock;
data->vdev.ioctl_ops = &video_i2c_ioctl_ops;
data->vdev.release = video_i2c_release;
data->vdev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
spin_lock_init(&data->slock);
INIT_LIST_HEAD(&data->vid_cap_active);
video_set_drvdata(&data->vdev, data);
i2c_set_clientdata(client, data);
ret = video_register_device(&data->vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0)
goto error_unregister_device;
return 0;
error_unregister_device:
v4l2_device_unregister(v4l2_dev);
mutex_destroy(&data->lock);
mutex_destroy(&data->queue_lock);
error_free_device:
kfree(data);
return ret;
}
static int video_i2c_remove(struct i2c_client *client)
{
struct video_i2c_data *data = i2c_get_clientdata(client);
video_unregister_device(&data->vdev);
v4l2_device_unregister(&data->v4l2_dev);
mutex_destroy(&data->lock);
mutex_destroy(&data->queue_lock);
return 0;
}
static const struct i2c_device_id video_i2c_id_table[] = {
{ "amg88xx", AMG88XX },
{}
};
MODULE_DEVICE_TABLE(i2c, video_i2c_id_table);
static const struct of_device_id video_i2c_of_match[] = {
{ .compatible = "panasonic,amg88xx", .data = &video_i2c_chip[AMG88XX] },
{}
};
MODULE_DEVICE_TABLE(of, video_i2c_of_match);
static struct i2c_driver video_i2c_driver = {
.driver = {
.name = VIDEO_I2C_DRIVER,
.of_match_table = video_i2c_of_match,
},
.probe = video_i2c_probe,
.remove = video_i2c_remove,
.id_table = video_i2c_id_table,
};
module_i2c_driver(video_i2c_driver);
MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
MODULE_DESCRIPTION("I2C transport video support");
MODULE_LICENSE("GPL v2");

View File

@ -54,9 +54,10 @@ static int media_device_close(struct file *filp)
return 0;
}
static int media_device_get_info(struct media_device *dev,
struct media_device_info *info)
static long media_device_get_info(struct media_device *dev, void *arg)
{
struct media_device_info *info = arg;
memset(info, 0, sizeof(*info));
if (dev->driver_name[0])
@ -93,9 +94,9 @@ static struct media_entity *find_entity(struct media_device *mdev, u32 id)
return NULL;
}
static long media_device_enum_entities(struct media_device *mdev,
struct media_entity_desc *entd)
static long media_device_enum_entities(struct media_device *mdev, void *arg)
{
struct media_entity_desc *entd = arg;
struct media_entity *ent;
ent = find_entity(mdev, entd->id);
@ -146,9 +147,9 @@ static void media_device_kpad_to_upad(const struct media_pad *kpad,
upad->flags = kpad->flags;
}
static long media_device_enum_links(struct media_device *mdev,
struct media_links_enum *links)
static long media_device_enum_links(struct media_device *mdev, void *arg)
{
struct media_links_enum *links = arg;
struct media_entity *entity;
entity = find_entity(mdev, links->entity);
@ -195,9 +196,9 @@ static long media_device_enum_links(struct media_device *mdev,
return 0;
}
static long media_device_setup_link(struct media_device *mdev,
struct media_link_desc *linkd)
static long media_device_setup_link(struct media_device *mdev, void *arg)
{
struct media_link_desc *linkd = arg;
struct media_link *link = NULL;
struct media_entity *source;
struct media_entity *sink;
@ -225,9 +226,9 @@ static long media_device_setup_link(struct media_device *mdev,
return __media_entity_setup_link(link, linkd->flags);
}
static long media_device_get_topology(struct media_device *mdev,
struct media_v2_topology *topo)
static long media_device_get_topology(struct media_device *mdev, void *arg)
{
struct media_v2_topology *topo = arg;
struct media_entity *entity;
struct media_interface *intf;
struct media_pad *pad;

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