media updates for v4.17-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJaw1yeAAoJEAhfPr2O5OEVDDgQAIYpin6obedJOm7zIm741Q0S
 fS2FL2pygyvHlVtU20ERHgvM6aD5tujekpDM4+GNgnq0aAabxvqBvdohmHQjyVSw
 FgszgY6kQSnI8S4Oy9RB8H/MFRq7Wz9Qf+KmJh0SfuUoMzBe2A40yLjYQ+sAMJr9
 mm0ijxxRpFYikVtIBgKDbjnx6wdkOs12M7YlJuI8N/tMBHMt+p2EfvqcX6GF725i
 sgLGcMsTJr1sUSyY8vnM2pAlKfZL2tZqigx5f9sB4UM7uHSw/oL/a/8I+t6Mju1X
 J1BD3L7UtTpwqO9sAR5BsJQ+0pAkXNOF+eLGs2p9rx4sO0DOLKoUptMI+YryvE86
 /SOlTskSSAeX/rBFyZJw1zv0/9mdGrHoyCy0q/lfDkD/mQkrUJDDZ7GPLqZ9rLUe
 2cXn1xMWB/soeR70oTyew0D2SZkp6y4DQr0Rwje7V8/SOWMmJvhaVIWhVIP9ZrS6
 AvCS7WUYTTVIX+td2glnLkJ5SaXXJyRYv8Utp/TUrYvCFOX7wsk7F0pRY4PE4PeZ
 BL7Bl8H9l3HGWWhdqPvw+ETdJgcbq/IwVUcpuuEPjkhDZEqHz//vzwoPt1nT4v6M
 gfqfaW5LaYuj0MYYqyxZMDwP3FWk4SsQ0NZzmaFs+yfE17bcWUMuf3ZVJtjmLxzk
 RUo0E/7RZsrw7LkCy0KF
 =bzhS
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - new CEC pin injection code for testing purposes

 - DVB frontend cxd2099 promoted from staging

 - new platform driver for Sony cxd2880 DVB devices

 - new sensor drivers: mt9t112, ov2685, ov5695, ov772x, tda1997x,
   tw9910.c

 - removal of unused cx18 and ivtv alsa mixers

 - the reneseas-ceu driver doesn't depend on soc_camera anymore and
   moved from staging

 - removed the mantis_vp3028 driver, unused since 2009

 - s5p-mfc: add support for version 10 of the MSP

 - added a decoder for imon protocol

 - atomisp: lots of cleanups

 - imx074 and mt9t031: don't depend on soc_camera anymore, being
   promoted from staging

 - added helper functions to better support DVB I2C binding

 - lots of driver improvements and cleanups

* tag 'media/v4.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (438 commits)
  media: v4l2-ioctl: rename a temp var that stores _IOC_SIZE(cmd)
  media: fimc-capture: get rid of two warnings
  media: dvb-usb-v2: fix a missing dependency of I2C_MUX
  media: uvc: to the right check at uvc_ioctl_enum_framesizes()
  media: cec-core: fix a bug at cec_error_inj_write()
  media: tda9840: cleanup a warning
  media: tm6000:  avoid casting just to print pointer address
  media: em28xx-input: improve error handling code
  media: zr364xx: avoid casting just to print pointer address
  media: vivid-radio-rx: add a cast to avoid a warning
  media: saa7134-alsa: don't use casts to print a buffer address
  media: solo6x10: get rid of an address space warning
  media: zoran: don't cast pointers to print them
  media: ir-kbd-i2c: change the if logic to avoid a warning
  media: ir-kbd-i2c: improve error handling code
  media: saa7134-input: improve error handling
  media: s2255drv: fix a casting warning
  media: ivtvfb: Cleanup some warnings
  media: videobuf-dma-sg: Fix a weird cast
  soc_camera: fix a weird cast on printk
  ...
This commit is contained in:
Linus Torvalds 2018-04-03 17:16:59 -07:00
commit ef1c4a6fa9
572 changed files with 37812 additions and 21347 deletions

View file

@ -0,0 +1,40 @@
What: /sys/kernel/debug/cec/*/error-inj
Date: March 2018
Contact: Hans Verkuil <hans.verkuil@cisco.com>
Description:
The CEC Framework allows for CEC error injection commands through
debugfs. Drivers that support this will create an error-inj file
through which the error injection commands can be given.
The basic syntax is as follows:
Leading spaces/tabs are ignored. If the next character is a '#' or the
end of the line was reached, then the whole line is ignored. Otherwise
a command is expected.
It is up to the driver to decide what commands to implement. The only
exception is that the command 'clear' without any arguments must be
implemented and that it will remove all current error injection
commands.
This ensures that you can always do 'echo clear >error-inj' to clear any
error injections without having to know the details of the driver-specific
commands.
Note that the output of 'error-inj' shall be valid as input to 'error-inj'.
So this must work:
$ cat error-inj >einj.txt
$ cat einj.txt >error-inj
Other than these basic rules described above this ABI is not considered
stable and may change in the future.
Drivers that implement this functionality must document the commands as
part of the CEC documentation and must keep that documentation up to date
when changes are made.
The following CEC error injection implementations exist:
- Documentation/media/uapi/cec/cec-pin-error-inj.rst

View file

@ -7,8 +7,9 @@ called VPU (Video Processing Unit).
Required properties:
- compatible : should be "fsl,<chip>-src" for i.MX SoCs:
(a) "fsl,imx27-vpu" for CodaDx6 present in i.MX27
(b) "fsl,imx53-vpu" for CODA7541 present in i.MX53
(c) "fsl,imx6q-vpu" for CODA960 present in i.MX6q
(b) "fsl,imx51-vpu" for CodaHx4 present in i.MX51
(c) "fsl,imx53-vpu" for CODA7541 present in i.MX53
(d) "fsl,imx6q-vpu" for CODA960 present in i.MX6q
- reg: should be register base and length as documented in the
SoC reference manual
- interrupts : Should contain the VPU interrupt. For CODA960,

View file

@ -13,7 +13,11 @@ Required Properties:
- "adi,adv7611" for the ADV7611
- "adi,adv7612" for the ADV7612
- reg: I2C slave address
- reg: I2C slave addresses
The ADV76xx has up to thirteen 256-byte maps that can be accessed via the
main I2C ports. Each map has it own I2C address and acts as a standard
slave device on the I2C bus. The main address is mandatory, others are
optional and revert to defaults if not specified.
- hpd-gpios: References to the GPIOs that control the HDMI hot-plug
detection pins, one per HDMI input. The active flag indicates the GPIO
@ -35,6 +39,11 @@ Optional Properties:
- reset-gpios: Reference to the GPIO connected to the device's reset pin.
- default-input: Select which input is selected after reset.
- reg-names : Names of maps with programmable addresses.
It can contain any map needing a non-default address.
Possible maps names are :
"main", "avlink", "cec", "infoframe", "esdp", "dpp", "afe",
"rep", "edid", "hdmi", "test", "cp", "vdp"
Optional Endpoint Properties:
@ -52,7 +61,12 @@ Example:
hdmi_receiver@4c {
compatible = "adi,adv7611";
reg = <0x4c>;
/*
* The edid page will be accessible @ 0x66 on the I2C bus. All
* other maps will retain their default addresses.
*/
reg = <0x4c>, <0x66>;
reg-names "main", "edid";
reset-gpios = <&ioexp 0 GPIO_ACTIVE_LOW>;
hpd-gpios = <&ioexp 2 GPIO_ACTIVE_HIGH>;

View file

@ -0,0 +1,41 @@
* Omnivision OV2685 MIPI CSI-2 sensor
Required Properties:
- compatible: shall be "ovti,ov2685"
- clocks: reference to the xvclk input clock
- clock-names: shall be "xvclk"
- avdd-supply: Analog voltage supply, 2.8 volts
- dovdd-supply: Digital I/O voltage supply, 1.8 volts
- dvdd-supply: Digital core voltage supply, 1.8 volts
- reset-gpios: Low active reset gpio
The device node shall contain one 'port' child node with an
'endpoint' subnode for its digital output video port,
in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
The endpoint optional property 'data-lanes' shall be "<1>".
Example:
&i2c7 {
ov2685: camera-sensor@3c {
compatible = "ovti,ov2685";
reg = <0x3c>;
pinctrl-names = "default";
pinctrl-0 = <&clk_24m_cam>;
clocks = <&cru SCLK_TESTCLKOUT1>;
clock-names = "xvclk";
avdd-supply = <&pp2800_cam>;
dovdd-supply = <&pp1800>;
dvdd-supply = <&pp1800>;
reset-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
port {
ucam_out: endpoint {
remote-endpoint = <&mipi_in_ucam>;
data-lanes = <1>;
};
};
};
};

View file

@ -0,0 +1,41 @@
* Omnivision OV5695 MIPI CSI-2 sensor
Required Properties:
- compatible: shall be "ovti,ov5695"
- clocks: reference to the xvclk input clock
- clock-names: shall be "xvclk"
- avdd-supply: Analog voltage supply, 2.8 volts
- dovdd-supply: Digital I/O voltage supply, 1.8 volts
- dvdd-supply: Digital core voltage supply, 1.2 volts
- reset-gpios: Low active reset gpio
The device node shall contain one 'port' child node with an
'endpoint' subnode for its digital output video port,
in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
The endpoint optional property 'data-lanes' shall be "<1 2>".
Example:
&i2c7 {
ov5695: camera-sensor@36 {
compatible = "ovti,ov5695";
reg = <0x36>;
pinctrl-names = "default";
pinctrl-0 = <&clk_24m_cam>;
clocks = <&cru SCLK_TESTCLKOUT1>;
clock-names = "xvclk";
avdd-supply = <&pp2800_cam>;
dovdd-supply = <&pp1800>;
dvdd-supply = <&pp1250_cam>;
reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
port {
wcam_out: endpoint {
remote-endpoint = <&mipi_in_wcam>;
data-lanes = <1 2>;
};
};
};
};

View file

@ -9,14 +9,21 @@ Required Properties:
- clocks: reference to the xclk input clock.
- clock-names: should be "xclk".
Required Endpoint Properties:
- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
Optional Properties:
- reset-gpios: reference to the GPIO connected to the resetb pin, if any.
Active is low.
- powerdown-gpios: reference to the GPIO connected to the pwdn pin, if any.
Active is high.
- ov7670,pclk-hb-disable: a boolean property to suppress pixel clock output
signal during horizontal blankings.
The device node must contain one 'port' child node for its digital output
video port, in accordance with the video interface bindings defined in
The device node must contain one 'port' child node with one 'endpoint' child
sub-node for its digital output video port, in accordance with the video
interface bindings defined in:
Documentation/devicetree/bindings/media/video-interfaces.txt.
Example:
@ -34,8 +41,13 @@ Example:
assigned-clocks = <&pck0>;
assigned-clock-rates = <25000000>;
ov7670,pclk-hb-disable;
port {
ov7670_0: endpoint {
hsync-active = <0>;
vsync-active = <0>;
remote-endpoint = <&isi_0>;
};
};

View file

@ -0,0 +1,36 @@
* Omnivision OV9650/OV9652 CMOS sensor
Required Properties:
- compatible: shall be one of
"ovti,ov9650"
"ovti,ov9652"
- clocks: reference to the xvclk input clock.
Optional Properties:
- reset-gpios: reference to the GPIO connected to the resetb pin, if any.
Active is high.
- powerdown-gpios: reference to the GPIO connected to the pwdn pin, if any.
Active is high.
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 {
ov9650: camera@30 {
compatible = "ovti,ov9650";
reg = <0x30>;
reset-gpios = <&axi_gpio_0 0 GPIO_ACTIVE_HIGH>;
powerdown-gpios = <&axi_gpio_0 1 GPIO_ACTIVE_HIGH>;
clocks = <&xclk>;
port {
ov9650_0: endpoint {
remote-endpoint = <&vcap1_in0>;
};
};
};
};

View file

@ -0,0 +1,178 @@
Device-Tree bindings for the NXP TDA1997x HDMI receiver
The TDA19971/73 are HDMI video receivers.
The TDA19971 Video port output pins can be used as follows:
- RGB 8bit per color (24 bits total): R[11:4] B[11:4] G[11:4]
- YUV444 8bit per color (24 bits total): Y[11:4] Cr[11:4] Cb[11:4]
- YUV422 semi-planar 8bit per component (16 bits total): Y[11:4] CbCr[11:4]
- YUV422 semi-planar 10bit per component (20 bits total): Y[11:2] CbCr[11:2]
- YUV422 semi-planar 12bit per component (24 bits total): - Y[11:0] CbCr[11:0]
- YUV422 BT656 8bit per component (8 bits total): YCbCr[11:4] (2-cycles)
- YUV422 BT656 10bit per component (10 bits total): YCbCr[11:2] (2-cycles)
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The TDA19973 Video port output pins can be used as follows:
- RGB 12bit per color (36 bits total): R[11:0] B[11:0] G[11:0]
- YUV444 12bit per color (36 bits total): Y[11:0] Cb[11:0] Cr[11:0]
- YUV422 semi-planar 12bit per component (24 bits total): Y[11:0] CbCr[11:0]
- YUV422 BT656 12bit per component (12 bits total): YCbCr[11:0] (2-cycles)
The Video port output pins are mapped via 4-bit 'pin groups' allowing
for a variety of connection possibilities including swapping pin order within
pin groups. The video_portcfg device-tree property consists of register mapping
pairs which map a chip-specific VP output register to a 4-bit pin group. If
the pin group needs to be bit-swapped you can use the *_S pin-group defines.
Required Properties:
- compatible :
- "nxp,tda19971" for the TDA19971
- "nxp,tda19973" for the TDA19973
- reg : I2C slave address
- interrupts : The interrupt number
- DOVDD-supply : Digital I/O supply
- DVDD-supply : Digital Core supply
- AVDD-supply : Analog supply
- nxp,vidout-portcfg : array of pairs mapping VP output pins to pin groups.
Optional Properties:
- nxp,audout-format : DAI bus format: "i2s" or "spdif".
- nxp,audout-width : width of audio output data bus (1-4).
- nxp,audout-layout : data layout (0=AP0 used, 1=AP0/AP1/AP2/AP3 used).
- nxp,audout-mclk-fs : Multiplication factor between stream rate and codec
mclk.
The port node shall contain one endpoint child node for its digital
output video port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Optional Endpoint Properties:
The following three properties are defined in video-interfaces.txt and
are valid for the output parallel bus endpoint:
- hsync-active: Horizontal synchronization polarity. Defaults to active high.
- vsync-active: Vertical synchronization polarity. Defaults to active high.
- data-active: Data polarity. Defaults to active high.
Examples:
- VP[15:0] connected to IMX6 CSI_DATA[19:4] for 16bit YUV422
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
* and Y[11:4] across 16bits in the same pixclk cycle.
*/
nxp,vidout-portcfg =
/* Y[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
/* Y[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
/* CbCc[11:8]<->VP[07:04]<->CSI_DATA[11:8] */
< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
/* CbCr[7:4]<->VP[03:00]<->CSI_DATA[7:4] */
< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};
- VP[15:8] connected to IMX6 CSI_DATA[19:12] for 8bit BT656
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp YUV422 semi-planar mode outputs CbCr[11:4]
* and Y[11:4] across 16bits in the same pixclk cycle.
*/
nxp,vidout-portcfg =
/* Y[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_G_Y_11_8 >,
/* Y[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_G_Y_7_4 >,
/* CbCc[11:8]<->VP[07:04]<->CSI_DATA[11:8] */
< TDA1997X_VP24_V07_04 TDA1997X_R_CR_CBCR_11_8 >,
/* CbCr[7:4]<->VP[03:00]<->CSI_DATA[7:4] */
< TDA1997X_VP24_V03_00 TDA1997X_R_CR_CBCR_7_4 >;
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};
- VP[15:8] connected to IMX6 CSI_DATA[19:12] for 8bit BT656
16bit I2S layout0 with a 128*fs clock (A_WS, AP0, A_CLK pins)
hdmi-receiver@48 {
compatible = "nxp,tda19971";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_tda1997x>;
reg = <0x48>;
interrupt-parent = <&gpio1>;
interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
DOVDD-supply = <&reg_3p3v>;
AVDD-supply = <&reg_1p8v>;
DVDD-supply = <&reg_1p8v>;
/* audio */
#sound-dai-cells = <0>;
nxp,audout-format = "i2s";
nxp,audout-layout = <0>;
nxp,audout-width = <16>;
nxp,audout-mclk-fs = <128>;
/*
* The 8bpp BT656 mode outputs YCbCr[11:4] across 8bits over
* 2 pixclk cycles.
*/
nxp,vidout-portcfg =
/* YCbCr[11:8]<->VP[15:12]<->CSI_DATA[19:16] */
< TDA1997X_VP24_V15_12 TDA1997X_R_CR_CBCR_11_8 >,
/* YCbCr[7:4]<->VP[11:08]<->CSI_DATA[15:12] */
< TDA1997X_VP24_V11_08 TDA1997X_R_CR_CBCR_7_4 >,
port {
tda1997x_to_ipu1_csi0_mux: endpoint {
remote-endpoint = <&ipu1_csi0_mux_from_parallel_sensor>;
bus-width = <16>;
hsync-active = <1>;
vsync-active = <1>;
data-active = <1>;
};
};
};

View file

@ -56,7 +56,7 @@ Board setup example (vin1 composite video input)
------------------------------------------------
&i2c2 {
status = "ok";
status = "okay";
pinctrl-0 = <&i2c2_pins>;
pinctrl-names = "default";
@ -79,7 +79,7 @@ Board setup example (vin1 composite video input)
pinctrl-0 = <&vin1_pins>;
pinctrl-names = "default";
status = "ok";
status = "okay";
port {
#address-cells = <1>;

View file

@ -0,0 +1,81 @@
Renesas Capture Engine Unit (CEU)
----------------------------------------------
The Capture Engine Unit is the image capture interface found in the Renesas
SH 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.
- reg: Registers address base and size.
- interrupts: The interrupt specifier.
The CEU supports a single parallel input and should contain a single 'port'
subnode with a single 'endpoint'. Connection to input devices are modeled
according to the video interfaces OF bindings specified in:
Documentation/devicetree/bindings/media/video-interfaces.txt
Optional endpoint properties applicable to parallel input bus described in
the above mentioned "video-interfaces.txt" file are supported.
- hsync-active: Active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
If property is not present, default is active high.
- vsync-active: Active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
If property is not present, default is active high.
Example:
The example describes the connection between the Capture Engine Unit and an
OV7670 image sensor connected to i2c1 interface.
ceu: ceu@e8210000 {
reg = <0xe8210000 0x209c>;
compatible = "renesas,r7s72100-ceu";
interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&vio_pins>;
status = "okay";
port {
ceu_in: endpoint {
remote-endpoint = <&ov7670_out>;
hsync-active = <1>;
vsync-active = <0>;
};
};
};
i2c1: i2c@fcfee400 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
status = "okay";
clock-frequency = <100000>;
ov7670: camera@21 {
compatible = "ovti,ov7670";
reg = <0x21>;
pinctrl-names = "default";
pinctrl-0 = <&vio_pins>;
reset-gpios = <&port3 11 GPIO_ACTIVE_LOW>;
powerdown-gpios = <&port3 12 GPIO_ACTIVE_HIGH>;
port {
ov7670_out: endpoint {
remote-endpoint = <&ceu_in>;
hsync-active = <1>;
vsync-active = <0>;
};
};
};
};

View file

@ -13,6 +13,7 @@ Required properties:
(c) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
(d) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
(e) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
(f) "samsung,mfc-v10" for MFC v10 present in Exynos7880 SoC
- reg : Physical base address of the IP registers and length of memory
mapped region.

View file

@ -0,0 +1,14 @@
Sony CXD2880 DVB-T2/T tuner + demodulator driver SPI adapter
Required properties:
- compatible: Should be "sony,cxd2880".
- reg: SPI chip select number for the device.
- spi-max-frequency: Maximum bus speed, should be set to <55000000> (55MHz).
Example:
cxd2880@0 {
compatible = "sony,cxd2880";
reg = <0>; /* CE0 */
spi-max-frequency = <55000000>; /* 55MHz */
};

View file

@ -11,6 +11,8 @@ Required properties:
Optional properties:
- linux,rc-map-name: see rc.txt file in the same directory.
- resets : phandle + reset specifier pair
- clock-frequency : IR Receiver clock frequency, in Hertz. Defaults to 8 MHz
if missing.
Example:
@ -18,6 +20,7 @@ ir0: ir@1c21800 {
compatible = "allwinner,sun4i-a10-ir";
clocks = <&apb0_gates 6>, <&ir0_clk>;
clock-names = "apb", "ir";
clock-frequency = <3000000>;
resets = <&apb0_rst 1>;
interrupts = <0 5 1>;
reg = <0x01C21800 0x40>;

View file

@ -110,11 +110,14 @@ your driver:
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
void (*adap_free)(struct cec_adapter *adap);
/* Error injection callbacks */
...
/* High-level callbacks */
...
};
The five low-level ops deal with various aspects of controlling the CEC adapter
The seven low-level ops deal with various aspects of controlling the CEC adapter
hardware:
@ -286,6 +289,70 @@ handling the receive interrupt. The framework expects to see the cec_transmit_do
call before the cec_received_msg call, otherwise it can get confused if the
received message was in reply to the transmitted message.
Optional: Implementing Error Injection Support
----------------------------------------------
If the CEC adapter supports Error Injection functionality, then that can
be exposed through the Error Injection callbacks:
.. code-block:: none
struct cec_adap_ops {
/* Low-level callbacks */
...
/* Error injection callbacks */
int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
/* High-level CEC message callback */
...
};
If both callbacks are set, then an ``error-inj`` file will appear in debugfs.
The basic syntax is as follows:
Leading spaces/tabs are ignored. If the next character is a ``#`` or the end of the
line was reached, then the whole line is ignored. Otherwise a command is expected.
This basic parsing is done in the CEC Framework. It is up to the driver to decide
what commands to implement. The only requirement is that the command ``clear`` without
any arguments must be implemented and that it will remove all current error injection
commands.
This ensures that you can always do ``echo clear >error-inj`` to clear any error
injections without having to know the details of the driver-specific commands.
Note that the output of ``error-inj`` shall be valid as input to ``error-inj``.
So this must work:
.. code-block:: none
$ cat error-inj >einj.txt
$ cat einj.txt >error-inj
The first callback is called when this file is read and it should show the
the current error injection state:
.. c:function::
int (*error_inj_show)(struct cec_adapter *adap, struct seq_file *sf);
It is recommended that it starts with a comment block with basic usage
information. It returns 0 for success and an error otherwise.
The second callback will parse commands written to the ``error-inj`` file:
.. c:function::
bool (*error_inj_parse_line)(struct cec_adapter *adap, char *line);
The ``line`` argument points to the start of the command. Any leading
spaces or tabs have already been skipped. It is a single line only (so there
are no embedded newlines) and it is 0-terminated. The callback is free to
modify the contents of the buffer. It is only called for lines containing a
command, so this callback is never called for empty lines or comment lines.
Return true if the command was valid or false if there were syntax errors.
Implementing the High-Level CEC Adapter
---------------------------------------
@ -298,6 +365,9 @@ CEC protocol driven. The following high-level callbacks are available:
/* Low-level callbacks */
...
/* Error injection callbacks */
...
/* High-level CEC message callback */
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
};

View file

@ -57,6 +57,7 @@ ignore symbol RC_PROTO_RC6_MCE
ignore symbol RC_PROTO_SHARP
ignore symbol RC_PROTO_XMP
ignore symbol RC_PROTO_CEC
ignore symbol RC_PROTO_IMON
# Undocumented macros

View file

@ -23,6 +23,7 @@ This part describes the CEC: Consumer Electronics Control
cec-intro
cec-funcs
cec-pin-error-inj
cec-header

View file

@ -0,0 +1,325 @@
CEC Pin Framework Error Injection
=================================
The CEC Pin Framework is a core CEC framework for CEC hardware that only
has low-level support for the CEC bus. Most hardware today will have
high-level CEC support where the hardware deals with driving the CEC bus,
but some older devices aren't that fancy. However, this framework also
allows you to connect the CEC pin to a GPIO on e.g. a Raspberry Pi and
you have now made a CEC adapter.
What makes doing this so interesting is that since we have full control
over the bus it is easy to support error injection. This is ideal to
test how well CEC adapters can handle error conditions.
Currently only the cec-gpio driver (when the CEC line is directly
connected to a pull-up GPIO line) and the AllWinner A10/A20 drm driver
support this framework.
If ``CONFIG_CEC_PIN_ERROR_INJ`` is enabled, then error injection is available
through debugfs. Specifically, in ``/sys/kernel/debug/cec/cecX/`` there is
now an ``error-inj`` file.
.. note::
The error injection commands are not a stable ABI and may change in the
future.
With ``cat error-inj`` you can see both the possible commands and the current
error injection status::
$ cat /sys/kernel/debug/cec/cec0/error-inj
# Clear error injections:
# clear clear all rx and tx error injections
# rx-clear clear all rx error injections
# tx-clear clear all tx error injections
# <op> clear clear all rx and tx error injections for <op>
# <op> rx-clear clear all rx error injections for <op>
# <op> tx-clear clear all tx error injections for <op>
#
# RX error injection:
# <op>[,<mode>] rx-nack NACK the message instead of sending an ACK
# <op>[,<mode>] rx-low-drive <bit> force a low-drive condition at this bit position
# <op>[,<mode>] rx-add-byte add a spurious byte to the received CEC message
# <op>[,<mode>] rx-remove-byte remove the last byte from the received CEC message
# <op>[,<mode>] rx-arb-lost <poll> generate a POLL message to trigger an arbitration lost
#
# TX error injection settings:
# tx-ignore-nack-until-eom ignore early NACKs until EOM
# tx-custom-low-usecs <usecs> define the 'low' time for the custom pulse
# tx-custom-high-usecs <usecs> define the 'high' time for the custom pulse
# tx-custom-pulse transmit the custom pulse once the bus is idle
#
# TX error injection:
# <op>[,<mode>] tx-no-eom don't set the EOM bit
# <op>[,<mode>] tx-early-eom set the EOM bit one byte too soon
# <op>[,<mode>] tx-add-bytes <num> append <num> (1-255) spurious bytes to the message
# <op>[,<mode>] tx-remove-byte drop the last byte from the message
# <op>[,<mode>] tx-short-bit <bit> make this bit shorter than allowed
# <op>[,<mode>] tx-long-bit <bit> make this bit longer than allowed
# <op>[,<mode>] tx-custom-bit <bit> send the custom pulse instead of this bit
# <op>[,<mode>] tx-short-start send a start pulse that's too short
# <op>[,<mode>] tx-long-start send a start pulse that's too long
# <op>[,<mode>] tx-custom-start send the custom pulse instead of the start pulse
# <op>[,<mode>] tx-last-bit <bit> stop sending after this bit
# <op>[,<mode>] tx-low-drive <bit> force a low-drive condition at this bit position
#
# <op> CEC message opcode (0-255) or 'any'
# <mode> 'once' (default), 'always', 'toggle' or 'off'
# <bit> CEC message bit (0-159)
# 10 bits per 'byte': bits 0-7: data, bit 8: EOM, bit 9: ACK
# <poll> CEC poll message used to test arbitration lost (0x00-0xff, default 0x0f)
# <usecs> microseconds (0-10000000, default 1000)
clear
You can write error injection commands to ``error-inj`` using
``echo 'cmd' >error-inj`` or ``cat cmd.txt >error-inj``. The ``cat error-inj``
output contains the current error commands. You can save the output to a file
and use it as an input to ``error-inj`` later.
Basic Syntax
------------
Leading spaces/tabs are ignored. If the next character is a ``#`` or the end
of the line was reached, then the whole line is ignored. Otherwise a command
is expected.
The error injection commands fall in two main groups: those relating to
receiving CEC messages and those relating to transmitting CEC messages. In
addition, there are commands to clear existing error injection commands and
to create custom pulses on the CEC bus.
Most error injection commands can be executed for specific CEC opcodes or for
all opcodes (``any``). Each command also has a 'mode' which can be ``off``
(can be used to turn off an existing error injection command), ``once``
(the default) which will trigger the error injection only once for the next
received or transmitted message, ``always`` to always trigger the error
injection and ``toggle`` to toggle the error injection on or off for every
transmit or receive.
So '``any rx-nack``' will NACK the next received CEC message,
'``any,always rx-nack``' will NACK all received CEC messages and
'``0x82,toggle rx-nack``' will only NACK if an Active Source message was
received and do that only for every other received message.
After an error was injected with mode ``once`` the error injection command
is cleared automatically, so ``once`` is a one-time deal.
All combinations of ``<op>`` and error injection commands can co-exist. So
this is fine::
0x9e tx-add-bytes 1
0x9e tx-early-eom
0x9f tx-add-bytes 2
any rx-nack
All four error injection commands will be active simultaneously.
However, if the same ``<op>`` and command combination is specified,
but with different arguments::
0x9e tx-add-bytes 1
0x9e tx-add-bytes 2
Then the second will overwrite the first.
Clear Error Injections
----------------------
``clear``
Clear all error injections.
``rx-clear``
Clear all receive error injections
``tx-clear``
Clear all transmit error injections
``<op> clear``
Clear all error injections for the given opcode.
``<op> rx-clear``
Clear all receive error injections for the given opcode.
``<op> tx-clear``
Clear all transmit error injections for the given opcode.
Receive Messages
----------------
``<op>[,<mode>] rx-nack``
NACK broadcast messages and messages directed to this CEC adapter.
Every byte of the message will be NACKed in case the transmitter
keeps transmitting after the first byte was NACKed.
``<op>[,<mode>] rx-low-drive <bit>``
Force a Low Drive condition at this bit position. If <op> specifies
a specific CEC opcode then the bit position must be at least 18,
otherwise the opcode hasn't been received yet. This tests if the
transmitter can handle the Low Drive condition correctly and reports
the error correctly. Note that a Low Drive in the first 4 bits can also
be interpreted as an Arbitration Lost condition by the transmitter.
This is implementation dependent.
``<op>[,<mode>] rx-add-byte``
Add a spurious 0x55 byte to the received CEC message, provided
the message was 15 bytes long or less. This is useful to test
the high-level protocol since spurious bytes should be ignored.
``<op>[,<mode>] rx-remove-byte``
Remove the last byte from the received CEC message, provided it
was at least 2 bytes long. This is useful to test the high-level
protocol since messages that are too short should be ignored.
``<op>[,<mode>] rx-arb-lost <poll>``
Generate a POLL message to trigger an Arbitration Lost condition.
This command is only allowed for ``<op>`` values of ``next`` or ``all``.
As soon as a start bit has been received the CEC adapter will switch
to transmit mode and it will transmit a POLL message. By default this is
0x0f, but it can also be specified explicitly via the ``<poll>`` argument.
This command can be used to test the Arbitration Lost condition in
the remote CEC transmitter. Arbitration happens when two CEC adapters
start sending a message at the same time. In that case the initiator
with the most leading zeroes wins and the other transmitter has to
stop transmitting ('Arbitration Lost'). This is very hard to test,
except by using this error injection command.
This does not work if the remote CEC transmitter has logical address
0 ('TV') since that will always win.
Transmit Messages
-----------------
``tx-ignore-nack-until-eom``
This setting changes the behavior of transmitting CEC messages. Normally
as soon as the receiver NACKs a byte the transmit will stop, but the
specification also allows that the full message is transmitted and only
at the end will the transmitter look at the ACK bit. This is not
recommended behavior since there is no point in keeping the CEC bus busy
for longer than is strictly needed. Especially given how slow the bus is.
This setting can be used to test how well a receiver deals with
transmitters that ignore NACKs until the very end of the message.
``<op>[,<mode>] tx-no-eom``
Don't set the EOM bit. Normally the last byte of the message has the EOM
(End-Of-Message) bit set. With this command the transmit will just stop
without ever sending an EOM. This can be used to test how a receiver
handles this case. Normally receivers have a time-out after which
they will go back to the Idle state.
``<op>[,<mode>] tx-early-eom``
Set the EOM bit one byte too soon. This obviously only works for messages
of two bytes or more. The EOM bit will be set for the second-to-last byte
and not for the final byte. The receiver should ignore the last byte in
this case. Since the resulting message is likely to be too short for this
same reason the whole message is typically ignored. The receiver should be
in Idle state after the last byte was transmitted.
``<op>[,<mode>] tx-add-bytes <num>``
Append ``<num>`` (1-255) spurious bytes to the message. The extra bytes
have the value of the byte position in the message. So if you transmit a
two byte message (e.g. a Get CEC Version message) and add 2 bytes, then
the full message received by the remote CEC adapter is
``0x40 0x9f 0x02 0x03``.
This command can be used to test buffer overflows in the receiver. E.g.
what does it do when it receives more than the maximum message size of 16
bytes.
``<op>[,<mode>] tx-remove-byte``
Drop the last byte from the message, provided the message is at least
two bytes long. The receiver should ignore messages that are too short.
``<op>[,<mode>] tx-short-bit <bit>``
Make this bit period shorter than allowed. The bit position cannot be
an Ack bit. If <op> specifies a specific CEC opcode then the bit position
must be at least 18, otherwise the opcode hasn't been received yet.
Normally the period of a data bit is between 2.05 and 2.75 milliseconds.
With this command the period of this bit is 1.8 milliseconds, this is
done by reducing the time the CEC bus is high. This bit period is less
than is allowed and the receiver should respond with a Low Drive
condition.
This command is ignored for 0 bits in bit positions 0 to 3. This is
because the receiver also looks for an Arbitration Lost condition in
those first four bits and it is undefined what will happen if it
sees a too-short 0 bit.
``<op>[,<mode>] tx-long-bit <bit>``
Make this bit period longer than is valid. The bit position cannot be
an Ack bit. If <op> specifies a specific CEC opcode then the bit position
must be at least 18, otherwise the opcode hasn't been received yet.
Normally the period of a data bit is between 2.05 and 2.75 milliseconds.
With this command the period of this bit is 2.9 milliseconds, this is
done by increasing the time the CEC bus is high.
Even though this bit period is longer than is valid it is undefined what
a receiver will do. It might just accept it, or it might time out and
return to Idle state. Unfortunately the CEC specification is silent about
this.
This command is ignored for 0 bits in bit positions 0 to 3. This is
because the receiver also looks for an Arbitration Lost condition in
those first four bits and it is undefined what will happen if it
sees a too-long 0 bit.
``<op>[,<mode>] tx-short-start``
Make this start bit period shorter than allowed. Normally the period of
a start bit is between 4.3 and 4.7 milliseconds. With this command the
period of the start bit is 4.1 milliseconds, this is done by reducing
the time the CEC bus is high. This start bit period is less than is
allowed and the receiver should return to Idle state when this is detected.
``<op>[,<mode>] tx-long-start``
Make this start bit period longer than is valid. Normally the period of
a start bit is between 4.3 and 4.7 milliseconds. With this command the
period of the start bit is 5 milliseconds, this is done by increasing
the time the CEC bus is high. This start bit period is more than is
valid and the receiver should return to Idle state when this is detected.
Even though this start bit period is longer than is valid it is undefined
what a receiver will do. It might just accept it, or it might time out and
return to Idle state. Unfortunately the CEC specification is silent about
this.
``<op>[,<mode>] tx-last-bit <bit>``
Just stop transmitting after this bit. If <op> specifies a specific CEC
opcode then the bit position must be at least 18, otherwise the opcode
hasn't been received yet. This command can be used to test how the receiver
reacts when a message just suddenly stops. It should time out and go back
to Idle state.
``<op>[,<mode>] tx-low-drive <bit>``
Force a Low Drive condition at this bit position. If <op> specifies a
specific CEC opcode then the bit position must be at least 18, otherwise
the opcode hasn't been received yet. This can be used to test how the
receiver handles Low Drive conditions. Note that if this happens at bit
positions 0-3 the receiver can interpret this as an Arbitration Lost
condition. This is implementation dependent.
Custom Pulses
-------------
``tx-custom-low-usecs <usecs>``
This defines the duration in microseconds that the custom pulse pulls
the CEC line low. The default is 1000 microseconds.
``tx-custom-high-usecs <usecs>``
This defines the duration in microseconds that the custom pulse keeps the
CEC line high (unless another CEC adapter pulls it low in that time).
The default is 1000 microseconds. The total period of the custom pulse is
``tx-custom-low-usecs + tx-custom-high-usecs``.
``<op>[,<mode>] tx-custom-bit <bit>``
Send the custom bit instead of a regular data bit. The bit position cannot
be an Ack bit. If <op> specifies a specific CEC opcode then the bit
position must be at least 18, otherwise the opcode hasn't been received yet.
``<op>[,<mode>] tx-custom-start``
Send the custom bit instead of a regular start bit.
``tx-custom-pulse``
Transmit a single custom pulse as soon as the CEC bus is idle.

View file

@ -144,10 +144,21 @@ id's until they get an error.
- .. row 9
- union
- __u32
- ``reserved[4]``
-
-
- Reserved for future extensions. Drivers and applications must set
the array to zero.
- .. row 10
- union
- .. row 11
-
- struct
@ -156,7 +167,7 @@ id's until they get an error.
-
- Valid for (sub-)devices that create a single device node.
- .. row 11
- .. row 12
-
-
@ -166,7 +177,7 @@ id's until they get an error.
- Device node major number.
- .. row 12
- .. row 13
-
-
@ -176,7 +187,7 @@ id's until they get an error.
- Device node minor number.
- .. row 13
- .. row 14
-
- __u8

View file

@ -125,6 +125,15 @@ returned during the enumeration process.
- Pad flags, see :ref:`media-pad-flag` for more details.
- .. row 4
- __u32
- ``reserved[2]``
- Reserved for future extensions. Drivers and applications must set
the array to zero.
.. c:type:: media_link_desc
@ -161,6 +170,15 @@ returned during the enumeration process.
- Link flags, see :ref:`media-link-flag` for more details.
- .. row 4
- __u32
- ``reserved[4]``
- Reserved for future extensions. Drivers and applications must set
the array to zero.
Return Value
============

View file

@ -68,7 +68,7 @@ desired arrays with the media graph elements.
- .. row 2
- __u64
- __u32
- ``num_entities``
@ -76,6 +76,14 @@ desired arrays with the media graph elements.
- .. row 3
- __u32
- ``reserved1``
- Applications and drivers shall set this to 0.
- .. row 4
- __u64
- ``ptr_entities``
@ -85,15 +93,23 @@ desired arrays with the media graph elements.
the ioctl won't store the entities. It will just update
``num_entities``
- .. row 4
- .. row 5
- __u64
- __u32
- ``num_interfaces``
- Number of interfaces in the graph
- .. row 5
- .. row 6
- __u32
- ``reserved2``
- Applications and drivers shall set this to 0.
- .. row 7
- __u64
@ -104,15 +120,23 @@ desired arrays with the media graph elements.
the ioctl won't store the interfaces. It will just update
``num_interfaces``
- .. row 6
- .. row 8
- __u64
- __u32
- ``num_pads``
- Total number of pads in the graph
- .. row 7
- .. row 9
- __u32
- ``reserved3``
- Applications and drivers shall set this to 0.
- .. row 10
- __u64
@ -122,15 +146,23 @@ desired arrays with the media graph elements.
converted to a 64-bits integer. It can be zero. if zero, the ioctl
won't store the pads. It will just update ``num_pads``
- .. row 8
- .. row 11
- __u64
- __u32
- ``num_links``
- Total number of data and interface links in the graph
- .. row 9
- .. row 12
- __u32
- ``reserved4``
- Applications and drivers shall set this to 0.
- .. row 13
- __u64
@ -334,7 +366,7 @@ desired arrays with the media graph elements.
- On pad to pad links: unique ID for the source pad.
On interface to entity links: unique ID for the entity.
On interface to entity links: unique ID for the interface.
- .. row 3

View file

@ -26,7 +26,7 @@ Types and flags used to represent the media graph elements
``MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN``
- Unknown entity. That generally indicates that a driver didn't
initialize properly the entity, with is a Kernel bug
initialize properly the entity, which is a Kernel bug
- .. row 2
@ -293,7 +293,7 @@ Types and flags used to represent the media graph elements
- ``MEDIA_ENT_F_PROC_VIDEO_STATISTICS``
- Video statistics computation (histogram, 3A, ...). An entity
- Video statistics computation (histogram, 3A, etc.). An entity
capable of statistics computation must have one sink pad and
one source pad. It computes statistics over the frames
received on its sink pad and outputs the statistics data on
@ -318,8 +318,19 @@ Types and flags used to represent the media graph elements
- Video interface bridge. A video interface bridge entity must have at
least one sink pad and at least one source pad. It receives video
frames on its sink pad from an input video bus of one type (HDMI, eDP,
MIPI CSI-2, ...), and outputs them on its source pad to an output
video bus of another type (eDP, MIPI CSI-2, parallel, ...).
MIPI CSI-2, etc.), and outputs them on its source pad to an output
video bus of another type (eDP, MIPI CSI-2, parallel, etc.).
- .. row 31
.. _MEDIA-ENT-F-DTV-DECODER:
- ``MEDIA_ENT_F_DTV_DECODER``
- Digital video decoder. The basic function of the video decoder is
to accept digital video from a wide variety of sources
and output it in some digital video standard, with appropriate
timing signals.
.. tabularcolumns:: |p{5.5cm}|p{12.0cm}|
@ -337,7 +348,7 @@ Types and flags used to represent the media graph elements
- ``MEDIA_ENT_FL_DEFAULT``
- Default entity for its type. Used to discover the default audio,
VBI and video devices, the default camera sensor, ...
VBI and video devices, the default camera sensor, etc.
- .. row 2
@ -345,7 +356,7 @@ Types and flags used to represent the media graph elements
- ``MEDIA_ENT_FL_CONNECTOR``
- The entity represents a data conector
- The entity represents a connector.
.. tabularcolumns:: |p{6.5cm}|p{6.0cm}|p{5.0cm}|

View file

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

View file

@ -13,7 +13,7 @@ Only pointers to buffers (planes) are exchanged, the data itself is not
copied. These pointers, together with meta-information like timestamps
or field parity, are stored in a struct :c:type:`v4l2_buffer`,
argument to the :ref:`VIDIOC_QUERYBUF`,
:ref:`VIDIOC_QBUF` and
:ref:`VIDIOC_QBUF <VIDIOC_QBUF>` and
:ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. In the multi-planar API,
some plane-specific members of struct :c:type:`v4l2_buffer`,
such as pointers and sizes for each plane, are stored in struct

View file

@ -1960,6 +1960,416 @@ enum v4l2_vp8_golden_frame_sel -
1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
High Efficiency Video Coding (HEVC/H.265) Control Reference
-----------------------------------------------------------
The HEVC/H.265 controls include controls for encoding parameters of HEVC/H.265
video codec.
.. _hevc-control-id:
HEVC/H.265 Control IDs
^^^^^^^^^^^^^^^^^^^^^^
``V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (integer)``
Minimum quantization parameter for HEVC.
Valid range: from 0 to 51.
``V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (integer)``
Maximum quantization parameter for HEVC.
Valid range: from 0 to 51.
``V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (integer)``
Quantization parameter for an I frame for HEVC.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP (integer)``
Quantization parameter for a P frame for HEVC.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP (integer)``
Quantization parameter for a B frame for HEVC.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP (boolean)``
HIERARCHICAL_QP allows the host to specify the quantization parameter
values for each temporal layer through HIERARCHICAL_QP_LAYER. This is
valid only if HIERARCHICAL_CODING_LAYER is greater than 1. Setting the
control value to 1 enables setting of the QP values for the layers.
.. _v4l2-hevc-hier-coding-type:
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_TYPE``
(enum)
enum v4l2_mpeg_video_hevc_hier_coding_type -
Selects the hierarchical coding type for encoding. Possible values are:
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{9.0cm}|p{8.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B``
- Use the B frame for hierarchical coding.
* - ``V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P``
- Use the P frame for hierarchical coding.
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER (integer)``
Selects the hierarchical coding layer. In normal encoding
(non-hierarchial coding), it should be zero. Possible values are [0, 6].
0 indicates HIERARCHICAL CODING LAYER 0, 1 indicates HIERARCHICAL CODING
LAYER 1 and so on.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 0.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 1.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 2.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 3.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 4.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 5.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_QP (integer)``
Indicates quantization parameter for hierarchical coding layer 6.
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
.. _v4l2-hevc-profile:
``V4L2_CID_MPEG_VIDEO_HEVC_PROFILE``
(enum)
enum v4l2_mpeg_video_hevc_profile -
Select the desired profile for HEVC encoder.
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{9.0cm}|p{8.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN``
- Main profile.
* - ``V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE``
- Main still picture profile.
* - ``V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10``
- Main 10 profile.
.. raw:: latex
\normalsize
.. _v4l2-hevc-level:
``V4L2_CID_MPEG_VIDEO_HEVC_LEVEL``
(enum)
enum v4l2_mpeg_video_hevc_level -
Selects the desired level for HEVC encoder.
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{9.0cm}|p{8.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_1``
- Level 1.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_2``
- Level 2.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1``
- Level 2.1
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_3``
- Level 3.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1``
- Level 3.1
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_4``
- Level 4.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1``
- Level 4.1
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_5``
- Level 5.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1``
- Level 5.1
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2``
- Level 5.2
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_6``
- Level 6.0
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_6_1``
- Level 6.1
* - ``V4L2_MPEG_VIDEO_HEVC_LEVEL_6_2``
- Level 6.2
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_FRAME_RATE_RESOLUTION (integer)``
Indicates the number of evenly spaced subintervals, called ticks, within
one second. This is a 16 bit unsigned integer and has a maximum value up to
0xffff and a minimum value of 1.
.. _v4l2-hevc-tier:
``V4L2_CID_MPEG_VIDEO_HEVC_TIER``
(enum)
enum v4l2_mpeg_video_hevc_tier -
TIER_FLAG specifies tiers information of the HEVC encoded picture. Tier
were made to deal with applications that differ in terms of maximum bit
rate. Setting the flag to 0 selects HEVC tier as Main tier and setting
this flag to 1 indicates High tier. High tier is for applications requiring
high bit rates.
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{9.0cm}|p{8.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_TIER_MAIN``
- Main tier.
* - ``V4L2_MPEG_VIDEO_HEVC_TIER_HIGH``
- High tier.
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_MAX_PARTITION_DEPTH (integer)``
Selects HEVC maximum coding unit depth.
.. _v4l2-hevc-loop-filter-mode:
``V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE``
(enum)
enum v4l2_mpeg_video_hevc_loop_filter_mode -
Loop filter mode for HEVC encoder. Possible values are:
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{10.7cm}|p{6.3cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED``
- Loop filter is disabled.
* - ``V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED``
- Loop filter is enabled.
* - ``V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY``
- Loop filter is disabled at the slice boundary.
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2 (integer)``
Selects HEVC loop filter beta offset. The valid range is [-6, +6].
``V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2 (integer)``
Selects HEVC loop filter tc offset. The valid range is [-6, +6].
.. _v4l2-hevc-refresh-type:
``V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE``
(enum)
enum v4l2_mpeg_video_hevc_hier_refresh_type -
Selects refresh type for HEVC encoder.
Host has to specify the period into
V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD.
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{8.0cm}|p{9.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE``
- Use the B frame for hierarchical coding.
* - ``V4L2_MPEG_VIDEO_HEVC_REFRESH_CRA``
- Use CRA (Clean Random Access Unit) picture encoding.
* - ``V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR``
- Use IDR (Instantaneous Decoding Refresh) picture encoding.
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD (integer)``
Selects the refresh period for HEVC encoder.
This specifies the number of I pictures between two CRA/IDR pictures.
This is valid only if REFRESH_TYPE is not 0.
``V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU (boolean)``
Indicates HEVC lossless encoding. Setting it to 0 disables lossless
encoding. Setting it to 1 enables lossless encoding.
``V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED (boolean)``
Indicates constant intra prediction for HEVC encoder. Specifies the
constrained intra prediction in which intra largest coding unit (LCU)
prediction is performed by using residual data and decoded samples of
neighboring intra LCU only. Setting the value to 1 enables constant intra
prediction and setting the value to 0 disables constant intra prediction.
``V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT (boolean)``
Indicates wavefront parallel processing for HEVC encoder. Setting it to 0
disables the feature and setting it to 1 enables the wavefront parallel
processing.
``V4L2_CID_MPEG_VIDEO_HEVC_GENERAL_PB (boolean)``
Setting the value to 1 enables combination of P and B frame for HEVC
encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_TEMPORAL_ID (boolean)``
Indicates temporal identifier for HEVC encoder which is enabled by
setting the value to 1.
``V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING (boolean)``
Indicates bi-linear interpolation is conditionally used in the intra
prediction filtering process in the CVS when set to 1. Indicates bi-linear
interpolation is not used in the CVS when set to 0.
``V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1 (integer)``
Indicates maximum number of merge candidate motion vectors.
Values are from 0 to 4.
``V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION (boolean)``
Indicates temporal motion vector prediction for HEVC encoder. Setting it to
1 enables the prediction. Setting it to 0 disables the prediction.
``V4L2_CID_MPEG_VIDEO_HEVC_WITHOUT_STARTCODE (boolean)``
Specifies if HEVC generates a stream with a size of the length field
instead of start code pattern. The size of the length field is configurable
through the V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD control. Setting
the value to 0 disables encoding without startcode pattern. Setting the
value to 1 will enables encoding without startcode pattern.
.. _v4l2-hevc-size-of-length-field:
``V4L2_CID_MPEG_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD``
(enum)
enum v4l2_mpeg_video_hevc_size_of_length_field -
Indicates the size of length field.
This is valid when encoding WITHOUT_STARTCODE_ENABLE is enabled.
.. raw:: latex
\footnotesize
.. tabularcolumns:: |p{6.0cm}|p{11.0cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_HEVC_SIZE_0``
- Generate start code pattern (Normal).
* - ``V4L2_MPEG_VIDEO_HEVC_SIZE_1``
- Generate size of length field instead of start code pattern and length is 1.
* - ``V4L2_MPEG_VIDEO_HEVC_SIZE_2``
- Generate size of length field instead of start code pattern and length is 2.
* - ``V4L2_MPEG_VIDEO_HEVC_SIZE_4``
- Generate size of length field instead of start code pattern and length is 4.
.. raw:: latex
\normalsize
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR (integer)``
Indicates bit rate for hierarchical coding layer 0 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR (integer)``
Indicates bit rate for hierarchical coding layer 1 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR (integer)``
Indicates bit rate for hierarchical coding layer 2 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR (integer)``
Indicates bit rate for hierarchical coding layer 3 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR (integer)``
Indicates bit rate for hierarchical coding layer 4 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR (integer)``
Indicates bit rate for hierarchical coding layer 5 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR (integer)``
Indicates bit rate for hierarchical coding layer 6 for HEVC encoder.
``V4L2_CID_MPEG_VIDEO_REF_NUMBER_FOR_PFRAMES (integer)``
Selects number of P reference pictures required for HEVC encoder.
P-Frame can use 1 or 2 frames for reference.
``V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR (integer)``
Indicates whether to generate SPS and PPS at every IDR. Setting it to 0
disables generating SPS and PPS at every IDR. Setting it to one enables
generating SPS and PPS at every IDR.
.. _camera-controls:
Camera Control Reference

View file

@ -39,7 +39,7 @@ When streaming I/O has been negotiated this function waits until a
buffer has been filled by the capture device and can be dequeued with
the :ref:`VIDIOC_DQBUF <VIDIOC_QBUF>` ioctl. For output devices this
function waits until the device is ready to accept a new buffer to be
queued up with the :ref:`VIDIOC_QBUF` ioctl for
queued up with the :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl for
display. When buffers are already in the outgoing queue of the driver
(capture) or the incoming queue isn't full (display) the function
returns immediately.
@ -52,11 +52,11 @@ flags in the ``revents`` field, output devices the ``POLLOUT`` and
``POLLWRNORM`` flags. When the function timed out it returns a value of
zero, on failure it returns -1 and the ``errno`` variable is set
appropriately. When the application did not call
:ref:`VIDIOC_STREAMON` the :ref:`poll() <func-poll>`
:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` the :ref:`poll() <func-poll>`
function succeeds, but sets the ``POLLERR`` flag in the ``revents``
field. When the application has called
:ref:`VIDIOC_STREAMON` for a capture device but
hasn't yet called :ref:`VIDIOC_QBUF`, the
:ref:`VIDIOC_STREAMON <VIDIOC_STREAMON>` for a capture device but
hasn't yet called :ref:`VIDIOC_QBUF <VIDIOC_QBUF>`, the
:ref:`poll() <func-poll>` function succeeds and sets the ``POLLERR`` flag in
the ``revents`` field. For output devices this same situation will cause
:ref:`poll() <func-poll>` to succeed as well, but it sets the ``POLLOUT`` and

View file

@ -90,3 +90,8 @@ Compressed Formats
- ``V4L2_PIX_FMT_VP9``
- 'VP90'
- VP9 video elementary stream.
* .. _V4L2-PIX-FMT-HEVC:
- ``V4L2_PIX_FMT_HEVC``
- 'HEVC'
- HEVC/H.265 video elementary stream.

View file

@ -40,7 +40,7 @@ Single-planar format structure
RGB formats in :ref:`rgb-formats`, YUV formats in
:ref:`yuv-formats`, and reserved codes in
:ref:`reserved-formats`
* - enum :c:type::`v4l2_field`
* - enum :c:type:`v4l2_field`
- ``field``
- Video images are typically interlaced. Applications can request to
capture or output only the top or bottom field, or both fields

View file

@ -16,10 +16,14 @@ Media Bus Formats
* - __u32
- ``width``
- Image width, in pixels.
- Image width in pixels.
* - __u32
- ``height``
- Image height, in pixels.
- Image height in pixels. If ``field`` is one of ``V4L2_FIELD_TOP``,
``V4L2_FIELD_BOTTOM`` or ``V4L2_FIELD_ALTERNATE`` then height
refers to the number of lines in the field, otherwise it refers to
the number of lines in the frame (which is twice the field height
for interlaced formats).
* - __u32
- ``code``
- Format code, from enum

View file

@ -66,7 +66,7 @@ union holding separate parameters for input and output devices.
-
- The buffer (stream) type, same as struct
:c:type:`v4l2_format` ``type``, set by the
application. See :c:type:`v4l2_buf_type`
application. See :c:type:`v4l2_buf_type`.
* - union
- ``parm``
-
@ -75,12 +75,13 @@ union holding separate parameters for input and output devices.
- struct :c:type:`v4l2_captureparm`
- ``capture``
- Parameters for capture devices, used when ``type`` is
``V4L2_BUF_TYPE_VIDEO_CAPTURE``.
``V4L2_BUF_TYPE_VIDEO_CAPTURE`` or
``V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE``.
* -
- struct :c:type:`v4l2_outputparm`
- ``output``
- Parameters for output devices, used when ``type`` is
``V4L2_BUF_TYPE_VIDEO_OUTPUT``.
``V4L2_BUF_TYPE_VIDEO_OUTPUT`` or ``V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE``.
* -
- __u8
- ``raw_data``\ [200]

View file

@ -34,7 +34,7 @@ Description
Applications can optionally call the :ref:`VIDIOC_PREPARE_BUF` ioctl to
pass ownership of the buffer to the driver before actually enqueuing it,
using the :ref:`VIDIOC_QBUF` ioctl, and to prepare it for future I/O. Such
using the :ref:`VIDIOC_QBUF <VIDIOC_QBUF>` ioctl, and to prepare it for future I/O. Such
preparations may include cache invalidation or cleaning. Performing them
in advance saves time during the actual I/O. In case such cache
operations are not required, the application can use one of

View file

@ -109,7 +109,7 @@ imx6-mipi-csi2
This is the MIPI CSI-2 receiver entity. It has one sink pad to receive
the MIPI CSI-2 stream (usually from a MIPI CSI-2 camera sensor). It has
four source pads, corresponding to the four MIPI CSI-2 demuxed virtual
channel outputs. Multpiple source pads can be enabled to independently
channel outputs. Multiple source pads can be enabled to independently
stream from multiple virtual channels.
This entity actually consists of two sub-blocks. One is the MIPI CSI-2
@ -213,9 +213,11 @@ To give an example of crop and /2 downscale, this will crop a
1280x960 input frame to 640x480, and then /2 downscale in both
dimensions to 320x240 (assumes ipu1_csi0 is linked to ipu1_csi0_mux):
media-ctl -V "'ipu1_csi0_mux':2[fmt:UYVY2X8/1280x960]"
media-ctl -V "'ipu1_csi0':0[crop:(0,0)/640x480]"
media-ctl -V "'ipu1_csi0':0[compose:(0,0)/320x240]"
.. code-block:: none
media-ctl -V "'ipu1_csi0_mux':2[fmt:UYVY2X8/1280x960]"
media-ctl -V "'ipu1_csi0':0[crop:(0,0)/640x480]"
media-ctl -V "'ipu1_csi0':0[compose:(0,0)/320x240]"
Frame Skipping in ipuX_csiY
---------------------------
@ -229,8 +231,10 @@ at the source pad.
The following example reduces an assumed incoming 60 Hz frame
rate by half at the IDMAC output source pad:
media-ctl -V "'ipu1_csi0':0[fmt:UYVY2X8/640x480@1/60]"
media-ctl -V "'ipu1_csi0':2[fmt:UYVY2X8/640x480@1/30]"
.. code-block:: none
media-ctl -V "'ipu1_csi0':0[fmt:UYVY2X8/640x480@1/60]"
media-ctl -V "'ipu1_csi0':2[fmt:UYVY2X8/640x480@1/30]"
Frame Interval Monitor in ipuX_csiY
-----------------------------------
@ -422,8 +426,7 @@ This pipeline uses the preprocess encode entity to route frames directly
from the CSI to the IC, to carry out scaling up to 1024x1024 resolution,
CSC, flipping, and image rotation:
-> ipuX_csiY:1 -> 0:ipuX_ic_prp:1 -> 0:ipuX_ic_prpenc:1 ->
ipuX_ic_prpenc capture
-> ipuX_csiY:1 -> 0:ipuX_ic_prp:1 -> 0:ipuX_ic_prpenc:1 -> ipuX_ic_prpenc capture
Motion Compensated De-interlace:
--------------------------------
@ -432,8 +435,7 @@ This pipeline routes frames from the CSI direct pad to the VDIC entity to
support motion-compensated de-interlacing (high motion mode only),
scaling up to 1024x1024, CSC, flip, and rotation:
-> ipuX_csiY:1 -> 0:ipuX_vdic:2 -> 0:ipuX_ic_prp:2 ->
0:ipuX_ic_prpvf:1 -> ipuX_ic_prpvf capture
-> ipuX_csiY:1 -> 0:ipuX_vdic:2 -> 0:ipuX_ic_prp:2 -> 0:ipuX_ic_prpvf:1 -> ipuX_ic_prpvf capture
Usage Notes
@ -458,8 +460,8 @@ This platform requires the OmniVision OV5642 module with a parallel
camera interface, and the OV5640 module with a MIPI CSI-2
interface. Both modules are available from Boundary Devices:
https://boundarydevices.com/product/nit6x_5mp
https://boundarydevices.com/product/nit6x_5mp_mipi
- https://boundarydevices.com/product/nit6x_5mp
- https://boundarydevices.com/product/nit6x_5mp_mipi
Note that if only one camera module is available, the other sensor
node can be disabled in the device tree.

View file

@ -3275,6 +3275,7 @@ F: include/media/cec-notifier.h
F: include/uapi/linux/cec.h
F: include/uapi/linux/cec-funcs.h
F: Documentation/devicetree/bindings/media/cec.txt
F: Documentation/ABI/testing/debugfs-cec-error-inj
CEC GPIO DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com>
@ -6865,6 +6866,13 @@ M: James Hogan <jhogan@kernel.org>
S: Maintained
F: drivers/media/rc/img-ir/
IMON SOUNDGRAPH USB IR RECEIVER
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/rc/imon_raw.c
F: drivers/media/rc/imon.c
IMS TWINTURBO FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
@ -8604,6 +8612,14 @@ T: git git://linuxtv.org/media_tree.git
S: Supported
F: drivers/media/dvb-frontends/ascot2e*
MEDIA DRIVERS FOR CXD2099AR CI CONTROLLERS
M: Jasmin Jessich <jasmin@anw.at>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/dvb-frontends/cxd2099*
MEDIA DRIVERS FOR CXD2841ER
M: Sergey Kozlov <serjk@netup.ru>
M: Abylay Ospan <aospan@netup.ru>
@ -8614,6 +8630,15 @@ T: git git://linuxtv.org/media_tree.git
S: Supported
F: drivers/media/dvb-frontends/cxd2841er*
MEDIA DRIVERS FOR CXD2880
M: Yasunari Takiguchi <Yasunari.Takiguchi@sony.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org/
T: git git://linuxtv.org/media_tree.git
S: Supported
F: drivers/media/dvb-frontends/cxd2880/*
F: drivers/media/spi/cxd2880*
MEDIA DRIVERS FOR DIGITAL DEVICES PCIE DEVICES
M: Daniel Scheller <d.scheller.oss@gmail.com>
L: linux-media@vger.kernel.org
@ -8681,6 +8706,16 @@ T: git git://linuxtv.org/media_tree.git
S: Supported
F: drivers/media/pci/netup_unidvb/*
MEDIA DRIVERS FOR RENESAS - CEU
M: Jacopo Mondi <jacopo@jmondi.org>
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,ceu.txt
F: drivers/media/platform/renesas-ceu.c
F: include/media/drv-intf/renesas-ceu.h
MEDIA DRIVERS FOR RENESAS - DRIF
M: Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>
L: linux-media@vger.kernel.org
@ -9365,6 +9400,14 @@ S: Maintained
F: drivers/media/i2c/mt9t001.c
F: include/media/i2c/mt9t001.h
MT9T112 APTINA CAMERA SENSOR
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Odd Fixes
F: drivers/media/i2c/mt9t112.c
F: include/media/i2c/mt9t112.h
MT9V032 APTINA CAMERA SENSOR
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
@ -10170,6 +10213,13 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov13858.c
OMNIVISION OV2685 SENSOR DRIVER
M: Shunqian Zheng <zhengsq@rock-chips.com>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov2685.c
OMNIVISION OV5640 SENSOR DRIVER
M: Steve Longerbeam <slongerbeam@gmail.com>
L: linux-media@vger.kernel.org
@ -10184,6 +10234,13 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov5647.c
OMNIVISION OV5695 SENSOR DRIVER
M: Shunqian Zheng <zhengsq@rock-chips.com>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov5695.c
OMNIVISION OV7670 SENSOR DRIVER
M: Jonathan Corbet <corbet@lwn.net>
L: linux-media@vger.kernel.org
@ -10192,6 +10249,14 @@ S: Maintained
F: drivers/media/i2c/ov7670.c
F: Documentation/devicetree/bindings/media/i2c/ov7670.txt
OMNIVISION OV772x SENSOR DRIVER
M: Jacopo Mondi <jacopo@jmondi.org>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Odd fixes
F: drivers/media/i2c/ov772x.c
F: include/media/i2c/ov772x.h
OMNIVISION OV7740 SENSOR DRIVER
M: Wenyou Yang <wenyou.yang@microchip.com>
L: linux-media@vger.kernel.org
@ -10200,6 +10265,16 @@ S: Maintained
F: drivers/media/i2c/ov7740.c
F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
OMNIVISION OV9650 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
R: Akinobu Mita <akinobu.mita@gmail.com>
R: Sylwester Nawrocki <s.nawrocki@samsung.com>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/i2c/ov9650.c
F: Documentation/devicetree/bindings/media/i2c/ov9650.txt
ONENAND FLASH DRIVER
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-mtd@lists.infradead.org
@ -12780,10 +12855,9 @@ S: Maintained
F: drivers/net/ethernet/smsc/smsc9420.*
SOC-CAMERA V4L2 SUBSYSTEM
M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
S: Maintained
S: Orphan
F: include/media/soc*
F: drivers/media/i2c/soc_camera/
F: drivers/media/platform/soc_camera/
@ -13512,6 +13586,14 @@ T: git git://linuxtv.org/mkrufky/tuners.git
S: Maintained
F: drivers/media/tuners/tda18271*
TDA1997x MEDIA DRIVER
M: Tim Harvey <tharvey@gateworks.com>
L: linux-media@vger.kernel.org
W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
S: Maintained
F: drivers/media/i2c/tda1997x.*
TDA827x MEDIA DRIVER
M: Michael Krufky <mkrufky@linuxtv.org>
L: linux-media@vger.kernel.org
@ -13593,6 +13675,12 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/rc/ttusbir.c
TECHWELL TW9910 VIDEO DECODER
L: linux-media@vger.kernel.org
S: Orphan
F: drivers/media/i2c/tw9910.c
F: include/media/i2c/tw9910.h
TEE SUBSYSTEM
M: Jens Wiklander <jens.wiklander@linaro.org>
S: Maintained

View file

@ -7,44 +7,47 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/init.h>
#include <asm/clock.h>
#include <asm/heartbeat.h>
#include <asm/suspend.h>
#include <cpu/sh7724.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/interrupt.h>
#include <linux/memblock.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/mtd/physmap.h>
#include <linux/mfd/tmio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/gpio_backlight.h>
#include <linux/platform_data/tsc2007.h>
#include <linux/platform_device.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/usb/r8a66597.h>
#include <linux/usb/renesas_usbhs.h>
#include <linux/i2c.h>
#include <linux/platform_data/tsc2007.h>
#include <linux/spi/spi.h>
#include <linux/spi/sh_msiof.h>
#include <linux/spi/mmc_spi.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/platform_data/gpio_backlight.h>
#include <linux/sh_eth.h>
#include <linux/sh_intc.h>
#include <linux/spi/mmc_spi.h>
#include <linux/spi/sh_msiof.h>
#include <linux/spi/spi.h>
#include <linux/usb/r8a66597.h>
#include <linux/usb/renesas_usbhs.h>
#include <linux/videodev2.h>
#include <video/sh_mobile_lcdc.h>
#include <media/drv-intf/renesas-ceu.h>
#include <media/i2c/mt9t112.h>
#include <media/i2c/tw9910.h>
#include <sound/sh_fsi.h>
#include <sound/simple_card.h>
#include <media/drv-intf/sh_mobile_ceu.h>
#include <media/soc_camera.h>
#include <media/i2c/tw9910.h>
#include <media/i2c/mt9t112.h>
#include <asm/heartbeat.h>
#include <asm/clock.h>
#include <asm/suspend.h>
#include <cpu/sh7724.h>
#include <video/sh_mobile_lcdc.h>
/*
* Address Interface BusWidth
@ -81,6 +84,10 @@
* amixer set 'Out Mixer Right DAC Right' on
*/
#define CEU_BUFFER_MEMORY_SIZE (4 << 20)
static phys_addr_t ceu0_dma_membase;
static phys_addr_t ceu1_dma_membase;
/* Heartbeat */
static unsigned char led_pos[] = { 0, 1, 2, 3 };
@ -382,8 +389,24 @@ static struct platform_device gpio_backlight_device = {
};
/* CEU0 */
static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
static struct ceu_platform_data ceu0_pdata = {
.num_subdevs = 2,
.subdevs = {
{ /* [0] = mt9t112 */
.flags = 0,
.bus_width = 8,
.bus_shift = 0,
.i2c_adapter_id = 0,
.i2c_address = 0x3c,
},
{ /* [1] = tw9910 */
.flags = 0,
.bus_width = 8,
.bus_shift = 0,
.i2c_adapter_id = 0,
.i2c_address = 0x45,
},
},
};
static struct resource ceu0_resources[] = {
@ -397,24 +420,30 @@ static struct resource ceu0_resources[] = {
.start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* place holder for contiguous memory */
},
};
static struct platform_device ceu0_device = {
.name = "sh_mobile_ceu",
.id = 0, /* "ceu0" clock */
.name = "renesas-ceu",
.id = 0, /* ceu.0 */
.num_resources = ARRAY_SIZE(ceu0_resources),
.resource = ceu0_resources,
.dev = {
.platform_data = &sh_mobile_ceu0_info,
.platform_data = &ceu0_pdata,
},
};
/* CEU1 */
static struct sh_mobile_ceu_info sh_mobile_ceu1_info = {
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
static struct ceu_platform_data ceu1_pdata = {
.num_subdevs = 1,
.subdevs = {
{ /* [0] = mt9t112 */
.flags = 0,
.bus_width = 8,
.bus_shift = 0,
.i2c_adapter_id = 1,
.i2c_address = 0x3c,
},
},
};
static struct resource ceu1_resources[] = {
@ -428,26 +457,71 @@ static struct resource ceu1_resources[] = {
.start = evt2irq(0x9e0),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* place holder for contiguous memory */
},
};
static struct platform_device ceu1_device = {
.name = "sh_mobile_ceu",
.id = 1, /* "ceu1" clock */
.name = "renesas-ceu",
.id = 1, /* ceu.1 */
.num_resources = ARRAY_SIZE(ceu1_resources),
.resource = ceu1_resources,
.dev = {
.platform_data = &sh_mobile_ceu1_info,
.platform_data = &ceu1_pdata,
},
};
/* Power up/down GPIOs for camera devices and video decoder */
static struct gpiod_lookup_table tw9910_gpios = {
.dev_id = "0-0045",
.table = {
GPIO_LOOKUP("sh7724_pfc", GPIO_PTU2, "pdn", GPIO_ACTIVE_HIGH),
},
};
static struct gpiod_lookup_table mt9t112_0_gpios = {
.dev_id = "0-003c",
.table = {
GPIO_LOOKUP("sh7724_pfc", GPIO_PTA3, "standby",
GPIO_ACTIVE_HIGH),
},
};
static struct gpiod_lookup_table mt9t112_1_gpios = {
.dev_id = "1-003c",
.table = {
GPIO_LOOKUP("sh7724_pfc", GPIO_PTA4, "standby",
GPIO_ACTIVE_HIGH),
},
};
/* I2C device */
static struct tw9910_video_info tw9910_info = {
.buswidth = 8,
.mpout = TW9910_MPO_FIELD,
};
static struct mt9t112_platform_data mt9t112_0_pdata = {
.flags = MT9T112_FLAG_PCLK_RISING_EDGE,
.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
};
static struct mt9t112_platform_data mt9t112_1_pdata = {
.flags = MT9T112_FLAG_PCLK_RISING_EDGE,
.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
};
static struct i2c_board_info i2c0_devices[] = {
{
I2C_BOARD_INFO("da7210", 0x1a),
},
{
I2C_BOARD_INFO("tw9910", 0x45),
.platform_data = &tw9910_info,
},
{
/* 1st camera */
I2C_BOARD_INFO("mt9t112", 0x3c),
.platform_data = &mt9t112_0_pdata,
},
};
static struct i2c_board_info i2c1_devices[] = {
@ -457,7 +531,12 @@ static struct i2c_board_info i2c1_devices[] = {
{
I2C_BOARD_INFO("lis3lv02d", 0x1c),
.irq = evt2irq(0x620),
}
},
{
/* 2nd camera */
I2C_BOARD_INFO("mt9t112", 0x3c),
.platform_data = &mt9t112_1_pdata,
},
};
/* KEYSC */
@ -724,115 +803,6 @@ static struct platform_device msiof0_device = {
#endif
/* I2C Video/Camera */
static struct i2c_board_info i2c_camera[] = {
{
I2C_BOARD_INFO("tw9910", 0x45),
},
{
/* 1st camera */
I2C_BOARD_INFO("mt9t112", 0x3c),
},
{
/* 2nd camera */
I2C_BOARD_INFO("mt9t112", 0x3c),
},
};
/* tw9910 */
static int tw9910_power(struct device *dev, int mode)
{
int val = mode ? 0 : 1;
gpio_set_value(GPIO_PTU2, val);
if (mode)
mdelay(100);
return 0;
}
static struct tw9910_video_info tw9910_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.mpout = TW9910_MPO_FIELD,
};
static struct soc_camera_link tw9910_link = {
.i2c_adapter_id = 0,
.bus_id = 1,
.power = tw9910_power,
.board_info = &i2c_camera[0],
.priv = &tw9910_info,
};
/* mt9t112 */
static int mt9t112_power1(struct device *dev, int mode)
{
gpio_set_value(GPIO_PTA3, mode);
if (mode)
mdelay(100);
return 0;
}
static struct mt9t112_camera_info mt9t112_info1 = {
.flags = MT9T112_FLAG_PCLK_RISING_EDGE | MT9T112_FLAG_DATAWIDTH_8,
.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
};
static struct soc_camera_link mt9t112_link1 = {
.i2c_adapter_id = 0,
.power = mt9t112_power1,
.bus_id = 0,
.board_info = &i2c_camera[1],
.priv = &mt9t112_info1,
};
static int mt9t112_power2(struct device *dev, int mode)
{
gpio_set_value(GPIO_PTA4, mode);
if (mode)
mdelay(100);
return 0;
}
static struct mt9t112_camera_info mt9t112_info2 = {
.flags = MT9T112_FLAG_PCLK_RISING_EDGE | MT9T112_FLAG_DATAWIDTH_8,
.divider = { 0x49, 0x6, 0, 6, 0, 9, 9, 6, 0 }, /* for 24MHz */
};
static struct soc_camera_link mt9t112_link2 = {
.i2c_adapter_id = 1,
.power = mt9t112_power2,
.bus_id = 1,
.board_info = &i2c_camera[2],
.priv = &mt9t112_info2,
};
static struct platform_device camera_devices[] = {
{
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &tw9910_link,
},
},
{
.name = "soc-camera-pdrv",
.id = 1,
.dev = {
.platform_data = &mt9t112_link1,
},
},
{
.name = "soc-camera-pdrv",
.id = 2,
.dev = {
.platform_data = &mt9t112_link2,
},
},
};
/* FSI */
static struct resource fsi_resources[] = {
[0] = {
@ -979,6 +949,11 @@ static struct platform_device sh_mmcif_device = {
};
#endif
static struct platform_device *ecovec_ceu_devices[] __initdata = {
&ceu0_device,
&ceu1_device,
};
static struct platform_device *ecovec_devices[] __initdata = {
&heartbeat_device,
&nor_flash_device,
@ -988,8 +963,6 @@ static struct platform_device *ecovec_devices[] __initdata = {
&usbhs_device,
&lcdc_device,
&gpio_backlight_device,
&ceu0_device,
&ceu1_device,
&keysc_device,
&cn12_power,
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
@ -1001,9 +974,6 @@ static struct platform_device *ecovec_devices[] __initdata = {
#else
&msiof0_device,
#endif
&camera_devices[0],
&camera_devices[1],
&camera_devices[2],
&fsi_device,
&fsi_da7210_device,
&irda_device,
@ -1240,7 +1210,6 @@ static int __init arch_setup(void)
gpio_request(GPIO_FN_VIO0_CLK, NULL);
gpio_request(GPIO_FN_VIO0_FLD, NULL);
gpio_request(GPIO_FN_VIO0_HD, NULL);
platform_resource_setup_memory(&ceu0_device, "ceu0", 4 << 20);
/* enable CEU1 */
gpio_request(GPIO_FN_VIO1_D7, NULL);
@ -1255,7 +1224,6 @@ static int __init arch_setup(void)
gpio_request(GPIO_FN_VIO1_HD, NULL);
gpio_request(GPIO_FN_VIO1_VD, NULL);
gpio_request(GPIO_FN_VIO1_CLK, NULL);
platform_resource_setup_memory(&ceu1_device, "ceu1", 4 << 20);
/* enable KEYSC */
gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
@ -1332,16 +1300,6 @@ static int __init arch_setup(void)
__raw_writew((__raw_readw(IODRIVEA) & ~0x3000) | 0x2000,
IODRIVEA);
/* enable Video */
gpio_request(GPIO_PTU2, NULL);
gpio_direction_output(GPIO_PTU2, 1);
/* enable Camera */
gpio_request(GPIO_PTA3, NULL);
gpio_request(GPIO_PTA4, NULL);
gpio_direction_output(GPIO_PTA3, 0);
gpio_direction_output(GPIO_PTA4, 0);
/* enable FSI */
gpio_request(GPIO_FN_FSIMCKB, NULL);
gpio_request(GPIO_FN_FSIIBSD, NULL);
@ -1390,6 +1348,11 @@ static int __init arch_setup(void)
gpio_request(GPIO_PTU5, NULL);
gpio_direction_output(GPIO_PTU5, 0);
/* Register gpio lookup tables for cameras and video decoder */
gpiod_add_lookup_table(&tw9910_gpios);
gpiod_add_lookup_table(&mt9t112_0_gpios);
gpiod_add_lookup_table(&mt9t112_1_gpios);
/* enable I2C device */
i2c_register_board_info(0, i2c0_devices,
ARRAY_SIZE(i2c0_devices));
@ -1431,6 +1394,25 @@ static int __init arch_setup(void)
gpio_set_value(GPIO_PTG4, 1);
#endif
/* Initialize CEU platform devices separately to map memory first */
device_initialize(&ecovec_ceu_devices[0]->dev);
arch_setup_pdev_archdata(ecovec_ceu_devices[0]);
dma_declare_coherent_memory(&ecovec_ceu_devices[0]->dev,
ceu0_dma_membase, ceu0_dma_membase,
ceu0_dma_membase +
CEU_BUFFER_MEMORY_SIZE - 1,
DMA_MEMORY_EXCLUSIVE);
platform_device_add(ecovec_ceu_devices[0]);
device_initialize(&ecovec_ceu_devices[1]->dev);
arch_setup_pdev_archdata(ecovec_ceu_devices[1]);
dma_declare_coherent_memory(&ecovec_ceu_devices[1]->dev,
ceu1_dma_membase, ceu1_dma_membase,
ceu1_dma_membase +
CEU_BUFFER_MEMORY_SIZE - 1,
DMA_MEMORY_EXCLUSIVE);
platform_device_add(ecovec_ceu_devices[1]);
return platform_add_devices(ecovec_devices,
ARRAY_SIZE(ecovec_devices));
}
@ -1443,6 +1425,24 @@ static int __init devices_setup(void)
}
device_initcall(devices_setup);
/* Reserve a portion of memory for CEU 0 and CEU 1 buffers */
static void __init ecovec_mv_mem_reserve(void)
{
phys_addr_t phys;
phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size);
memblock_remove(phys, size);
ceu0_dma_membase = phys;
phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size);
memblock_remove(phys, size);
ceu1_dma_membase = phys;
}
static struct sh_machine_vector mv_ecovec __initmv = {
.mv_name = "R0P7724 (EcoVec)",
.mv_mem_reserve = ecovec_mv_mem_reserve,
};

View file

@ -1,17 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Renesas System Solutions Asia Pte. Ltd - Migo-R
*
* Copyright (C) 2008 Magnus Damm
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*/
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/input/sh_keysc.h>
#include <linux/memblock.h>
#include <linux/mmc/host.h>
#include <linux/mtd/physmap.h>
#include <linux/mfd/tmio.h>
@ -23,10 +22,11 @@
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/videodev2.h>
#include <linux/sh_intc.h>
#include <video/sh_mobile_lcdc.h>
#include <media/drv-intf/sh_mobile_ceu.h>
#include <media/drv-intf/renesas-ceu.h>
#include <media/i2c/ov772x.h>
#include <media/soc_camera.h>
#include <media/i2c/tw9910.h>
@ -45,6 +45,9 @@
* 0x18000000 8GB 8 NAND Flash (K9K8G08U0A)
*/
#define CEU_BUFFER_MEMORY_SIZE (4 << 20)
static phys_addr_t ceu_dma_membase;
static struct smc91x_platdata smc91x_info = {
.flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
};
@ -301,65 +304,24 @@ static struct platform_device migor_lcdc_device = {
},
};
static struct clk *camera_clk;
static DEFINE_MUTEX(camera_lock);
static void camera_power_on(int is_tw)
{
mutex_lock(&camera_lock);
/* Use 10 MHz VIO_CKO instead of 24 MHz to work
* around signal quality issues on Panel Board V2.1.
*/
camera_clk = clk_get(NULL, "video_clk");
clk_set_rate(camera_clk, 10000000);
clk_enable(camera_clk); /* start VIO_CKO */
/* use VIO_RST to take camera out of reset */
mdelay(10);
if (is_tw) {
gpio_set_value(GPIO_PTT2, 0);
gpio_set_value(GPIO_PTT0, 0);
} else {
gpio_set_value(GPIO_PTT0, 1);
}
gpio_set_value(GPIO_PTT3, 0);
mdelay(10);
gpio_set_value(GPIO_PTT3, 1);
mdelay(10); /* wait to let chip come out of reset */
}
static void camera_power_off(void)
{
clk_disable(camera_clk); /* stop VIO_CKO */
clk_put(camera_clk);
gpio_set_value(GPIO_PTT3, 0);
mutex_unlock(&camera_lock);
}
static int ov7725_power(struct device *dev, int mode)
{
if (mode)
camera_power_on(0);
else
camera_power_off();
return 0;
}
static int tw9910_power(struct device *dev, int mode)
{
if (mode)
camera_power_on(1);
else
camera_power_off();
return 0;
}
static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
.flags = SH_CEU_FLAG_USE_8BIT_BUS,
static struct ceu_platform_data ceu_pdata = {
.num_subdevs = 2,
.subdevs = {
{ /* [0] = ov772x */
.flags = 0,
.bus_width = 8,
.bus_shift = 0,
.i2c_adapter_id = 0,
.i2c_address = 0x21,
},
{ /* [1] = tw9910 */
.flags = 0,
.bus_width = 8,
.bus_shift = 0,
.i2c_adapter_id = 0,
.i2c_address = 0x45,
},
},
};
static struct resource migor_ceu_resources[] = {
@ -373,18 +335,32 @@ static struct resource migor_ceu_resources[] = {
.start = evt2irq(0x880),
.flags = IORESOURCE_IRQ,
},
[2] = {
/* place holder for contiguous memory */
},
};
static struct platform_device migor_ceu_device = {
.name = "sh_mobile_ceu",
.id = 0, /* "ceu0" clock */
.name = "renesas-ceu",
.id = 0, /* ceu.0 */
.num_resources = ARRAY_SIZE(migor_ceu_resources),
.resource = migor_ceu_resources,
.dev = {
.platform_data = &sh_mobile_ceu_info,
.platform_data = &ceu_pdata,
},
};
/* Powerdown/reset gpios for CEU image sensors */
static struct gpiod_lookup_table ov7725_gpios = {
.dev_id = "0-0021",
.table = {
GPIO_LOOKUP("sh7722_pfc", GPIO_PTT0, "pwdn", GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("sh7722_pfc", GPIO_PTT3, "rstb", GPIO_ACTIVE_LOW),
},
};
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_PTT3, "rstb", GPIO_ACTIVE_LOW),
},
};
@ -423,6 +399,15 @@ static struct platform_device sdhi_cn9_device = {
},
};
static struct ov772x_camera_info ov7725_info = {
.flags = 0,
};
static struct tw9910_video_info tw9910_info = {
.buswidth = 8,
.mpout = TW9910_MPO_FIELD,
};
static struct i2c_board_info migor_i2c_devices[] = {
{
I2C_BOARD_INFO("rs5c372b", 0x32),
@ -434,51 +419,13 @@ static struct i2c_board_info migor_i2c_devices[] = {
{
I2C_BOARD_INFO("wm8978", 0x1a),
},
};
static struct i2c_board_info migor_i2c_camera[] = {
{
I2C_BOARD_INFO("ov772x", 0x21),
.platform_data = &ov7725_info,
},
{
I2C_BOARD_INFO("tw9910", 0x45),
},
};
static struct ov772x_camera_info ov7725_info;
static struct soc_camera_link ov7725_link = {
.power = ov7725_power,
.board_info = &migor_i2c_camera[0],
.i2c_adapter_id = 0,
.priv = &ov7725_info,
};
static struct tw9910_video_info tw9910_info = {
.buswidth = SOCAM_DATAWIDTH_8,
.mpout = TW9910_MPO_FIELD,
};
static struct soc_camera_link tw9910_link = {
.power = tw9910_power,
.board_info = &migor_i2c_camera[1],
.i2c_adapter_id = 0,
.priv = &tw9910_info,
};
static struct platform_device migor_camera[] = {
{
.name = "soc-camera-pdrv",
.id = 0,
.dev = {
.platform_data = &ov7725_link,
},
}, {
.name = "soc-camera-pdrv",
.id = 1,
.dev = {
.platform_data = &tw9910_link,
},
.platform_data = &tw9910_info,
},
};
@ -486,12 +433,9 @@ static struct platform_device *migor_devices[] __initdata = {
&smc91x_eth_device,
&sh_keysc_device,
&migor_lcdc_device,
&migor_ceu_device,
&migor_nor_flash_device,
&migor_nand_flash_device,
&sdhi_cn9_device,
&migor_camera[0],
&migor_camera[1],
};
extern char migor_sdram_enter_start;
@ -501,6 +445,8 @@ extern char migor_sdram_leave_end;
static int __init migor_devices_setup(void)
{
struct clk *video_clk;
/* register board specific self-refresh code */
sh_mobile_register_self_refresh(SUSP_SH_STANDBY | SUSP_SH_SF,
&migor_sdram_enter_start,
@ -620,20 +566,8 @@ static int __init migor_devices_setup(void)
gpio_request(GPIO_FN_VIO_D9, NULL);
gpio_request(GPIO_FN_VIO_D8, NULL);
gpio_request(GPIO_PTT3, NULL); /* VIO_RST */
gpio_direction_output(GPIO_PTT3, 0);
gpio_request(GPIO_PTT2, NULL); /* TV_IN_EN */
gpio_direction_output(GPIO_PTT2, 1);
gpio_request(GPIO_PTT0, NULL); /* CAM_EN */
#ifdef CONFIG_SH_MIGOR_RTA_WVGA
gpio_direction_output(GPIO_PTT0, 0);
#else
gpio_direction_output(GPIO_PTT0, 1);
#endif
__raw_writew(__raw_readw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
/* SIU: Port B */
gpio_request(GPIO_FN_SIUBOLR, NULL);
gpio_request(GPIO_FN_SIUBOBT, NULL);
@ -647,9 +581,36 @@ static int __init migor_devices_setup(void)
*/
__raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA);
/*
* Use 10 MHz VIO_CKO instead of 24 MHz to work around signal quality
* issues on Panel Board V2.1.
*/
video_clk = clk_get(NULL, "video_clk");
if (!IS_ERR(video_clk)) {
clk_set_rate(video_clk, clk_round_rate(video_clk, 10000000));
clk_put(video_clk);
}
/* Add a clock alias for ov7725 xclk source. */
clk_add_alias("xclk", "0-0021", "video_clk", NULL);
/* Register GPIOs for video sources. */
gpiod_add_lookup_table(&ov7725_gpios);
gpiod_add_lookup_table(&tw9910_gpios);
i2c_register_board_info(0, migor_i2c_devices,
ARRAY_SIZE(migor_i2c_devices));
/* Initialize CEU platform device separately to map memory first */
device_initialize(&migor_ceu_device.dev);
arch_setup_pdev_archdata(&migor_ceu_device);
dma_declare_coherent_memory(&migor_ceu_device.dev,
ceu_dma_membase, ceu_dma_membase,
ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1,
DMA_MEMORY_EXCLUSIVE);
platform_device_add(&migor_ceu_device);
return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
}
arch_initcall(migor_devices_setup);
@ -665,10 +626,24 @@ static int migor_mode_pins(void)
return MODE_PIN0 | MODE_PIN1 | MODE_PIN5;
}
/* Reserve a portion of memory for CEU buffers */
static void __init migor_mv_mem_reserve(void)
{
phys_addr_t phys;
phys_addr_t size = CEU_BUFFER_MEMORY_SIZE;
phys = memblock_alloc_base(size, PAGE_SIZE, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size);
memblock_remove(phys, size);
ceu_dma_membase = phys;
}
/*
* The Machine Vector
*/
static struct sh_machine_vector mv_migor __initmv = {
.mv_name = "Migo-R",
.mv_mode_pins = migor_mode_pins,
.mv_mem_reserve = migor_mv_mem_reserve,
};

View file

@ -223,7 +223,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]),
CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]),
CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]),
CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU]),
CLKDEV_DEV_ID("renesas-ceu.0", &mstp_clks[HWBLK_CEU]),
CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU]),
CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),

View file

@ -338,14 +338,14 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]),
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]),
CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU1]),
CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[HWBLK_CEU1]),
CLKDEV_DEV_ID("renesas-ceu.1", &mstp_clks[HWBLK_CEU1]),
CLKDEV_CON_ID("beu1", &mstp_clks[HWBLK_BEU1]),
CLKDEV_CON_ID("2ddmac0", &mstp_clks[HWBLK_2DDMAC]),
CLKDEV_DEV_ID("sh_fsi.0", &mstp_clks[HWBLK_SPU]),
CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]),
CLKDEV_DEV_ID("sh-vou", &mstp_clks[HWBLK_VOU]),
CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU0]),
CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU0]),
CLKDEV_DEV_ID("renesas-ceu.0", &mstp_clks[HWBLK_CEU0]),
CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU0]),
CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),

View file

@ -38,6 +38,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-ctrls.h>
#include <media/videobuf2-v4l2.h>
#include <media/videobuf2-dma-sg.h>
@ -81,7 +82,10 @@ struct sur40_blob {
__le32 area; /* size in pixels/pressure (?) */
u8 padding[32];
u8 padding[24];
__le32 tag_id; /* valid when type == 0x04 (SUR40_TAG) */
__le32 unknown;
} __packed;
@ -146,6 +150,40 @@ struct sur40_image_header {
#define SUR40_TOUCH 0x02
#define SUR40_TAG 0x04
/* video controls */
#define SUR40_BRIGHTNESS_MAX 0xff
#define SUR40_BRIGHTNESS_MIN 0x00
#define SUR40_BRIGHTNESS_DEF 0xff
#define SUR40_CONTRAST_MAX 0x0f
#define SUR40_CONTRAST_MIN 0x00
#define SUR40_CONTRAST_DEF 0x0a
#define SUR40_GAIN_MAX 0x09
#define SUR40_GAIN_MIN 0x00
#define SUR40_GAIN_DEF 0x08
#define SUR40_BACKLIGHT_MAX 0x01
#define SUR40_BACKLIGHT_MIN 0x00
#define SUR40_BACKLIGHT_DEF 0x01
#define sur40_str(s) #s
#define SUR40_PARAM_RANGE(lo, hi) " (range " sur40_str(lo) "-" sur40_str(hi) ")"
/* module parameters */
static uint brightness = SUR40_BRIGHTNESS_DEF;
module_param(brightness, uint, 0644);
MODULE_PARM_DESC(brightness, "set initial brightness"
SUR40_PARAM_RANGE(SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX));
static uint contrast = SUR40_CONTRAST_DEF;
module_param(contrast, uint, 0644);
MODULE_PARM_DESC(contrast, "set initial contrast"
SUR40_PARAM_RANGE(SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX));
static uint gain = SUR40_GAIN_DEF;
module_param(gain, uint, 0644);
MODULE_PARM_DESC(gain, "set initial gain"
SUR40_PARAM_RANGE(SUR40_GAIN_MIN, SUR40_GAIN_MAX));
static const struct v4l2_pix_format sur40_pix_format[] = {
{
.pixelformat = V4L2_TCH_FMT_TU08,
@ -178,6 +216,7 @@ struct sur40_state {
struct video_device vdev;
struct mutex lock;
struct v4l2_pix_format pix_fmt;
struct v4l2_ctrl_handler hdl;
struct vb2_queue queue;
struct list_head buf_list;
@ -187,6 +226,7 @@ struct sur40_state {
struct sur40_data *bulk_in_buffer;
size_t bulk_in_size;
u8 bulk_in_epaddr;
u8 vsvideo;
char phys[64];
};
@ -200,6 +240,11 @@ struct sur40_buffer {
static const struct video_device sur40_video_device;
static const struct vb2_queue sur40_queue;
static void sur40_process_video(struct sur40_state *sur40);
static int sur40_s_ctrl(struct v4l2_ctrl *ctrl);
static const struct v4l2_ctrl_ops sur40_ctrl_ops = {
.s_ctrl = sur40_s_ctrl,
};
/*
* Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
@ -220,6 +265,81 @@ static int sur40_command(struct sur40_state *dev,
0x00, index, buffer, size, 1000);
}
/* poke a byte in the panel register space */
static int sur40_poke(struct sur40_state *dev, u8 offset, u8 value)
{
int result;
u8 index = 0x96; // 0xae for permanent write
result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x32, index, NULL, 0, 1000);
if (result < 0)
goto error;
msleep(5);
result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x72, offset, NULL, 0, 1000);
if (result < 0)
goto error;
msleep(5);
result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0xb2, value, NULL, 0, 1000);
if (result < 0)
goto error;
msleep(5);
error:
return result;
}
static int sur40_set_preprocessor(struct sur40_state *dev, u8 value)
{
u8 setting_07[2] = { 0x01, 0x00 };
u8 setting_17[2] = { 0x85, 0x80 };
int result;
if (value > 1)
return -ERANGE;
result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x07, setting_07[value], NULL, 0, 1000);
if (result < 0)
goto error;
msleep(5);
result = usb_control_msg(dev->usbdev, usb_sndctrlpipe(dev->usbdev, 0),
SUR40_POKE, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
0x17, setting_17[value], NULL, 0, 1000);
if (result < 0)
goto error;
msleep(5);
error:
return result;
}
static void sur40_set_vsvideo(struct sur40_state *handle, u8 value)
{
int i;
for (i = 0; i < 4; i++)
sur40_poke(handle, 0x1c+i, value);
handle->vsvideo = value;
}
static void sur40_set_irlevel(struct sur40_state *handle, u8 value)
{
int i;
for (i = 0; i < 8; i++)
sur40_poke(handle, 0x08+(2*i), value);
}
/* Initialization routine, called from sur40_open */
static int sur40_init(struct sur40_state *dev)
{
@ -631,6 +751,36 @@ static int sur40_probe(struct usb_interface *interface,
sur40->vdev.queue = &sur40->queue;
video_set_drvdata(&sur40->vdev, sur40);
/* initialize the control handler for 4 controls */
v4l2_ctrl_handler_init(&sur40->hdl, 4);
sur40->v4l2.ctrl_handler = &sur40->hdl;
sur40->vsvideo = (SUR40_CONTRAST_DEF << 4) | SUR40_GAIN_DEF;
v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_BRIGHTNESS,
SUR40_BRIGHTNESS_MIN, SUR40_BRIGHTNESS_MAX, 1, clamp(brightness,
(uint)SUR40_BRIGHTNESS_MIN, (uint)SUR40_BRIGHTNESS_MAX));
v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_CONTRAST,
SUR40_CONTRAST_MIN, SUR40_CONTRAST_MAX, 1, clamp(contrast,
(uint)SUR40_CONTRAST_MIN, (uint)SUR40_CONTRAST_MAX));
v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops, V4L2_CID_GAIN,
SUR40_GAIN_MIN, SUR40_GAIN_MAX, 1, clamp(gain,
(uint)SUR40_GAIN_MIN, (uint)SUR40_GAIN_MAX));
v4l2_ctrl_new_std(&sur40->hdl, &sur40_ctrl_ops,
V4L2_CID_BACKLIGHT_COMPENSATION, SUR40_BACKLIGHT_MIN,
SUR40_BACKLIGHT_MAX, 1, SUR40_BACKLIGHT_DEF);
v4l2_ctrl_handler_setup(&sur40->hdl);
if (sur40->hdl.error) {
dev_err(&interface->dev,
"Unable to register video controls.");
v4l2_ctrl_handler_free(&sur40->hdl);
goto err_unreg_v4l2;
}
error = video_register_device(&sur40->vdev, VFL_TYPE_TOUCH, -1);
if (error) {
dev_err(&interface->dev,
@ -663,6 +813,7 @@ static void sur40_disconnect(struct usb_interface *interface)
{
struct sur40_state *sur40 = usb_get_intfdata(interface);
v4l2_ctrl_handler_free(&sur40->hdl);
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
@ -856,6 +1007,31 @@ static int sur40_vidioc_g_fmt(struct file *file, void *priv,
return 0;
}
static int sur40_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct sur40_state *sur40 = container_of(ctrl->handler,
struct sur40_state, hdl);
u8 value = sur40->vsvideo;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
sur40_set_irlevel(sur40, ctrl->val);
break;
case V4L2_CID_CONTRAST:
value = (value & 0x0f) | (ctrl->val << 4);
sur40_set_vsvideo(sur40, value);
break;
case V4L2_CID_GAIN:
value = (value & 0xf0) | (ctrl->val);
sur40_set_vsvideo(sur40, value);
break;
case V4L2_CID_BACKLIGHT_COMPENSATION:
sur40_set_preprocessor(sur40, ctrl->val);
break;
}
return 0;
}
static int sur40_ioctl_parm(struct file *file, void *priv,
struct v4l2_streamparm *p)
{

View file

@ -141,6 +141,7 @@ config DVB_CORE
tristate
depends on MEDIA_SUPPORT
depends on MEDIA_DIGITAL_TV_SUPPORT
depends on (I2C || I2C=n)
default y
select CRC32

View file

@ -4,3 +4,9 @@ config MEDIA_CEC_RC
depends on CEC_CORE=m || RC_CORE=y
---help---
Pass on CEC remote control messages to the RC framework.
config CEC_PIN_ERROR_INJ
bool "Enable CEC error injection support"
depends on CEC_PIN && DEBUG_FS
---help---
This option enables CEC error injection using debugfs.

View file

@ -9,4 +9,8 @@ ifeq ($(CONFIG_CEC_PIN),y)
cec-objs += cec-pin.o
endif
ifeq ($(CONFIG_CEC_PIN_ERROR_INJ),y)
cec-objs += cec-pin-error-inj.o
endif
obj-$(CONFIG_CEC_CORE) += cec.o

View file

@ -1,20 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cec-adap.c - HDMI Consumer Electronics Control framework - CEC adapter
*
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/errno.h>
@ -85,8 +73,8 @@ static unsigned int cec_log_addr2dev(const struct cec_adapter *adap, u8 log_addr
void cec_queue_event_fh(struct cec_fh *fh,
const struct cec_event *new_ev, u64 ts)
{
static const u8 max_events[CEC_NUM_EVENTS] = {
1, 1, 64, 64, 8, 8,
static const u16 max_events[CEC_NUM_EVENTS] = {
1, 1, 800, 800, 8, 8,
};
struct cec_event_entry *entry;
unsigned int ev_idx = new_ev->event - 1;
@ -154,11 +142,13 @@ static void cec_queue_event(struct cec_adapter *adap,
}
/* Notify userspace that the CEC pin changed state at the given time. */
void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
bool dropped_events, ktime_t ts)
{
struct cec_event ev = {
.event = is_high ? CEC_EVENT_PIN_CEC_HIGH :
CEC_EVENT_PIN_CEC_LOW,
.flags = dropped_events ? CEC_EVENT_FL_DROPPED_EVENTS : 0,
};
struct cec_fh *fh;
@ -711,16 +701,31 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
else
msg->flags = 0;
if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
msg->msg[2] = adap->phys_addr >> 8;
msg->msg[3] = adap->phys_addr & 0xff;
}
/* Sanity checks */
if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
dprintk(1, "%s: invalid length %d\n", __func__, msg->len);
return -EINVAL;
}
memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
if (msg->timeout)
dprintk(2, "%s: %*ph (wait for 0x%02x%s)\n",
__func__, msg->len, msg->msg, msg->reply,
!block ? ", nb" : "");
else
dprintk(2, "%s: %*ph%s\n",
__func__, msg->len, msg->msg, !block ? " (nb)" : "");
if (msg->timeout && msg->len == 1) {
dprintk(1, "%s: can't reply for poll msg\n", __func__);
dprintk(1, "%s: can't reply to poll msg\n", __func__);
return -EINVAL;
}
memset(msg->msg + msg->len, 0, sizeof(msg->msg) - msg->len);
if (msg->len == 1) {
if (cec_msg_destination(msg) == 0xf) {
dprintk(1, "%s: invalid poll message\n", __func__);
@ -780,19 +785,6 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
if (!msg->sequence)
msg->sequence = ++adap->sequence;
if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
msg->msg[2] = adap->phys_addr >> 8;
msg->msg[3] = adap->phys_addr & 0xff;
}
if (msg->timeout)
dprintk(2, "%s: %*ph (wait for 0x%02x%s)\n",
__func__, msg->len, msg->msg, msg->reply,
!block ? ", nb" : "");
else
dprintk(2, "%s: %*ph%s\n",
__func__, msg->len, msg->msg, !block ? " (nb)" : "");
data->msg = *msg;
data->fh = fh;
data->adap = adap;

View file

@ -1,20 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cec-api.c - HDMI Consumer Electronics Control framework - API
*
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/errno.h>

View file

@ -1,20 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cec-core.c - HDMI Consumer Electronics Control framework - Core
*
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/errno.h>
@ -207,6 +195,55 @@ void cec_register_cec_notifier(struct cec_adapter *adap,
EXPORT_SYMBOL_GPL(cec_register_cec_notifier);
#endif
#ifdef CONFIG_DEBUG_FS
static ssize_t cec_error_inj_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
struct seq_file *sf = file->private_data;
struct cec_adapter *adap = sf->private;
char *buf;
char *line;
char *p;
buf = memdup_user_nul(ubuf, min_t(size_t, PAGE_SIZE, count));
if (IS_ERR(buf))
return PTR_ERR(buf);
p = buf;
while (p && *p) {
p = skip_spaces(p);
line = strsep(&p, "\n");
if (!*line || *line == '#')
continue;
if (!adap->ops->error_inj_parse_line(adap, line)) {
kfree(buf);
return -EINVAL;
}
}
kfree(buf);
return count;
}
static int cec_error_inj_show(struct seq_file *sf, void *unused)
{
struct cec_adapter *adap = sf->private;
return adap->ops->error_inj_show(adap, sf);
}
static int cec_error_inj_open(struct inode *inode, struct file *file)
{
return single_open(file, cec_error_inj_show, inode->i_private);
}
static const struct file_operations cec_error_inj_fops = {
.open = cec_error_inj_open,
.write = cec_error_inj_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
#endif
struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
void *priv, const char *name, u32 caps,
u8 available_las)
@ -346,7 +383,16 @@ int cec_register_adapter(struct cec_adapter *adap,
pr_warn("cec-%s: Failed to create status file\n", adap->name);
debugfs_remove_recursive(adap->cec_dir);
adap->cec_dir = NULL;
return 0;
}
if (!adap->ops->error_inj_show || !adap->ops->error_inj_parse_line)
return 0;
adap->error_inj_file = debugfs_create_file("error-inj", 0644,
adap->cec_dir, adap,
&cec_error_inj_fops);
if (IS_ERR_OR_NULL(adap->error_inj_file))
pr_warn("cec-%s: Failed to create error-inj file\n",
adap->name);
#endif
return 0;
}

View file

@ -1,20 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cec-edid - HDMI Consumer Electronics Control EDID & CEC helper functions
*
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/module.h>

View file

@ -1,21 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* cec-notifier.c - notify CEC drivers of physical address changes
*
* Copyright 2016 Russell King <rmk+kernel@arm.linux.org.uk>
* Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/export.h>

View file

@ -0,0 +1,342 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sched/types.h>
#include <media/cec-pin.h>
#include "cec-pin-priv.h"
struct cec_error_inj_cmd {
unsigned int mode_offset;
int arg_idx;
const char *cmd;
};
static const struct cec_error_inj_cmd cec_error_inj_cmds[] = {
{ CEC_ERROR_INJ_RX_NACK_OFFSET, -1, "rx-nack" },
{ CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET,
CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX, "rx-low-drive" },
{ CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET, -1, "rx-add-byte" },
{ CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET, -1, "rx-remove-byte" },
{ CEC_ERROR_INJ_RX_ARB_LOST_OFFSET,
CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX, "rx-arb-lost" },
{ CEC_ERROR_INJ_TX_NO_EOM_OFFSET, -1, "tx-no-eom" },
{ CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET, -1, "tx-early-eom" },
{ CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET,
CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX, "tx-add-bytes" },
{ CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET, -1, "tx-remove-byte" },
{ CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET,
CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX, "tx-short-bit" },
{ CEC_ERROR_INJ_TX_LONG_BIT_OFFSET,
CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX, "tx-long-bit" },
{ CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET,
CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX, "tx-custom-bit" },
{ CEC_ERROR_INJ_TX_SHORT_START_OFFSET, -1, "tx-short-start" },
{ CEC_ERROR_INJ_TX_LONG_START_OFFSET, -1, "tx-long-start" },
{ CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET, -1, "tx-custom-start" },
{ CEC_ERROR_INJ_TX_LAST_BIT_OFFSET,
CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX, "tx-last-bit" },
{ CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET,
CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX, "tx-low-drive" },
{ 0, -1, NULL }
};
u16 cec_pin_rx_error_inj(struct cec_pin *pin)
{
u16 cmd = CEC_ERROR_INJ_OP_ANY;
/* Only when 18 bits have been received do we have a valid cmd */
if (!(pin->error_inj[cmd] & CEC_ERROR_INJ_RX_MASK) &&
pin->rx_bit >= 18)
cmd = pin->rx_msg.msg[1];
return (pin->error_inj[cmd] & CEC_ERROR_INJ_RX_MASK) ? cmd :
CEC_ERROR_INJ_OP_ANY;
}
u16 cec_pin_tx_error_inj(struct cec_pin *pin)
{
u16 cmd = CEC_ERROR_INJ_OP_ANY;
if (!(pin->error_inj[cmd] & CEC_ERROR_INJ_TX_MASK) &&
pin->tx_msg.len > 1)
cmd = pin->tx_msg.msg[1];
return (pin->error_inj[cmd] & CEC_ERROR_INJ_TX_MASK) ? cmd :
CEC_ERROR_INJ_OP_ANY;
}
bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line)
{
static const char *delims = " \t\r";
struct cec_pin *pin = adap->pin;
unsigned int i;
bool has_pos = false;
char *p = line;
char *token;
char *comma;
u64 *error;
u8 *args;
bool has_op;
u32 op;
u8 mode;
u8 pos;
u8 v;
p = skip_spaces(p);
token = strsep(&p, delims);
if (!strcmp(token, "clear")) {
memset(pin->error_inj, 0, sizeof(pin->error_inj));
pin->rx_toggle = pin->tx_toggle = false;
pin->tx_ignore_nack_until_eom = false;
pin->tx_custom_pulse = false;
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT;
return true;
}
if (!strcmp(token, "rx-clear")) {
for (i = 0; i <= CEC_ERROR_INJ_OP_ANY; i++)
pin->error_inj[i] &= ~CEC_ERROR_INJ_RX_MASK;
pin->rx_toggle = false;
return true;
}
if (!strcmp(token, "tx-clear")) {
for (i = 0; i <= CEC_ERROR_INJ_OP_ANY; i++)
pin->error_inj[i] &= ~CEC_ERROR_INJ_TX_MASK;
pin->tx_toggle = false;
pin->tx_ignore_nack_until_eom = false;
pin->tx_custom_pulse = false;
pin->tx_custom_low_usecs = CEC_TIM_CUSTOM_DEFAULT;
pin->tx_custom_high_usecs = CEC_TIM_CUSTOM_DEFAULT;
return true;
}
if (!strcmp(token, "tx-ignore-nack-until-eom")) {
pin->tx_ignore_nack_until_eom = true;
return true;
}
if (!strcmp(token, "tx-custom-pulse")) {
pin->tx_custom_pulse = true;
cec_pin_start_timer(pin);
return true;
}
if (!p)
return false;
p = skip_spaces(p);
if (!strcmp(token, "tx-custom-low-usecs")) {
u32 usecs;
if (kstrtou32(p, 0, &usecs) || usecs > 10000000)
return false;
pin->tx_custom_low_usecs = usecs;
return true;
}
if (!strcmp(token, "tx-custom-high-usecs")) {
u32 usecs;
if (kstrtou32(p, 0, &usecs) || usecs > 10000000)
return false;
pin->tx_custom_high_usecs = usecs;
return true;
}
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
return false;
mode = CEC_ERROR_INJ_MODE_ONCE;
if (comma) {
if (!strcmp(comma, "off"))
mode = CEC_ERROR_INJ_MODE_OFF;
else if (!strcmp(comma, "once"))
mode = CEC_ERROR_INJ_MODE_ONCE;
else if (!strcmp(comma, "always"))
mode = CEC_ERROR_INJ_MODE_ALWAYS;
else if (!strcmp(comma, "toggle"))
mode = CEC_ERROR_INJ_MODE_TOGGLE;
else
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);
has_pos = !kstrtou8(p, 0, &pos);
}
if (!strcmp(token, "clear")) {
*error = 0;
return true;
}
if (!strcmp(token, "rx-clear")) {
*error &= ~CEC_ERROR_INJ_RX_MASK;
return true;
}
if (!strcmp(token, "tx-clear")) {
*error &= ~CEC_ERROR_INJ_TX_MASK;
return true;
}
for (i = 0; cec_error_inj_cmds[i].cmd; i++) {
const char *cmd = cec_error_inj_cmds[i].cmd;
unsigned int mode_offset;
u64 mode_mask;
int arg_idx;
bool is_bit_pos = true;
if (strcmp(token, cmd))
continue;
mode_offset = cec_error_inj_cmds[i].mode_offset;
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;
}
if (arg_idx >= 0 && is_bit_pos) {
if (!has_pos || pos >= 160)
return false;
if (has_op && pos < 10 + 8)
return false;
/* Invalid bit position may not be the Ack bit */
if ((mode_offset == CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET ||
mode_offset == CEC_ERROR_INJ_TX_LONG_BIT_OFFSET ||
mode_offset == CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET) &&
(pos % 10) == 9)
return false;
}
*error &= ~mode_mask;
*error |= (u64)mode << mode_offset;
if (arg_idx >= 0)
args[arg_idx] = pos;
return true;
}
return false;
}
static void cec_pin_show_cmd(struct seq_file *sf, u32 cmd, u8 mode)
{
if (cmd == CEC_ERROR_INJ_OP_ANY)
seq_puts(sf, "any,");
else
seq_printf(sf, "0x%02x,", cmd);
switch (mode) {
case CEC_ERROR_INJ_MODE_ONCE:
seq_puts(sf, "once ");
break;
case CEC_ERROR_INJ_MODE_ALWAYS:
seq_puts(sf, "always ");
break;
case CEC_ERROR_INJ_MODE_TOGGLE:
seq_puts(sf, "toggle ");
break;
default:
seq_puts(sf, "off ");
break;
}
}
int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf)
{
struct cec_pin *pin = adap->pin;
unsigned int i, j;
seq_puts(sf, "# Clear error injections:\n");
seq_puts(sf, "# clear clear all rx and tx error injections\n");
seq_puts(sf, "# rx-clear clear all rx error injections\n");
seq_puts(sf, "# tx-clear clear all tx error injections\n");
seq_puts(sf, "# <op> clear clear all rx and tx error injections for <op>\n");
seq_puts(sf, "# <op> rx-clear clear all rx error injections for <op>\n");
seq_puts(sf, "# <op> tx-clear clear all tx error injections for <op>\n");
seq_puts(sf, "#\n");
seq_puts(sf, "# RX error injection:\n");
seq_puts(sf, "# <op>[,<mode>] rx-nack NACK the message instead of sending an ACK\n");
seq_puts(sf, "# <op>[,<mode>] rx-low-drive <bit> force a low-drive condition at this bit position\n");
seq_puts(sf, "# <op>[,<mode>] rx-add-byte add a spurious byte to the received CEC message\n");
seq_puts(sf, "# <op>[,<mode>] rx-remove-byte remove the last byte from the received CEC message\n");
seq_puts(sf, "# <op>[,<mode>] rx-arb-lost <poll> generate a POLL message to trigger an arbitration lost\n");
seq_puts(sf, "#\n");
seq_puts(sf, "# TX error injection settings:\n");
seq_puts(sf, "# tx-ignore-nack-until-eom ignore early NACKs until EOM\n");
seq_puts(sf, "# tx-custom-low-usecs <usecs> define the 'low' time for the custom pulse\n");
seq_puts(sf, "# tx-custom-high-usecs <usecs> define the 'high' time for the custom pulse\n");
seq_puts(sf, "# tx-custom-pulse transmit the custom pulse once the bus is idle\n");
seq_puts(sf, "#\n");
seq_puts(sf, "# TX error injection:\n");
seq_puts(sf, "# <op>[,<mode>] tx-no-eom don't set the EOM bit\n");
seq_puts(sf, "# <op>[,<mode>] tx-early-eom set the EOM bit one byte too soon\n");
seq_puts(sf, "# <op>[,<mode>] tx-add-bytes <num> append <num> (1-255) spurious bytes to the message\n");
seq_puts(sf, "# <op>[,<mode>] tx-remove-byte drop the last byte from the message\n");
seq_puts(sf, "# <op>[,<mode>] tx-short-bit <bit> make this bit shorter than allowed\n");
seq_puts(sf, "# <op>[,<mode>] tx-long-bit <bit> make this bit longer than allowed\n");
seq_puts(sf, "# <op>[,<mode>] tx-custom-bit <bit> send the custom pulse instead of this bit\n");
seq_puts(sf, "# <op>[,<mode>] tx-short-start send a start pulse that's too short\n");
seq_puts(sf, "# <op>[,<mode>] tx-long-start send a start pulse that's too long\n");
seq_puts(sf, "# <op>[,<mode>] tx-custom-start send the custom pulse instead of the start pulse\n");
seq_puts(sf, "# <op>[,<mode>] tx-last-bit <bit> stop sending after this bit\n");
seq_puts(sf, "# <op>[,<mode>] tx-low-drive <bit> force a low-drive condition at this bit position\n");
seq_puts(sf, "#\n");
seq_puts(sf, "# <op> CEC message opcode (0-255) or 'any'\n");
seq_puts(sf, "# <mode> 'once' (default), 'always', 'toggle' or 'off'\n");
seq_puts(sf, "# <bit> CEC message bit (0-159)\n");
seq_puts(sf, "# 10 bits per 'byte': bits 0-7: data, bit 8: EOM, bit 9: ACK\n");
seq_puts(sf, "# <poll> CEC poll message used to test arbitration lost (0x00-0xff, default 0x0f)\n");
seq_puts(sf, "# <usecs> microseconds (0-10000000, default 1000)\n");
seq_puts(sf, "\nclear\n");
for (i = 0; i < ARRAY_SIZE(pin->error_inj); i++) {
u64 e = pin->error_inj[i];
for (j = 0; cec_error_inj_cmds[j].cmd; j++) {
const char *cmd = cec_error_inj_cmds[j].cmd;
unsigned int mode;
unsigned int mode_offset;
int arg_idx;
mode_offset = cec_error_inj_cmds[j].mode_offset;
arg_idx = cec_error_inj_cmds[j].arg_idx;
mode = (e >> mode_offset) & CEC_ERROR_INJ_MODE_MASK;
if (!mode)
continue;
cec_pin_show_cmd(sf, i, mode);
seq_puts(sf, cmd);
if (arg_idx >= 0)
seq_printf(sf, " %u",
pin->error_inj_args[i][arg_idx]);
seq_puts(sf, "\n");
}
}
if (pin->tx_ignore_nack_until_eom)
seq_puts(sf, "tx-ignore-nack-until-eom\n");
if (pin->tx_custom_pulse)
seq_puts(sf, "tx-custom-pulse\n");
if (pin->tx_custom_low_usecs != CEC_TIM_CUSTOM_DEFAULT)
seq_printf(sf, "tx-custom-low-usecs %u\n",
pin->tx_custom_low_usecs);
if (pin->tx_custom_high_usecs != CEC_TIM_CUSTOM_DEFAULT)
seq_printf(sf, "tx-custom-high-usecs %u\n",
pin->tx_custom_high_usecs);
return 0;
}

View file

@ -1,20 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* cec-pin-priv.h - internal cec-pin header
*
* Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef LINUX_CEC_PIN_PRIV_H
@ -40,14 +28,30 @@ enum cec_pin_state {
CEC_ST_TX_START_BIT_LOW,
/* Drive CEC high for the start bit */
CEC_ST_TX_START_BIT_HIGH,
/* Generate a start bit period that is too short */
CEC_ST_TX_START_BIT_HIGH_SHORT,
/* Generate a start bit period that is too long */
CEC_ST_TX_START_BIT_HIGH_LONG,
/* Drive CEC low for the start bit using the custom timing */
CEC_ST_TX_START_BIT_LOW_CUSTOM,
/* Drive CEC high for the start bit using the custom timing */
CEC_ST_TX_START_BIT_HIGH_CUSTOM,
/* Drive CEC low for the 0 bit */
CEC_ST_TX_DATA_BIT_0_LOW,
/* Drive CEC high for the 0 bit */
CEC_ST_TX_DATA_BIT_0_HIGH,
/* Generate a bit period that is too short */
CEC_ST_TX_DATA_BIT_0_HIGH_SHORT,
/* Generate a bit period that is too long */
CEC_ST_TX_DATA_BIT_0_HIGH_LONG,
/* Drive CEC low for the 1 bit */
CEC_ST_TX_DATA_BIT_1_LOW,
/* Drive CEC high for the 1 bit */
CEC_ST_TX_DATA_BIT_1_HIGH,
/* Generate a bit period that is too short */
CEC_ST_TX_DATA_BIT_1_HIGH_SHORT,
/* Generate a bit period that is too long */
CEC_ST_TX_DATA_BIT_1_HIGH_LONG,
/*
* Wait for start of sample time to check for Ack bit or first
* four initiator bits to check for Arbitration Lost.
@ -55,6 +59,20 @@ enum cec_pin_state {
CEC_ST_TX_DATA_BIT_1_HIGH_PRE_SAMPLE,
/* Wait for end of bit period after sampling */
CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE,
/* Generate a bit period that is too short */
CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_SHORT,
/* Generate a bit period that is too long */
CEC_ST_TX_DATA_BIT_1_HIGH_POST_SAMPLE_LONG,
/* Drive CEC low for a data bit using the custom timing */
CEC_ST_TX_DATA_BIT_LOW_CUSTOM,
/* Drive CEC high for a data bit using the custom timing */
CEC_ST_TX_DATA_BIT_HIGH_CUSTOM,
/* Drive CEC low for a standalone pulse using the custom timing */
CEC_ST_TX_PULSE_LOW_CUSTOM,
/* Drive CEC high for a standalone pulse using the custom timing */
CEC_ST_TX_PULSE_HIGH_CUSTOM,
/* Start low drive */
CEC_ST_TX_LOW_DRIVE,
/* Rx states */
@ -66,8 +84,8 @@ enum cec_pin_state {
CEC_ST_RX_DATA_SAMPLE,
/* Wait for earliest end of bit period after sampling */
CEC_ST_RX_DATA_POST_SAMPLE,
/* Wait for CEC to go high (i.e. end of bit period */
CEC_ST_RX_DATA_HIGH,
/* Wait for CEC to go low (i.e. end of bit period) */
CEC_ST_RX_DATA_WAIT_FOR_LOW,
/* Drive CEC low to send 0 Ack bit */
CEC_ST_RX_ACK_LOW,
/* End of 0 Ack time, wait for earliest end of bit period */
@ -76,9 +94,9 @@ enum cec_pin_state {
CEC_ST_RX_ACK_HIGH_POST,
/* Wait for earliest end of bit period and end of message */
CEC_ST_RX_ACK_FINISH,
/* Start low drive */
CEC_ST_LOW_DRIVE,
CEC_ST_RX_LOW_DRIVE,
/* Monitor pin using interrupts */
CEC_ST_RX_IRQ,
@ -86,7 +104,58 @@ enum cec_pin_state {
CEC_PIN_STATES
};
#define CEC_NUM_PIN_EVENTS 128
/* Error Injection */
/* Error injection modes */
#define CEC_ERROR_INJ_MODE_OFF 0
#define CEC_ERROR_INJ_MODE_ONCE 1
#define CEC_ERROR_INJ_MODE_ALWAYS 2
#define CEC_ERROR_INJ_MODE_TOGGLE 3
#define CEC_ERROR_INJ_MODE_MASK 3ULL
/* Receive error injection options */
#define CEC_ERROR_INJ_RX_NACK_OFFSET 0
#define CEC_ERROR_INJ_RX_LOW_DRIVE_OFFSET 2
#define CEC_ERROR_INJ_RX_ADD_BYTE_OFFSET 4
#define CEC_ERROR_INJ_RX_REMOVE_BYTE_OFFSET 6
#define CEC_ERROR_INJ_RX_ARB_LOST_OFFSET 8
#define CEC_ERROR_INJ_RX_MASK 0xffffULL
/* Transmit error injection options */
#define CEC_ERROR_INJ_TX_NO_EOM_OFFSET 16
#define CEC_ERROR_INJ_TX_EARLY_EOM_OFFSET 18
#define CEC_ERROR_INJ_TX_SHORT_BIT_OFFSET 20
#define CEC_ERROR_INJ_TX_LONG_BIT_OFFSET 22
#define CEC_ERROR_INJ_TX_CUSTOM_BIT_OFFSET 24
#define CEC_ERROR_INJ_TX_SHORT_START_OFFSET 26
#define CEC_ERROR_INJ_TX_LONG_START_OFFSET 28
#define CEC_ERROR_INJ_TX_CUSTOM_START_OFFSET 30
#define CEC_ERROR_INJ_TX_LAST_BIT_OFFSET 32
#define CEC_ERROR_INJ_TX_ADD_BYTES_OFFSET 34
#define CEC_ERROR_INJ_TX_REMOVE_BYTE_OFFSET 36
#define CEC_ERROR_INJ_TX_LOW_DRIVE_OFFSET 38
#define CEC_ERROR_INJ_TX_MASK 0xffffffffffff0000ULL
#define CEC_ERROR_INJ_RX_LOW_DRIVE_ARG_IDX 0
#define CEC_ERROR_INJ_RX_ARB_LOST_ARG_IDX 1
#define CEC_ERROR_INJ_TX_ADD_BYTES_ARG_IDX 2
#define CEC_ERROR_INJ_TX_SHORT_BIT_ARG_IDX 3
#define CEC_ERROR_INJ_TX_LONG_BIT_ARG_IDX 4
#define CEC_ERROR_INJ_TX_CUSTOM_BIT_ARG_IDX 5
#define CEC_ERROR_INJ_TX_LAST_BIT_ARG_IDX 6
#define CEC_ERROR_INJ_TX_LOW_DRIVE_ARG_IDX 7
#define CEC_ERROR_INJ_NUM_ARGS 8
/* Special CEC op values */
#define CEC_ERROR_INJ_OP_ANY 0x00000100
/* The default for the low/high time of the custom pulse */
#define CEC_TIM_CUSTOM_DEFAULT 1000
#define CEC_NUM_PIN_EVENTS 128
#define CEC_PIN_EVENT_FL_IS_HIGH (1 << 0)
#define CEC_PIN_EVENT_FL_DROPPED (1 << 1)
#define CEC_PIN_IRQ_UNCHANGED 0
#define CEC_PIN_IRQ_DISABLE 1
@ -110,24 +179,63 @@ struct cec_pin {
u32 tx_bit;
bool tx_nacked;
u32 tx_signal_free_time;
bool tx_toggle;
struct cec_msg rx_msg;
u32 rx_bit;
bool rx_toggle;
u32 rx_start_bit_low_too_short_cnt;
u64 rx_start_bit_low_too_short_ts;
u32 rx_start_bit_low_too_short_delta;
u32 rx_start_bit_too_short_cnt;
u64 rx_start_bit_too_short_ts;
u32 rx_start_bit_too_short_delta;
u32 rx_start_bit_too_long_cnt;
u32 rx_data_bit_too_short_cnt;
u64 rx_data_bit_too_short_ts;
u32 rx_data_bit_too_short_delta;
u32 rx_data_bit_too_long_cnt;
u32 rx_low_drive_cnt;
struct cec_msg work_rx_msg;
u8 work_tx_status;
ktime_t work_tx_ts;
atomic_t work_irq_change;
atomic_t work_pin_events;
atomic_t work_pin_num_events;
unsigned int work_pin_events_wr;
unsigned int work_pin_events_rd;
ktime_t work_pin_ts[CEC_NUM_PIN_EVENTS];
bool work_pin_is_high[CEC_NUM_PIN_EVENTS];
u8 work_pin_events[CEC_NUM_PIN_EVENTS];
bool work_pin_events_dropped;
u32 work_pin_events_dropped_cnt;
ktime_t timer_ts;
u32 timer_cnt;
u32 timer_100ms_overruns;
u32 timer_300ms_overruns;
u32 timer_max_overrun;
u32 timer_sum_overrun;
u32 tx_custom_low_usecs;
u32 tx_custom_high_usecs;
bool tx_ignore_nack_until_eom;
bool tx_custom_pulse;
bool tx_generated_poll;
bool tx_post_eom;
u8 tx_extra_bytes;
u32 tx_low_drive_cnt;
#ifdef CONFIG_CEC_PIN_ERROR_INJ
u64 error_inj[CEC_ERROR_INJ_OP_ANY + 1];
u8 error_inj_args[CEC_ERROR_INJ_OP_ANY + 1][CEC_ERROR_INJ_NUM_ARGS];
#endif
};
void cec_pin_start_timer(struct cec_pin *pin);
#ifdef CONFIG_CEC_PIN_ERROR_INJ
bool cec_pin_error_inj_parse_line(struct cec_adapter *adap, char *line);
int cec_pin_error_inj_show(struct cec_adapter *adap, struct seq_file *sf);
u16 cec_pin_rx_error_inj(struct cec_pin *pin);
u16 cec_pin_tx_error_inj(struct cec_pin *pin);
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* cec-priv.h - HDMI Consumer Electronics Control internal header
*
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef _CEC_PRIV_H

View file

@ -631,7 +631,8 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
cb->p = buffer;
cb->offset_in_common = buffer - (u8 *) common_buffer;
cb->phys = common_buffer_phys + cb->offset_in_common;
if (common_buffer_phys)
cb->phys = common_buffer_phys + cb->offset_in_common;
return cb;
}
@ -690,17 +691,21 @@ int smscore_register_device(struct smsdevice_params_t *params,
/* alloc common buffer */
dev->common_buffer_size = params->buffer_size * params->num_buffers;
dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,
&dev->common_buffer_phys,
GFP_KERNEL | GFP_DMA);
if (!dev->common_buffer) {
if (params->usb_device)
buffer = kzalloc(dev->common_buffer_size, GFP_KERNEL);
else
buffer = dma_alloc_coherent(params->device,
dev->common_buffer_size,
&dev->common_buffer_phys,
GFP_KERNEL | GFP_DMA);
if (!buffer) {
smscore_unregister_device(dev);
return -ENOMEM;
}
dev->common_buffer = buffer;
/* prepare dma buffers */
for (buffer = dev->common_buffer;
dev->num_buffers < params->num_buffers;
for (; dev->num_buffers < params->num_buffers;
dev->num_buffers++, buffer += params->buffer_size) {
struct smscore_buffer_t *cb;
@ -720,6 +725,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
dev->board_id = SMS_BOARD_UNKNOWN;
dev->context = params->context;
dev->device = params->device;
dev->usb_device = params->usb_device;
dev->setmode_handler = params->setmode_handler;
dev->detectmode_handler = params->detectmode_handler;
dev->sendrequest_handler = params->sendrequest_handler;
@ -1231,10 +1237,15 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
pr_debug("freed %d buffers\n", num_buffers);
if (coredev->common_buffer)
dma_free_coherent(NULL, coredev->common_buffer_size,
coredev->common_buffer, coredev->common_buffer_phys);
if (coredev->common_buffer) {
if (coredev->usb_device)
kfree(coredev->common_buffer);
else
dma_free_coherent(coredev->device,
coredev->common_buffer_size,
coredev->common_buffer,
coredev->common_buffer_phys);
}
kfree(coredev->fw_buf);
list_del(&coredev->entry);

View file

@ -134,6 +134,7 @@ struct smscore_buffer_t {
struct smsdevice_params_t {
struct device *device;
struct usb_device *usb_device;
int buffer_size;
int num_buffers;
@ -176,6 +177,7 @@ struct smscore_device_t {
void *context;
struct device *device;
struct usb_device *usb_device;
char devpath[32];
unsigned long device_flags;

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* v4l2-tpg-colors.c - A table that converts colors to various colorspaces
*
@ -20,19 +21,6 @@
* in order to preserve precision.
*
* Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/videodev2.h>

View file

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* v4l2-tpg-core.c - Test Pattern Generator
*
@ -5,19 +6,6 @@
* vivi.c source for the copyright information of those functions.
*
* Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/module.h>
@ -1155,13 +1143,13 @@ static void gen_twopix(struct tpg_data *tpg,
case V4L2_PIX_FMT_NV24:
buf[0][offset] = r_y_h;
buf[1][2 * offset] = g_u_s;
buf[1][2 * offset + 1] = b_v;
buf[1][(2 * offset + 1) % 8] = b_v;
break;
case V4L2_PIX_FMT_NV42:
buf[0][offset] = r_y_h;
buf[1][2 * offset] = b_v;
buf[1][2 * offset + 1] = g_u_s;
buf[1][(2 * offset + 1) %8] = g_u_s;
break;
case V4L2_PIX_FMT_YUYV:

View file

@ -1696,6 +1696,15 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
for (i = 0; i < q->num_buffers; ++i) {
struct vb2_buffer *vb = q->bufs[i];
if (vb->state == VB2_BUF_STATE_PREPARED ||
vb->state == VB2_BUF_STATE_QUEUED) {
unsigned int plane;
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish,
vb->planes[plane].mem_priv);
}
if (vb->state != VB2_BUF_STATE_DEQUEUED) {
vb->state = VB2_BUF_STATE_PREPARED;
call_void_vb_qop(vb, buf_finish, vb);

View file

@ -106,7 +106,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr,
if (nums[i-1] + 1 != nums[i])
goto fail_map;
buf->vaddr = (__force void *)
ioremap_nocache(nums[0] << PAGE_SHIFT, size);
ioremap_nocache(__pfn_to_phys(nums[0]), size + offset);
} else {
buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1,
PAGE_KERNEL);

View file

@ -1254,8 +1254,8 @@ static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
ca->pub->slot_ts_enable(ca->pub, slot);
sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
dvb_ca_en50221_thread_update_delay(ca);
pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
ca->dvbdev->adapter->num);
pr_info("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
ca->dvbdev->adapter->num);
break;
case DVB_CA_SLOTSTATE_RUNNING:

View file

@ -2294,7 +2294,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
@ -2328,7 +2328,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);

View file

@ -24,6 +24,7 @@
#include <linux/string.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/device.h>
@ -941,6 +942,55 @@ out:
return err;
}
#if IS_ENABLED(CONFIG_I2C)
struct i2c_client *dvb_module_probe(const char *module_name,
const char *name,
struct i2c_adapter *adap,
unsigned char addr,
void *platform_data)
{
struct i2c_client *client;
struct i2c_board_info *board_info;
board_info = kzalloc(sizeof(*board_info), GFP_KERNEL);
if (!board_info)
return NULL;
if (name)
strlcpy(board_info->type, name, I2C_NAME_SIZE);
else
strlcpy(board_info->type, module_name, I2C_NAME_SIZE);
board_info->addr = addr;
board_info->platform_data = platform_data;
request_module(module_name);
client = i2c_new_device(adap, board_info);
if (client == NULL || client->dev.driver == NULL) {
kfree(board_info);
return NULL;
}
if (!try_module_get(client->dev.driver->owner)) {
i2c_unregister_device(client);
client = NULL;
}
kfree(board_info);
return client;
}
EXPORT_SYMBOL_GPL(dvb_module_probe);
void dvb_module_release(struct i2c_client *client)
{
if (!client)
return;
module_put(client->dev.driver->owner);
i2c_unregister_device(client);
}
EXPORT_SYMBOL_GPL(dvb_module_release);
#endif
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct dvb_device *dvbdev = dev_get_drvdata(dev);

View file

@ -462,7 +462,7 @@ config DVB_TDA10048
config DVB_AF9013
tristate "Afatech AF9013 demodulator"
depends on DVB_CORE && I2C
depends on DVB_CORE && I2C && I2C_MUX
select REGMAP
default m if !MEDIA_SUBDRV_AUTOSELECT
help
@ -546,6 +546,8 @@ config DVB_GP8PSK_FE
depends on DVB_CORE
default DVB_USB_GP8PSK
source "drivers/media/dvb-frontends/cxd2880/Kconfig"
comment "DVB-C (cable) frontends"
depends on DVB_CORE
@ -822,13 +824,6 @@ config DVB_A8293
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
config DVB_SP2
tristate "CIMaX SP2"
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
CIMaX SP2/SP2HF Common Interface module.
config DVB_LGS8GL5
tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
depends on DVB_CORE && I2C
@ -904,6 +899,27 @@ config DVB_HELENE
help
Say Y when you want to support this frontend.
comment "Common Interface (EN50221) controller drivers"
depends on DVB_CORE
config DVB_CXD2099
tristate "CXD2099AR Common Interface driver"
depends on DVB_CORE && I2C
select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
A driver for the CI controller currently found mostly on
Digital Devices DuoFlex CI (single) addon modules.
Say Y when you want to support these devices.
config DVB_SP2
tristate "CIMaX SP2"
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
CIMaX SP2/SP2HF Common Interface module.
comment "Tools to develop new frontends"
config DVB_DUMMY_FE

View file

@ -129,3 +129,5 @@ obj-$(CONFIG_DVB_HORUS3A) += horus3a.o
obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
obj-$(CONFIG_DVB_HELENE) += helene.o
obj-$(CONFIG_DVB_ZD1301_DEMOD) += zd1301_demod.o
obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
obj-$(CONFIG_DVB_CXD2880) += cxd2880/

File diff suppressed because it is too large Load diff

View file

@ -38,13 +38,9 @@
* @api_version: Firmware API version.
* @gpio: GPIOs.
* @get_dvb_frontend: Get DVB frontend callback.
*
* AF9013/5 GPIOs (mostly guessed):
* * demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
* * demod#1-gpio#1 - xtal setting (?)
* * demod#1-gpio#3 - tuner#1
* * demod#2-gpio#0 - tuner#2
* * demod#2-gpio#1 - xtal setting (?)
* @get_i2c_adapter: Get I2C adapter.
* @pid_filter_ctrl: Control PID filter.
* @pid_filter: Set PID to PID filter.
*/
struct af9013_platform_data {
/*
@ -84,36 +80,18 @@ struct af9013_platform_data {
u8 gpio[4];
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *);
/* private: For legacy media attach wrapper. Do not set value. */
bool attach_in_use;
u8 i2c_addr;
u32 clock;
struct i2c_adapter* (*get_i2c_adapter)(struct i2c_client *);
int (*pid_filter_ctrl)(struct dvb_frontend *, int);
int (*pid_filter)(struct dvb_frontend *, u8, u16, int);
};
#define af9013_config af9013_platform_data
#define AF9013_TS_USB AF9013_TS_MODE_USB
#define AF9013_TS_PARALLEL AF9013_TS_MODE_PARALLEL
#define AF9013_TS_SERIAL AF9013_TS_MODE_SERIAL
#if IS_REACHABLE(CONFIG_DVB_AF9013)
/**
* Attach an af9013 demod
*
* @config: pointer to &struct af9013_config with demod configuration.
* @i2c: i2c adapter to use.
*
* return: FE pointer on success, NULL on failure.
/*
* AF9013/5 GPIOs (mostly guessed)
* demod#1-gpio#0 - set demod#2 i2c-addr for dual devices
* demod#1-gpio#1 - xtal setting (?)
* demod#1-gpio#3 - tuner#1
* demod#2-gpio#0 - tuner#2
* demod#2-gpio#1 - xtal setting (?)
*/
extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
struct i2c_adapter *i2c);
#else
static inline struct dvb_frontend *af9013_attach(
const struct af9013_config *config, struct i2c_adapter *i2c)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_AF9013 */
#endif /* AF9013_H */

File diff suppressed because it is too large Load diff

View file

@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/mutex.h>
@ -33,8 +34,9 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount);
struct cxd {
struct dvb_ca_en50221 en;
struct i2c_adapter *i2c;
struct cxd2099_cfg cfg;
struct i2c_client *client;
struct regmap *regmap;
u8 regs[0x23];
u8 lastaddress;
@ -56,69 +58,12 @@ struct cxd {
u8 wbuf[1028];
};
static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 data)
{
u8 m[2] = {reg, data};
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
if (i2c_transfer(adapter, &msg, 1) != 1) {
dev_err(&adapter->dev,
"Failed to write to I2C register %02x@%02x!\n",
reg, adr);
return -1;
}
return 0;
}
static int i2c_write(struct i2c_adapter *adapter, u8 adr,
u8 *data, u16 len)
{
struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
if (i2c_transfer(adapter, &msg, 1) != 1) {
dev_err(&adapter->dev, "Failed to write to I2C!\n");
return -1;
}
return 0;
}
static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 *val)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = val, .len = 1} };
if (i2c_transfer(adapter, msgs, 2) != 2) {
dev_err(&adapter->dev, "error in %s()\n", __func__);
return -1;
}
return 0;
}
static int i2c_read(struct i2c_adapter *adapter, u8 adr,
u8 reg, u8 *data, u16 n)
{
struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
.buf = &reg, .len = 1},
{.addr = adr, .flags = I2C_M_RD,
.buf = data, .len = n} };
if (i2c_transfer(adapter, msgs, 2) != 2) {
dev_err(&adapter->dev, "error in %s()\n", __func__);
return -1;
}
return 0;
}
static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
{
int status = 0;
if (ci->lastaddress != adr)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
status = regmap_write(ci->regmap, 0, adr);
if (!status) {
ci->lastaddress = adr;
@ -127,7 +72,7 @@ static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
if (ci->cfg.max_i2c && len > ci->cfg.max_i2c)
len = ci->cfg.max_i2c;
status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len);
status = regmap_raw_read(ci->regmap, 1, data, len);
if (status)
return status;
data += len;
@ -145,64 +90,66 @@ static int read_reg(struct cxd *ci, u8 reg, u8 *val)
static int read_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
u8 addr[2] = {address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
status = regmap_raw_write(ci->regmap, 2, addr, 2);
if (!status)
status = i2c_read(ci->i2c, ci->cfg.adr, 3, data, n);
status = regmap_raw_read(ci->regmap, 3, data, n);
return status;
}
static int write_pccard(struct cxd *ci, u16 address, u8 *data, u8 n)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
u8 addr[2] = {address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
status = regmap_raw_write(ci->regmap, 2, addr, 2);
if (!status) {
u8 buf[256] = {3};
u8 buf[256];
memcpy(buf + 1, data, n);
status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1);
memcpy(buf, data, n);
status = regmap_raw_write(ci->regmap, 3, buf, n);
}
return status;
}
static int read_io(struct cxd *ci, u16 address, u8 *val)
static int read_io(struct cxd *ci, u16 address, unsigned int *val)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
u8 addr[2] = {address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
status = regmap_raw_write(ci->regmap, 2, addr, 2);
if (!status)
status = i2c_read(ci->i2c, ci->cfg.adr, 3, val, 1);
status = regmap_read(ci->regmap, 3, val);
return status;
}
static int write_io(struct cxd *ci, u16 address, u8 val)
{
int status;
u8 addr[3] = {2, address & 0xff, address >> 8};
u8 buf[2] = {3, val};
u8 addr[2] = {address & 0xff, address >> 8};
status = i2c_write(ci->i2c, ci->cfg.adr, addr, 3);
status = regmap_raw_write(ci->regmap, 2, addr, 2);
if (!status)
status = i2c_write(ci->i2c, ci->cfg.adr, buf, 2);
status = regmap_write(ci->regmap, 3, val);
return status;
}
static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask)
{
int status = 0;
unsigned int regval;
if (ci->lastaddress != reg)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg);
if (!status && reg >= 6 && reg <= 8 && mask != 0xff)
status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]);
status = regmap_write(ci->regmap, 0, reg);
if (!status && reg >= 6 && reg <= 8 && mask != 0xff) {
status = regmap_read(ci->regmap, 1, &regval);
ci->regs[reg] = regval;
}
ci->lastaddress = reg;
ci->regs[reg] = (ci->regs[reg] & (~mask)) | val;
if (!status)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]);
status = regmap_write(ci->regmap, 1, ci->regs[reg]);
if (reg == 0x20)
ci->regs[reg] &= 0x7f;
return status;
@ -219,19 +166,18 @@ static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n)
u8 *buf = ci->wbuf;
if (ci->lastaddress != adr)
status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
status = regmap_write(ci->regmap, 0, adr);
if (status)
return status;
ci->lastaddress = adr;
buf[0] = 1;
while (n) {
int len = n;
if (ci->cfg.max_i2c && (len + 1 > ci->cfg.max_i2c))
len = ci->cfg.max_i2c - 1;
memcpy(buf + 1, data, len);
status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1);
memcpy(buf, data, len);
status = regmap_raw_write(ci->regmap, 1, buf, len);
if (status)
return status;
n -= len;
@ -273,7 +219,7 @@ static void cam_mode(struct cxd *ci, int mode)
if (!ci->en.read_data)
return;
ci->write_busy = 0;
dev_info(&ci->i2c->dev, "enable cam buffer mode\n");
dev_info(&ci->client->dev, "enable cam buffer mode\n");
write_reg(ci, 0x0d, 0x00);
write_reg(ci, 0x0e, 0x01);
write_regm(ci, 0x08, 0x40, 0x40);
@ -464,7 +410,7 @@ static int read_cam_control(struct dvb_ca_en50221 *ca,
int slot, u8 address)
{
struct cxd *ci = ca->data;
u8 val;
unsigned int val;
mutex_lock(&ci->lock);
set_mode(ci, 0);
@ -518,7 +464,7 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
{
struct cxd *ci = ca->data;
dev_dbg(&ci->i2c->dev, "%s\n", __func__);
dev_dbg(&ci->client->dev, "%s\n", __func__);
if (ci->cammode)
read_data(ca, slot, ci->rbuf, 0);
mutex_lock(&ci->lock);
@ -577,7 +523,7 @@ static int campoll(struct cxd *ci)
if (ci->slot_stat) {
ci->slot_stat = 0;
write_regm(ci, 0x03, 0x00, 0x08);
dev_info(&ci->i2c->dev, "NO CAM\n");
dev_info(&ci->client->dev, "NO CAM\n");
ci->ready = 0;
}
}
@ -660,26 +606,41 @@ static struct dvb_ca_en50221 en_templ = {
.write_data = write_data,
};
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
void *priv,
struct i2c_adapter *i2c)
static int cxd2099_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct cxd *ci;
u8 val;
if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
dev_info(&i2c->dev, "No CXD2099AR detected at 0x%02x\n",
cfg->adr);
return NULL;
}
struct cxd2099_cfg *cfg = client->dev.platform_data;
static const struct regmap_config rm_cfg = {
.reg_bits = 8,
.val_bits = 8,
};
unsigned int val;
int ret;
ci = kzalloc(sizeof(*ci), GFP_KERNEL);
if (!ci)
return NULL;
if (!ci) {
ret = -ENOMEM;
goto err;
}
ci->client = client;
memcpy(&ci->cfg, cfg, sizeof(ci->cfg));
ci->regmap = regmap_init_i2c(client, &rm_cfg);
if (IS_ERR(ci->regmap)) {
ret = PTR_ERR(ci->regmap);
goto err_kfree;
}
ret = regmap_read(ci->regmap, 0x00, &val);
if (ret < 0) {
dev_info(&client->dev, "No CXD2099AR detected at 0x%02x\n",
client->addr);
goto err_rmexit;
}
mutex_init(&ci->lock);
ci->cfg = *cfg;
ci->i2c = i2c;
ci->lastaddress = 0xff;
ci->clk_reg_b = 0x4a;
ci->clk_reg_f = 0x1b;
@ -687,18 +648,56 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
ci->en = en_templ;
ci->en.data = ci;
init(ci);
dev_info(&i2c->dev, "Attached CXD2099AR at 0x%02x\n", ci->cfg.adr);
dev_info(&client->dev, "Attached CXD2099AR at 0x%02x\n", client->addr);
*cfg->en = &ci->en;
if (!buffermode) {
ci->en.read_data = NULL;
ci->en.write_data = NULL;
} else {
dev_info(&i2c->dev, "Using CXD2099AR buffer mode");
dev_info(&client->dev, "Using CXD2099AR buffer mode");
}
return &ci->en;
i2c_set_clientdata(client, ci);
return 0;
err_rmexit:
regmap_exit(ci->regmap);
err_kfree:
kfree(ci);
err:
return ret;
}
EXPORT_SYMBOL(cxd2099_attach);
static int cxd2099_remove(struct i2c_client *client)
{
struct cxd *ci = i2c_get_clientdata(client);
regmap_exit(ci->regmap);
kfree(ci);
return 0;
}
static const struct i2c_device_id cxd2099_id[] = {
{"cxd2099", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, cxd2099_id);
static struct i2c_driver cxd2099_driver = {
.driver = {
.name = "cxd2099",
},
.probe = cxd2099_probe,
.remove = cxd2099_remove,
.id_table = cxd2099_id,
};
module_i2c_driver(cxd2099_driver);
MODULE_DESCRIPTION("CXD2099AR Common Interface controller driver");
MODULE_AUTHOR("Ralph Metzler");

View file

@ -20,26 +20,13 @@
struct cxd2099_cfg {
u32 bitrate;
u8 adr;
u8 polarity;
u8 clock_mode;
u32 max_i2c;
/* ptr to DVB CA struct */
struct dvb_ca_en50221 **en;
};
#if defined(CONFIG_DVB_CXD2099) || \
(defined(CONFIG_DVB_CXD2099_MODULE) && defined(MODULE))
struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
void *priv, struct i2c_adapter *i2c);
#else
static inline struct
dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg, void *priv,
struct i2c_adapter *i2c)
{
dev_warn(&i2c->dev, "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif
#endif

View file

@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
config DVB_CXD2880
tristate "Sony CXD2880 DVB-T2/T tuner + demodulator"
depends on DVB_CORE && SPI
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Say Y when you want to support this frontend.

View file

@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0
cxd2880-objs := cxd2880_common.o \
cxd2880_devio_spi.o \
cxd2880_integ.o \
cxd2880_io.o \
cxd2880_spi_device.o \
cxd2880_tnrdmd.o \
cxd2880_tnrdmd_dvbt2.o \
cxd2880_tnrdmd_dvbt2_mon.o \
cxd2880_tnrdmd_dvbt.o \
cxd2880_tnrdmd_dvbt_mon.o\
cxd2880_tnrdmd_mon.o\
cxd2880_top.o
obj-$(CONFIG_DVB_CXD2880) += cxd2880.o
ccflags-y += -Idrivers/media/dvb-frontends

View file

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver public definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_H
#define CXD2880_H
struct cxd2880_config {
struct spi_device *spi;
struct mutex *spi_mutex; /* For SPI access exclusive control */
};
#if IS_REACHABLE(CONFIG_DVB_CXD2880)
extern struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe,
struct cxd2880_config *cfg);
#else
static inline struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe,
struct cxd2880_config *cfg)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_CXD2880 */
#endif /* CXD2880_H */

View file

@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_common.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_common.h"
int cxd2880_convert2s_complement(u32 value, u32 bitlen)
{
if (!bitlen || bitlen >= 32)
return (int)value;
if (value & (u32)(1 << (bitlen - 1)))
return (int)(GENMASK(31, bitlen) | value);
else
return (int)(GENMASK(bitlen - 1, 0) & value);
}

View file

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_common.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver common definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_COMMON_H
#define CXD2880_COMMON_H
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/string.h>
int cxd2880_convert2s_complement(u32 value, u32 bitlen);
#endif

View file

@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_devio_spi.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* I/O interface via SPI
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_devio_spi.h"
#define BURST_WRITE_MAX 128
static int cxd2880_io_spi_read_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 *data,
u32 size)
{
int ret = 0;
struct cxd2880_spi *spi = NULL;
u8 send_data[6];
u8 *read_data_top = data;
if (!io || !io->if_object || !data)
return -EINVAL;
if (sub_address + size > 0x100)
return -EINVAL;
spi = io->if_object;
if (tgt == CXD2880_IO_TGT_SYS)
send_data[0] = 0x0b;
else
send_data[0] = 0x0a;
send_data[3] = 0;
send_data[4] = 0;
send_data[5] = 0;
while (size > 0) {
send_data[1] = sub_address;
if (size > 255)
send_data[2] = 255;
else
send_data[2] = size;
ret =
spi->write_read(spi, send_data, sizeof(send_data),
read_data_top, send_data[2]);
if (ret)
return ret;
sub_address += send_data[2];
read_data_top += send_data[2];
size -= send_data[2];
}
return ret;
}
static int cxd2880_io_spi_write_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address,
const u8 *data, u32 size)
{
int ret = 0;
struct cxd2880_spi *spi = NULL;
u8 send_data[BURST_WRITE_MAX + 4];
const u8 *write_data_top = data;
if (!io || !io->if_object || !data)
return -EINVAL;
if (size > BURST_WRITE_MAX)
return -EINVAL;
if (sub_address + size > 0x100)
return -EINVAL;
spi = io->if_object;
if (tgt == CXD2880_IO_TGT_SYS)
send_data[0] = 0x0f;
else
send_data[0] = 0x0e;
while (size > 0) {
send_data[1] = sub_address;
if (size > 255)
send_data[2] = 255;
else
send_data[2] = size;
memcpy(&send_data[3], write_data_top, send_data[2]);
if (tgt == CXD2880_IO_TGT_SYS) {
send_data[3 + send_data[2]] = 0x00;
ret = spi->write(spi, send_data, send_data[2] + 4);
} else {
ret = spi->write(spi, send_data, send_data[2] + 3);
}
if (ret)
return ret;
sub_address += send_data[2];
write_data_top += send_data[2];
size -= send_data[2];
}
return ret;
}
int cxd2880_io_spi_create(struct cxd2880_io *io,
struct cxd2880_spi *spi, u8 slave_select)
{
if (!io || !spi)
return -EINVAL;
io->read_regs = cxd2880_io_spi_read_reg;
io->write_regs = cxd2880_io_spi_write_reg;
io->write_reg = cxd2880_io_common_write_one_reg;
io->if_object = spi;
io->i2c_address_sys = 0;
io->i2c_address_demod = 0;
io->slave_select = slave_select;
return 0;
}

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_devio_spi.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* I/O interface via SPI
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DEVIO_SPI_H
#define CXD2880_DEVIO_SPI_H
#include "cxd2880_common.h"
#include "cxd2880_io.h"
#include "cxd2880_spi.h"
#include "cxd2880_tnrdmd.h"
int cxd2880_io_spi_create(struct cxd2880_io *io,
struct cxd2880_spi *spi,
u8 slave_select);
#endif

View file

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dtv.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DTV related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DTV_H
#define CXD2880_DTV_H
enum cxd2880_dtv_sys {
CXD2880_DTV_SYS_UNKNOWN,
CXD2880_DTV_SYS_DVBT,
CXD2880_DTV_SYS_DVBT2,
CXD2880_DTV_SYS_ANY
};
enum cxd2880_dtv_bandwidth {
CXD2880_DTV_BW_UNKNOWN = 0,
CXD2880_DTV_BW_1_7_MHZ = 1,
CXD2880_DTV_BW_5_MHZ = 5,
CXD2880_DTV_BW_6_MHZ = 6,
CXD2880_DTV_BW_7_MHZ = 7,
CXD2880_DTV_BW_8_MHZ = 8
};
#endif

View file

@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dvbt.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DVBT_H
#define CXD2880_DVBT_H
#include "cxd2880_common.h"
enum cxd2880_dvbt_constellation {
CXD2880_DVBT_CONSTELLATION_QPSK,
CXD2880_DVBT_CONSTELLATION_16QAM,
CXD2880_DVBT_CONSTELLATION_64QAM,
CXD2880_DVBT_CONSTELLATION_RESERVED_3
};
enum cxd2880_dvbt_hierarchy {
CXD2880_DVBT_HIERARCHY_NON,
CXD2880_DVBT_HIERARCHY_1,
CXD2880_DVBT_HIERARCHY_2,
CXD2880_DVBT_HIERARCHY_4
};
enum cxd2880_dvbt_coderate {
CXD2880_DVBT_CODERATE_1_2,
CXD2880_DVBT_CODERATE_2_3,
CXD2880_DVBT_CODERATE_3_4,
CXD2880_DVBT_CODERATE_5_6,
CXD2880_DVBT_CODERATE_7_8,
CXD2880_DVBT_CODERATE_RESERVED_5,
CXD2880_DVBT_CODERATE_RESERVED_6,
CXD2880_DVBT_CODERATE_RESERVED_7
};
enum cxd2880_dvbt_guard {
CXD2880_DVBT_GUARD_1_32,
CXD2880_DVBT_GUARD_1_16,
CXD2880_DVBT_GUARD_1_8,
CXD2880_DVBT_GUARD_1_4
};
enum cxd2880_dvbt_mode {
CXD2880_DVBT_MODE_2K,
CXD2880_DVBT_MODE_8K,
CXD2880_DVBT_MODE_RESERVED_2,
CXD2880_DVBT_MODE_RESERVED_3
};
enum cxd2880_dvbt_profile {
CXD2880_DVBT_PROFILE_HP = 0,
CXD2880_DVBT_PROFILE_LP
};
struct cxd2880_dvbt_tpsinfo {
enum cxd2880_dvbt_constellation constellation;
enum cxd2880_dvbt_hierarchy hierarchy;
enum cxd2880_dvbt_coderate rate_hp;
enum cxd2880_dvbt_coderate rate_lp;
enum cxd2880_dvbt_guard guard;
enum cxd2880_dvbt_mode mode;
u8 fnum;
u8 length_indicator;
u16 cell_id;
u8 cell_id_ok;
u8 reserved_even;
u8 reserved_odd;
};
#endif

View file

@ -0,0 +1,385 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dvbt2.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T2 related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DVBT2_H
#define CXD2880_DVBT2_H
#include "cxd2880_common.h"
enum cxd2880_dvbt2_profile {
CXD2880_DVBT2_PROFILE_BASE,
CXD2880_DVBT2_PROFILE_LITE,
CXD2880_DVBT2_PROFILE_ANY
};
enum cxd2880_dvbt2_version {
CXD2880_DVBT2_V111,
CXD2880_DVBT2_V121,
CXD2880_DVBT2_V131
};
enum cxd2880_dvbt2_s1 {
CXD2880_DVBT2_S1_BASE_SISO = 0x00,
CXD2880_DVBT2_S1_BASE_MISO = 0x01,
CXD2880_DVBT2_S1_NON_DVBT2 = 0x02,
CXD2880_DVBT2_S1_LITE_SISO = 0x03,
CXD2880_DVBT2_S1_LITE_MISO = 0x04,
CXD2880_DVBT2_S1_RSVD3 = 0x05,
CXD2880_DVBT2_S1_RSVD4 = 0x06,
CXD2880_DVBT2_S1_RSVD5 = 0x07,
CXD2880_DVBT2_S1_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_base_s2 {
CXD2880_DVBT2_BASE_S2_M2K_G_ANY = 0x00,
CXD2880_DVBT2_BASE_S2_M8K_G_DVBT = 0x01,
CXD2880_DVBT2_BASE_S2_M4K_G_ANY = 0x02,
CXD2880_DVBT2_BASE_S2_M1K_G_ANY = 0x03,
CXD2880_DVBT2_BASE_S2_M16K_G_ANY = 0x04,
CXD2880_DVBT2_BASE_S2_M32K_G_DVBT = 0x05,
CXD2880_DVBT2_BASE_S2_M8K_G_DVBT2 = 0x06,
CXD2880_DVBT2_BASE_S2_M32K_G_DVBT2 = 0x07,
CXD2880_DVBT2_BASE_S2_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_lite_s2 {
CXD2880_DVBT2_LITE_S2_M2K_G_ANY = 0x00,
CXD2880_DVBT2_LITE_S2_M8K_G_DVBT = 0x01,
CXD2880_DVBT2_LITE_S2_M4K_G_ANY = 0x02,
CXD2880_DVBT2_LITE_S2_M16K_G_DVBT2 = 0x03,
CXD2880_DVBT2_LITE_S2_M16K_G_DVBT = 0x04,
CXD2880_DVBT2_LITE_S2_RSVD1 = 0x05,
CXD2880_DVBT2_LITE_S2_M8K_G_DVBT2 = 0x06,
CXD2880_DVBT2_LITE_S2_RSVD2 = 0x07,
CXD2880_DVBT2_LITE_S2_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_guard {
CXD2880_DVBT2_G1_32 = 0x00,
CXD2880_DVBT2_G1_16 = 0x01,
CXD2880_DVBT2_G1_8 = 0x02,
CXD2880_DVBT2_G1_4 = 0x03,
CXD2880_DVBT2_G1_128 = 0x04,
CXD2880_DVBT2_G19_128 = 0x05,
CXD2880_DVBT2_G19_256 = 0x06,
CXD2880_DVBT2_G_RSVD1 = 0x07,
CXD2880_DVBT2_G_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_mode {
CXD2880_DVBT2_M2K = 0x00,
CXD2880_DVBT2_M8K = 0x01,
CXD2880_DVBT2_M4K = 0x02,
CXD2880_DVBT2_M1K = 0x03,
CXD2880_DVBT2_M16K = 0x04,
CXD2880_DVBT2_M32K = 0x05,
CXD2880_DVBT2_M_RSVD1 = 0x06,
CXD2880_DVBT2_M_RSVD2 = 0x07
};
enum cxd2880_dvbt2_bw {
CXD2880_DVBT2_BW_8 = 0x00,
CXD2880_DVBT2_BW_7 = 0x01,
CXD2880_DVBT2_BW_6 = 0x02,
CXD2880_DVBT2_BW_5 = 0x03,
CXD2880_DVBT2_BW_10 = 0x04,
CXD2880_DVBT2_BW_1_7 = 0x05,
CXD2880_DVBT2_BW_RSVD1 = 0x06,
CXD2880_DVBT2_BW_RSVD2 = 0x07,
CXD2880_DVBT2_BW_RSVD3 = 0x08,
CXD2880_DVBT2_BW_RSVD4 = 0x09,
CXD2880_DVBT2_BW_RSVD5 = 0x0a,
CXD2880_DVBT2_BW_RSVD6 = 0x0b,
CXD2880_DVBT2_BW_RSVD7 = 0x0c,
CXD2880_DVBT2_BW_RSVD8 = 0x0d,
CXD2880_DVBT2_BW_RSVD9 = 0x0e,
CXD2880_DVBT2_BW_RSVD10 = 0x0f,
CXD2880_DVBT2_BW_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1pre_type {
CXD2880_DVBT2_L1PRE_TYPE_TS = 0x00,
CXD2880_DVBT2_L1PRE_TYPE_GS = 0x01,
CXD2880_DVBT2_L1PRE_TYPE_TS_GS = 0x02,
CXD2880_DVBT2_L1PRE_TYPE_RESERVED = 0x03,
CXD2880_DVBT2_L1PRE_TYPE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_papr {
CXD2880_DVBT2_PAPR_0 = 0x00,
CXD2880_DVBT2_PAPR_1 = 0x01,
CXD2880_DVBT2_PAPR_2 = 0x02,
CXD2880_DVBT2_PAPR_3 = 0x03,
CXD2880_DVBT2_PAPR_RSVD1 = 0x04,
CXD2880_DVBT2_PAPR_RSVD2 = 0x05,
CXD2880_DVBT2_PAPR_RSVD3 = 0x06,
CXD2880_DVBT2_PAPR_RSVD4 = 0x07,
CXD2880_DVBT2_PAPR_RSVD5 = 0x08,
CXD2880_DVBT2_PAPR_RSVD6 = 0x09,
CXD2880_DVBT2_PAPR_RSVD7 = 0x0a,
CXD2880_DVBT2_PAPR_RSVD8 = 0x0b,
CXD2880_DVBT2_PAPR_RSVD9 = 0x0c,
CXD2880_DVBT2_PAPR_RSVD10 = 0x0d,
CXD2880_DVBT2_PAPR_RSVD11 = 0x0e,
CXD2880_DVBT2_PAPR_RSVD12 = 0x0f,
CXD2880_DVBT2_PAPR_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_constell {
CXD2880_DVBT2_L1POST_BPSK = 0x00,
CXD2880_DVBT2_L1POST_QPSK = 0x01,
CXD2880_DVBT2_L1POST_QAM16 = 0x02,
CXD2880_DVBT2_L1POST_QAM64 = 0x03,
CXD2880_DVBT2_L1POST_C_RSVD1 = 0x04,
CXD2880_DVBT2_L1POST_C_RSVD2 = 0x05,
CXD2880_DVBT2_L1POST_C_RSVD3 = 0x06,
CXD2880_DVBT2_L1POST_C_RSVD4 = 0x07,
CXD2880_DVBT2_L1POST_C_RSVD5 = 0x08,
CXD2880_DVBT2_L1POST_C_RSVD6 = 0x09,
CXD2880_DVBT2_L1POST_C_RSVD7 = 0x0a,
CXD2880_DVBT2_L1POST_C_RSVD8 = 0x0b,
CXD2880_DVBT2_L1POST_C_RSVD9 = 0x0c,
CXD2880_DVBT2_L1POST_C_RSVD10 = 0x0d,
CXD2880_DVBT2_L1POST_C_RSVD11 = 0x0e,
CXD2880_DVBT2_L1POST_C_RSVD12 = 0x0f,
CXD2880_DVBT2_L1POST_CONSTELL_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_cr {
CXD2880_DVBT2_L1POST_R1_2 = 0x00,
CXD2880_DVBT2_L1POST_R_RSVD1 = 0x01,
CXD2880_DVBT2_L1POST_R_RSVD2 = 0x02,
CXD2880_DVBT2_L1POST_R_RSVD3 = 0x03,
CXD2880_DVBT2_L1POST_R_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_fec_type {
CXD2880_DVBT2_L1POST_FEC_LDPC16K = 0x00,
CXD2880_DVBT2_L1POST_FEC_RSVD1 = 0x01,
CXD2880_DVBT2_L1POST_FEC_RSVD2 = 0x02,
CXD2880_DVBT2_L1POST_FEC_RSVD3 = 0x03,
CXD2880_DVBT2_L1POST_FEC_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_pp {
CXD2880_DVBT2_PP1 = 0x00,
CXD2880_DVBT2_PP2 = 0x01,
CXD2880_DVBT2_PP3 = 0x02,
CXD2880_DVBT2_PP4 = 0x03,
CXD2880_DVBT2_PP5 = 0x04,
CXD2880_DVBT2_PP6 = 0x05,
CXD2880_DVBT2_PP7 = 0x06,
CXD2880_DVBT2_PP8 = 0x07,
CXD2880_DVBT2_PP_RSVD1 = 0x08,
CXD2880_DVBT2_PP_RSVD2 = 0x09,
CXD2880_DVBT2_PP_RSVD3 = 0x0a,
CXD2880_DVBT2_PP_RSVD4 = 0x0b,
CXD2880_DVBT2_PP_RSVD5 = 0x0c,
CXD2880_DVBT2_PP_RSVD6 = 0x0d,
CXD2880_DVBT2_PP_RSVD7 = 0x0e,
CXD2880_DVBT2_PP_RSVD8 = 0x0f,
CXD2880_DVBT2_PP_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_code_rate {
CXD2880_DVBT2_R1_2 = 0x00,
CXD2880_DVBT2_R3_5 = 0x01,
CXD2880_DVBT2_R2_3 = 0x02,
CXD2880_DVBT2_R3_4 = 0x03,
CXD2880_DVBT2_R4_5 = 0x04,
CXD2880_DVBT2_R5_6 = 0x05,
CXD2880_DVBT2_R1_3 = 0x06,
CXD2880_DVBT2_R2_5 = 0x07,
CXD2880_DVBT2_PLP_CR_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_constell {
CXD2880_DVBT2_QPSK = 0x00,
CXD2880_DVBT2_QAM16 = 0x01,
CXD2880_DVBT2_QAM64 = 0x02,
CXD2880_DVBT2_QAM256 = 0x03,
CXD2880_DVBT2_CON_RSVD1 = 0x04,
CXD2880_DVBT2_CON_RSVD2 = 0x05,
CXD2880_DVBT2_CON_RSVD3 = 0x06,
CXD2880_DVBT2_CON_RSVD4 = 0x07,
CXD2880_DVBT2_CONSTELL_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_type {
CXD2880_DVBT2_PLP_TYPE_COMMON = 0x00,
CXD2880_DVBT2_PLP_TYPE_DATA1 = 0x01,
CXD2880_DVBT2_PLP_TYPE_DATA2 = 0x02,
CXD2880_DVBT2_PLP_TYPE_RSVD1 = 0x03,
CXD2880_DVBT2_PLP_TYPE_RSVD2 = 0x04,
CXD2880_DVBT2_PLP_TYPE_RSVD3 = 0x05,
CXD2880_DVBT2_PLP_TYPE_RSVD4 = 0x06,
CXD2880_DVBT2_PLP_TYPE_RSVD5 = 0x07,
CXD2880_DVBT2_PLP_TYPE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_payload {
CXD2880_DVBT2_PLP_PAYLOAD_GFPS = 0x00,
CXD2880_DVBT2_PLP_PAYLOAD_GCS = 0x01,
CXD2880_DVBT2_PLP_PAYLOAD_GSE = 0x02,
CXD2880_DVBT2_PLP_PAYLOAD_TS = 0x03,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD1 = 0x04,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD2 = 0x05,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD3 = 0x06,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD4 = 0x07,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD5 = 0x08,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD6 = 0x09,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD7 = 0x0a,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD8 = 0x0b,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD9 = 0x0c,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD10 = 0x0d,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD11 = 0x0e,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD12 = 0x0f,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD13 = 0x10,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD14 = 0x11,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD15 = 0x12,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD16 = 0x13,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD17 = 0x14,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD18 = 0x15,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD19 = 0x16,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD20 = 0x17,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD21 = 0x18,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD22 = 0x19,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD23 = 0x1a,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD24 = 0x1b,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD25 = 0x1c,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD26 = 0x1d,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD27 = 0x1e,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD28 = 0x1f,
CXD2880_DVBT2_PLP_PAYLOAD_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_fec {
CXD2880_DVBT2_FEC_LDPC_16K = 0x00,
CXD2880_DVBT2_FEC_LDPC_64K = 0x01,
CXD2880_DVBT2_FEC_RSVD1 = 0x02,
CXD2880_DVBT2_FEC_RSVD2 = 0x03,
CXD2880_DVBT2_FEC_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_mode {
CXD2880_DVBT2_PLP_MODE_NOTSPECIFIED = 0x00,
CXD2880_DVBT2_PLP_MODE_NM = 0x01,
CXD2880_DVBT2_PLP_MODE_HEM = 0x02,
CXD2880_DVBT2_PLP_MODE_RESERVED = 0x03,
CXD2880_DVBT2_PLP_MODE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_btype {
CXD2880_DVBT2_PLP_COMMON,
CXD2880_DVBT2_PLP_DATA
};
enum cxd2880_dvbt2_stream {
CXD2880_DVBT2_STREAM_GENERIC_PACKETIZED = 0x00,
CXD2880_DVBT2_STREAM_GENERIC_CONTINUOUS = 0x01,
CXD2880_DVBT2_STREAM_GENERIC_ENCAPSULATED = 0x02,
CXD2880_DVBT2_STREAM_TRANSPORT = 0x03,
CXD2880_DVBT2_STREAM_UNKNOWN = 0xff
};
struct cxd2880_dvbt2_l1pre {
enum cxd2880_dvbt2_l1pre_type type;
u8 bw_ext;
enum cxd2880_dvbt2_s1 s1;
u8 s2;
u8 mixed;
enum cxd2880_dvbt2_mode fft_mode;
u8 l1_rep;
enum cxd2880_dvbt2_guard gi;
enum cxd2880_dvbt2_papr papr;
enum cxd2880_dvbt2_l1post_constell mod;
enum cxd2880_dvbt2_l1post_cr cr;
enum cxd2880_dvbt2_l1post_fec_type fec;
u32 l1_post_size;
u32 l1_post_info_size;
enum cxd2880_dvbt2_pp pp;
u8 tx_id_availability;
u16 cell_id;
u16 network_id;
u16 sys_id;
u8 num_frames;
u16 num_symbols;
u8 regen;
u8 post_ext;
u8 num_rf_freqs;
u8 rf_idx;
enum cxd2880_dvbt2_version t2_version;
u8 l1_post_scrambled;
u8 t2_base_lite;
u32 crc32;
};
struct cxd2880_dvbt2_plp {
u8 id;
enum cxd2880_dvbt2_plp_type type;
enum cxd2880_dvbt2_plp_payload payload;
u8 ff;
u8 first_rf_idx;
u8 first_frm_idx;
u8 group_id;
enum cxd2880_dvbt2_plp_constell constell;
enum cxd2880_dvbt2_plp_code_rate plp_cr;
u8 rot;
enum cxd2880_dvbt2_plp_fec fec;
u16 num_blocks_max;
u8 frm_int;
u8 til_len;
u8 til_type;
u8 in_band_a_flag;
u8 in_band_b_flag;
u16 rsvd;
enum cxd2880_dvbt2_plp_mode plp_mode;
u8 static_flag;
u8 static_padding_flag;
};
struct cxd2880_dvbt2_l1post {
u16 sub_slices_per_frame;
u8 num_plps;
u8 num_aux;
u8 aux_cfg_rfu;
u8 rf_idx;
u32 freq;
u8 fef_type;
u32 fef_length;
u8 fef_intvl;
};
struct cxd2880_dvbt2_ofdm {
u8 mixed;
u8 is_miso;
enum cxd2880_dvbt2_mode mode;
enum cxd2880_dvbt2_guard gi;
enum cxd2880_dvbt2_pp pp;
u8 bw_ext;
enum cxd2880_dvbt2_papr papr;
u16 num_symbols;
};
struct cxd2880_dvbt2_bbheader {
enum cxd2880_dvbt2_stream stream_input;
u8 is_single_input_stream;
u8 is_constant_coding_modulation;
u8 issy_indicator;
u8 null_packet_deletion;
u8 ext;
u8 input_stream_identifier;
u16 user_packet_length;
u16 data_field_length;
u8 sync_byte;
u32 issy;
enum cxd2880_dvbt2_plp_mode plp_mode;
};
#endif

View file

@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_integ.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* integration layer common functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <linux/ktime.h>
#include <linux/errno.h>
#include "cxd2880_tnrdmd.h"
#include "cxd2880_tnrdmd_mon.h"
#include "cxd2880_integ.h"
int cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd)
{
int ret;
ktime_t start;
u8 cpu_task_completed = 0;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_tnrdmd_init1(tnr_dmd);
if (ret)
return ret;
start = ktime_get();
while (1) {
ret =
cxd2880_tnrdmd_check_internal_cpu_status(tnr_dmd,
&cpu_task_completed);
if (ret)
return ret;
if (cpu_task_completed)
break;
if (ktime_to_ms(ktime_sub(ktime_get(), start)) >
CXD2880_TNRDMD_WAIT_INIT_TIMEOUT)
return -ETIMEDOUT;
usleep_range(CXD2880_TNRDMD_WAIT_INIT_INTVL,
CXD2880_TNRDMD_WAIT_INIT_INTVL + 1000);
}
return cxd2880_tnrdmd_init2(tnr_dmd);
}
int cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd)
{
if (!tnr_dmd)
return -EINVAL;
atomic_set(&tnr_dmd->cancel, 1);
return 0;
}
int cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd *tnr_dmd)
{
if (!tnr_dmd)
return -EINVAL;
if (atomic_read(&tnr_dmd->cancel) != 0)
return -ECANCELED;
return 0;
}

View file

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_integ.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* integration layer common interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_INTEG_H
#define CXD2880_INTEG_H
#include "cxd2880_tnrdmd.h"
#define CXD2880_TNRDMD_WAIT_INIT_TIMEOUT 500
#define CXD2880_TNRDMD_WAIT_INIT_INTVL 10
#define CXD2880_TNRDMD_WAIT_AGC_STABLE 100
int cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd
*tnr_dmd);
#endif

View file

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_io.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* register I/O interface functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_io.h"
int cxd2880_io_common_write_one_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data)
{
if (!io)
return -EINVAL;
return io->write_regs(io, tgt, sub_address, &data, 1);
}
int cxd2880_io_set_reg_bits(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data, u8 mask)
{
int ret;
if (!io)
return -EINVAL;
if (mask == 0x00)
return 0;
if (mask != 0xff) {
u8 rdata = 0x00;
ret = io->read_regs(io, tgt, sub_address, &rdata, 1);
if (ret)
return ret;
data = (data & mask) | (rdata & (mask ^ 0xff));
}
return io->write_reg(io, tgt, sub_address, data);
}
int cxd2880_io_write_multi_regs(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
const struct cxd2880_reg_value reg_value[],
u8 size)
{
int ret;
int i;
if (!io)
return -EINVAL;
for (i = 0; i < size ; i++) {
ret = io->write_reg(io, tgt, reg_value[i].addr,
reg_value[i].value);
if (ret)
return ret;
}
return 0;
}

View file

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_io.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* register I/O interface definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_IO_H
#define CXD2880_IO_H
#include "cxd2880_common.h"
enum cxd2880_io_tgt {
CXD2880_IO_TGT_SYS,
CXD2880_IO_TGT_DMD
};
struct cxd2880_reg_value {
u8 addr;
u8 value;
};
struct cxd2880_io {
int (*read_regs)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
u8 *data, u32 size);
int (*write_regs)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
const u8 *data, u32 size);
int (*write_reg)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
u8 data);
void *if_object;
u8 i2c_address_sys;
u8 i2c_address_demod;
u8 slave_select;
void *user;
};
int cxd2880_io_common_write_one_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data);
int cxd2880_io_set_reg_bits(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data, u8 mask);
int cxd2880_io_write_multi_regs(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
const struct cxd2880_reg_value reg_value[],
u8 size);
#endif

View file

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_spi.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_SPI_H
#define CXD2880_SPI_H
#include "cxd2880_common.h"
enum cxd2880_spi_mode {
CXD2880_SPI_MODE_0,
CXD2880_SPI_MODE_1,
CXD2880_SPI_MODE_2,
CXD2880_SPI_MODE_3
};
struct cxd2880_spi {
int (*read)(struct cxd2880_spi *spi, u8 *data,
u32 size);
int (*write)(struct cxd2880_spi *spi, const u8 *data,
u32 size);
int (*write_read)(struct cxd2880_spi *spi,
const u8 *tx_data, u32 tx_size,
u8 *rx_data, u32 rx_size);
u32 flags;
void *user;
};
#endif

View file

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_spi_device.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <linux/spi/spi.h>
#include "cxd2880_spi_device.h"
static int cxd2880_spi_device_write(struct cxd2880_spi *spi,
const u8 *data, u32 size)
{
struct cxd2880_spi_device *spi_device = NULL;
struct spi_message msg;
struct spi_transfer tx;
int result = 0;
if (!spi || !spi->user || !data || size == 0)
return -EINVAL;
spi_device = spi->user;
memset(&tx, 0, sizeof(tx));
tx.tx_buf = data;
tx.len = size;
spi_message_init(&msg);
spi_message_add_tail(&tx, &msg);
result = spi_sync(spi_device->spi, &msg);
if (result < 0)
return -EIO;
return 0;
}
static int cxd2880_spi_device_write_read(struct cxd2880_spi *spi,
const u8 *tx_data,
u32 tx_size,
u8 *rx_data,
u32 rx_size)
{
struct cxd2880_spi_device *spi_device = NULL;
int result = 0;
if (!spi || !spi->user || !tx_data ||
!tx_size || !rx_data || !rx_size)
return -EINVAL;
spi_device = spi->user;
result = spi_write_then_read(spi_device->spi, tx_data,
tx_size, rx_data, rx_size);
if (result < 0)
return -EIO;
return 0;
}
int
cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
enum cxd2880_spi_mode mode,
u32 speed_hz)
{
int result = 0;
struct spi_device *spi = spi_device->spi;
switch (mode) {
case CXD2880_SPI_MODE_0:
spi->mode = SPI_MODE_0;
break;
case CXD2880_SPI_MODE_1:
spi->mode = SPI_MODE_1;
break;
case CXD2880_SPI_MODE_2:
spi->mode = SPI_MODE_2;
break;
case CXD2880_SPI_MODE_3:
spi->mode = SPI_MODE_3;
break;
default:
return -EINVAL;
}
spi->max_speed_hz = speed_hz;
spi->bits_per_word = 8;
result = spi_setup(spi);
if (result != 0) {
pr_err("spi_setup failed %d\n", result);
return -EINVAL;
}
return 0;
}
int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
struct cxd2880_spi_device *spi_device)
{
if (!spi || !spi_device)
return -EINVAL;
spi->read = NULL;
spi->write = cxd2880_spi_device_write;
spi->write_read = cxd2880_spi_device_write_read;
spi->flags = 0;
spi->user = spi_device;
return 0;
}

View file

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_spi_device.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_SPI_DEVICE_H
#define CXD2880_SPI_DEVICE_H
#include "cxd2880_spi.h"
struct cxd2880_spi_device {
struct spi_device *spi;
};
int cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
enum cxd2880_spi_mode mode,
u32 speedHz);
int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
struct cxd2880_spi_device *spi_device);
#endif /* CXD2880_SPI_DEVICE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,365 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common control interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_H
#define CXD2880_TNRDMD_H
#include <linux/atomic.h>
#include "cxd2880_common.h"
#include "cxd2880_io.h"
#include "cxd2880_dtv.h"
#include "cxd2880_dvbt.h"
#include "cxd2880_dvbt2.h"
#define CXD2880_TNRDMD_MAX_CFG_MEM_COUNT 100
#define slvt_unfreeze_reg(tnr_dmd) ((void)((tnr_dmd)->io->write_reg\
((tnr_dmd)->io, CXD2880_IO_TGT_DMD, 0x01, 0x00)))
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_UNDERFLOW 0x0001
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_OVERFLOW 0x0002
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_EMPTY 0x0004
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_FULL 0x0008
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_RRDY 0x0010
#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_COMMAND 0x0020
#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_ACCESS 0x0040
#define CXD2880_TNRDMD_INTERRUPT_TYPE_CPU_ERROR 0x0100
#define CXD2880_TNRDMD_INTERRUPT_TYPE_LOCK 0x0200
#define CXD2880_TNRDMD_INTERRUPT_TYPE_INV_LOCK 0x0400
#define CXD2880_TNRDMD_INTERRUPT_TYPE_NOOFDM 0x0800
#define CXD2880_TNRDMD_INTERRUPT_TYPE_EWS 0x1000
#define CXD2880_TNRDMD_INTERRUPT_TYPE_EEW 0x2000
#define CXD2880_TNRDMD_INTERRUPT_TYPE_FEC_FAIL 0x4000
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_L1POST_OK 0x01
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_DMD_LOCK 0x02
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_TS_LOCK 0x04
enum cxd2880_tnrdmd_chip_id {
CXD2880_TNRDMD_CHIP_ID_UNKNOWN = 0x00,
CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X = 0x62,
CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11 = 0x6a
};
#define CXD2880_TNRDMD_CHIP_ID_VALID(chip_id) \
(((chip_id) == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) || \
((chip_id) == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11))
enum cxd2880_tnrdmd_state {
CXD2880_TNRDMD_STATE_UNKNOWN,
CXD2880_TNRDMD_STATE_SLEEP,
CXD2880_TNRDMD_STATE_ACTIVE,
CXD2880_TNRDMD_STATE_INVALID
};
enum cxd2880_tnrdmd_divermode {
CXD2880_TNRDMD_DIVERMODE_SINGLE,
CXD2880_TNRDMD_DIVERMODE_MAIN,
CXD2880_TNRDMD_DIVERMODE_SUB
};
enum cxd2880_tnrdmd_clockmode {
CXD2880_TNRDMD_CLOCKMODE_UNKNOWN,
CXD2880_TNRDMD_CLOCKMODE_A,
CXD2880_TNRDMD_CLOCKMODE_B,
CXD2880_TNRDMD_CLOCKMODE_C
};
enum cxd2880_tnrdmd_tsout_if {
CXD2880_TNRDMD_TSOUT_IF_TS,
CXD2880_TNRDMD_TSOUT_IF_SPI,
CXD2880_TNRDMD_TSOUT_IF_SDIO
};
enum cxd2880_tnrdmd_xtal_share {
CXD2880_TNRDMD_XTAL_SHARE_NONE,
CXD2880_TNRDMD_XTAL_SHARE_EXTREF,
CXD2880_TNRDMD_XTAL_SHARE_MASTER,
CXD2880_TNRDMD_XTAL_SHARE_SLAVE
};
enum cxd2880_tnrdmd_spectrum_sense {
CXD2880_TNRDMD_SPECTRUM_NORMAL,
CXD2880_TNRDMD_SPECTRUM_INV
};
enum cxd2880_tnrdmd_cfg_id {
CXD2880_TNRDMD_CFG_OUTPUT_SEL_MSB,
CXD2880_TNRDMD_CFG_TSVALID_ACTIVE_HI,
CXD2880_TNRDMD_CFG_TSSYNC_ACTIVE_HI,
CXD2880_TNRDMD_CFG_TSERR_ACTIVE_HI,
CXD2880_TNRDMD_CFG_LATCH_ON_POSEDGE,
CXD2880_TNRDMD_CFG_TSCLK_CONT,
CXD2880_TNRDMD_CFG_TSCLK_MASK,
CXD2880_TNRDMD_CFG_TSVALID_MASK,
CXD2880_TNRDMD_CFG_TSERR_MASK,
CXD2880_TNRDMD_CFG_TSERR_VALID_DIS,
CXD2880_TNRDMD_CFG_TSPIN_CURRENT,
CXD2880_TNRDMD_CFG_TSPIN_PULLUP_MANUAL,
CXD2880_TNRDMD_CFG_TSPIN_PULLUP,
CXD2880_TNRDMD_CFG_TSCLK_FREQ,
CXD2880_TNRDMD_CFG_TSBYTECLK_MANUAL,
CXD2880_TNRDMD_CFG_TS_PACKET_GAP,
CXD2880_TNRDMD_CFG_TS_BACKWARDS_COMPATIBLE,
CXD2880_TNRDMD_CFG_PWM_VALUE,
CXD2880_TNRDMD_CFG_INTERRUPT,
CXD2880_TNRDMD_CFG_INTERRUPT_LOCK_SEL,
CXD2880_TNRDMD_CFG_INTERRUPT_INV_LOCK_SEL,
CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_EMPTY_THRS,
CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_FULL_THRS,
CXD2880_TNRDMD_CFG_TS_BUF_RRDY_THRS,
CXD2880_TNRDMD_CFG_FIXED_CLOCKMODE,
CXD2880_TNRDMD_CFG_CABLE_INPUT,
CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_BASE,
CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_LITE,
CXD2880_TNRDMD_CFG_BLINDTUNE_DVBT2_FIRST,
CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD,
CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD,
CXD2880_TNRDMD_CFG_DVBT_PER_MES,
CXD2880_TNRDMD_CFG_DVBT2_BBER_MES,
CXD2880_TNRDMD_CFG_DVBT2_LBER_MES,
CXD2880_TNRDMD_CFG_DVBT2_PER_MES,
};
enum cxd2880_tnrdmd_lock_result {
CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT,
CXD2880_TNRDMD_LOCK_RESULT_LOCKED,
CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
};
enum cxd2880_tnrdmd_gpio_mode {
CXD2880_TNRDMD_GPIO_MODE_OUTPUT = 0x00,
CXD2880_TNRDMD_GPIO_MODE_INPUT = 0x01,
CXD2880_TNRDMD_GPIO_MODE_INT = 0x02,
CXD2880_TNRDMD_GPIO_MODE_FEC_FAIL = 0x03,
CXD2880_TNRDMD_GPIO_MODE_PWM = 0x04,
CXD2880_TNRDMD_GPIO_MODE_EWS = 0x05,
CXD2880_TNRDMD_GPIO_MODE_EEW = 0x06
};
enum cxd2880_tnrdmd_serial_ts_clk {
CXD2880_TNRDMD_SERIAL_TS_CLK_FULL,
CXD2880_TNRDMD_SERIAL_TS_CLK_HALF
};
struct cxd2880_tnrdmd_cfg_mem {
enum cxd2880_io_tgt tgt;
u8 bank;
u8 address;
u8 value;
u8 bit_mask;
};
struct cxd2880_tnrdmd_pid_cfg {
u8 is_en;
u16 pid;
};
struct cxd2880_tnrdmd_pid_ftr_cfg {
u8 is_negative;
struct cxd2880_tnrdmd_pid_cfg pid_cfg[32];
};
struct cxd2880_tnrdmd_lna_thrs {
u8 off_on;
u8 on_off;
};
struct cxd2880_tnrdmd_lna_thrs_tbl_air {
struct cxd2880_tnrdmd_lna_thrs thrs[24];
};
struct cxd2880_tnrdmd_lna_thrs_tbl_cable {
struct cxd2880_tnrdmd_lna_thrs thrs[32];
};
struct cxd2880_tnrdmd_create_param {
enum cxd2880_tnrdmd_tsout_if ts_output_if;
u8 en_internal_ldo;
enum cxd2880_tnrdmd_xtal_share xtal_share_type;
u8 xosc_cap;
u8 xosc_i;
u8 is_cxd2881gg;
u8 stationary_use;
};
struct cxd2880_tnrdmd_diver_create_param {
enum cxd2880_tnrdmd_tsout_if ts_output_if;
u8 en_internal_ldo;
u8 xosc_cap_main;
u8 xosc_i_main;
u8 xosc_i_sub;
u8 is_cxd2881gg;
u8 stationary_use;
};
struct cxd2880_tnrdmd {
struct cxd2880_tnrdmd *diver_sub;
struct cxd2880_io *io;
struct cxd2880_tnrdmd_create_param create_param;
enum cxd2880_tnrdmd_divermode diver_mode;
enum cxd2880_tnrdmd_clockmode fixed_clk_mode;
u8 is_cable_input;
u8 en_fef_intmtnt_base;
u8 en_fef_intmtnt_lite;
u8 blind_tune_dvbt2_first;
int (*rf_lvl_cmpstn)(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
struct cxd2880_tnrdmd_lna_thrs_tbl_air *lna_thrs_tbl_air;
struct cxd2880_tnrdmd_lna_thrs_tbl_cable *lna_thrs_tbl_cable;
u8 srl_ts_clk_mod_cnts;
enum cxd2880_tnrdmd_serial_ts_clk srl_ts_clk_frq;
u8 ts_byte_clk_manual_setting;
u8 is_ts_backwards_compatible_mode;
struct cxd2880_tnrdmd_cfg_mem cfg_mem[CXD2880_TNRDMD_MAX_CFG_MEM_COUNT];
u8 cfg_mem_last_entry;
struct cxd2880_tnrdmd_pid_ftr_cfg pid_ftr_cfg;
u8 pid_ftr_cfg_en;
void *user;
enum cxd2880_tnrdmd_chip_id chip_id;
enum cxd2880_tnrdmd_state state;
enum cxd2880_tnrdmd_clockmode clk_mode;
u32 frequency_khz;
enum cxd2880_dtv_sys sys;
enum cxd2880_dtv_bandwidth bandwidth;
u8 scan_mode;
atomic_t cancel;
};
int cxd2880_tnrdmd_create(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_io *io,
struct cxd2880_tnrdmd_create_param
*create_param);
int cxd2880_tnrdmd_diver_create(struct cxd2880_tnrdmd
*tnr_dmd_main,
struct cxd2880_io *io_main,
struct cxd2880_tnrdmd *tnr_dmd_sub,
struct cxd2880_io *io_sub,
struct
cxd2880_tnrdmd_diver_create_param
*create_param);
int cxd2880_tnrdmd_init1(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_init2(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_check_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *task_completed);
int cxd2880_tnrdmd_common_tune_setting1(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_sys sys,
u32 frequency_khz,
enum cxd2880_dtv_bandwidth
bandwidth, u8 one_seg_opt,
u8 one_seg_opt_shft_dir);
int cxd2880_tnrdmd_common_tune_setting2(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_sys sys,
u8 en_fef_intmtnt_ctrl);
int cxd2880_tnrdmd_sleep(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_set_cfg(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_tnrdmd_cfg_id id,
int value);
int cxd2880_tnrdmd_gpio_set_cfg(struct cxd2880_tnrdmd *tnr_dmd,
u8 id,
u8 en,
enum cxd2880_tnrdmd_gpio_mode mode,
u8 open_drain, u8 invert);
int cxd2880_tnrdmd_gpio_set_cfg_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id,
u8 en,
enum cxd2880_tnrdmd_gpio_mode
mode, u8 open_drain,
u8 invert);
int cxd2880_tnrdmd_gpio_read(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 *value);
int cxd2880_tnrdmd_gpio_read_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 *value);
int cxd2880_tnrdmd_gpio_write(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 value);
int cxd2880_tnrdmd_gpio_write_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 value);
int cxd2880_tnrdmd_interrupt_read(struct cxd2880_tnrdmd *tnr_dmd,
u16 *value);
int cxd2880_tnrdmd_interrupt_clear(struct cxd2880_tnrdmd *tnr_dmd,
u16 value);
int cxd2880_tnrdmd_ts_buf_clear(struct cxd2880_tnrdmd *tnr_dmd,
u8 clear_overflow_flag,
u8 clear_underflow_flag,
u8 clear_buf);
int cxd2880_tnrdmd_chip_id(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_tnrdmd_chip_id *chip_id);
int cxd2880_tnrdmd_set_and_save_reg_bits(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_io_tgt tgt,
u8 bank, u8 address,
u8 value, u8 bit_mask);
int cxd2880_tnrdmd_set_scan_mode(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dtv_sys sys,
u8 scan_mode_end);
int cxd2880_tnrdmd_set_pid_ftr(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_tnrdmd_pid_ftr_cfg
*pid_ftr_cfg);
int cxd2880_tnrdmd_set_rf_lvl_cmpstn(struct cxd2880_tnrdmd
*tnr_dmd,
int (*rf_lvl_cmpstn)
(struct cxd2880_tnrdmd *,
int *));
int cxd2880_tnrdmd_set_rf_lvl_cmpstn_sub(struct cxd2880_tnrdmd *tnr_dmd,
int (*rf_lvl_cmpstn)
(struct cxd2880_tnrdmd *,
int *));
int cxd2880_tnrdmd_set_lna_thrs(struct cxd2880_tnrdmd *tnr_dmd,
struct
cxd2880_tnrdmd_lna_thrs_tbl_air
*tbl_air,
struct
cxd2880_tnrdmd_lna_thrs_tbl_cable
*tbl_cable);
int cxd2880_tnrdmd_set_lna_thrs_sub(struct cxd2880_tnrdmd *tnr_dmd,
struct
cxd2880_tnrdmd_lna_thrs_tbl_air
*tbl_air,
struct
cxd2880_tnrdmd_lna_thrs_tbl_cable
*tbl_cable);
int cxd2880_tnrdmd_set_ts_pin_high_low(struct cxd2880_tnrdmd
*tnr_dmd, u8 en, u8 value);
int cxd2880_tnrdmd_set_ts_output(struct cxd2880_tnrdmd *tnr_dmd,
u8 en);
int slvt_freeze_reg(struct cxd2880_tnrdmd *tnr_dmd);
#endif

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_driver_version.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* version information
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#define CXD2880_TNRDMD_DRIVER_VERSION "1.4.1 - 1.0.4"
#define CXD2880_TNRDMD_DRIVER_RELEASE_DATE "2018-01-17"

View file

@ -0,0 +1,919 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_dvbt.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control functions for DVB-T
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <media/dvb_frontend.h>
#include "cxd2880_tnrdmd_dvbt.h"
#include "cxd2880_tnrdmd_dvbt_mon.h"
static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
{0x00, 0x00}, {0x31, 0x01},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
{0x00, 0x04}, {0x5c, 0xfb}, {0x00, 0x10}, {0xa4, 0x03},
{0x00, 0x14}, {0xb0, 0x00}, {0x00, 0x25},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq3[] = {
{0x00, 0x12}, {0x44, 0x00},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq4[] = {
{0x00, 0x11}, {0x87, 0xd2},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq5[] = {
{0x00, 0x00}, {0xfd, 0x01},
};
static const struct cxd2880_reg_value sleep_dmd_setting_seq1[] = {
{0x00, 0x04}, {0x5c, 0xd8}, {0x00, 0x10}, {0xa4, 0x00},
};
static const struct cxd2880_reg_value sleep_dmd_setting_seq2[] = {
{0x00, 0x11}, {0x87, 0x04},
};
static int x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_bandwidth
bandwidth,
enum cxd2880_tnrdmd_clockmode
clk_mode)
{
static const u8 clk_mode_ckffrq_a[2] = { 0x52, 0x49 };
static const u8 clk_mode_ckffrq_b[2] = { 0x5d, 0x55 };
static const u8 clk_mode_ckffrq_c[2] = { 0x60, 0x00 };
static const u8 ratectl_margin[2] = { 0x01, 0xf0 };
static const u8 maxclkcnt_a[3] = { 0x73, 0xca, 0x49 };
static const u8 maxclkcnt_b[3] = { 0xc8, 0x13, 0xaa };
static const u8 maxclkcnt_c[3] = { 0xdc, 0x6c, 0x00 };
static const u8 bw8_nomi_ac[5] = { 0x15, 0x00, 0x00, 0x00, 0x00};
static const u8 bw8_nomi_b[5] = { 0x14, 0x6a, 0xaa, 0xaa, 0xaa};
static const u8 bw8_gtdofst_a[2] = { 0x01, 0x28 };
static const u8 bw8_gtdofst_b[2] = { 0x11, 0x44 };
static const u8 bw8_gtdofst_c[2] = { 0x15, 0x28 };
static const u8 bw8_mrc_a[5] = { 0x30, 0x00, 0x00, 0x90, 0x00 };
static const u8 bw8_mrc_b[5] = { 0x36, 0x71, 0x00, 0xa3, 0x55 };
static const u8 bw8_mrc_c[5] = { 0x38, 0x00, 0x00, 0xa8, 0x00 };
static const u8 bw8_notch[4] = { 0xb3, 0x00, 0x01, 0x02 };
static const u8 bw7_nomi_ac[5] = { 0x18, 0x00, 0x00, 0x00, 0x00};
static const u8 bw7_nomi_b[5] = { 0x17, 0x55, 0x55, 0x55, 0x55};
static const u8 bw7_gtdofst_a[2] = { 0x12, 0x4c };
static const u8 bw7_gtdofst_b[2] = { 0x1f, 0x15 };
static const u8 bw7_gtdofst_c[2] = { 0x1f, 0xf8 };
static const u8 bw7_mrc_a[5] = { 0x36, 0xdb, 0x00, 0xa4, 0x92 };
static const u8 bw7_mrc_b[5] = { 0x3e, 0x38, 0x00, 0xba, 0xaa };
static const u8 bw7_mrc_c[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
static const u8 bw7_notch[4] = { 0xb8, 0x00, 0x00, 0x03 };
static const u8 bw6_nomi_ac[5] = { 0x1c, 0x00, 0x00, 0x00, 0x00};
static const u8 bw6_nomi_b[5] = { 0x1b, 0x38, 0xe3, 0x8e, 0x38};
static const u8 bw6_gtdofst_a[2] = { 0x1f, 0xf8 };
static const u8 bw6_gtdofst_b[2] = { 0x24, 0x43 };
static const u8 bw6_gtdofst_c[2] = { 0x25, 0x4c };
static const u8 bw6_mrc_a[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
static const u8 bw6_mrc_b[5] = { 0x48, 0x97, 0x00, 0xd9, 0xc7 };
static const u8 bw6_mrc_c[5] = { 0x4a, 0xaa, 0x00, 0xdf, 0xff };
static const u8 bw6_notch[4] = { 0xbe, 0xab, 0x00, 0x03 };
static const u8 bw5_nomi_ac[5] = { 0x21, 0x99, 0x99, 0x99, 0x99};
static const u8 bw5_nomi_b[5] = { 0x20, 0xaa, 0xaa, 0xaa, 0xaa};
static const u8 bw5_gtdofst_a[2] = { 0x26, 0x5d };
static const u8 bw5_gtdofst_b[2] = { 0x2b, 0x84 };
static const u8 bw5_gtdofst_c[2] = { 0x2c, 0xc2 };
static const u8 bw5_mrc_a[5] = { 0x4c, 0xcc, 0x00, 0xe6, 0x66 };
static const u8 bw5_mrc_b[5] = { 0x57, 0x1c, 0x01, 0x05, 0x55 };
static const u8 bw5_mrc_c[5] = { 0x59, 0x99, 0x01, 0x0c, 0xcc };
static const u8 bw5_notch[4] = { 0xc8, 0x01, 0x00, 0x03 };
const u8 *data = NULL;
u8 sst_data;
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
tune_dmd_setting_seq1,
ARRAY_SIZE(tune_dmd_setting_seq1));
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = clk_mode_ckffrq_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = clk_mode_ckffrq_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = clk_mode_ckffrq_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x65, data, 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x5d, 0x07);
if (ret)
return ret;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
u8 data[2] = { 0x01, 0x01 };
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xce, data, 2);
if (ret)
return ret;
}
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq2,
ARRAY_SIZE(tune_dmd_setting_seq2));
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xf0, ratectl_margin, 2);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN ||
tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq3,
ARRAY_SIZE(tune_dmd_setting_seq3));
if (ret)
return ret;
}
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq4,
ARRAY_SIZE(tune_dmd_setting_seq4));
if (ret)
return ret;
}
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = maxclkcnt_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = maxclkcnt_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = maxclkcnt_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x68, data, 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (bandwidth) {
case CXD2880_DTV_BW_8_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x00);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw8_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x35;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x34;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw8_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw8_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw8_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_7_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x02);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw7_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x2f;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x2e;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw7_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw7_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw7_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_6_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw6_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x29;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x2a;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw6_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw6_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw6_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_5_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x06);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw5_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x24;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x23;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw5_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw5_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw5_notch[2], 2);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
return cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq5,
ARRAY_SIZE(tune_dmd_setting_seq5));
}
static int x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd
*tnr_dmd)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
sleep_dmd_setting_seq1,
ARRAY_SIZE(sleep_dmd_setting_seq1));
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
sleep_dmd_setting_seq2,
ARRAY_SIZE(sleep_dmd_setting_seq2));
return ret;
}
static int dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dvbt_profile profile)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x10);
if (ret)
return ret;
return tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x67,
(profile == CXD2880_DVBT_PROFILE_HP)
? 0x00 : 0x01);
}
int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param)
{
int ret;
if (!tnr_dmd || !tune_param)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT,
tune_param->center_freq_khz,
tune_param->bandwidth, 0, 0);
if (ret)
return ret;
ret =
x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth,
tnr_dmd->clk_mode);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
ret =
x_tune_dvbt_demod_setting(tnr_dmd->diver_sub,
tune_param->bandwidth,
tnr_dmd->diver_sub->clk_mode);
if (ret)
return ret;
}
return dvbt_set_profile(tnr_dmd, tune_param->profile);
}
int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param)
{
int ret;
if (!tnr_dmd || !tune_param)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT,
0);
if (ret)
return ret;
tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
tnr_dmd->frequency_khz = tune_param->center_freq_khz;
tnr_dmd->sys = CXD2880_DTV_SYS_DVBT;
tnr_dmd->bandwidth = tune_param->bandwidth;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT;
tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
}
return 0;
}
int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd *tnr_dmd)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret = x_sleep_dvbt_demod_setting(tnr_dmd);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub);
return ret;
}
int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock)
{
int ret;
u8 sync_stat = 0;
u8 ts_lock = 0;
u8 unlock_detected = 0;
u8 unlock_detected_sub = 0;
if (!tnr_dmd || !lock)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
&unlock_detected);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
if (sync_stat == 6)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
}
if (sync_stat == 6) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
}
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
&unlock_detected_sub);
if (ret)
return ret;
if (sync_stat == 6)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected && unlock_detected_sub)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
}
int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock)
{
int ret;
u8 sync_stat = 0;
u8 ts_lock = 0;
u8 unlock_detected = 0;
u8 unlock_detected_sub = 0;
if (!tnr_dmd || !lock)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
&unlock_detected);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
if (ts_lock)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
}
if (ts_lock) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
} else if (!unlock_detected) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
}
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
&unlock_detected_sub);
if (ret)
return ret;
if (unlock_detected && unlock_detected_sub)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
}

View file

@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control interface for DVB-T
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT_H
#define CXD2880_TNRDMD_DVBT_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
struct cxd2880_dvbt_tune_param {
u32 center_freq_khz;
enum cxd2880_dtv_bandwidth bandwidth;
enum cxd2880_dvbt_profile profile;
};
int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt2.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control interface for DVB-T2
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT2_H
#define CXD2880_TNRDMD_DVBT2_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
enum cxd2880_tnrdmd_dvbt2_tune_info {
CXD2880_TNRDMD_DVBT2_TUNE_INFO_OK,
CXD2880_TNRDMD_DVBT2_TUNE_INFO_INVALID_PLP_ID
};
struct cxd2880_dvbt2_tune_param {
u32 center_freq_khz;
enum cxd2880_dtv_bandwidth bandwidth;
u16 data_plp_id;
enum cxd2880_dvbt2_profile profile;
enum cxd2880_tnrdmd_dvbt2_tune_info tune_info;
};
#define CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO 0xffff
int cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
*tnr_dmd, u8 auto_plp,
u8 plp_id);
int cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *l1_post_valid);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt2_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T2 monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT2_MON_H
#define CXD2880_TNRDMD_DVBT2_MON_H
#include "cxd2880_tnrdmd.h"
#include "cxd2880_dvbt2.h"
int cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *sync_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset);
int cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset);
int cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_l1pre
*l1_pre);
int cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_version
*ver);
int cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_ofdm *ofdm);
int cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd
*tnr_dmd, u8 *plp_ids,
u8 *num_plps);
int cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_dvbt2_plp_btype
type,
struct cxd2880_dvbt2_plp
*plp_info);
int cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *plp_error);
int cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd
*tnr_dmd, u8 *l1_change);
int cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt2_l1post
*l1_post);
int cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_plp_btype
type,
struct cxd2880_dvbt2_bbheader
*bbheader);
int cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_dvbt2_plp_btype
type,
u32 *ts_rate_bps);
int cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense);
int cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr);
int cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main,
int *snr_sub);
int cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen);
int cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm);
int cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *ppm);
int cxd2880_tnrdmd_dvbt2_mon_qam(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dvbt2_plp_btype type,
enum cxd2880_dvbt2_plp_constell
*qam);
int cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_plp_btype
type,
enum
cxd2880_dvbt2_plp_code_rate
*code_rate);
int cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_profile
*profile);
int cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
int cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *ssi);
#endif

View file

@ -0,0 +1,775 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_dvbt_mon.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T monitor functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_tnrdmd_mon.h"
#include "cxd2880_tnrdmd_dvbt.h"
#include "cxd2880_tnrdmd_dvbt_mon.h"
#include <media/dvb_math.h>
static const int ref_dbm_1000[3][5] = {
{-93000, -91000, -90000, -89000, -88000},
{-87000, -85000, -84000, -83000, -82000},
{-82000, -80000, -78000, -77000, -76000},
};
static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected)
{
u8 rdata = 0x00;
int ret;
if (!tnr_dmd || !sync_stat || !ts_lock_stat || !unlock_detected)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, &rdata, 1);
if (ret)
return ret;
*unlock_detected = (rdata & 0x10) ? 1 : 0;
*sync_stat = rdata & 0x07;
*ts_lock_stat = (rdata & 0x20) ? 1 : 0;
if (*sync_stat == 0x07)
return -EAGAIN;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *unlock_detected)
{
u8 ts_lock_stat = 0;
if (!tnr_dmd || !sync_stat || !unlock_detected)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd->diver_sub,
sync_stat,
&ts_lock_stat,
unlock_detected);
}
int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt_mode
*mode,
enum cxd2880_dvbt_guard
*guard)
{
u8 rdata = 0x00;
int ret;
if (!tnr_dmd || !mode || !guard)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret =
cxd2880_tnrdmd_dvbt_mon_mode_guard(tnr_dmd->diver_sub,
mode, guard);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1b, &rdata, 1);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*mode = (enum cxd2880_dvbt_mode)((rdata >> 2) & 0x03);
*guard = (enum cxd2880_dvbt_guard)(rdata & 0x03);
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset)
{
u8 rdata[4];
u32 ctl_val = 0;
int ret;
if (!tnr_dmd || !offset)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1d, rdata, 4);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
ctl_val =
((rdata[0] & 0x1f) << 24) | (rdata[1] << 16) | (rdata[2] << 8) |
(rdata[3]);
*offset = cxd2880_convert2s_complement(ctl_val, 29);
*offset = -1 * ((*offset) * tnr_dmd->bandwidth / 235);
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset)
{
if (!tnr_dmd || !offset)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_carrier_offset(tnr_dmd->diver_sub,
offset);
}
int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt_tpsinfo
*info)
{
u8 rdata[7];
u8 cell_id_ok = 0;
int ret;
if (!tnr_dmd || !info)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret =
cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd->diver_sub,
info);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x29, rdata, 7);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x11);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xd5, &cell_id_ok, 1);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
info->constellation =
(enum cxd2880_dvbt_constellation)((rdata[0] >> 6) & 0x03);
info->hierarchy = (enum cxd2880_dvbt_hierarchy)((rdata[0] >> 3) & 0x07);
info->rate_hp = (enum cxd2880_dvbt_coderate)(rdata[0] & 0x07);
info->rate_lp = (enum cxd2880_dvbt_coderate)((rdata[1] >> 5) & 0x07);
info->guard = (enum cxd2880_dvbt_guard)((rdata[1] >> 3) & 0x03);
info->mode = (enum cxd2880_dvbt_mode)((rdata[1] >> 1) & 0x03);
info->fnum = (rdata[2] >> 6) & 0x03;
info->length_indicator = rdata[2] & 0x3f;
info->cell_id = (rdata[3] << 8) | rdata[4];
info->reserved_even = rdata[5] & 0x3f;
info->reserved_odd = rdata[6] & 0x3f;
info->cell_id_ok = cell_id_ok & 0x01;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen)
{
u8 rdata[3];
int ret;
if (!tnr_dmd || !pen)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x26, rdata, 3);
if (ret)
return ret;
if (!(rdata[0] & 0x01))
return -EAGAIN;
*pen = (rdata[1] << 8) | rdata[2];
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense)
{
u8 data = 0;
int ret;
if (!tnr_dmd || !sense)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense(tnr_dmd->diver_sub,
sense);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1c, &data, sizeof(data));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*sense =
(data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV :
CXD2880_TNRDMD_SPECTRUM_NORMAL;
return ret;
}
static int dvbt_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd,
u16 *reg_value)
{
u8 rdata[2];
int ret;
if (!tnr_dmd || !reg_value)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x13, rdata, 2);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*reg_value = (rdata[0] << 8) | rdata[1];
return ret;
}
static int dvbt_calc_snr(struct cxd2880_tnrdmd *tnr_dmd,
u32 reg_value, int *snr)
{
if (!tnr_dmd || !snr)
return -EINVAL;
if (reg_value == 0)
return -EAGAIN;
if (reg_value > 4996)
reg_value = 4996;
*snr = intlog10(reg_value) - intlog10(5350 - reg_value);
*snr = (*snr + 839) / 1678 + 28500;
return 0;
}
int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr)
{
u16 reg_value = 0;
int ret;
if (!tnr_dmd || !snr)
return -EINVAL;
*snr = -1000 * 1000;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
if (ret)
return ret;
ret = dvbt_calc_snr(tnr_dmd, reg_value, snr);
} else {
int snr_main = 0;
int snr_sub = 0;
ret =
cxd2880_tnrdmd_dvbt_mon_snr_diver(tnr_dmd, snr, &snr_main,
&snr_sub);
}
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main, int *snr_sub)
{
u16 reg_value = 0;
u32 reg_value_sum = 0;
int ret;
if (!tnr_dmd || !snr || !snr_main || !snr_sub)
return -EINVAL;
*snr = -1000 * 1000;
*snr_main = -1000 * 1000;
*snr_sub = -1000 * 1000;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
if (!ret) {
ret = dvbt_calc_snr(tnr_dmd, reg_value, snr_main);
if (ret)
reg_value = 0;
} else if (ret == -EAGAIN) {
reg_value = 0;
} else {
return ret;
}
reg_value_sum += reg_value;
ret = dvbt_read_snr_reg(tnr_dmd->diver_sub, &reg_value);
if (!ret) {
ret = dvbt_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub);
if (ret)
reg_value = 0;
} else if (ret == -EAGAIN) {
reg_value = 0;
} else {
return ret;
}
reg_value_sum += reg_value;
return dvbt_calc_snr(tnr_dmd, reg_value_sum, snr);
}
int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm)
{
u8 ctl_val_reg[5];
u8 nominal_rate_reg[5];
u32 trl_ctl_val = 0;
u32 trcg_nominal_rate = 0;
int num;
int den;
s8 diff_upper = 0;
int ret;
if (!tnr_dmd || !ppm)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x21, ctl_val_reg,
sizeof(ctl_val_reg));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, nominal_rate_reg,
sizeof(nominal_rate_reg));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
diff_upper =
(ctl_val_reg[0] & 0x7f) - (nominal_rate_reg[0] & 0x7f);
if (diff_upper < -1 || diff_upper > 1)
return -EAGAIN;
trl_ctl_val = ctl_val_reg[1] << 24;
trl_ctl_val |= ctl_val_reg[2] << 16;
trl_ctl_val |= ctl_val_reg[3] << 8;
trl_ctl_val |= ctl_val_reg[4];
trcg_nominal_rate = nominal_rate_reg[1] << 24;
trcg_nominal_rate |= nominal_rate_reg[2] << 16;
trcg_nominal_rate |= nominal_rate_reg[3] << 8;
trcg_nominal_rate |= nominal_rate_reg[4];
trl_ctl_val >>= 1;
trcg_nominal_rate >>= 1;
if (diff_upper == 1)
num =
(int)((trl_ctl_val + 0x80000000u) -
trcg_nominal_rate);
else if (diff_upper == -1)
num =
-(int)((trcg_nominal_rate + 0x80000000u) -
trl_ctl_val);
else
num = (int)(trl_ctl_val - trcg_nominal_rate);
den = (nominal_rate_reg[0] & 0x7f) << 24;
den |= nominal_rate_reg[1] << 16;
den |= nominal_rate_reg[2] << 8;
den |= nominal_rate_reg[3];
den = (den + (390625 / 2)) / 390625;
den >>= 1;
if (num >= 0)
*ppm = (num + (den / 2)) / den;
else
*ppm = (num - (den / 2)) / den;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd, int *ppm)
{
if (!tnr_dmd || !ppm)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_sampling_offset(tnr_dmd->diver_sub, ppm);
}
static int dvbt_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd,
int rf_lvl, u8 *ssi)
{
struct cxd2880_dvbt_tpsinfo tps;
int prel;
int temp_ssi = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps);
if (ret)
return ret;
if (tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3 ||
tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5)
return -EINVAL;
prel = rf_lvl - ref_dbm_1000[tps.constellation][tps.rate_hp];
if (prel < -15000)
temp_ssi = 0;
else if (prel < 0)
temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000;
else if (prel < 20000)
temp_ssi = (((4 * prel) + 500) / 1000) + 10;
else if (prel < 35000)
temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90;
else
temp_ssi = 100;
*ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi)
{
int rf_lvl = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl);
if (ret)
return ret;
return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
}
int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi)
{
int rf_lvl = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl);
if (ret)
return ret;
return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
}
static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd)
{
u8 sync = 0;
u8 tslock = 0;
u8 early_unlock = 0;
int ret;
if (!tnr_dmd)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync, &tslock,
&early_unlock);
if (ret)
return ret;
if (sync != 6)
return -EAGAIN;
return 0;
}

View file

@ -0,0 +1,77 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT_MON_H
#define CXD2880_TNRDMD_DVBT_MON_H
#include "cxd2880_tnrdmd.h"
#include "cxd2880_dvbt.h"
int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt_mode
*mode,
enum cxd2880_dvbt_guard
*guard);
int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset);
int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset);
int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt_tpsinfo
*info);
int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen);
int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense);
int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr);
int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main, int *snr_sub);
int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm);
int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *ppm);
int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
#endif

View file

@ -0,0 +1,150 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_mon.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common monitor functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd_mon.h"
static const u8 rf_lvl_seq[2] = {
0x80, 0x00,
};
int cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db)
{
u8 rdata[2];
int ret;
if (!tnr_dmd || !rf_lvl_db)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, 0x01);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x10);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x5b, rf_lvl_seq, 2);
if (ret)
return ret;
usleep_range(2000, 3000);
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x1a);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x15, rdata, 2);
if (ret)
return ret;
if (rdata[0] || rdata[1])
return -EINVAL;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x11, rdata, 2);
if (ret)
return ret;
*rf_lvl_db =
cxd2880_convert2s_complement((rdata[0] << 3) |
((rdata[1] & 0xe0) >> 5), 11);
*rf_lvl_db *= 125;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, 0x00);
if (ret)
return ret;
if (tnr_dmd->rf_lvl_cmpstn)
ret = tnr_dmd->rf_lvl_cmpstn(tnr_dmd, rf_lvl_db);
return ret;
}
int cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db)
{
if (!tnr_dmd || !rf_lvl_db)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, rf_lvl_db);
}
int cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd, u16 *status)
{
u8 data[2] = { 0 };
int ret;
if (!tnr_dmd || !status)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x1a);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x15, data, 2);
if (ret)
return ret;
*status = (data[0] << 8) | data[1];
return 0;
}
int cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
u16 *status)
{
if (!tnr_dmd || !status)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_mon_internal_cpu_status(tnr_dmd->diver_sub,
status);
}

View file

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_MON_H
#define CXD2880_TNRDMD_MON_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
int cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
int cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
int cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd, u16 *status);
int cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
u16 *status);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1285,7 +1285,7 @@ int dib0090_gain_control(struct dvb_frontend *fe)
#endif
if (*tune_state == CT_AGC_STEP_1) { /* quickly go to the correct range of the ADC power */
if (ABS(adc_error) < 50 || state->agc_step++ > 5) {
if (abs(adc_error) < 50 || state->agc_step++ > 5) {
#ifdef CONFIG_STANDARD_DAB
if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB) {
@ -1754,7 +1754,7 @@ static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum front
*tune_state = CT_TUNER_STEP_1;
} else {
/* the minimum was what we have seen in the step before */
if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
if (abs(state->adc_diff) > abs(state->min_adc_diff)) {
dprintk("Since adc_diff N = %d > adc_diff step N-1 = %d, Come back one step\n", state->adc_diff, state->min_adc_diff);
state->step--;
}

View file

@ -809,7 +809,7 @@ static int dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
{
u32 internal = dib7000p_get_internal_freq(state);
s32 unit_khz_dds_val;
u32 abs_offset_khz = ABS(offset_khz);
u32 abs_offset_khz = abs(offset_khz);
u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
if (internal == 0) {

View file

@ -2677,7 +2677,7 @@ static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff)
static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz)
{
s16 unit_khz_dds_val;
u32 abs_offset_khz = ABS(offset_khz);
u32 abs_offset_khz = abs(offset_khz);
u32 dds = state->cfg.pll->ifreq & 0x1ffffff;
u8 invert = !!(state->cfg.pll->ifreq & (1 << 25));
u8 ratio;

View file

@ -424,7 +424,7 @@ static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
struct i2c_algorithm *algo, const char *name,
struct dibx000_i2c_master *mst)
{
strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
strlcpy(i2c_adap->name, name, sizeof(i2c_adap->name));
i2c_adap->algo = algo;
i2c_adap->algo_data = NULL;
i2c_set_adapdata(i2c_adap, mst);

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