mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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:
commit
3036bc4536
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
100
Documentation/devicetree/bindings/media/cdns,csi2rx.txt
Normal file
100
Documentation/devicetree/bindings/media/cdns,csi2rx.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
98
Documentation/devicetree/bindings/media/cdns,csi2tx.txt
Normal file
98
Documentation/devicetree/bindings/media/cdns,csi2tx.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
52
Documentation/devicetree/bindings/media/i2c/ov7251.txt
Normal file
52
Documentation/devicetree/bindings/media/i2c/ov7251.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
40
Documentation/devicetree/bindings/media/i2c/ov772x.txt
Normal file
40
Documentation/devicetree/bindings/media/i2c/ov772x.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -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>;
|
||||
};
|
||||
...
|
||||
};
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
101
Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
Normal file
101
Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -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.
|
||||
|
@ -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}|
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -41,6 +41,6 @@ applicable to all devices.
|
||||
extended-controls
|
||||
format
|
||||
planar-apis
|
||||
crop
|
||||
selection-api
|
||||
crop
|
||||
streaming-par
|
||||
|
@ -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
|
||||
===================
|
||||
|
@ -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.
|
@ -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.
|
39
Documentation/media/uapi/v4l/selection-api-vs-crop-api.rst
Normal file
39
Documentation/media/uapi/v4l/selection-api-vs-crop-api.rst
Normal 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.
|
@ -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
|
||||
|
@ -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 |
@ -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.
|
||||
|
||||
|
@ -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)
|
||||
-
|
||||
|
@ -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
|
||||
-
|
||||
|
31
MAINTAINERS
31
MAINTAINERS
@ -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>
|
||||
|
@ -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),
|
||||
},
|
||||
};
|
||||
|
@ -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, ©->state);
|
||||
|
||||
return ©->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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 ||
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -10,6 +10,7 @@ struct stv0910_cfg {
|
||||
u8 parallel;
|
||||
u8 rptlvl;
|
||||
u8 single;
|
||||
u8 tsspeed;
|
||||
};
|
||||
|
||||
#if IS_REACHABLE(CONFIG_DVB_STV0910)
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
1318
drivers/media/i2c/imx258.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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, ®_val[0]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_3, ®_val[0]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_2, ®_val[1]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_2, ®_val[1]);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_1, ®_val[2]);
|
||||
err = imx274_read_reg(priv, IMX274_VMAX_REG_1, ®_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);
|
||||
|
@ -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");
|
||||
|
@ -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),
|
||||
},
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
1503
drivers/media/i2c/ov7251.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
564
drivers/media/i2c/video-i2c.c
Normal file
564
drivers/media/i2c/video-i2c.c
Normal 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 *)®
|
||||
|
||||
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");
|
@ -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
Loading…
Reference in New Issue
Block a user