浏览代码

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

Pull media updates from Mauro Carvalho Chehab:

 - Documentation for digital TV (both kAPI and uAPI) are now in sync
   with the implementation (except for legacy/deprecated ioctls). This
   is a major step, as there were always a gap there

 - New sensor driver: imx274

 - New cec driver: cec-gpio

 - New platform driver for rockship rga and tegra CEC

 - New RC driver: tango-ir

 - Several cleanups at atomisp driver

 - Core improvements for RC, CEC, V4L2 async probing support and DVB

 - Lots of drivers cleanup, fixes and improvements.

* tag 'media/v4.15-1' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (332 commits)
  dvb_frontend: don't use-after-free the frontend struct
  media: dib0700: fix invalid dvb_detach argument
  media: v4l2-ctrls: Don't validate BITMASK twice
  media: s5p-mfc: fix lockdep warning
  media: dvb-core: always call invoke_release() in fe_free()
  media: usb: dvb-usb-v2: dvb_usb_core: remove redundant code in dvb_usb_fe_sleep
  media: au0828: make const array addr_list static
  media: cx88: make const arrays default_addr_list and pvr2000_addr_list static
  media: drxd: make const array fastIncrDecLUT static
  media: usb: fix spelling mistake: "synchronuously" -> "synchronously"
  media: ddbridge: fix build warnings
  media: av7110: avoid 2038 overflow in debug print
  media: Don't do DMA on stack for firmware upload in the AS102 driver
  media: v4l: async: fix unregister for implicitly registered sub-device notifiers
  media: v4l: async: fix return of unitialized variable ret
  media: imx274: fix missing return assignment from call to imx274_mode_regs
  media: camss-vfe: always initialize reg at vfe_set_xbar_cfg()
  media: atomisp: make function calls cleaner
  media: atomisp: get rid of storage_class.h
  media: atomisp: get rid of wrong stddef.h include
  ...
Linus Torvalds 8 年之前
父节点
当前提交
5d352e69c6
共有 100 个文件被更改,包括 4450 次插入1758 次删除
  1. 32 0
      Documentation/devicetree/bindings/media/cec-gpio.txt
  2. 6 3
      Documentation/devicetree/bindings/media/exynos5-gsc.txt
  3. 33 0
      Documentation/devicetree/bindings/media/i2c/imx274.txt
  4. 2 0
      Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
  5. 33 0
      Documentation/devicetree/bindings/media/rockchip-rga.txt
  6. 21 0
      Documentation/devicetree/bindings/media/tango-ir.txt
  7. 27 0
      Documentation/devicetree/bindings/media/tegra-cec.txt
  8. 23 1
      Documentation/devicetree/bindings/media/video-interfaces.txt
  9. 0 2
      Documentation/media/cec.h.rst.exceptions
  10. 5 2
      Documentation/media/kapi/cec-core.rst
  11. 4 0
      Documentation/media/kapi/dtv-ca.rst
  12. 55 0
      Documentation/media/kapi/dtv-common.rst
  13. 7 567
      Documentation/media/kapi/dtv-core.rst
  14. 82 0
      Documentation/media/kapi/dtv-demux.rst
  15. 443 0
      Documentation/media/kapi/dtv-frontend.rst
  16. 4 0
      Documentation/media/kapi/dtv-net.rst
  17. 3 0
      Documentation/media/kapi/v4l2-async.rst
  18. 1 0
      Documentation/media/kapi/v4l2-core.rst
  19. 20 2
      Documentation/media/uapi/cec/cec-ioc-dqevent.rst
  20. 5 5
      Documentation/media/uapi/cec/cec-ioc-receive.rst
  21. 6 372
      Documentation/media/uapi/dvb/examples.rst
  22. 5 2
      Documentation/media/uapi/dvb/fe-get-property.rst
  23. 1 1
      Documentation/media/uapi/dvb/net-types.rst
  24. 31 0
      MAINTAINERS
  25. 1 0
      arch/arm/boot/dts/omap3-n9.dts
  26. 2 2
      arch/arm/boot/dts/omap3-n950-n9.dtsi
  27. 1 0
      arch/arm/boot/dts/omap3-n950.dts
  28. 17 1
      drivers/media/cec/cec-adap.c
  29. 15 4
      drivers/media/cec/cec-api.c
  30. 4 5
      drivers/media/cec/cec-core.c
  31. 133 0
      drivers/media/cec/cec-pin-priv.h
  32. 24 16
      drivers/media/cec/cec-pin.c
  33. 2 4
      drivers/media/common/cypress_firmware.c
  34. 3 3
      drivers/media/common/saa7146/saa7146_fops.c
  35. 7 7
      drivers/media/common/saa7146/saa7146_vbi.c
  36. 2 3
      drivers/media/common/saa7146/saa7146_video.c
  37. 16 23
      drivers/media/common/siano/smscoreapi.c
  38. 12 0
      drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
  39. 3 5
      drivers/media/dvb-core/dmxdev.c
  40. 88 2
      drivers/media/dvb-core/dmxdev.h
  41. 9 8
      drivers/media/dvb-core/dvb_demux.c
  42. 224 24
      drivers/media/dvb-core/dvb_demux.h
  43. 257 261
      drivers/media/dvb-core/dvb_frontend.c
  44. 52 65
      drivers/media/dvb-core/dvb_frontend.h
  45. 32 2
      drivers/media/dvb-core/dvb_net.h
  46. 27 5
      drivers/media/dvb-core/dvbdev.c
  47. 113 24
      drivers/media/dvb-core/dvbdev.h
  48. 3 3
      drivers/media/dvb-frontends/Kconfig
  49. 3 4
      drivers/media/dvb-frontends/as102_fe.c
  50. 4 6
      drivers/media/dvb-frontends/cx24113.c
  51. 8 14
      drivers/media/dvb-frontends/cx24116.c
  52. 4 5
      drivers/media/dvb-frontends/drxd_hard.c
  53. 7 15
      drivers/media/dvb-frontends/ds3000.c
  54. 0 14
      drivers/media/dvb-frontends/lg2160.c
  55. 2 1
      drivers/media/dvb-frontends/lgdt3306a.c
  56. 7 16
      drivers/media/dvb-frontends/mb86a20s.c
  57. 1 1
      drivers/media/dvb-frontends/mxl5xx.c
  58. 0 1
      drivers/media/dvb-frontends/si2168.c
  59. 4 5
      drivers/media/dvb-frontends/sp2.c
  60. 0 7
      drivers/media/dvb-frontends/stv0288.c
  61. 0 9
      drivers/media/dvb-frontends/stv6110.c
  62. 16 0
      drivers/media/i2c/Kconfig
  63. 1 0
      drivers/media/i2c/Makefile
  64. 1 1
      drivers/media/i2c/adv7180.c
  65. 6 1
      drivers/media/i2c/adv748x/adv748x-afe.c
  66. 4 6
      drivers/media/i2c/adv7604.c
  67. 2 4
      drivers/media/i2c/adv7842.c
  68. 1 1
      drivers/media/i2c/cx25840/cx25840-core.c
  69. 6 1
      drivers/media/i2c/dw9714.c
  70. 1 1
      drivers/media/i2c/et8ek8/et8ek8_driver.c
  71. 1811 0
      drivers/media/i2c/imx274.c
  72. 0 1
      drivers/media/i2c/ir-kbd-i2c.c
  73. 1 1
      drivers/media/i2c/max2175.c
  74. 1 1
      drivers/media/i2c/mt9m111.c
  75. 38 23
      drivers/media/i2c/ov13858.c
  76. 8 9
      drivers/media/i2c/ov2640.c
  77. 1 1
      drivers/media/i2c/ov5640.c
  78. 36 15
      drivers/media/i2c/ov5647.c
  79. 26 11
      drivers/media/i2c/ov5670.c
  80. 1 4
      drivers/media/i2c/ov6650.c
  81. 122 7
      drivers/media/i2c/ov7670.c
  82. 0 1
      drivers/media/i2c/ov9650.c
  83. 75 74
      drivers/media/i2c/smiapp/smiapp-core.c
  84. 3 0
      drivers/media/i2c/smiapp/smiapp-regs.c
  85. 1 0
      drivers/media/i2c/smiapp/smiapp.h
  86. 4 7
      drivers/media/i2c/soc_camera/ov9640.c
  87. 2 4
      drivers/media/i2c/soc_camera/ov9740.c
  88. 209 11
      drivers/media/i2c/tc358743.c
  89. 92 2
      drivers/media/i2c/tc358743_regs.h
  90. 3 5
      drivers/media/i2c/tvaudio.c
  91. 8 5
      drivers/media/media-entity.c
  92. 2 2
      drivers/media/pci/b2c2/Kconfig
  93. 3 3
      drivers/media/pci/bt8xx/bttv-driver.c
  94. 10 9
      drivers/media/pci/bt8xx/bttv-input.c
  95. 1 1
      drivers/media/pci/bt8xx/bttv-vbi.c
  96. 2 1
      drivers/media/pci/bt8xx/bttvp.h
  97. 0 5
      drivers/media/pci/cobalt/cobalt-driver.c
  98. 13 15
      drivers/media/pci/cx18/cx18-driver.c
  99. 2 2
      drivers/media/pci/cx18/cx18-fileops.c
  100. 1 1
      drivers/media/pci/cx18/cx18-fileops.h

+ 32 - 0
Documentation/devicetree/bindings/media/cec-gpio.txt

@@ -0,0 +1,32 @@
+* HDMI CEC GPIO driver
+
+The HDMI CEC GPIO module supports CEC implementations where the CEC line
+is hooked up to a pull-up GPIO line and - optionally - the HPD line is
+hooked up to another GPIO line.
+
+Required properties:
+  - compatible: value must be "cec-gpio".
+  - cec-gpios: gpio that the CEC line is connected to. The line should be
+    tagged as open drain.
+
+If the CEC line is associated with an HDMI receiver/transmitter, then the
+following property is also required:
+
+  - hdmi-phandle - phandle to the HDMI controller, see also cec.txt.
+
+If the CEC line is not associated with an HDMI receiver/transmitter, then
+the following property is optional:
+
+  - hpd-gpios: gpio that the HPD line is connected to.
+
+Example for the Raspberry Pi 3 where the CEC line is connected to
+pin 26 aka BCM7 aka CE1 on the GPIO pin header and the HPD line is
+connected to pin 11 aka BCM17:
+
+#include <dt-bindings/gpio/gpio.h>
+
+cec-gpio {
+       compatible = "cec-gpio";
+       cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+       hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+};

+ 6 - 3
Documentation/devicetree/bindings/media/exynos5-gsc.txt

@@ -3,8 +3,11 @@
 G-Scaler is used for scaling and color space conversion on EXYNOS5 SoCs.
 G-Scaler is used for scaling and color space conversion on EXYNOS5 SoCs.
 
 
 Required properties:
 Required properties:
-- compatible: should be "samsung,exynos5-gsc" (for Exynos 5250, 5420 and
-	      5422 SoCs) or "samsung,exynos5433-gsc" (Exynos 5433)
+- compatible: should be one of
+	      "samsung,exynos5250-gsc"
+	      "samsung,exynos5420-gsc"
+	      "samsung,exynos5433-gsc"
+	      "samsung,exynos5-gsc" (deprecated)
 - reg: should contain G-Scaler physical address location and length.
 - reg: should contain G-Scaler physical address location and length.
 - interrupts: should contain G-Scaler interrupt number
 - interrupts: should contain G-Scaler interrupt number
 
 
@@ -15,7 +18,7 @@ Optional properties:
 Example:
 Example:
 
 
 gsc_0:  gsc@0x13e00000 {
 gsc_0:  gsc@0x13e00000 {
-	compatible = "samsung,exynos5-gsc";
+	compatible = "samsung,exynos5250-gsc";
 	reg = <0x13e00000 0x1000>;
 	reg = <0x13e00000 0x1000>;
 	interrupts = <0 85 0>;
 	interrupts = <0 85 0>;
 };
 };

+ 33 - 0
Documentation/devicetree/bindings/media/i2c/imx274.txt

@@ -0,0 +1,33 @@
+* Sony 1/2.5-Inch 8.51Mp CMOS Digital Image Sensor
+
+The Sony imx274 is a 1/2.5-inch CMOS active pixel digital image sensor with
+an active array size of 3864H x 2202V. It is programmable through I2C
+interface. The I2C address is fixed to 0x1a as per sensor data sheet.
+Image data is sent through MIPI CSI-2, which is configured as 4 lanes
+at 1440 Mbps.
+
+
+Required Properties:
+- compatible: value should be "sony,imx274" for imx274 sensor
+- reg: I2C bus address of the device
+
+Optional Properties:
+- reset-gpios: Sensor reset GPIO
+
+The imx274 device node should contain one 'port' child node with
+an 'endpoint' subnode. For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+	sensor@1a {
+		compatible = "sony,imx274";
+		reg = <0x1a>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reset-gpios = <&gpio_sensor 0 0>;
+		port {
+			sensor_out: endpoint {
+				remote-endpoint = <&csiss_in>;
+			};
+		};
+	};

+ 2 - 0
Documentation/devicetree/bindings/media/i2c/nokia,smia.txt

@@ -27,6 +27,8 @@ Optional properties
 - nokia,nvm-size: The size of the NVM, in bytes. If the size is not given,
 - nokia,nvm-size: The size of the NVM, in bytes. If the size is not given,
   the NVM contents will not be read.
   the NVM contents will not be read.
 - reset-gpios: XSHUTDOWN GPIO
 - reset-gpios: XSHUTDOWN GPIO
+- flash-leds: See ../video-interfaces.txt
+- lens-focus: See ../video-interfaces.txt
 
 
 
 
 Endpoint node mandatory properties
 Endpoint node mandatory properties

+ 33 - 0
Documentation/devicetree/bindings/media/rockchip-rga.txt

@@ -0,0 +1,33 @@
+device-tree bindings for rockchip 2D raster graphic acceleration controller (RGA)
+
+RGA is a standalone 2D raster graphic acceleration unit. It accelerates 2D
+graphics operations, such as point/line drawing, image scaling, rotation,
+BitBLT, alpha blending and image blur/sharpness.
+
+Required properties:
+- compatible: value should be one of the following
+		"rockchip,rk3288-rga";
+		"rockchip,rk3399-rga";
+
+- interrupts: RGA interrupt specifier.
+
+- clocks: phandle to RGA sclk/hclk/aclk clocks
+
+- clock-names: should be "aclk", "hclk" and "sclk"
+
+- resets: Must contain an entry for each entry in reset-names.
+  See ../reset/reset.txt for details.
+- reset-names: should be "core", "axi" and "ahb"
+
+Example:
+SoC-specific DT entry:
+	rga: rga@ff680000 {
+		compatible = "rockchip,rk3399-rga";
+		reg = <0xff680000 0x10000>;
+		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&cru ACLK_RGA>, <&cru HCLK_RGA>, <&cru SCLK_RGA_CORE>;
+		clock-names = "aclk", "hclk", "sclk";
+
+		resets = <&cru SRST_RGA_CORE>, <&cru SRST_A_RGA>, <&cru SRST_H_RGA>;
+		reset-names = "core, "axi", "ahb";
+	};

+ 21 - 0
Documentation/devicetree/bindings/media/tango-ir.txt

@@ -0,0 +1,21 @@
+Sigma Designs Tango IR NEC/RC-5/RC-6 decoder (SMP86xx and SMP87xx)
+
+Required properties:
+
+- compatible: "sigma,smp8642-ir"
+- reg: address/size of NEC+RC5 area, address/size of RC6 area
+- interrupts: spec for IR IRQ
+- clocks: spec for IR clock (typically the crystal oscillator)
+
+Optional properties:
+
+- linux,rc-map-name: see Documentation/devicetree/bindings/media/rc.txt
+
+Example:
+
+	ir@10518 {
+		compatible = "sigma,smp8642-ir";
+		reg = <0x10518 0x18>, <0x105e0 0x1c>;
+		interrupts = <21 IRQ_TYPE_EDGE_RISING>;
+		clocks = <&xtal>;
+	};

+ 27 - 0
Documentation/devicetree/bindings/media/tegra-cec.txt

@@ -0,0 +1,27 @@
+* Tegra HDMI CEC hardware
+
+The HDMI CEC module is present in Tegra SoCs and its purpose is to
+handle communication between HDMI connected devices over the CEC bus.
+
+Required properties:
+  - compatible : value should be one of the following:
+	"nvidia,tegra114-cec"
+	"nvidia,tegra124-cec"
+	"nvidia,tegra210-cec"
+  - reg : Physical base address of the IP registers and length of memory
+	  mapped region.
+  - interrupts : HDMI CEC interrupt number to the CPU.
+  - clocks : from common clock binding: handle to HDMI CEC clock.
+  - clock-names : from common clock binding: must contain "cec",
+		  corresponding to the entry in the clocks property.
+  - hdmi-phandle : phandle to the HDMI controller, see also cec.txt.
+
+Example:
+
+cec@70015000 {
+	compatible = "nvidia,tegra124-cec";
+	reg = <0x0 0x70015000 0x0 0x00001000>;
+	interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&tegra_car TEGRA124_CLK_CEC>;
+	clock-names = "cec";
+};

+ 23 - 1
Documentation/devicetree/bindings/media/video-interfaces.txt

@@ -55,6 +55,15 @@ divided into two separate ITU-R BT.656 8-bit busses.  In such case bus-width
 and data-shift properties can be used to assign physical data lines to each
 and data-shift properties can be used to assign physical data lines to each
 endpoint node (logical bus).
 endpoint node (logical bus).
 
 
+Documenting bindings for devices
+--------------------------------
+
+All required and optional bindings the device supports shall be explicitly
+documented in device DT binding documentation. This also includes port and
+endpoint nodes for the device, including unit-addresses and reg properties where
+relevant.
+
+Please also see Documentation/devicetree/bindings/graph.txt .
 
 
 Required properties
 Required properties
 -------------------
 -------------------
@@ -67,6 +76,16 @@ are required in a relevant parent node:
 		    identifier, should be 1.
 		    identifier, should be 1.
  - #size-cells    : should be zero.
  - #size-cells    : should be zero.
 
 
+
+Optional properties
+-------------------
+
+- flash-leds: An array of phandles, each referring to a flash LED, a sub-node
+  of the LED driver device node.
+
+- lens-focus: A phandle to the node of the focus lens controller.
+
+
 Optional endpoint properties
 Optional endpoint properties
 ----------------------------
 ----------------------------
 
 
@@ -99,7 +118,10 @@ Optional endpoint properties
   determines the logical lane number, while the value of an entry indicates
   determines the logical lane number, while the value of an entry indicates
   physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have
   physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have
   "data-lanes = <1 2>;", assuming the clock lane is on hardware lane 0.
   "data-lanes = <1 2>;", assuming the clock lane is on hardware lane 0.
-  This property is valid for serial busses only (e.g. MIPI CSI-2).
+  If the hardware does not support lane reordering, monotonically
+  incremented values shall be used from 0 or 1 onwards, depending on
+  whether or not there is also a clock lane. This property is valid for
+  serial busses only (e.g. MIPI CSI-2).
 - clock-lanes: an array of physical clock lane indexes. Position of an entry
 - clock-lanes: an array of physical clock lane indexes. Position of an entry
   determines the logical lane number, while the value of an entry indicates
   determines the logical lane number, while the value of an entry indicates
   physical lane, e.g. for a MIPI CSI-2 bus we could have "clock-lanes = <0>;",
   physical lane, e.g. for a MIPI CSI-2 bus we could have "clock-lanes = <0>;",

+ 0 - 2
Documentation/media/cec.h.rst.exceptions

@@ -24,8 +24,6 @@ ignore define CEC_VENDOR_ID_NONE
 ignore define CEC_MODE_INITIATOR_MSK
 ignore define CEC_MODE_INITIATOR_MSK
 ignore define CEC_MODE_FOLLOWER_MSK
 ignore define CEC_MODE_FOLLOWER_MSK
 
 
-ignore define CEC_EVENT_FL_INITIAL_STATE
-
 # Part of CEC 2.0 spec - shouldn't be documented too?
 # Part of CEC 2.0 spec - shouldn't be documented too?
 ignore define CEC_LOG_ADDR_TV
 ignore define CEC_LOG_ADDR_TV
 ignore define CEC_LOG_ADDR_RECORD_1
 ignore define CEC_LOG_ADDR_RECORD_1

+ 5 - 2
Documentation/media/kapi/cec-core.rst

@@ -227,8 +227,8 @@ CEC_TX_STATUS_LOW_DRIVE:
 	retransmission.
 	retransmission.
 
 
 CEC_TX_STATUS_ERROR:
 CEC_TX_STATUS_ERROR:
-	some unspecified error occurred: this can be one of
-	the previous two if the hardware cannot differentiate or something
+	some unspecified error occurred: this can be one of ARB_LOST
+	or LOW_DRIVE if the hardware cannot differentiate or something
 	else entirely.
 	else entirely.
 
 
 CEC_TX_STATUS_MAX_RETRIES:
 CEC_TX_STATUS_MAX_RETRIES:
@@ -238,6 +238,9 @@ CEC_TX_STATUS_MAX_RETRIES:
 	doesn't have to make another attempt to transmit the message
 	doesn't have to make another attempt to transmit the message
 	since the hardware did that already.
 	since the hardware did that already.
 
 
+The hardware must be able to differentiate between OK, NACK and 'something
+else'.
+
 The \*_cnt arguments are the number of error conditions that were seen.
 The \*_cnt arguments are the number of error conditions that were seen.
 This may be 0 if no information is available. Drivers that do not support
 This may be 0 if no information is available. Drivers that do not support
 hardware retry can just set the counter corresponding to the transmit error
 hardware retry can just set the counter corresponding to the transmit error

+ 4 - 0
Documentation/media/kapi/dtv-ca.rst

@@ -0,0 +1,4 @@
+Digital TV Conditional Access kABI
+----------------------------------
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_ca_en50221.h

+ 55 - 0
Documentation/media/kapi/dtv-common.rst

@@ -0,0 +1,55 @@
+Digital TV Common functions
+---------------------------
+
+Math functions
+~~~~~~~~~~~~~~
+
+Provide some commonly-used math functions, usually required in order to
+estimate signal strength and signal to noise measurements in dB.
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_math.h
+
+
+DVB devices
+~~~~~~~~~~~
+
+Those functions are responsible for handling the DVB device nodes.
+
+.. kernel-doc:: drivers/media/dvb-core/dvbdev.h
+
+Digital TV Ring buffer
+~~~~~~~~~~~~~~~~~~~~~~
+
+Those routines implement ring buffers used to handle digital TV data and
+copy it from/to userspace.
+
+.. note::
+
+  1) For performance reasons read and write routines don't check buffer sizes
+     and/or number of bytes free/available. This has to be done before these
+     routines are called. For example:
+
+   .. code-block:: c
+
+        /* write @buflen: bytes */
+        free = dvb_ringbuffer_free(rbuf);
+        if (free >= buflen)
+                count = dvb_ringbuffer_write(rbuf, buffer, buflen);
+        else
+                /* do something */
+
+        /* read min. 1000, max. @bufsize: bytes */
+        avail = dvb_ringbuffer_avail(rbuf);
+        if (avail >= 1000)
+                count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
+        else
+                /* do something */
+
+  2) If there is exactly one reader and one writer, there is no need
+     to lock read or write operations.
+     Two or more readers must be locked against each other.
+     Flushing the buffer counts as a read operation.
+     Resetting the buffer counts as a read and write operation.
+     Two or more writers must be locked against each other.
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_ringbuffer.h

+ 7 - 567
Documentation/media/kapi/dtv-core.rst

@@ -26,572 +26,12 @@ I2C bus.
    abandoned standard, not used anymore) and ATSC version 3.0 current
    abandoned standard, not used anymore) and ATSC version 3.0 current
    proposals. Currently, the DVB subsystem doesn't implement those standards.
    proposals. Currently, the DVB subsystem doesn't implement those standards.
 
 
-Digital TV Common functions
----------------------------
 
 
-.. kernel-doc:: drivers/media/dvb-core/dvb_math.h
+.. toctree::
+    :maxdepth: 1
 
 
-.. kernel-doc:: drivers/media/dvb-core/dvbdev.h
-
-Digital TV Ring buffer
-----------------------
-
-Those routines implement ring buffers used to handle digital TV data and
-copy it from/to userspace.
-
-.. note::
-
-  1) For performance reasons read and write routines don't check buffer sizes
-     and/or number of bytes free/available. This has to be done before these
-     routines are called. For example:
-
-   .. code-block:: c
-
-        /* write @buflen: bytes */
-        free = dvb_ringbuffer_free(rbuf);
-        if (free >= buflen)
-                count = dvb_ringbuffer_write(rbuf, buffer, buflen);
-        else
-                /* do something */
-
-        /* read min. 1000, max. @bufsize: bytes */
-        avail = dvb_ringbuffer_avail(rbuf);
-        if (avail >= 1000)
-                count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize));
-        else
-                /* do something */
-
-  2) If there is exactly one reader and one writer, there is no need
-     to lock read or write operations.
-     Two or more readers must be locked against each other.
-     Flushing the buffer counts as a read operation.
-     Resetting the buffer counts as a read and write operation.
-     Two or more writers must be locked against each other.
-
-.. kernel-doc:: drivers/media/dvb-core/dvb_ringbuffer.h
-
-
-Digital TV Frontend kABI
-------------------------
-
-Digital TV Frontend
-~~~~~~~~~~~~~~~~~~~
-
-The Digital TV Frontend kABI defines a driver-internal interface for
-registering low-level, hardware specific driver to a hardware independent
-frontend layer. It is only of interest for Digital TV device driver writers.
-The header file for this API is named ``dvb_frontend.h`` and located in
-``drivers/media/dvb-core``.
-
-Demodulator driver
-^^^^^^^^^^^^^^^^^^
-
-The demodulator driver is responsible to talk with the decoding part of the
-hardware. Such driver should implement :c:type:`dvb_frontend_ops`, with
-tells what type of digital TV standards are supported, and points to a
-series of functions that allow the DVB core to command the hardware via
-the code under ``drivers/media/dvb-core/dvb_frontend.c``.
-
-A typical example of such struct in a driver ``foo`` is::
-
-	static struct dvb_frontend_ops foo_ops = {
-		.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
-		.info = {
-			.name	= "foo DVB-T/T2/C driver",
-			.caps = FE_CAN_FEC_1_2 |
-				FE_CAN_FEC_2_3 |
-				FE_CAN_FEC_3_4 |
-				FE_CAN_FEC_5_6 |
-				FE_CAN_FEC_7_8 |
-				FE_CAN_FEC_AUTO |
-				FE_CAN_QPSK |
-				FE_CAN_QAM_16 |
-				FE_CAN_QAM_32 |
-				FE_CAN_QAM_64 |
-				FE_CAN_QAM_128 |
-				FE_CAN_QAM_256 |
-				FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_HIERARCHY_AUTO |
-				FE_CAN_MUTE_TS |
-				FE_CAN_2G_MODULATION,
-			.frequency_min = 42000000, /* Hz */
-			.frequency_max = 1002000000, /* Hz */
-			.symbol_rate_min = 870000,
-			.symbol_rate_max = 11700000
-		},
-		.init = foo_init,
-		.sleep = foo_sleep,
-		.release = foo_release,
-		.set_frontend = foo_set_frontend,
-		.get_frontend = foo_get_frontend,
-		.read_status = foo_get_status_and_stats,
-		.tune = foo_tune,
-		.i2c_gate_ctrl = foo_i2c_gate_ctrl,
-		.get_frontend_algo = foo_get_algo,
-	};
-
-A typical example of such struct in a driver ``bar`` meant to be used on
-Satellite TV reception is::
-
-	static const struct dvb_frontend_ops bar_ops = {
-		.delsys = { SYS_DVBS, SYS_DVBS2 },
-		.info = {
-			.name		= "Bar DVB-S/S2 demodulator",
-			.frequency_min	= 500000, /* KHz */
-			.frequency_max	= 2500000, /* KHz */
-			.frequency_stepsize	= 0,
-			.symbol_rate_min = 1000000,
-			.symbol_rate_max = 45000000,
-			.symbol_rate_tolerance = 500,
-			.caps = FE_CAN_INVERSION_AUTO |
-				FE_CAN_FEC_AUTO |
-				FE_CAN_QPSK,
-		},
-		.init = bar_init,
-		.sleep = bar_sleep,
-		.release = bar_release,
-		.set_frontend = bar_set_frontend,
-		.get_frontend = bar_get_frontend,
-		.read_status = bar_get_status_and_stats,
-		.i2c_gate_ctrl = bar_i2c_gate_ctrl,
-		.get_frontend_algo = bar_get_algo,
-		.tune = bar_tune,
-
-		/* Satellite-specific */
-		.diseqc_send_master_cmd = bar_send_diseqc_msg,
-		.diseqc_send_burst = bar_send_burst,
-		.set_tone = bar_set_tone,
-		.set_voltage = bar_set_voltage,
-	};
-
-.. note::
-
-   #) For satellite digital TV standards (DVB-S, DVB-S2, ISDB-S), the
-      frequencies are specified in kHz, while, for terrestrial and cable
-      standards, they're specified in Hz. Due to that, if the same frontend
-      supports both types, you'll need to have two separate
-      :c:type:`dvb_frontend_ops` structures, one for each standard.
-   #) The ``.i2c_gate_ctrl`` field is present only when the hardware has
-      allows controlling an I2C gate (either directly of via some GPIO pin),
-      in order to remove the tuner from the I2C bus after a channel is
-      tuned.
-   #) All new drivers should implement the
-      :ref:`DVBv5 statistics <dvbv5_stats>` via ``.read_status``.
-      Yet, there are a number of callbacks meant to get statistics for
-      signal strength, S/N and UCB. Those are there to provide backward
-      compatibility with legacy applications that don't support the DVBv5
-      API. Implementing those callbacks are optional. Those callbacks may be
-      removed in the future, after we have all existing drivers supporting
-      DVBv5 stats.
-   #) Other callbacks are required for satellite TV standards, in order to
-      control LNBf and DiSEqC: ``.diseqc_send_master_cmd``,
-      ``.diseqc_send_burst``, ``.set_tone``, ``.set_voltage``.
-
-.. |delta|   unicode:: U+00394
-
-The ``drivers/media/dvb-core/dvb_frontend.c`` has a kernel thread with is
-responsible for tuning the device. It supports multiple algoritms to
-detect a channel, as defined at enum :c:func:`dvbfe_algo`.
-
-The algorithm to be used is obtained via ``.get_frontend_algo``. If the driver
-doesn't fill its field at struct :c:type:`dvb_frontend_ops`, it will default to
-``DVBFE_ALGO_SW``, meaning that the dvb-core will do a zigzag when tuning,
-e. g. it will try first to use the specified center frequency ``f``,
-then, it will do ``f`` + |delta|, ``f`` - |delta|, ``f`` + 2 x |delta|,
-``f`` - 2 x |delta| and so on.
-
-If the hardware has internally a some sort of zigzag algorithm, you should
-define a ``.get_frontend_algo`` function that would return ``DVBFE_ALGO_HW``.
-
-.. note::
-
-   The core frontend support also supports
-   a third type (``DVBFE_ALGO_CUSTOM``), in order to allow the driver to
-   define its own hardware-assisted algorithm. Very few hardware need to
-   use it nowadays. Using ``DVBFE_ALGO_CUSTOM`` require to provide other
-   function callbacks at struct :c:type:`dvb_frontend_ops`.
-
-Attaching frontend driver to the bridge driver
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Before using the Digital TV frontend core, the bridge driver should attach
-the frontend demod, tuner and SEC devices and call
-:c:func:`dvb_register_frontend()`,
-in order to register the new frontend at the subsystem. At device
-detach/removal, the bridge driver should call
-:c:func:`dvb_unregister_frontend()` to
-remove the frontend from the core and then :c:func:`dvb_frontend_detach()`
-to free the memory allocated by the frontend drivers.
-
-The drivers should also call :c:func:`dvb_frontend_suspend()` as part of
-their handler for the :c:type:`device_driver`.\ ``suspend()``, and
-:c:func:`dvb_frontend_resume()` as
-part of their handler for :c:type:`device_driver`.\ ``resume()``.
-
-A few other optional functions are provided to handle some special cases.
-
-.. _dvbv5_stats:
-
-Digital TV Frontend statistics
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Introduction
-^^^^^^^^^^^^
-
-Digital TV frontends provide a range of
-:ref:`statistics <frontend-stat-properties>` meant to help tuning the device
-and measuring the quality of service.
-
-For each statistics measurement, the driver should set the type of scale used,
-or ``FE_SCALE_NOT_AVAILABLE`` if the statistics is not available on a given
-time. Drivers should also provide the number of statistics for each type.
-that's usually 1 for most video standards [#f2]_.
-
-Drivers should initialize each statistic counters with length and
-scale at its init code. For example, if the frontend provides signal
-strength, it should have, on its init code::
-
-	struct dtv_frontend_properties *c = &state->fe.dtv_property_cache;
-
-	c->strength.len = 1;
-	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
-
-And, when the statistics got updated, set the scale::
-
-	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
-	c->strength.stat[0].uvalue = strength;
-
-.. [#f2] For ISDB-T, it may provide both a global statistics and a per-layer
-   set of statistics. On such cases, len should be equal to 4. The first
-   value corresponds to the global stat; the other ones to each layer, e. g.:
-
-   - c->cnr.stat[0] for global S/N carrier ratio,
-   - c->cnr.stat[1] for Layer A S/N carrier ratio,
-   - c->cnr.stat[2] for layer B S/N carrier ratio,
-   - c->cnr.stat[3] for layer C S/N carrier ratio.
-
-.. note:: Please prefer to use ``FE_SCALE_DECIBEL`` instead of
-   ``FE_SCALE_RELATIVE`` for signal strength and CNR measurements.
-
-Groups of statistics
-^^^^^^^^^^^^^^^^^^^^
-
-There are several groups of statistics currently supported:
-
-Signal strength (:ref:`DTV-STAT-SIGNAL-STRENGTH`)
-  - Measures the signal strength level at the analog part of the tuner or
-    demod.
-
-  - Typically obtained from the gain applied to the tuner and/or frontend
-    in order to detect the carrier. When no carrier is detected, the gain is
-    at the maximum value (so, strength is on its minimal).
-
-  - As the gain is visible through the set of registers that adjust the gain,
-    typically, this statistics is always available [#f3]_.
-
-  - Drivers should try to make it available all the times, as this statistics
-    can be used when adjusting an antenna position and to check for troubles
-    at the cabling.
-
-  .. [#f3] On a few devices, the gain keeps floating if no carrier.
-     On such devices, strength report should check first if carrier is
-     detected at the tuner (``FE_HAS_CARRIER``, see :c:type:`fe_status`),
-     and otherwise return the lowest possible value.
-
-Carrier Signal to Noise ratio (:ref:`DTV-STAT-CNR`)
-  - Signal to Noise ratio for the main carrier.
-
-  - Signal to Noise measurement depends on the device. On some hardware, is
-    available when the main carrier is detected. On those hardware, CNR
-    measurement usually comes from the tuner (e. g. after ``FE_HAS_CARRIER``,
-    see :c:type:`fe_status`).
-
-    On other devices, it requires inner FEC decoding,
-    as the frontend measures it indirectly from other parameters (e. g. after
-    ``FE_HAS_VITERBI``, see :c:type:`fe_status`).
-
-    Having it available after inner FEC is more common.
-
-Bit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POST-TOTAL-BIT-COUNT`)
-  - Those counters measure the number of bits and bit errors errors after
-    the forward error correction (FEC) on the inner coding block
-    (after Viterbi, LDPC or other inner code).
-
-  - Due to its nature, those statistics depend on full coding lock
-    (e. g. after ``FE_HAS_SYNC`` or after ``FE_HAS_LOCK``,
-    see :c:type:`fe_status`).
-
-Bit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-TOTAL-BIT-COUNT`)
-  - Those counters measure the number of bits and bit errors errors before
-    the forward error correction (FEC) on the inner coding block
-    (before Viterbi, LDPC or other inner code).
-
-  - Not all frontends provide this kind of statistics.
-
-  - Due to its nature, those statistics depend on inner coding lock (e. g.
-    after ``FE_HAS_VITERBI``, see :c:type:`fe_status`).
-
-Block counts (:ref:`DTV-STAT-ERROR-BLOCK-COUNT` and :ref:`DTV-STAT-TOTAL-BLOCK-COUNT`)
-  - Those counters measure the number of blocks and block errors errors after
-    the forward error correction (FEC) on the inner coding block
-    (before Viterbi, LDPC or other inner code).
-
-  - Due to its nature, those statistics depend on full coding lock
-    (e. g. after ``FE_HAS_SYNC`` or after
-    ``FE_HAS_LOCK``, see :c:type:`fe_status`).
-
-.. note:: All counters should be monotonically increased as they're
-   collected from the hardware.
-
-A typical example of the logic that handle status and statistics is::
-
-	static int foo_get_status_and_stats(struct dvb_frontend *fe)
-	{
-		struct foo_state *state = fe->demodulator_priv;
-		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-		int rc;
-		enum fe_status *status;
-
-		/* Both status and strength are always available */
-		rc = foo_read_status(fe, &status);
-		if (rc < 0)
-			return rc;
-
-		rc = foo_read_strength(fe);
-		if (rc < 0)
-			return rc;
-
-		/* Check if CNR is available */
-		if (!(fe->status & FE_HAS_CARRIER))
-			return 0;
-
-		rc = foo_read_cnr(fe);
-		if (rc < 0)
-			return rc;
-
-		/* Check if pre-BER stats are available */
-		if (!(fe->status & FE_HAS_VITERBI))
-			return 0;
-
-		rc = foo_get_pre_ber(fe);
-		if (rc < 0)
-			return rc;
-
-		/* Check if post-BER stats are available */
-		if (!(fe->status & FE_HAS_SYNC))
-			return 0;
-
-		rc = foo_get_post_ber(fe);
-		if (rc < 0)
-			return rc;
-	}
-
-	static const struct dvb_frontend_ops ops = {
-		/* ... */
-		.read_status = foo_get_status_and_stats,
-	};
-
-Statistics collect
-^^^^^^^^^^^^^^^^^^
-
-On almost all frontend hardware, the bit and byte counts are stored by
-the hardware after a certain amount of time or after the total bit/block
-counter reaches a certain value (usually programable), for example, on
-every 1000 ms or after receiving 1,000,000 bits.
-
-So, if you read the registers too soon, you'll end by reading the same
-value as in the previous reading, causing the monotonic value to be
-incremented too often.
-
-Drivers should take the responsibility to avoid too often reads. That
-can be done using two approaches:
-
-if the driver have a bit that indicates when a collected data is ready
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-Driver should check such bit before making the statistics available.
-
-An example of such behavior can be found at this code snippet (adapted
-from mb86a20s driver's logic)::
-
-	static int foo_get_pre_ber(struct dvb_frontend *fe)
-	{
-		struct foo_state *state = fe->demodulator_priv;
-		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-		int rc, bit_error;
-
-		/* Check if the BER measures are already available */
-		rc = foo_read_u8(state, 0x54);
-		if (rc < 0)
-			return rc;
-
-		if (!rc)
-			return 0;
-
-		/* Read Bit Error Count */
-		bit_error = foo_read_u32(state, 0x55);
-		if (bit_error < 0)
-			return bit_error;
-
-		/* Read Total Bit Count */
-		rc = foo_read_u32(state, 0x51);
-		if (rc < 0)
-			return rc;
-
-		c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
-		c->pre_bit_error.stat[0].uvalue += bit_error;
-		c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
-		c->pre_bit_count.stat[0].uvalue += rc;
-
-		return 0;
-	}
-
-If the driver doesn't provide a statistics available check bit
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-A few devices, however, may not provide a way to check if the stats are
-available (or the way to check it is unknown). They may not even provide
-a way to directly read the total number of bits or blocks.
-
-On those devices, the driver need to ensure that it won't be reading from
-the register too often and/or estimate the total number of bits/blocks.
-
-On such drivers, a typical routine to get statistics would be like
-(adapted from dib8000 driver's logic)::
-
-	struct foo_state {
-		/* ... */
-
-		unsigned long per_jiffies_stats;
-	}
-
-	static int foo_get_pre_ber(struct dvb_frontend *fe)
-	{
-		struct foo_state *state = fe->demodulator_priv;
-		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-		int rc, bit_error;
-		u64 bits;
-
-		/* Check if time for stats was elapsed */
-		if (!time_after(jiffies, state->per_jiffies_stats))
-			return 0;
-
-		/* Next stat should be collected in 1000 ms */
-		state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
-
-		/* Read Bit Error Count */
-		bit_error = foo_read_u32(state, 0x55);
-		if (bit_error < 0)
-			return bit_error;
-
-		/*
-		 * On this particular frontend, there's no register that
-		 * would provide the number of bits per 1000ms sample. So,
-		 * some function would calculate it based on DTV properties
-		 */
-		bits = get_number_of_bits_per_1000ms(fe);
-
-		c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
-		c->pre_bit_error.stat[0].uvalue += bit_error;
-		c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
-		c->pre_bit_count.stat[0].uvalue += bits;
-
-		return 0;
-	}
-
-Please notice that, on both cases, we're getting the statistics using the
-:c:type:`dvb_frontend_ops` ``.read_status`` callback. The rationale is that
-the frontend core will automatically call this function periodically
-(usually, 3 times per second, when the frontend is locked).
-
-That warrants that we won't miss to collect a counter and increment the
-monotonic stats at the right time.
-
-Digital TV Frontend functions and types
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. kernel-doc:: drivers/media/dvb-core/dvb_frontend.h
-
-
-Digital TV Demux kABI
----------------------
-
-Digital TV Demux
-~~~~~~~~~~~~~~~~
-
-The Kernel Digital TV Demux kABI defines a driver-internal interface for
-registering low-level, hardware specific driver to a hardware independent
-demux layer. It is only of interest for Digital TV device driver writers.
-The header file for this kABI is named demux.h and located in
-drivers/media/dvb-core.
-
-The demux kABI should be implemented for each demux in the system. It is
-used to select the TS source of a demux and to manage the demux resources.
-When the demux client allocates a resource via the demux kABI, it receives
-a pointer to the kABI of that resource.
-
-Each demux receives its TS input from a DVB front-end or from memory, as
-set via this demux kABI. In a system with more than one front-end, the kABI
-can be used to select one of the DVB front-ends as a TS source for a demux,
-unless this is fixed in the HW platform.
-
-The demux kABI only controls front-ends regarding to their connections with
-demuxes; the kABI used to set the other front-end parameters, such as
-tuning, are devined via the Digital TV Frontend kABI.
-
-The functions that implement the abstract interface demux should be defined
-static or module private and registered to the Demux core for external
-access. It is not necessary to implement every function in the struct
-&dmx_demux. For example, a demux interface might support Section filtering,
-but not PES filtering. The kABI client is expected to check the value of any
-function pointer before calling the function: the value of ``NULL`` means
-that the function is not available.
-
-Whenever the functions of the demux API modify shared data, the
-possibilities of lost update and race condition problems should be
-addressed, e.g. by protecting parts of code with mutexes.
-
-Note that functions called from a bottom half context must not sleep.
-Even a simple memory allocation without using ``GFP_ATOMIC`` can result in a
-kernel thread being put to sleep if swapping is needed. For example, the
-Linux Kernel calls the functions of a network device interface from a
-bottom half context. Thus, if a demux kABI function is called from network
-device code, the function must not sleep.
-
-
-
-Demux Callback API
-------------------
-
-Demux Callback
-~~~~~~~~~~~~~~
-
-This kernel-space API comprises the callback functions that deliver filtered
-data to the demux client. Unlike the other DVB kABIs, these functions are
-provided by the client and called from the demux code.
-
-The function pointers of this abstract interface are not packed into a
-structure as in the other demux APIs, because the callback functions are
-registered and used independent of each other. As an example, it is possible
-for the API client to provide several callback functions for receiving TS
-packets and no callbacks for PES packets or sections.
-
-The functions that implement the callback API need not be re-entrant: when
-a demux driver calls one of these functions, the driver is not allowed to
-call the function again before the original call returns. If a callback is
-triggered by a hardware interrupt, it is recommended to use the Linux
-bottom half mechanism or start a tasklet instead of making the callback
-function call directly from a hardware interrupt.
-
-This mechanism is implemented by :c:func:`dmx_ts_cb()` and :c:func:`dmx_section_cb()`
-callbacks.
-
-.. kernel-doc:: drivers/media/dvb-core/demux.h
-
-Digital TV Conditional Access kABI
-----------------------------------
-
-.. kernel-doc:: drivers/media/dvb-core/dvb_ca_en50221.h
+    dtv-common
+    dtv-frontend
+    dtv-demux
+    dtv-ca
+    dtv-net

+ 82 - 0
Documentation/media/kapi/dtv-demux.rst

@@ -0,0 +1,82 @@
+Digital TV Demux kABI
+---------------------
+
+Digital TV Demux
+~~~~~~~~~~~~~~~~
+
+The Kernel Digital TV Demux kABI defines a driver-internal interface for
+registering low-level, hardware specific driver to a hardware independent
+demux layer. It is only of interest for Digital TV device driver writers.
+The header file for this kABI is named ``demux.h`` and located in
+``drivers/media/dvb-core``.
+
+The demux kABI should be implemented for each demux in the system. It is
+used to select the TS source of a demux and to manage the demux resources.
+When the demux client allocates a resource via the demux kABI, it receives
+a pointer to the kABI of that resource.
+
+Each demux receives its TS input from a DVB front-end or from memory, as
+set via this demux kABI. In a system with more than one front-end, the kABI
+can be used to select one of the DVB front-ends as a TS source for a demux,
+unless this is fixed in the HW platform.
+
+The demux kABI only controls front-ends regarding to their connections with
+demuxes; the kABI used to set the other front-end parameters, such as
+tuning, are devined via the Digital TV Frontend kABI.
+
+The functions that implement the abstract interface demux should be defined
+static or module private and registered to the Demux core for external
+access. It is not necessary to implement every function in the struct
+:c:type:`dmx_demux`. For example, a demux interface might support Section filtering,
+but not PES filtering. The kABI client is expected to check the value of any
+function pointer before calling the function: the value of ``NULL`` means
+that the function is not available.
+
+Whenever the functions of the demux API modify shared data, the
+possibilities of lost update and race condition problems should be
+addressed, e.g. by protecting parts of code with mutexes.
+
+Note that functions called from a bottom half context must not sleep.
+Even a simple memory allocation without using ``GFP_ATOMIC`` can result in a
+kernel thread being put to sleep if swapping is needed. For example, the
+Linux Kernel calls the functions of a network device interface from a
+bottom half context. Thus, if a demux kABI function is called from network
+device code, the function must not sleep.
+
+Demux Callback API
+~~~~~~~~~~~~~~~~~~
+
+This kernel-space API comprises the callback functions that deliver filtered
+data to the demux client. Unlike the other DVB kABIs, these functions are
+provided by the client and called from the demux code.
+
+The function pointers of this abstract interface are not packed into a
+structure as in the other demux APIs, because the callback functions are
+registered and used independent of each other. As an example, it is possible
+for the API client to provide several callback functions for receiving TS
+packets and no callbacks for PES packets or sections.
+
+The functions that implement the callback API need not be re-entrant: when
+a demux driver calls one of these functions, the driver is not allowed to
+call the function again before the original call returns. If a callback is
+triggered by a hardware interrupt, it is recommended to use the Linux
+bottom half mechanism or start a tasklet instead of making the callback
+function call directly from a hardware interrupt.
+
+This mechanism is implemented by :c:func:`dmx_ts_cb()` and :c:func:`dmx_section_cb()`
+callbacks.
+
+Digital TV Demux device registration functions and data structures
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/media/dvb-core/dmxdev.h
+
+High-level Digital TV demux interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_demux.h
+
+Driver-internal low-level hardware specific driver demux interface
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/media/dvb-core/demux.h

+ 443 - 0
Documentation/media/kapi/dtv-frontend.rst

@@ -0,0 +1,443 @@
+Digital TV Frontend kABI
+------------------------
+
+Digital TV Frontend
+~~~~~~~~~~~~~~~~~~~
+
+The Digital TV Frontend kABI defines a driver-internal interface for
+registering low-level, hardware specific driver to a hardware independent
+frontend layer. It is only of interest for Digital TV device driver writers.
+The header file for this API is named ``dvb_frontend.h`` and located in
+``drivers/media/dvb-core``.
+
+Demodulator driver
+^^^^^^^^^^^^^^^^^^
+
+The demodulator driver is responsible to talk with the decoding part of the
+hardware. Such driver should implement :c:type:`dvb_frontend_ops`, with
+tells what type of digital TV standards are supported, and points to a
+series of functions that allow the DVB core to command the hardware via
+the code under ``drivers/media/dvb-core/dvb_frontend.c``.
+
+A typical example of such struct in a driver ``foo`` is::
+
+	static struct dvb_frontend_ops foo_ops = {
+		.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
+		.info = {
+			.name	= "foo DVB-T/T2/C driver",
+			.caps = FE_CAN_FEC_1_2 |
+				FE_CAN_FEC_2_3 |
+				FE_CAN_FEC_3_4 |
+				FE_CAN_FEC_5_6 |
+				FE_CAN_FEC_7_8 |
+				FE_CAN_FEC_AUTO |
+				FE_CAN_QPSK |
+				FE_CAN_QAM_16 |
+				FE_CAN_QAM_32 |
+				FE_CAN_QAM_64 |
+				FE_CAN_QAM_128 |
+				FE_CAN_QAM_256 |
+				FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_HIERARCHY_AUTO |
+				FE_CAN_MUTE_TS |
+				FE_CAN_2G_MODULATION,
+			.frequency_min = 42000000, /* Hz */
+			.frequency_max = 1002000000, /* Hz */
+			.symbol_rate_min = 870000,
+			.symbol_rate_max = 11700000
+		},
+		.init = foo_init,
+		.sleep = foo_sleep,
+		.release = foo_release,
+		.set_frontend = foo_set_frontend,
+		.get_frontend = foo_get_frontend,
+		.read_status = foo_get_status_and_stats,
+		.tune = foo_tune,
+		.i2c_gate_ctrl = foo_i2c_gate_ctrl,
+		.get_frontend_algo = foo_get_algo,
+	};
+
+A typical example of such struct in a driver ``bar`` meant to be used on
+Satellite TV reception is::
+
+	static const struct dvb_frontend_ops bar_ops = {
+		.delsys = { SYS_DVBS, SYS_DVBS2 },
+		.info = {
+			.name		= "Bar DVB-S/S2 demodulator",
+			.frequency_min	= 500000, /* KHz */
+			.frequency_max	= 2500000, /* KHz */
+			.frequency_stepsize	= 0,
+			.symbol_rate_min = 1000000,
+			.symbol_rate_max = 45000000,
+			.symbol_rate_tolerance = 500,
+			.caps = FE_CAN_INVERSION_AUTO |
+				FE_CAN_FEC_AUTO |
+				FE_CAN_QPSK,
+		},
+		.init = bar_init,
+		.sleep = bar_sleep,
+		.release = bar_release,
+		.set_frontend = bar_set_frontend,
+		.get_frontend = bar_get_frontend,
+		.read_status = bar_get_status_and_stats,
+		.i2c_gate_ctrl = bar_i2c_gate_ctrl,
+		.get_frontend_algo = bar_get_algo,
+		.tune = bar_tune,
+
+		/* Satellite-specific */
+		.diseqc_send_master_cmd = bar_send_diseqc_msg,
+		.diseqc_send_burst = bar_send_burst,
+		.set_tone = bar_set_tone,
+		.set_voltage = bar_set_voltage,
+	};
+
+.. note::
+
+   #) For satellite digital TV standards (DVB-S, DVB-S2, ISDB-S), the
+      frequencies are specified in kHz, while, for terrestrial and cable
+      standards, they're specified in Hz. Due to that, if the same frontend
+      supports both types, you'll need to have two separate
+      :c:type:`dvb_frontend_ops` structures, one for each standard.
+   #) The ``.i2c_gate_ctrl`` field is present only when the hardware has
+      allows controlling an I2C gate (either directly of via some GPIO pin),
+      in order to remove the tuner from the I2C bus after a channel is
+      tuned.
+   #) All new drivers should implement the
+      :ref:`DVBv5 statistics <dvbv5_stats>` via ``.read_status``.
+      Yet, there are a number of callbacks meant to get statistics for
+      signal strength, S/N and UCB. Those are there to provide backward
+      compatibility with legacy applications that don't support the DVBv5
+      API. Implementing those callbacks are optional. Those callbacks may be
+      removed in the future, after we have all existing drivers supporting
+      DVBv5 stats.
+   #) Other callbacks are required for satellite TV standards, in order to
+      control LNBf and DiSEqC: ``.diseqc_send_master_cmd``,
+      ``.diseqc_send_burst``, ``.set_tone``, ``.set_voltage``.
+
+.. |delta|   unicode:: U+00394
+
+The ``drivers/media/dvb-core/dvb_frontend.c`` has a kernel thread with is
+responsible for tuning the device. It supports multiple algorithms to
+detect a channel, as defined at enum :c:func:`dvbfe_algo`.
+
+The algorithm to be used is obtained via ``.get_frontend_algo``. If the driver
+doesn't fill its field at struct :c:type:`dvb_frontend_ops`, it will default to
+``DVBFE_ALGO_SW``, meaning that the dvb-core will do a zigzag when tuning,
+e. g. it will try first to use the specified center frequency ``f``,
+then, it will do ``f`` + |delta|, ``f`` - |delta|, ``f`` + 2 x |delta|,
+``f`` - 2 x |delta| and so on.
+
+If the hardware has internally a some sort of zigzag algorithm, you should
+define a ``.get_frontend_algo`` function that would return ``DVBFE_ALGO_HW``.
+
+.. note::
+
+   The core frontend support also supports
+   a third type (``DVBFE_ALGO_CUSTOM``), in order to allow the driver to
+   define its own hardware-assisted algorithm. Very few hardware need to
+   use it nowadays. Using ``DVBFE_ALGO_CUSTOM`` require to provide other
+   function callbacks at struct :c:type:`dvb_frontend_ops`.
+
+Attaching frontend driver to the bridge driver
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Before using the Digital TV frontend core, the bridge driver should attach
+the frontend demod, tuner and SEC devices and call
+:c:func:`dvb_register_frontend()`,
+in order to register the new frontend at the subsystem. At device
+detach/removal, the bridge driver should call
+:c:func:`dvb_unregister_frontend()` to
+remove the frontend from the core and then :c:func:`dvb_frontend_detach()`
+to free the memory allocated by the frontend drivers.
+
+The drivers should also call :c:func:`dvb_frontend_suspend()` as part of
+their handler for the :c:type:`device_driver`.\ ``suspend()``, and
+:c:func:`dvb_frontend_resume()` as
+part of their handler for :c:type:`device_driver`.\ ``resume()``.
+
+A few other optional functions are provided to handle some special cases.
+
+.. _dvbv5_stats:
+
+Digital TV Frontend statistics
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Introduction
+^^^^^^^^^^^^
+
+Digital TV frontends provide a range of
+:ref:`statistics <frontend-stat-properties>` meant to help tuning the device
+and measuring the quality of service.
+
+For each statistics measurement, the driver should set the type of scale used,
+or ``FE_SCALE_NOT_AVAILABLE`` if the statistics is not available on a given
+time. Drivers should also provide the number of statistics for each type.
+that's usually 1 for most video standards [#f2]_.
+
+Drivers should initialize each statistic counters with length and
+scale at its init code. For example, if the frontend provides signal
+strength, it should have, on its init code::
+
+	struct dtv_frontend_properties *c = &state->fe.dtv_property_cache;
+
+	c->strength.len = 1;
+	c->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+And, when the statistics got updated, set the scale::
+
+	c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+	c->strength.stat[0].uvalue = strength;
+
+.. [#f2] For ISDB-T, it may provide both a global statistics and a per-layer
+   set of statistics. On such cases, len should be equal to 4. The first
+   value corresponds to the global stat; the other ones to each layer, e. g.:
+
+   - c->cnr.stat[0] for global S/N carrier ratio,
+   - c->cnr.stat[1] for Layer A S/N carrier ratio,
+   - c->cnr.stat[2] for layer B S/N carrier ratio,
+   - c->cnr.stat[3] for layer C S/N carrier ratio.
+
+.. note:: Please prefer to use ``FE_SCALE_DECIBEL`` instead of
+   ``FE_SCALE_RELATIVE`` for signal strength and CNR measurements.
+
+Groups of statistics
+^^^^^^^^^^^^^^^^^^^^
+
+There are several groups of statistics currently supported:
+
+Signal strength (:ref:`DTV-STAT-SIGNAL-STRENGTH`)
+  - Measures the signal strength level at the analog part of the tuner or
+    demod.
+
+  - Typically obtained from the gain applied to the tuner and/or frontend
+    in order to detect the carrier. When no carrier is detected, the gain is
+    at the maximum value (so, strength is on its minimal).
+
+  - As the gain is visible through the set of registers that adjust the gain,
+    typically, this statistics is always available [#f3]_.
+
+  - Drivers should try to make it available all the times, as this statistics
+    can be used when adjusting an antenna position and to check for troubles
+    at the cabling.
+
+  .. [#f3] On a few devices, the gain keeps floating if no carrier.
+     On such devices, strength report should check first if carrier is
+     detected at the tuner (``FE_HAS_CARRIER``, see :c:type:`fe_status`),
+     and otherwise return the lowest possible value.
+
+Carrier Signal to Noise ratio (:ref:`DTV-STAT-CNR`)
+  - Signal to Noise ratio for the main carrier.
+
+  - Signal to Noise measurement depends on the device. On some hardware, is
+    available when the main carrier is detected. On those hardware, CNR
+    measurement usually comes from the tuner (e. g. after ``FE_HAS_CARRIER``,
+    see :c:type:`fe_status`).
+
+    On other devices, it requires inner FEC decoding,
+    as the frontend measures it indirectly from other parameters (e. g. after
+    ``FE_HAS_VITERBI``, see :c:type:`fe_status`).
+
+    Having it available after inner FEC is more common.
+
+Bit counts post-FEC (:ref:`DTV-STAT-POST-ERROR-BIT-COUNT` and :ref:`DTV-STAT-POST-TOTAL-BIT-COUNT`)
+  - Those counters measure the number of bits and bit errors errors after
+    the forward error correction (FEC) on the inner coding block
+    (after Viterbi, LDPC or other inner code).
+
+  - Due to its nature, those statistics depend on full coding lock
+    (e. g. after ``FE_HAS_SYNC`` or after ``FE_HAS_LOCK``,
+    see :c:type:`fe_status`).
+
+Bit counts pre-FEC (:ref:`DTV-STAT-PRE-ERROR-BIT-COUNT` and :ref:`DTV-STAT-PRE-TOTAL-BIT-COUNT`)
+  - Those counters measure the number of bits and bit errors errors before
+    the forward error correction (FEC) on the inner coding block
+    (before Viterbi, LDPC or other inner code).
+
+  - Not all frontends provide this kind of statistics.
+
+  - Due to its nature, those statistics depend on inner coding lock (e. g.
+    after ``FE_HAS_VITERBI``, see :c:type:`fe_status`).
+
+Block counts (:ref:`DTV-STAT-ERROR-BLOCK-COUNT` and :ref:`DTV-STAT-TOTAL-BLOCK-COUNT`)
+  - Those counters measure the number of blocks and block errors errors after
+    the forward error correction (FEC) on the inner coding block
+    (before Viterbi, LDPC or other inner code).
+
+  - Due to its nature, those statistics depend on full coding lock
+    (e. g. after ``FE_HAS_SYNC`` or after
+    ``FE_HAS_LOCK``, see :c:type:`fe_status`).
+
+.. note:: All counters should be monotonically increased as they're
+   collected from the hardware.
+
+A typical example of the logic that handle status and statistics is::
+
+	static int foo_get_status_and_stats(struct dvb_frontend *fe)
+	{
+		struct foo_state *state = fe->demodulator_priv;
+		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+		int rc;
+		enum fe_status *status;
+
+		/* Both status and strength are always available */
+		rc = foo_read_status(fe, &status);
+		if (rc < 0)
+			return rc;
+
+		rc = foo_read_strength(fe);
+		if (rc < 0)
+			return rc;
+
+		/* Check if CNR is available */
+		if (!(fe->status & FE_HAS_CARRIER))
+			return 0;
+
+		rc = foo_read_cnr(fe);
+		if (rc < 0)
+			return rc;
+
+		/* Check if pre-BER stats are available */
+		if (!(fe->status & FE_HAS_VITERBI))
+			return 0;
+
+		rc = foo_get_pre_ber(fe);
+		if (rc < 0)
+			return rc;
+
+		/* Check if post-BER stats are available */
+		if (!(fe->status & FE_HAS_SYNC))
+			return 0;
+
+		rc = foo_get_post_ber(fe);
+		if (rc < 0)
+			return rc;
+	}
+
+	static const struct dvb_frontend_ops ops = {
+		/* ... */
+		.read_status = foo_get_status_and_stats,
+	};
+
+Statistics collect
+^^^^^^^^^^^^^^^^^^
+
+On almost all frontend hardware, the bit and byte counts are stored by
+the hardware after a certain amount of time or after the total bit/block
+counter reaches a certain value (usually programable), for example, on
+every 1000 ms or after receiving 1,000,000 bits.
+
+So, if you read the registers too soon, you'll end by reading the same
+value as in the previous reading, causing the monotonic value to be
+incremented too often.
+
+Drivers should take the responsibility to avoid too often reads. That
+can be done using two approaches:
+
+if the driver have a bit that indicates when a collected data is ready
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Driver should check such bit before making the statistics available.
+
+An example of such behavior can be found at this code snippet (adapted
+from mb86a20s driver's logic)::
+
+	static int foo_get_pre_ber(struct dvb_frontend *fe)
+	{
+		struct foo_state *state = fe->demodulator_priv;
+		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+		int rc, bit_error;
+
+		/* Check if the BER measures are already available */
+		rc = foo_read_u8(state, 0x54);
+		if (rc < 0)
+			return rc;
+
+		if (!rc)
+			return 0;
+
+		/* Read Bit Error Count */
+		bit_error = foo_read_u32(state, 0x55);
+		if (bit_error < 0)
+			return bit_error;
+
+		/* Read Total Bit Count */
+		rc = foo_read_u32(state, 0x51);
+		if (rc < 0)
+			return rc;
+
+		c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->pre_bit_error.stat[0].uvalue += bit_error;
+		c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->pre_bit_count.stat[0].uvalue += rc;
+
+		return 0;
+	}
+
+If the driver doesn't provide a statistics available check bit
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+A few devices, however, may not provide a way to check if the stats are
+available (or the way to check it is unknown). They may not even provide
+a way to directly read the total number of bits or blocks.
+
+On those devices, the driver need to ensure that it won't be reading from
+the register too often and/or estimate the total number of bits/blocks.
+
+On such drivers, a typical routine to get statistics would be like
+(adapted from dib8000 driver's logic)::
+
+	struct foo_state {
+		/* ... */
+
+		unsigned long per_jiffies_stats;
+	}
+
+	static int foo_get_pre_ber(struct dvb_frontend *fe)
+	{
+		struct foo_state *state = fe->demodulator_priv;
+		struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+		int rc, bit_error;
+		u64 bits;
+
+		/* Check if time for stats was elapsed */
+		if (!time_after(jiffies, state->per_jiffies_stats))
+			return 0;
+
+		/* Next stat should be collected in 1000 ms */
+		state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
+
+		/* Read Bit Error Count */
+		bit_error = foo_read_u32(state, 0x55);
+		if (bit_error < 0)
+			return bit_error;
+
+		/*
+		 * On this particular frontend, there's no register that
+		 * would provide the number of bits per 1000ms sample. So,
+		 * some function would calculate it based on DTV properties
+		 */
+		bits = get_number_of_bits_per_1000ms(fe);
+
+		c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+		c->pre_bit_error.stat[0].uvalue += bit_error;
+		c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+		c->pre_bit_count.stat[0].uvalue += bits;
+
+		return 0;
+	}
+
+Please notice that, on both cases, we're getting the statistics using the
+:c:type:`dvb_frontend_ops` ``.read_status`` callback. The rationale is that
+the frontend core will automatically call this function periodically
+(usually, 3 times per second, when the frontend is locked).
+
+That warrants that we won't miss to collect a counter and increment the
+monotonic stats at the right time.
+
+Digital TV Frontend functions and types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_frontend.h

+ 4 - 0
Documentation/media/kapi/dtv-net.rst

@@ -0,0 +1,4 @@
+Digital TV Network kABI
+-----------------------
+
+.. kernel-doc:: drivers/media/dvb-core/dvb_net.h

+ 3 - 0
Documentation/media/kapi/v4l2-async.rst

@@ -0,0 +1,3 @@
+V4L2 async kAPI
+^^^^^^^^^^^^^^^
+.. kernel-doc:: include/media/v4l2-async.h

+ 1 - 0
Documentation/media/kapi/v4l2-core.rst

@@ -19,6 +19,7 @@ Video4Linux devices
     v4l2-mc
     v4l2-mc
     v4l2-mediabus
     v4l2-mediabus
     v4l2-mem2mem
     v4l2-mem2mem
+    v4l2-async
     v4l2-fwnode
     v4l2-fwnode
     v4l2-rect
     v4l2-rect
     v4l2-tuner
     v4l2-tuner

+ 20 - 2
Documentation/media/uapi/cec/cec-ioc-dqevent.rst

@@ -161,6 +161,24 @@ it is guaranteed that the state did change in between the two events.
       - Generated if the CEC pin goes from a low voltage to a high voltage.
       - Generated if the CEC pin goes from a low voltage to a high voltage.
         Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
         Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
 	capability set.
 	capability set.
+    * .. _`CEC-EVENT-PIN-HPD-LOW`:
+
+      - ``CEC_EVENT_PIN_HPD_LOW``
+      - 5
+      - Generated if the HPD pin goes from a high voltage to a low voltage.
+	Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
+	capability set. When open() is called, the HPD pin can be read and
+	if the HPD is low, then an initial event will be generated for that
+	filehandle.
+    * .. _`CEC-EVENT-PIN-HPD-HIGH`:
+
+      - ``CEC_EVENT_PIN_HPD_HIGH``
+      - 6
+      - Generated if the HPD pin goes from a low voltage to a high voltage.
+	Only applies to adapters that have the ``CEC_CAP_MONITOR_PIN``
+	capability set. When open() is called, the HPD pin can be read and
+	if the HPD is high, then an initial event will be generated for that
+	filehandle.
 
 
 
 
 .. tabularcolumns:: |p{6.0cm}|p{0.6cm}|p{10.9cm}|
 .. tabularcolumns:: |p{6.0cm}|p{0.6cm}|p{10.9cm}|
@@ -172,9 +190,9 @@ it is guaranteed that the state did change in between the two events.
     :stub-columns: 0
     :stub-columns: 0
     :widths:       3 1 8
     :widths:       3 1 8
 
 
-    * .. _`CEC-EVENT-FL-INITIAL-VALUE`:
+    * .. _`CEC-EVENT-FL-INITIAL-STATE`:
 
 
-      - ``CEC_EVENT_FL_INITIAL_VALUE``
+      - ``CEC_EVENT_FL_INITIAL_STATE``
       - 1
       - 1
       - Set for the initial events that are generated when the device is
       - Set for the initial events that are generated when the device is
 	opened. See the table above for which events do this. This allows
 	opened. See the table above for which events do this. This allows

+ 5 - 5
Documentation/media/uapi/cec/cec-ioc-receive.rst

@@ -131,7 +131,7 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
       - ``tx_status``
       - ``tx_status``
       - The status bits of the transmitted message. See
       - The status bits of the transmitted message. See
 	:ref:`cec-tx-status` for the possible status values. It is 0 if
 	:ref:`cec-tx-status` for the possible status values. It is 0 if
-	this messages was received, not transmitted.
+	this message was received, not transmitted.
     * - __u8
     * - __u8
       - ``msg[16]``
       - ``msg[16]``
       - The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
       - The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
@@ -168,7 +168,7 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
       - ``tx_status``
       - ``tx_status``
       - The status bits of the transmitted message. See
       - The status bits of the transmitted message. See
 	:ref:`cec-tx-status` for the possible status values. It is 0 if
 	:ref:`cec-tx-status` for the possible status values. It is 0 if
-	this messages was received, not transmitted.
+	this message was received, not transmitted.
     * - __u8
     * - __u8
       - ``tx_arb_lost_cnt``
       - ``tx_arb_lost_cnt``
       - A counter of the number of transmit attempts that resulted in the
       - A counter of the number of transmit attempts that resulted in the
@@ -256,9 +256,9 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
       - ``CEC_TX_STATUS_ERROR``
       - ``CEC_TX_STATUS_ERROR``
       - 0x10
       - 0x10
       - Some error occurred. This is used for any errors that do not fit
       - Some error occurred. This is used for any errors that do not fit
-	the previous two, either because the hardware could not tell which
-	error occurred, or because the hardware tested for other
-	conditions besides those two.
+	``CEC_TX_STATUS_ARB_LOST`` or ``CEC_TX_STATUS_LOW_DRIVE``, either because
+	the hardware could not tell which error occurred, or because the hardware
+	tested for other conditions besides those two.
     * .. _`CEC-TX-STATUS-MAX-RETRIES`:
     * .. _`CEC-TX-STATUS-MAX-RETRIES`:
 
 
       - ``CEC_TX_STATUS_MAX_RETRIES``
       - ``CEC_TX_STATUS_MAX_RETRIES``

+ 6 - 372
Documentation/media/uapi/dvb/examples.rst

@@ -6,377 +6,11 @@
 Examples
 Examples
 ********
 ********
 
 
-In this section we would like to present some examples for using the Digital
-TV API.
+In the past, we used to have a set of examples here. However, those
+examples got out of date and doesn't even compile nowadays.
 
 
-.. note::
+Also, nowadays, the best is to use the libdvbv5 DVB API nowadays,
+with is fully documented.
 
 
-   This section is out of date, and the code below won't even
-   compile. Please refer to the
-   `libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__ for
-   updated/recommended examples.
-
-
-.. _tuning:
-
-Example: Tuning
-===============
-
-We will start with a generic tuning subroutine that uses the frontend
-and SEC, as well as the demux devices. The example is given for QPSK
-tuners, but can easily be adjusted for QAM.
-
-
-.. code-block:: c
-
-     #include <sys/ioctl.h>
-     #include <stdio.h>
-     #include <stdint.h>
-     #include <sys/types.h>
-     #include <sys/stat.h>
-     #include <fcntl.h>
-     #include <time.h>
-     #include <unistd.h>
-
-     #include <linux/dvb/dmx.h>
-     #include <linux/dvb/frontend.h>
-     #include <linux/dvb/sec.h>
-     #include <sys/poll.h>
-
-     #define DMX "/dev/dvb/adapter0/demux1"
-     #define FRONT "/dev/dvb/adapter0/frontend1"
-     #define SEC "/dev/dvb/adapter0/sec1"
-
-     /* routine for checking if we have a signal and other status information*/
-     int FEReadStatus(int fd, fe_status_t *stat)
-     {
-	 int ans;
-
-	 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
-	     perror("FE READ STATUS: ");
-	     return -1;
-	 }
-
-	 if (*stat & FE_HAS_POWER)
-	     printf("FE HAS POWER\\n");
-
-	 if (*stat & FE_HAS_SIGNAL)
-	     printf("FE HAS SIGNAL\\n");
-
-	 if (*stat & FE_SPECTRUM_INV)
-	     printf("SPEKTRUM INV\\n");
-
-	 return 0;
-     }
-
-
-     /* tune qpsk */
-     /* freq:             frequency of transponder                      */
-     /* vpid, apid, tpid: PIDs of video, audio and teletext TS packets  */
-     /* diseqc:           DiSEqC address of the used LNB                */
-     /* pol:              Polarisation                                  */
-     /* srate:            Symbol Rate                                   */
-     /* fec.              FEC                                           */
-     /* lnb_lof1:         local frequency of lower LNB band             */
-     /* lnb_lof2:         local frequency of upper LNB band             */
-     /* lnb_slof:         switch frequency of LNB                       */
-
-     int set_qpsk_channel(int freq, int vpid, int apid, int tpid,
-	     int diseqc, int pol, int srate, int fec, int lnb_lof1,
-	     int lnb_lof2, int lnb_slof)
-     {
-	 struct secCommand scmd;
-	 struct secCmdSequence scmds;
-	 struct dmx_pes_filter_params pesFilterParams;
-	 FrontendParameters frp;
-	 struct pollfd pfd[1];
-	 FrontendEvent event;
-	 int demux1, demux2, demux3, front;
-
-	 frequency = (uint32_t) freq;
-	 symbolrate = (uint32_t) srate;
-
-	 if((front = open(FRONT,O_RDWR)) < 0){
-	     perror("FRONTEND DEVICE: ");
-	     return -1;
-	 }
-
-	 if((sec = open(SEC,O_RDWR)) < 0){
-	     perror("SEC DEVICE: ");
-	     return -1;
-	 }
-
-	 if (demux1 < 0){
-	     if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
-		 < 0){
-		 perror("DEMUX DEVICE: ");
-		 return -1;
-	     }
-	 }
-
-	 if (demux2 < 0){
-	     if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
-		 < 0){
-		 perror("DEMUX DEVICE: ");
-		 return -1;
-	     }
-	 }
-
-	 if (demux3 < 0){
-	     if ((demux3=open(DMX, O_RDWR|O_NONBLOCK))
-		 < 0){
-		 perror("DEMUX DEVICE: ");
-		 return -1;
-	     }
-	 }
-
-	 if (freq < lnb_slof) {
-	     frp.Frequency = (freq - lnb_lof1);
-	     scmds.continuousTone = SEC_TONE_OFF;
-	 } else {
-	     frp.Frequency = (freq - lnb_lof2);
-	     scmds.continuousTone = SEC_TONE_ON;
-	 }
-	 frp.Inversion = INVERSION_AUTO;
-	 if (pol) scmds.voltage = SEC_VOLTAGE_18;
-	 else scmds.voltage = SEC_VOLTAGE_13;
-
-	 scmd.type=0;
-	 scmd.u.diseqc.addr=0x10;
-	 scmd.u.diseqc.cmd=0x38;
-	 scmd.u.diseqc.numParams=1;
-	 scmd.u.diseqc.params[0] = 0xF0 | ((diseqc * 4) & 0x0F) |
-	     (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
-	     (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
-
-	 scmds.miniCommand=SEC_MINI_NONE;
-	 scmds.numCommands=1;
-	 scmds.commands=&scmd;
-	 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
-	     perror("SEC SEND: ");
-	     return -1;
-	 }
-
-	 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){
-	     perror("SEC SEND: ");
-	     return -1;
-	 }
-
-	 frp.u.qpsk.SymbolRate = srate;
-	 frp.u.qpsk.FEC_inner = fec;
-
-	 if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){
-	     perror("QPSK TUNE: ");
-	     return -1;
-	 }
-
-	 pfd[0].fd = front;
-	 pfd[0].events = POLLIN;
-
-	 if (poll(pfd,1,3000)){
-	     if (pfd[0].revents & POLLIN){
-		 printf("Getting QPSK event\\n");
-		 if ( ioctl(front, FE_GET_EVENT, &event)
-
-		      == -EOVERFLOW){
-		     perror("qpsk get event");
-		     return -1;
-		 }
-		 printf("Received ");
-		 switch(event.type){
-		 case FE_UNEXPECTED_EV:
-		     printf("unexpected event\\n");
-		     return -1;
-		 case FE_FAILURE_EV:
-		     printf("failure event\\n");
-		     return -1;
-
-		 case FE_COMPLETION_EV:
-		     printf("completion event\\n");
-		 }
-	     }
-	 }
-
-
-	 pesFilterParams.pid     = vpid;
-	 pesFilterParams.input   = DMX_IN_FRONTEND;
-	 pesFilterParams.output  = DMX_OUT_DECODER;
-	 pesFilterParams.pes_type = DMX_PES_VIDEO;
-	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
-	 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
-	     perror("set_vpid");
-	     return -1;
-	 }
-
-	 pesFilterParams.pid     = apid;
-	 pesFilterParams.input   = DMX_IN_FRONTEND;
-	 pesFilterParams.output  = DMX_OUT_DECODER;
-	 pesFilterParams.pes_type = DMX_PES_AUDIO;
-	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
-	 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
-	     perror("set_apid");
-	     return -1;
-	 }
-
-	 pesFilterParams.pid     = tpid;
-	 pesFilterParams.input   = DMX_IN_FRONTEND;
-	 pesFilterParams.output  = DMX_OUT_DECODER;
-	 pesFilterParams.pes_type = DMX_PES_TELETEXT;
-	 pesFilterParams.flags   = DMX_IMMEDIATE_START;
-	 if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
-	     perror("set_tpid");
-	     return -1;
-	 }
-
-	 return has_signal(fds);
-     }
-
-The program assumes that you are using a universal LNB and a standard
-DiSEqC switch with up to 4 addresses. Of course, you could build in some
-more checking if tuning was successful and maybe try to repeat the
-tuning process. Depending on the external hardware, i.e. LNB and DiSEqC
-switch, and weather conditions this may be necessary.
-
-
-.. _the_dvr_device:
-
-Example: The DVR device
-========================
-
-The following program code shows how to use the DVR device for
-recording.
-
-
-.. code-block:: c
-
-     #include <sys/ioctl.h>
-     #include <stdio.h>
-     #include <stdint.h>
-     #include <sys/types.h>
-     #include <sys/stat.h>
-     #include <fcntl.h>
-     #include <time.h>
-     #include <unistd.h>
-
-     #include <linux/dvb/dmx.h>
-     #include <linux/dvb/video.h>
-     #include <sys/poll.h>
-     #define DVR "/dev/dvb/adapter0/dvr1"
-     #define AUDIO "/dev/dvb/adapter0/audio1"
-     #define VIDEO "/dev/dvb/adapter0/video1"
-
-     #define BUFFY (188*20)
-     #define MAX_LENGTH (1024*1024*5) /* record 5MB */
-
-
-     /* switch the demuxes to recording, assuming the transponder is tuned */
-
-     /* demux1, demux2: file descriptor of video and audio filters */
-     /* vpid, apid:     PIDs of video and audio channels           */
-
-     int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid)
-     {
-	 struct dmx_pes_filter_params pesFilterParams;
-
-	 if (demux1 < 0){
-	     if ((demux1=open(DMX, O_RDWR|O_NONBLOCK))
-		 < 0){
-		 perror("DEMUX DEVICE: ");
-		 return -1;
-	     }
-	 }
-
-	 if (demux2 < 0){
-	     if ((demux2=open(DMX, O_RDWR|O_NONBLOCK))
-		 < 0){
-		 perror("DEMUX DEVICE: ");
-		 return -1;
-	     }
-	 }
-
-	 pesFilterParams.pid = vpid;
-	 pesFilterParams.input = DMX_IN_FRONTEND;
-	 pesFilterParams.output = DMX_OUT_TS_TAP;
-	 pesFilterParams.pes_type = DMX_PES_VIDEO;
-	 pesFilterParams.flags = DMX_IMMEDIATE_START;
-	 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
-	     perror("DEMUX DEVICE");
-	     return -1;
-	 }
-	 pesFilterParams.pid = apid;
-	 pesFilterParams.input = DMX_IN_FRONTEND;
-	 pesFilterParams.output = DMX_OUT_TS_TAP;
-	 pesFilterParams.pes_type = DMX_PES_AUDIO;
-	 pesFilterParams.flags = DMX_IMMEDIATE_START;
-	 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){
-	     perror("DEMUX DEVICE");
-	     return -1;
-	 }
-	 return 0;
-     }
-
-     /* start recording MAX_LENGTH , assuming the transponder is tuned */
-
-     /* demux1, demux2: file descriptor of video and audio filters */
-     /* vpid, apid:     PIDs of video and audio channels           */
-     int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid)
-     {
-	 int i;
-	 int len;
-	 int written;
-	 uint8_t buf[BUFFY];
-	 uint64_t length;
-	 struct pollfd pfd[1];
-	 int dvr, dvr_out;
-
-	 /* open dvr device */
-	 if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){
-		 perror("DVR DEVICE");
-		 return -1;
-	 }
-
-	 /* switch video and audio demuxes to dvr */
-	 printf ("Switching dvr on\\n");
-	 i = switch_to_record(demux1, demux2, vpid, apid);
-	 printf("finished: ");
-
-	 printf("Recording %2.0f MB of test file in TS format\\n",
-	    MAX_LENGTH/(1024.0*1024.0));
-	 length = 0;
-
-	 /* open output file */
-	 if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT
-		      |O_TRUNC, S_IRUSR|S_IWUSR
-		      |S_IRGRP|S_IWGRP|S_IROTH|
-		      S_IWOTH)) < 0){
-	     perror("Can't open file for dvr test");
-	     return -1;
-	 }
-
-	 pfd[0].fd = dvr;
-	 pfd[0].events = POLLIN;
-
-	 /* poll for dvr data and write to file */
-	 while (length < MAX_LENGTH ) {
-	     if (poll(pfd,1,1)){
-		 if (pfd[0].revents & POLLIN){
-		     len = read(dvr, buf, BUFFY);
-		     if (len < 0){
-			 perror("recording");
-			 return -1;
-		     }
-		     if (len > 0){
-			 written = 0;
-			 while (written < len)
-			     written +=
-				 write (dvr_out,
-				    buf, len);
-			 length += len;
-			 printf("written %2.0f MB\\r",
-			    length/1024./1024.);
-		     }
-		 }
-	     }
-	 }
-	 return 0;
-     }
+Please refer to the `libdvbv5 <https://linuxtv.org/docs/libdvbv5/index.html>`__
+for updated/recommended examples.

+ 5 - 2
Documentation/media/uapi/dvb/fe-get-property.rst

@@ -48,8 +48,11 @@ depends on the delivery system and on the device:
 
 
    -  This call requires read/write access to the device.
    -  This call requires read/write access to the device.
 
 
-   -  At return, the values are updated to reflect the actual parameters
-      used.
+.. note::
+
+   At return, the values aren't updated to reflect the actual
+   parameters used. If the actual parameters are needed, an explicit
+   call to ``FE_GET_PROPERTY`` is needed.
 
 
 -  ``FE_GET_PROPERTY:``
 -  ``FE_GET_PROPERTY:``
 
 

+ 1 - 1
Documentation/media/uapi/dvb/net-types.rst

@@ -1,6 +1,6 @@
 .. -*- coding: utf-8; mode: rst -*-
 .. -*- coding: utf-8; mode: rst -*-
 
 
-.. _dmx_types:
+.. _net_types:
 
 
 **************
 **************
 Net Data Types
 Net Data Types

+ 31 - 0
MAINTAINERS

@@ -1956,6 +1956,14 @@ M:	Lennert Buytenhek <kernel@wantstofly.org>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 S:	Maintained
 
 
+ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT
+M:	Hans Verkuil <hans.verkuil@cisco.com>
+L:	linux-tegra@vger.kernel.org
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/platform/tegra-cec/
+F:	Documentation/devicetree/bindings/media/tegra-cec.txt
+
 ARM/TETON BGA MACHINE SUPPORT
 ARM/TETON BGA MACHINE SUPPORT
 M:	"Mark F. Brown" <mark.brown314@gmail.com>
 M:	"Mark F. Brown" <mark.brown314@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -3264,6 +3272,15 @@ F:	include/uapi/linux/cec.h
 F:	include/uapi/linux/cec-funcs.h
 F:	include/uapi/linux/cec-funcs.h
 F:	Documentation/devicetree/bindings/media/cec.txt
 F:	Documentation/devicetree/bindings/media/cec.txt
 
 
+CEC GPIO DRIVER
+M:	Hans Verkuil <hans.verkuil@cisco.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+W:	http://linuxtv.org
+S:	Supported
+F:	drivers/media/platform/cec-gpio/
+F:	Documentation/devicetree/bindings/media/cec-gpio.txt
+
 CELL BROADBAND ENGINE ARCHITECTURE
 CELL BROADBAND ENGINE ARCHITECTURE
 M:	Arnd Bergmann <arnd@arndb.de>
 M:	Arnd Bergmann <arnd@arndb.de>
 L:	linuxppc-dev@lists.ozlabs.org
 L:	linuxppc-dev@lists.ozlabs.org
@@ -11572,6 +11589,13 @@ F:	drivers/hid/hid-roccat*
 F:	include/linux/hid-roccat*
 F:	include/linux/hid-roccat*
 F:	Documentation/ABI/*/sysfs-driver-hid-roccat*
 F:	Documentation/ABI/*/sysfs-driver-hid-roccat*
 
 
+ROCKCHIP RASTER 2D GRAPHIC ACCELERATION UNIT DRIVER
+M:	Jacob chen <jacob2.chen@rock-chips.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/media/platform/rockchip/rga/
+F:	Documentation/devicetree/bindings/media/rockchip-rga.txt
+
 ROCKER DRIVER
 ROCKER DRIVER
 M:	Jiri Pirko <jiri@resnulli.us>
 M:	Jiri Pirko <jiri@resnulli.us>
 L:	netdev@vger.kernel.org
 L:	netdev@vger.kernel.org
@@ -12721,6 +12745,13 @@ L:	stable@vger.kernel.org
 S:	Supported
 S:	Supported
 F:	Documentation/process/stable-kernel-rules.rst
 F:	Documentation/process/stable-kernel-rules.rst
 
 
+STAGING - ATOMISP DRIVER
+M:	Alan Cox <alan@linux.intel.com>
+M:	Sakari Ailus <sakari.ailus@linux.intel.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/media/atomisp/
+
 STAGING - COMEDI
 STAGING - COMEDI
 M:	Ian Abbott <abbotti@mev.co.uk>
 M:	Ian Abbott <abbotti@mev.co.uk>
 M:	H Hartley Sweeten <hsweeten@visionengravers.com>
 M:	H Hartley Sweeten <hsweeten@visionengravers.com>

+ 1 - 0
arch/arm/boot/dts/omap3-n9.dts

@@ -26,6 +26,7 @@
 		clocks = <&isp 0>;
 		clocks = <&isp 0>;
 		clock-frequency = <9600000>;
 		clock-frequency = <9600000>;
 		nokia,nvm-size = <(16 * 64)>;
 		nokia,nvm-size = <(16 * 64)>;
+		flash-leds = <&as3645a_flash &as3645a_indicator>;
 		port {
 		port {
 			smia_1_1: endpoint {
 			smia_1_1: endpoint {
 				link-frequencies = /bits/ 64 <199200000 210000000 499200000>;
 				link-frequencies = /bits/ 64 <199200000 210000000 499200000>;

+ 2 - 2
arch/arm/boot/dts/omap3-n950-n9.dtsi

@@ -271,14 +271,14 @@
 		#size-cells = <0>;
 		#size-cells = <0>;
 		reg = <0x30>;
 		reg = <0x30>;
 		compatible = "ams,as3645a";
 		compatible = "ams,as3645a";
-		flash@0 {
+		as3645a_flash: flash@0 {
 			reg = <0x0>;
 			reg = <0x0>;
 			flash-timeout-us = <150000>;
 			flash-timeout-us = <150000>;
 			flash-max-microamp = <320000>;
 			flash-max-microamp = <320000>;
 			led-max-microamp = <60000>;
 			led-max-microamp = <60000>;
 			ams,input-max-microamp = <1750000>;
 			ams,input-max-microamp = <1750000>;
 		};
 		};
-		indicator@1 {
+		as3645a_indicator: indicator@1 {
 			reg = <0x1>;
 			reg = <0x1>;
 			led-max-microamp = <10000>;
 			led-max-microamp = <10000>;
 		};
 		};

+ 1 - 0
arch/arm/boot/dts/omap3-n950.dts

@@ -60,6 +60,7 @@
 		clocks = <&isp 0>;
 		clocks = <&isp 0>;
 		clock-frequency = <9600000>;
 		clock-frequency = <9600000>;
 		nokia,nvm-size = <(16 * 64)>;
 		nokia,nvm-size = <(16 * 64)>;
+		flash-leds = <&as3645a_flash &as3645a_indicator>;
 		port {
 		port {
 			smia_1_1: endpoint {
 			smia_1_1: endpoint {
 				link-frequencies = /bits/ 64 <210000000 333600000 398400000>;
 				link-frequencies = /bits/ 64 <210000000 333600000 398400000>;

+ 17 - 1
drivers/media/cec/cec-adap.c

@@ -86,7 +86,7 @@ void cec_queue_event_fh(struct cec_fh *fh,
 			const struct cec_event *new_ev, u64 ts)
 			const struct cec_event *new_ev, u64 ts)
 {
 {
 	static const u8 max_events[CEC_NUM_EVENTS] = {
 	static const u8 max_events[CEC_NUM_EVENTS] = {
-		1, 1, 64, 64,
+		1, 1, 64, 64, 8, 8,
 	};
 	};
 	struct cec_event_entry *entry;
 	struct cec_event_entry *entry;
 	unsigned int ev_idx = new_ev->event - 1;
 	unsigned int ev_idx = new_ev->event - 1;
@@ -170,6 +170,22 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
 }
 }
 EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
 EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
 
 
+/* Notify userspace that the HPD pin changed state at the given time. */
+void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
+{
+	struct cec_event ev = {
+		.event = is_high ? CEC_EVENT_PIN_HPD_HIGH :
+				   CEC_EVENT_PIN_HPD_LOW,
+	};
+	struct cec_fh *fh;
+
+	mutex_lock(&adap->devnode.lock);
+	list_for_each_entry(fh, &adap->devnode.fhs, list)
+		cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
+	mutex_unlock(&adap->devnode.lock);
+}
+EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
+
 /*
 /*
  * Queue a new message for this filehandle.
  * Queue a new message for this filehandle.
  *
  *

+ 15 - 4
drivers/media/cec/cec-api.c

@@ -32,6 +32,7 @@
 
 
 #include <media/cec-pin.h>
 #include <media/cec-pin.h>
 #include "cec-priv.h"
 #include "cec-priv.h"
+#include "cec-pin-priv.h"
 
 
 static inline struct cec_devnode *cec_devnode_data(struct file *filp)
 static inline struct cec_devnode *cec_devnode_data(struct file *filp)
 {
 {
@@ -529,7 +530,7 @@ static int cec_open(struct inode *inode, struct file *filp)
 	 * Initial events that are automatically sent when the cec device is
 	 * Initial events that are automatically sent when the cec device is
 	 * opened.
 	 * opened.
 	 */
 	 */
-	struct cec_event ev_state = {
+	struct cec_event ev = {
 		.event = CEC_EVENT_STATE_CHANGE,
 		.event = CEC_EVENT_STATE_CHANGE,
 		.flags = CEC_EVENT_FL_INITIAL_STATE,
 		.flags = CEC_EVENT_FL_INITIAL_STATE,
 	};
 	};
@@ -569,9 +570,19 @@ static int cec_open(struct inode *inode, struct file *filp)
 	filp->private_data = fh;
 	filp->private_data = fh;
 
 
 	/* Queue up initial state events */
 	/* Queue up initial state events */
-	ev_state.state_change.phys_addr = adap->phys_addr;
-	ev_state.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
-	cec_queue_event_fh(fh, &ev_state, 0);
+	ev.state_change.phys_addr = adap->phys_addr;
+	ev.state_change.log_addr_mask = adap->log_addrs.log_addr_mask;
+	cec_queue_event_fh(fh, &ev, 0);
+#ifdef CONFIG_CEC_PIN
+	if (adap->pin && adap->pin->ops->read_hpd) {
+		err = adap->pin->ops->read_hpd(adap);
+		if (err >= 0) {
+			ev.event = err ? CEC_EVENT_PIN_HPD_HIGH :
+					 CEC_EVENT_PIN_HPD_LOW;
+			cec_queue_event_fh(fh, &ev, 0);
+		}
+	}
+#endif
 
 
 	list_add(&fh->list, &devnode->fhs);
 	list_add(&fh->list, &devnode->fhs);
 	mutex_unlock(&devnode->lock);
 	mutex_unlock(&devnode->lock);

+ 4 - 5
drivers/media/cec/cec-core.c

@@ -112,10 +112,6 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode,
 	int minor;
 	int minor;
 	int ret;
 	int ret;
 
 
-	/* Initialization */
-	INIT_LIST_HEAD(&devnode->fhs);
-	mutex_init(&devnode->lock);
-
 	/* Part 1: Find a free minor number */
 	/* Part 1: Find a free minor number */
 	mutex_lock(&cec_devnode_lock);
 	mutex_lock(&cec_devnode_lock);
 	minor = find_next_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES, 0);
 	minor = find_next_zero_bit(cec_devnode_nums, CEC_NUM_DEVICES, 0);
@@ -242,6 +238,10 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 	INIT_LIST_HEAD(&adap->wait_queue);
 	INIT_LIST_HEAD(&adap->wait_queue);
 	init_waitqueue_head(&adap->kthread_waitq);
 	init_waitqueue_head(&adap->kthread_waitq);
 
 
+	/* adap->devnode initialization */
+	INIT_LIST_HEAD(&adap->devnode.fhs);
+	mutex_init(&adap->devnode.lock);
+
 	adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
 	adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);
 	if (IS_ERR(adap->kthread)) {
 	if (IS_ERR(adap->kthread)) {
 		pr_err("cec-%s: kernel_thread() failed\n", name);
 		pr_err("cec-%s: kernel_thread() failed\n", name);
@@ -277,7 +277,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
 	adap->rc->input_id.version = 1;
 	adap->rc->input_id.version = 1;
 	adap->rc->driver_name = CEC_NAME;
 	adap->rc->driver_name = CEC_NAME;
 	adap->rc->allowed_protocols = RC_PROTO_BIT_CEC;
 	adap->rc->allowed_protocols = RC_PROTO_BIT_CEC;
-	adap->rc->enabled_protocols = RC_PROTO_BIT_CEC;
 	adap->rc->priv = adap;
 	adap->rc->priv = adap;
 	adap->rc->map_name = RC_MAP_CEC;
 	adap->rc->map_name = RC_MAP_CEC;
 	adap->rc->timeout = MS_TO_NS(100);
 	adap->rc->timeout = MS_TO_NS(100);

+ 133 - 0
drivers/media/cec/cec-pin-priv.h

@@ -0,0 +1,133 @@
+/*
+ * 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
+#define LINUX_CEC_PIN_PRIV_H
+
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <media/cec-pin.h>
+
+enum cec_pin_state {
+	/* CEC is off */
+	CEC_ST_OFF,
+	/* CEC is idle, waiting for Rx or Tx */
+	CEC_ST_IDLE,
+
+	/* Tx states */
+
+	/* Pending Tx, waiting for Signal Free Time to expire */
+	CEC_ST_TX_WAIT,
+	/* Low-drive was detected, wait for bus to go high */
+	CEC_ST_TX_WAIT_FOR_HIGH,
+	/* Drive CEC low for the start bit */
+	CEC_ST_TX_START_BIT_LOW,
+	/* Drive CEC high for the start bit */
+	CEC_ST_TX_START_BIT_HIGH,
+	/* 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,
+	/* 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,
+	/*
+	 * Wait for start of sample time to check for Ack bit or first
+	 * four initiator bits to check for Arbitration Lost.
+	 */
+	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,
+
+	/* Rx states */
+
+	/* Start bit low detected */
+	CEC_ST_RX_START_BIT_LOW,
+	/* Start bit high detected */
+	CEC_ST_RX_START_BIT_HIGH,
+	/* Wait for bit sample time */
+	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,
+	/* 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 */
+	CEC_ST_RX_ACK_LOW_POST,
+	/* Wait for CEC to go high (i.e. end of bit period */
+	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,
+	/* Monitor pin using interrupts */
+	CEC_ST_RX_IRQ,
+
+	/* Total number of pin states */
+	CEC_PIN_STATES
+};
+
+#define CEC_NUM_PIN_EVENTS 128
+
+#define CEC_PIN_IRQ_UNCHANGED	0
+#define CEC_PIN_IRQ_DISABLE	1
+#define CEC_PIN_IRQ_ENABLE	2
+
+struct cec_pin {
+	struct cec_adapter		*adap;
+	const struct cec_pin_ops	*ops;
+	struct task_struct		*kthread;
+	wait_queue_head_t		kthread_waitq;
+	struct hrtimer			timer;
+	ktime_t				ts;
+	unsigned int			wait_usecs;
+	u16				la_mask;
+	bool				enabled;
+	bool				monitor_all;
+	bool				rx_eom;
+	bool				enable_irq_failed;
+	enum cec_pin_state		state;
+	struct cec_msg			tx_msg;
+	u32				tx_bit;
+	bool				tx_nacked;
+	u32				tx_signal_free_time;
+	struct cec_msg			rx_msg;
+	u32				rx_bit;
+
+	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;
+	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];
+	ktime_t				timer_ts;
+	u32				timer_cnt;
+	u32				timer_100ms_overruns;
+	u32				timer_300ms_overruns;
+	u32				timer_max_overrun;
+	u32				timer_sum_overrun;
+};
+
+#endif

+ 24 - 16
drivers/media/cec/cec-pin.c

@@ -20,6 +20,7 @@
 #include <linux/sched/types.h>
 #include <linux/sched/types.h>
 
 
 #include <media/cec-pin.h>
 #include <media/cec-pin.h>
+#include "cec-pin-priv.h"
 
 
 /* All timings are in microseconds */
 /* All timings are in microseconds */
 
 
@@ -132,7 +133,7 @@ static void cec_pin_to_idle(struct cec_pin *pin)
 	pin->rx_msg.len = 0;
 	pin->rx_msg.len = 0;
 	memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg));
 	memset(pin->rx_msg.msg, 0, sizeof(pin->rx_msg.msg));
 	pin->state = CEC_ST_IDLE;
 	pin->state = CEC_ST_IDLE;
-	pin->ts = 0;
+	pin->ts = ns_to_ktime(0);
 }
 }
 
 
 /*
 /*
@@ -426,7 +427,7 @@ static void cec_pin_rx_states(struct cec_pin *pin, ktime_t ts)
 		v = cec_pin_read(pin);
 		v = cec_pin_read(pin);
 		if (v && pin->rx_eom) {
 		if (v && pin->rx_eom) {
 			pin->work_rx_msg = pin->rx_msg;
 			pin->work_rx_msg = pin->rx_msg;
-			pin->work_rx_msg.rx_ts = ts;
+			pin->work_rx_msg.rx_ts = ktime_to_ns(ts);
 			wake_up_interruptible(&pin->kthread_waitq);
 			wake_up_interruptible(&pin->kthread_waitq);
 			pin->ts = ts;
 			pin->ts = ts;
 			pin->state = CEC_ST_RX_ACK_FINISH;
 			pin->state = CEC_ST_RX_ACK_FINISH;
@@ -457,7 +458,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
 	s32 delta;
 	s32 delta;
 
 
 	ts = ktime_get();
 	ts = ktime_get();
-	if (pin->timer_ts) {
+	if (ktime_to_ns(pin->timer_ts)) {
 		delta = ktime_us_delta(ts, pin->timer_ts);
 		delta = ktime_us_delta(ts, pin->timer_ts);
 		pin->timer_cnt++;
 		pin->timer_cnt++;
 		if (delta > 100 && pin->state != CEC_ST_IDLE) {
 		if (delta > 100 && pin->state != CEC_ST_IDLE) {
@@ -481,17 +482,19 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
 		if (pin->wait_usecs > 150) {
 		if (pin->wait_usecs > 150) {
 			pin->wait_usecs -= 100;
 			pin->wait_usecs -= 100;
 			pin->timer_ts = ktime_add_us(ts, 100);
 			pin->timer_ts = ktime_add_us(ts, 100);
-			hrtimer_forward_now(timer, 100000);
+			hrtimer_forward_now(timer, ns_to_ktime(100000));
 			return HRTIMER_RESTART;
 			return HRTIMER_RESTART;
 		}
 		}
 		if (pin->wait_usecs > 100) {
 		if (pin->wait_usecs > 100) {
 			pin->wait_usecs /= 2;
 			pin->wait_usecs /= 2;
 			pin->timer_ts = ktime_add_us(ts, pin->wait_usecs);
 			pin->timer_ts = ktime_add_us(ts, pin->wait_usecs);
-			hrtimer_forward_now(timer, pin->wait_usecs * 1000);
+			hrtimer_forward_now(timer,
+					ns_to_ktime(pin->wait_usecs * 1000));
 			return HRTIMER_RESTART;
 			return HRTIMER_RESTART;
 		}
 		}
 		pin->timer_ts = ktime_add_us(ts, pin->wait_usecs);
 		pin->timer_ts = ktime_add_us(ts, pin->wait_usecs);
-		hrtimer_forward_now(timer, pin->wait_usecs * 1000);
+		hrtimer_forward_now(timer,
+				    ns_to_ktime(pin->wait_usecs * 1000));
 		pin->wait_usecs = 0;
 		pin->wait_usecs = 0;
 		return HRTIMER_RESTART;
 		return HRTIMER_RESTART;
 	}
 	}
@@ -531,7 +534,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
 			pin->state = CEC_ST_RX_START_BIT_LOW;
 			pin->state = CEC_ST_RX_START_BIT_LOW;
 			break;
 			break;
 		}
 		}
-		if (pin->ts == 0)
+		if (ktime_to_ns(pin->ts) == 0)
 			pin->ts = ts;
 			pin->ts = ts;
 		if (pin->tx_msg.len) {
 		if (pin->tx_msg.len) {
 			/*
 			/*
@@ -572,12 +575,13 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
 	if (!adap->monitor_pin_cnt || states[pin->state].usecs <= 150) {
 	if (!adap->monitor_pin_cnt || states[pin->state].usecs <= 150) {
 		pin->wait_usecs = 0;
 		pin->wait_usecs = 0;
 		pin->timer_ts = ktime_add_us(ts, states[pin->state].usecs);
 		pin->timer_ts = ktime_add_us(ts, states[pin->state].usecs);
-		hrtimer_forward_now(timer, states[pin->state].usecs * 1000);
+		hrtimer_forward_now(timer,
+				ns_to_ktime(states[pin->state].usecs * 1000));
 		return HRTIMER_RESTART;
 		return HRTIMER_RESTART;
 	}
 	}
 	pin->wait_usecs = states[pin->state].usecs - 100;
 	pin->wait_usecs = states[pin->state].usecs - 100;
 	pin->timer_ts = ktime_add_us(ts, 100);
 	pin->timer_ts = ktime_add_us(ts, 100);
-	hrtimer_forward_now(timer, 100000);
+	hrtimer_forward_now(timer, ns_to_ktime(100000));
 	return HRTIMER_RESTART;
 	return HRTIMER_RESTART;
 }
 }
 
 
@@ -596,7 +600,7 @@ static int cec_pin_thread_func(void *_adap)
 
 
 		if (pin->work_rx_msg.len) {
 		if (pin->work_rx_msg.len) {
 			cec_received_msg_ts(adap, &pin->work_rx_msg,
 			cec_received_msg_ts(adap, &pin->work_rx_msg,
-					    pin->work_rx_msg.rx_ts);
+				ns_to_ktime(pin->work_rx_msg.rx_ts));
 			pin->work_rx_msg.len = 0;
 			pin->work_rx_msg.len = 0;
 		}
 		}
 		if (pin->work_tx_status) {
 		if (pin->work_tx_status) {
@@ -623,13 +627,15 @@ static int cec_pin_thread_func(void *_adap)
 			pin->ops->disable_irq(adap);
 			pin->ops->disable_irq(adap);
 			cec_pin_high(pin);
 			cec_pin_high(pin);
 			cec_pin_to_idle(pin);
 			cec_pin_to_idle(pin);
-			hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
+			hrtimer_start(&pin->timer, ns_to_ktime(0),
+				      HRTIMER_MODE_REL);
 			break;
 			break;
 		case CEC_PIN_IRQ_ENABLE:
 		case CEC_PIN_IRQ_ENABLE:
 			pin->enable_irq_failed = !pin->ops->enable_irq(adap);
 			pin->enable_irq_failed = !pin->ops->enable_irq(adap);
 			if (pin->enable_irq_failed) {
 			if (pin->enable_irq_failed) {
 				cec_pin_to_idle(pin);
 				cec_pin_to_idle(pin);
-				hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
+				hrtimer_start(&pin->timer, ns_to_ktime(0),
+					      HRTIMER_MODE_REL);
 			}
 			}
 			break;
 			break;
 		default:
 		default:
@@ -653,7 +659,7 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable)
 		cec_pin_read(pin);
 		cec_pin_read(pin);
 		cec_pin_to_idle(pin);
 		cec_pin_to_idle(pin);
 		pin->tx_msg.len = 0;
 		pin->tx_msg.len = 0;
-		pin->timer_ts = 0;
+		pin->timer_ts = ns_to_ktime(0);
 		atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
 		atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
 		pin->kthread = kthread_run(cec_pin_thread_func, adap,
 		pin->kthread = kthread_run(cec_pin_thread_func, adap,
 					   "cec-pin");
 					   "cec-pin");
@@ -661,7 +667,8 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable)
 			pr_err("cec-pin: kernel_thread() failed\n");
 			pr_err("cec-pin: kernel_thread() failed\n");
 			return PTR_ERR(pin->kthread);
 			return PTR_ERR(pin->kthread);
 		}
 		}
-		hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
+		hrtimer_start(&pin->timer, ns_to_ktime(0),
+			      HRTIMER_MODE_REL);
 	} else {
 	} else {
 		if (pin->ops->disable_irq)
 		if (pin->ops->disable_irq)
 			pin->ops->disable_irq(adap);
 			pin->ops->disable_irq(adap);
@@ -699,7 +706,8 @@ static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts,
 		pin->ops->disable_irq(adap);
 		pin->ops->disable_irq(adap);
 		cec_pin_high(pin);
 		cec_pin_high(pin);
 		cec_pin_to_idle(pin);
 		cec_pin_to_idle(pin);
-		hrtimer_start(&pin->timer, 0, HRTIMER_MODE_REL);
+		hrtimer_start(&pin->timer, ns_to_ktime(0),
+			      HRTIMER_MODE_REL);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -789,7 +797,7 @@ struct cec_adapter *cec_pin_allocate_adapter(const struct cec_pin_ops *pin_ops,
 			    caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN,
 			    caps | CEC_CAP_MONITOR_ALL | CEC_CAP_MONITOR_PIN,
 			    CEC_MAX_LOG_ADDRS);
 			    CEC_MAX_LOG_ADDRS);
 
 
-	if (PTR_ERR_OR_ZERO(adap)) {
+	if (IS_ERR(adap)) {
 		kfree(pin);
 		kfree(pin);
 		return adap;
 		return adap;
 	}
 	}

+ 2 - 4
drivers/media/common/cypress_firmware.c

@@ -74,11 +74,9 @@ int cypress_load_firmware(struct usb_device *udev,
 	struct hexline *hx;
 	struct hexline *hx;
 	int ret, pos = 0;
 	int ret, pos = 0;
 
 
-	hx = kmalloc(sizeof(struct hexline), GFP_KERNEL);
-	if (!hx) {
-		dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME);
+	hx = kmalloc(sizeof(*hx), GFP_KERNEL);
+	if (!hx)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	/* stop the CPU */
 	/* stop the CPU */
 	hx->data[0] = 1;
 	hx->data[0] = 1;

+ 3 - 3
drivers/media/common/saa7146/saa7146_fops.c

@@ -163,9 +163,9 @@ void saa7146_buffer_next(struct saa7146_dev *dev,
 	}
 	}
 }
 }
 
 
-void saa7146_buffer_timeout(unsigned long data)
+void saa7146_buffer_timeout(struct timer_list *t)
 {
 {
-	struct saa7146_dmaqueue *q = (struct saa7146_dmaqueue*)data;
+	struct saa7146_dmaqueue *q = from_timer(q, t, timeout);
 	struct saa7146_dev *dev = q->dev;
 	struct saa7146_dev *dev = q->dev;
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -559,7 +559,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 	vbi->start[1] = 312;
 	vbi->start[1] = 312;
 	vbi->count[1] = 16;
 	vbi->count[1] = 16;
 
 
-	init_timer(&vv->vbi_read_timeout);
+	timer_setup(&vv->vbi_read_timeout, NULL, 0);
 
 
 	vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
 	vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
 	vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
 	vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;

+ 7 - 7
drivers/media/common/saa7146/saa7146_vbi.c

@@ -349,9 +349,10 @@ static void vbi_stop(struct saa7146_fh *fh, struct file *file)
 	spin_unlock_irqrestore(&dev->slock, flags);
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
 }
 
 
-static void vbi_read_timeout(unsigned long data)
+static void vbi_read_timeout(struct timer_list *t)
 {
 {
-	struct file *file = (struct file*)data;
+	struct saa7146_vv *vv = from_timer(vv, t, vbi_read_timeout);
+	struct file *file = vv->vbi_read_timeout_file;
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_dev *dev = fh->dev;
 	struct saa7146_dev *dev = fh->dev;
 
 
@@ -366,8 +367,7 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 
 
 	INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
 	INIT_LIST_HEAD(&vv->vbi_dmaq.queue);
 
 
-	setup_timer(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout,
-		    (unsigned long)(&vv->vbi_dmaq));
+	timer_setup(&vv->vbi_dmaq.timeout, saa7146_buffer_timeout, 0);
 	vv->vbi_dmaq.dev              = dev;
 	vv->vbi_dmaq.dev              = dev;
 
 
 	init_waitqueue_head(&vv->vbi_wq);
 	init_waitqueue_head(&vv->vbi_wq);
@@ -402,8 +402,8 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
 			    sizeof(struct saa7146_buf),
 			    sizeof(struct saa7146_buf),
 			    file, &dev->v4l2_lock);
 			    file, &dev->v4l2_lock);
 
 
-	vv->vbi_read_timeout.function = vbi_read_timeout;
-	vv->vbi_read_timeout.data = (unsigned long)file;
+	vv->vbi_read_timeout.function = (TIMER_FUNC_TYPE)vbi_read_timeout;
+	vv->vbi_read_timeout_file = file;
 
 
 	/* initialize the brs */
 	/* initialize the brs */
 	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
 	if ( 0 != (SAA7146_USE_PORT_B_FOR_VBI & dev->ext_vv_data->flags)) {
@@ -489,7 +489,7 @@ static ssize_t vbi_read(struct file *file, char __user *data, size_t count, loff
 	return ret;
 	return ret;
 }
 }
 
 
-struct saa7146_use_ops saa7146_vbi_uops = {
+const struct saa7146_use_ops saa7146_vbi_uops = {
 	.init		= vbi_init,
 	.init		= vbi_init,
 	.open		= vbi_open,
 	.open		= vbi_open,
 	.release	= vbi_close,
 	.release	= vbi_close,

+ 2 - 3
drivers/media/common/saa7146/saa7146_video.c

@@ -1201,8 +1201,7 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 {
 {
 	INIT_LIST_HEAD(&vv->video_dmaq.queue);
 	INIT_LIST_HEAD(&vv->video_dmaq.queue);
 
 
-	setup_timer(&vv->video_dmaq.timeout, saa7146_buffer_timeout,
-		    (unsigned long)(&vv->video_dmaq));
+	timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0);
 	vv->video_dmaq.dev              = dev;
 	vv->video_dmaq.dev              = dev;
 
 
 	/* set some default values */
 	/* set some default values */
@@ -1303,7 +1302,7 @@ out:
 	return ret;
 	return ret;
 }
 }
 
 
-struct saa7146_use_ops saa7146_video_uops = {
+const struct saa7146_use_ops saa7146_video_uops = {
 	.init = video_init,
 	.init = video_init,
 	.open = video_open,
 	.open = video_open,
 	.release = video_close,
 	.release = video_close,

+ 16 - 23
drivers/media/common/siano/smscoreapi.c

@@ -447,7 +447,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
 			return entry;
 			return entry;
 		}
 		}
 	}
 	}
-	entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 	if (entry) {
 	if (entry) {
 		entry->mode = default_mode;
 		entry->mode = default_mode;
 		strcpy(entry->devpath, devpath);
 		strcpy(entry->devpath, devpath);
@@ -536,9 +536,7 @@ int smscore_register_hotplug(hotplug_t hotplug)
 	int rc = 0;
 	int rc = 0;
 
 
 	kmutex_lock(&g_smscore_deviceslock);
 	kmutex_lock(&g_smscore_deviceslock);
-
-	notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),
-			   GFP_KERNEL);
+	notifyee = kmalloc(sizeof(*notifyee), GFP_KERNEL);
 	if (notifyee) {
 	if (notifyee) {
 		/* now notify callback about existing devices */
 		/* now notify callback about existing devices */
 		first = &g_smscore_devices;
 		first = &g_smscore_devices;
@@ -627,7 +625,7 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
 {
 {
 	struct smscore_buffer_t *cb;
 	struct smscore_buffer_t *cb;
 
 
-	cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
+	cb = kzalloc(sizeof(*cb), GFP_KERNEL);
 	if (!cb)
 	if (!cb)
 		return NULL;
 		return NULL;
 
 
@@ -655,7 +653,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 	struct smscore_device_t *dev;
 	struct smscore_device_t *dev;
 	u8 *buffer;
 	u8 *buffer;
 
 
-	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 	if (!dev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
@@ -751,7 +749,7 @@ static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 		void *buffer, size_t size, struct completion *completion) {
 		void *buffer, size_t size, struct completion *completion) {
 	int rc;
 	int rc;
 
 
-	if (completion == NULL)
+	if (!completion)
 		return -EINVAL;
 		return -EINVAL;
 	init_completion(completion);
 	init_completion(completion);
 
 
@@ -1153,8 +1151,8 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
 	}
 	}
 	pr_debug("Firmware name: %s\n", fw_filename);
 	pr_debug("Firmware name: %s\n", fw_filename);
 
 
-	if (loadfirmware_handler == NULL && !(coredev->device_flags
-			& SMS_DEVICE_FAMILY2))
+	if (!loadfirmware_handler &&
+	    !(coredev->device_flags & SMS_DEVICE_FAMILY2))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	rc = request_firmware(&fw, fw_filename, coredev->device);
 	rc = request_firmware(&fw, fw_filename, coredev->device);
@@ -1301,10 +1299,8 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode)
 
 
 	buffer = kmalloc(sizeof(struct sms_msg_data) +
 	buffer = kmalloc(sizeof(struct sms_msg_data) +
 			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
 			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
-	if (!buffer) {
-		pr_err("Could not allocate buffer for init device message.\n");
+	if (!buffer)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
 	msg = (struct sms_msg_data *)SMS_ALIGN_ADDRESS(buffer);
 	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
 	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_INIT_DEVICE_REQ,
@@ -1686,11 +1682,10 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
 		pr_err("The msg ID already registered to another client.\n");
 		pr_err("The msg ID already registered to another client.\n");
 		return -EEXIST;
 		return -EEXIST;
 	}
 	}
-	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
-	if (!listentry) {
-		pr_err("Can't allocate memory for client id.\n");
+	listentry = kzalloc(sizeof(*listentry), GFP_KERNEL);
+	if (!listentry)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
+
 	listentry->id = id;
 	listentry->id = id;
 	listentry->data_type = data_type;
 	listentry->data_type = data_type;
 	list_add_locked(&listentry->entry, &client->idlist,
 	list_add_locked(&listentry->entry, &client->idlist,
@@ -1724,11 +1719,9 @@ int smscore_register_client(struct smscore_device_t *coredev,
 		return -EEXIST;
 		return -EEXIST;
 	}
 	}
 
 
-	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
-	if (!newclient) {
-		pr_err("Failed to allocate memory for client.\n");
+	newclient = kzalloc(sizeof(*newclient), GFP_KERNEL);
+	if (!newclient)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	INIT_LIST_HEAD(&newclient->idlist);
 	INIT_LIST_HEAD(&newclient->idlist);
 	newclient->coredev = coredev;
 	newclient->coredev = coredev;
@@ -1796,7 +1789,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
 	struct sms_msg_hdr *phdr = (struct sms_msg_hdr *) buffer;
 	int rc;
 	int rc;
 
 
-	if (client == NULL) {
+	if (!client) {
 		pr_err("Got NULL client\n");
 		pr_err("Got NULL client\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -1804,7 +1797,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 	coredev = client->coredev;
 	coredev = client->coredev;
 
 
 	/* check that no other channel with same id exists */
 	/* check that no other channel with same id exists */
-	if (coredev == NULL) {
+	if (!coredev) {
 		pr_err("Got NULL coredev\n");
 		pr_err("Got NULL coredev\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -1961,7 +1954,7 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
 	if (pin_num > MAX_GPIO_PIN_NUMBER)
 	if (pin_num > MAX_GPIO_PIN_NUMBER)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (p_gpio_config == NULL)
+	if (!p_gpio_config)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);
 	total_len = sizeof(struct sms_msg_hdr) + (sizeof(u32) * 6);

+ 12 - 0
drivers/media/common/v4l2-tpg/v4l2-tpg-core.c

@@ -238,6 +238,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 		tpg->color_enc = TGP_COLOR_ENC_RGB;
 		tpg->color_enc = TGP_COLOR_ENC_RGB;
 		break;
 		break;
 	case V4L2_PIX_FMT_GREY:
 	case V4L2_PIX_FMT_GREY:
+	case V4L2_PIX_FMT_Y10:
+	case V4L2_PIX_FMT_Y12:
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16_BE:
 	case V4L2_PIX_FMT_Y16_BE:
 		tpg->color_enc = TGP_COLOR_ENC_LUMA;
 		tpg->color_enc = TGP_COLOR_ENC_LUMA;
@@ -352,6 +354,8 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc)
 	case V4L2_PIX_FMT_YUV444:
 	case V4L2_PIX_FMT_YUV444:
 	case V4L2_PIX_FMT_YUV555:
 	case V4L2_PIX_FMT_YUV555:
 	case V4L2_PIX_FMT_YUV565:
 	case V4L2_PIX_FMT_YUV565:
+	case V4L2_PIX_FMT_Y10:
+	case V4L2_PIX_FMT_Y12:
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16_BE:
 	case V4L2_PIX_FMT_Y16_BE:
 		tpg->twopixelsize[0] = 2 * 2;
 		tpg->twopixelsize[0] = 2 * 2;
@@ -1056,6 +1060,14 @@ static void gen_twopix(struct tpg_data *tpg,
 	case V4L2_PIX_FMT_GREY:
 	case V4L2_PIX_FMT_GREY:
 		buf[0][offset] = r_y_h;
 		buf[0][offset] = r_y_h;
 		break;
 		break;
+	case V4L2_PIX_FMT_Y10:
+		buf[0][offset] = (r_y_h << 2) & 0xff;
+		buf[0][offset+1] = r_y_h >> 6;
+		break;
+	case V4L2_PIX_FMT_Y12:
+		buf[0][offset] = (r_y_h << 4) & 0xff;
+		buf[0][offset+1] = r_y_h >> 4;
+		break;
 	case V4L2_PIX_FMT_Y16:
 	case V4L2_PIX_FMT_Y16:
 		/*
 		/*
 		 * Ideally both bytes should be set to r_y_h, but then you won't
 		 * Ideally both bytes should be set to r_y_h, but then you won't

+ 3 - 5
drivers/media/dvb-core/dmxdev.c

@@ -329,9 +329,9 @@ static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter,
 	return 0;
 	return 0;
 }
 }
 
 
-static void dvb_dmxdev_filter_timeout(unsigned long data)
+static void dvb_dmxdev_filter_timeout(struct timer_list *t)
 {
 {
-	struct dmxdev_filter *dmxdevfilter = (struct dmxdev_filter *)data;
+	struct dmxdev_filter *dmxdevfilter = from_timer(dmxdevfilter, t, timer);
 
 
 	dmxdevfilter->buffer.error = -ETIMEDOUT;
 	dmxdevfilter->buffer.error = -ETIMEDOUT;
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 	spin_lock_irq(&dmxdevfilter->dev->lock);
@@ -346,8 +346,6 @@ static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter)
 
 
 	del_timer(&dmxdevfilter->timer);
 	del_timer(&dmxdevfilter->timer);
 	if (para->timeout) {
 	if (para->timeout) {
-		dmxdevfilter->timer.function = dvb_dmxdev_filter_timeout;
-		dmxdevfilter->timer.data = (unsigned long)dmxdevfilter;
 		dmxdevfilter->timer.expires =
 		dmxdevfilter->timer.expires =
 		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
 		    jiffies + 1 + (HZ / 2 + HZ * para->timeout) / 1000;
 		add_timer(&dmxdevfilter->timer);
 		add_timer(&dmxdevfilter->timer);
@@ -754,7 +752,7 @@ static int dvb_demux_open(struct inode *inode, struct file *file)
 	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
 	dvb_ringbuffer_init(&dmxdevfilter->buffer, NULL, 8192);
 	dmxdevfilter->type = DMXDEV_TYPE_NONE;
 	dmxdevfilter->type = DMXDEV_TYPE_NONE;
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
 	dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_ALLOCATED);
-	init_timer(&dmxdevfilter->timer);
+	timer_setup(&dmxdevfilter->timer, dvb_dmxdev_filter_timeout, 0);
 
 
 	dvbdev->users++;
 	dvbdev->users++;
 
 

+ 88 - 2
drivers/media/dvb-core/dmxdev.h

@@ -36,12 +36,33 @@
 #include "demux.h"
 #include "demux.h"
 #include "dvb_ringbuffer.h"
 #include "dvb_ringbuffer.h"
 
 
+/**
+ * enum dmxdev_type - type of demux filter type.
+ *
+ * @DMXDEV_TYPE_NONE:	no filter set.
+ * @DMXDEV_TYPE_SEC:	section filter.
+ * @DMXDEV_TYPE_PES:	Program Elementary Stream (PES) filter.
+ */
 enum dmxdev_type {
 enum dmxdev_type {
 	DMXDEV_TYPE_NONE,
 	DMXDEV_TYPE_NONE,
 	DMXDEV_TYPE_SEC,
 	DMXDEV_TYPE_SEC,
 	DMXDEV_TYPE_PES,
 	DMXDEV_TYPE_PES,
 };
 };
 
 
+/**
+ * enum dmxdev_state - state machine for the dmxdev.
+ *
+ * @DMXDEV_STATE_FREE:		indicates that the filter is freed.
+ * @DMXDEV_STATE_ALLOCATED:	indicates that the filter was allocated
+ *				to be used.
+ * @DMXDEV_STATE_SET:		indicates that the filter parameters are set.
+ * @DMXDEV_STATE_GO:		indicates that the filter is running.
+ * @DMXDEV_STATE_DONE:		indicates that a packet was already filtered
+ *				and the filter is now disabled.
+ *				Set only if %DMX_ONESHOT. See
+ *				&dmx_sct_filter_params.
+ * @DMXDEV_STATE_TIMEDOUT:	Indicates a timeout condition.
+ */
 enum dmxdev_state {
 enum dmxdev_state {
 	DMXDEV_STATE_FREE,
 	DMXDEV_STATE_FREE,
 	DMXDEV_STATE_ALLOCATED,
 	DMXDEV_STATE_ALLOCATED,
@@ -51,12 +72,49 @@ enum dmxdev_state {
 	DMXDEV_STATE_TIMEDOUT
 	DMXDEV_STATE_TIMEDOUT
 };
 };
 
 
+/**
+ * struct dmxdev_feed - digital TV dmxdev feed
+ *
+ * @pid:	Program ID to be filtered
+ * @ts:		pointer to &struct dmx_ts_feed
+ * @next:	&struct list_head pointing to the next feed.
+ */
+
 struct dmxdev_feed {
 struct dmxdev_feed {
 	u16 pid;
 	u16 pid;
 	struct dmx_ts_feed *ts;
 	struct dmx_ts_feed *ts;
 	struct list_head next;
 	struct list_head next;
 };
 };
 
 
+/**
+ * struct dmxdev_filter - digital TV dmxdev filter
+ *
+ * @filter:	a dmxdev filter. Currently used only for section filter:
+ *		if the filter is Section, it contains a
+ *		&struct dmx_section_filter @sec pointer.
+ * @feed:	a dmxdev feed. Depending on the feed type, it can be:
+ *		for TS feed: a &struct list_head @ts list of TS and PES
+ *		feeds;
+ *		for section feed: a &struct dmx_section_feed @sec pointer.
+ * @params:	dmxdev filter parameters. Depending on the feed type, it
+ *		can be:
+ *		for section filter: a &struct dmx_sct_filter_params @sec
+ *		embedded struct;
+ *		for a TS filter: a &struct dmx_pes_filter_params @pes
+ *		embedded struct.
+ * @type:	type of the dmxdev filter, as defined by &enum dmxdev_type.
+ * @state:	state of the dmxdev filter, as defined by &enum dmxdev_state.
+ * @dev:	pointer to &struct dmxdev.
+ * @buffer:	an embedded &struct dvb_ringbuffer buffer.
+ * @mutex:	protects the access to &struct dmxdev_filter.
+ * @timer:	&struct timer_list embedded timer, used to check for
+ *		feed timeouts.
+ *		Only for section filter.
+ * @todo:	index for the @secheader.
+ *		Only for section filter.
+ * @secheader:	buffer cache to parse the section header.
+ *		Only for section filter.
+ */
 struct dmxdev_filter {
 struct dmxdev_filter {
 	union {
 	union {
 		struct dmx_section_filter *sec;
 		struct dmx_section_filter *sec;
@@ -86,7 +144,23 @@ struct dmxdev_filter {
 	u8 secheader[3];
 	u8 secheader[3];
 };
 };
 
 
-
+/**
+ * struct dmxdev - Describes a digital TV demux device.
+ *
+ * @dvbdev:		pointer to &struct dvb_device associated with
+ *			the demux device node.
+ * @dvr_dvbdev:		pointer to &struct dvb_device associated with
+ *			the dvr device node.
+ * @filter:		pointer to &struct dmxdev_filter.
+ * @demux:		pointer to &struct dmx_demux.
+ * @filternum:		number of filters.
+ * @capabilities:	demux capabilities as defined by &enum dmx_demux_caps.
+ * @exit:		flag to indicate that the demux is being released.
+ * @dvr_orig_fe:	pointer to &struct dmx_frontend.
+ * @dvr_buffer:		embedded &struct dvb_ringbuffer for DVB output.
+ * @mutex:		protects the usage of this structure.
+ * @lock:		protects access to &dmxdev->filter->data.
+ */
 struct dmxdev {
 struct dmxdev {
 	struct dvb_device *dvbdev;
 	struct dvb_device *dvbdev;
 	struct dvb_device *dvr_dvbdev;
 	struct dvb_device *dvr_dvbdev;
@@ -108,8 +182,20 @@ struct dmxdev {
 	spinlock_t lock;
 	spinlock_t lock;
 };
 };
 
 
+/**
+ * dvb_dmxdev_init - initializes a digital TV demux and registers both demux
+ *	and DVR devices.
+ *
+ * @dmxdev: pointer to &struct dmxdev.
+ * @adap: pointer to &struct dvb_adapter.
+ */
+int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *adap);
 
 
-int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *);
+/**
+ * dvb_dmxdev_release - releases a digital TV demux and unregisters it.
+ *
+ * @dmxdev: pointer to &struct dmxdev.
+ */
 void dvb_dmxdev_release(struct dmxdev *dmxdev);
 void dvb_dmxdev_release(struct dmxdev *dmxdev);
 
 
 #endif /* _DMXDEV_H_ */
 #endif /* _DMXDEV_H_ */

+ 9 - 8
drivers/media/dvb-core/dvb_demux.c

@@ -223,10 +223,10 @@ static void dvb_dmx_swfilter_section_new(struct dvb_demux_feed *feed)
  *  when the second packet arrives.
  *  when the second packet arrives.
  *
  *
  * Fix:
  * Fix:
- * when demux is started, let feed->pusi_seen = 0 to
+ * when demux is started, let feed->pusi_seen = false to
  * prevent initial feeding of garbage from the end of
  * prevent initial feeding of garbage from the end of
  * previous section. When you for the first time see PUSI=1
  * previous section. When you for the first time see PUSI=1
- * then set feed->pusi_seen = 1
+ * then set feed->pusi_seen = true
  */
  */
 static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
 static int dvb_dmx_swfilter_section_copy_dump(struct dvb_demux_feed *feed,
 					      const u8 *buf, u8 len)
 					      const u8 *buf, u8 len)
@@ -318,10 +318,10 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
 		 */
 		 */
 #endif
 #endif
 		/*
 		/*
-		 * Discontinuity detected. Reset pusi_seen = 0 to
+		 * Discontinuity detected. Reset pusi_seen to
 		 * stop feeding of suspicious data until next PUSI=1 arrives
 		 * stop feeding of suspicious data until next PUSI=1 arrives
 		 */
 		 */
-		feed->pusi_seen = 0;
+		feed->pusi_seen = false;
 		dvb_dmx_swfilter_section_new(feed);
 		dvb_dmx_swfilter_section_new(feed);
 	}
 	}
 
 
@@ -335,8 +335,8 @@ static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed,
 
 
 			dvb_dmx_swfilter_section_copy_dump(feed, before,
 			dvb_dmx_swfilter_section_copy_dump(feed, before,
 							   before_len);
 							   before_len);
-			/* before start of new section, set pusi_seen = 1 */
-			feed->pusi_seen = 1;
+			/* before start of new section, set pusi_seen */
+			feed->pusi_seen = true;
 			dvb_dmx_swfilter_section_new(feed);
 			dvb_dmx_swfilter_section_new(feed);
 			dvb_dmx_swfilter_section_copy_dump(feed, after,
 			dvb_dmx_swfilter_section_copy_dump(feed, after,
 							   after_len);
 							   after_len);
@@ -367,6 +367,7 @@ static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 			else
 			else
 				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
 				feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts);
 		}
 		}
+		/* Used only on full-featured devices */
 		if (feed->ts_type & TS_DECODER)
 		if (feed->ts_type & TS_DECODER)
 			if (feed->demux->write_to_decoder)
 			if (feed->demux->write_to_decoder)
 				feed->demux->write_to_decoder(feed, buf, 188);
 				feed->demux->write_to_decoder(feed, buf, 188);
@@ -898,14 +899,14 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed)
 		return;
 		return;
 	do {
 	do {
 		sf = &f->filter;
 		sf = &f->filter;
-		doneq = 0;
+		doneq = false;
 		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
 		for (i = 0; i < DVB_DEMUX_MASK_MAX; i++) {
 			mode = sf->filter_mode[i];
 			mode = sf->filter_mode[i];
 			mask = sf->filter_mask[i];
 			mask = sf->filter_mask[i];
 			f->maskandmode[i] = mask & mode;
 			f->maskandmode[i] = mask & mode;
 			doneq |= f->maskandnotmode[i] = mask & ~mode;
 			doneq |= f->maskandnotmode[i] = mask & ~mode;
 		}
 		}
-		f->doneq = doneq ? 1 : 0;
+		f->doneq = doneq ? true : false;
 	} while ((f = f->next));
 	} while ((f = f->next));
 }
 }
 
 

+ 224 - 24
drivers/media/dvb-core/dvb_demux.h

@@ -26,15 +26,33 @@
 
 
 #include "demux.h"
 #include "demux.h"
 
 
-#define DMX_TYPE_TS  0
-#define DMX_TYPE_SEC 1
-#define DMX_TYPE_PES 2
+/**
+ * enum dvb_dmx_filter_type - type of demux feed.
+ *
+ * @DMX_TYPE_TS:	feed is in TS mode.
+ * @DMX_TYPE_SEC:	feed is in Section mode.
+ */
+enum dvb_dmx_filter_type {
+	DMX_TYPE_TS,
+	DMX_TYPE_SEC,
+};
 
 
-#define DMX_STATE_FREE      0
-#define DMX_STATE_ALLOCATED 1
-#define DMX_STATE_SET       2
-#define DMX_STATE_READY     3
-#define DMX_STATE_GO        4
+/**
+ * enum dvb_dmx_state - state machine for a demux filter.
+ *
+ * @DMX_STATE_FREE:		indicates that the filter is freed.
+ * @DMX_STATE_ALLOCATED:	indicates that the filter was allocated
+ *				to be used.
+ * @DMX_STATE_READY:		indicates that the filter is ready
+ *				to be used.
+ * @DMX_STATE_GO:		indicates that the filter is running.
+ */
+enum dvb_dmx_state {
+	DMX_STATE_FREE,
+	DMX_STATE_ALLOCATED,
+	DMX_STATE_READY,
+	DMX_STATE_GO,
+};
 
 
 #define DVB_DEMUX_MASK_MAX 18
 #define DVB_DEMUX_MASK_MAX 18
 
 
@@ -42,24 +60,66 @@
 
 
 #define SPEED_PKTS_INTERVAL 50000
 #define SPEED_PKTS_INTERVAL 50000
 
 
+/**
+ * struct dvb_demux_filter - Describes a DVB demux section filter.
+ *
+ * @filter:		Section filter as defined by &struct dmx_section_filter.
+ * @maskandmode:	logical ``and`` bit mask.
+ * @maskandnotmode:	logical ``and not`` bit mask.
+ * @doneq:		flag that indicates when a filter is ready.
+ * @next:		pointer to the next section filter.
+ * @feed:		&struct dvb_demux_feed pointer.
+ * @index:		index of the used demux filter.
+ * @state:		state of the filter as described by &enum dvb_dmx_state.
+ * @type:		type of the filter as described
+ *			by &enum dvb_dmx_filter_type.
+ */
+
 struct dvb_demux_filter {
 struct dvb_demux_filter {
 	struct dmx_section_filter filter;
 	struct dmx_section_filter filter;
 	u8 maskandmode[DMX_MAX_FILTER_SIZE];
 	u8 maskandmode[DMX_MAX_FILTER_SIZE];
 	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
 	u8 maskandnotmode[DMX_MAX_FILTER_SIZE];
-	int doneq;
+	bool doneq;
 
 
 	struct dvb_demux_filter *next;
 	struct dvb_demux_filter *next;
 	struct dvb_demux_feed *feed;
 	struct dvb_demux_feed *feed;
 	int index;
 	int index;
-	int state;
-	int type;
+	enum dvb_dmx_state state;
+	enum dvb_dmx_filter_type type;
 
 
+	/* private: used only by av7110 */
 	u16 hw_handle;
 	u16 hw_handle;
-	struct timer_list timer;
 };
 };
 
 
-#define DMX_FEED_ENTRY(pos) list_entry(pos, struct dvb_demux_feed, list_head)
-
+/**
+ * struct dvb_demux_feed - describes a DVB field
+ *
+ * @feed:	a digital TV feed. It can either be a TS or a section feed:
+ *		if the feed is TS, it contains &struct dvb_ts_feed @ts;
+ *		if the feed is section, it contains
+ *		&struct dmx_section_feed @sec.
+ * @cb:		digital TV callbacks. depending on the feed type, it can be:
+ *		if the feed is TS, it contains a dmx_ts_cb() @ts callback;
+ *		if the feed is section, it contains a dmx_section_cb() @sec
+ *		callback.
+ *
+ * @demux:	pointer to &struct dvb_demux.
+ * @priv:	private data that can optionally be used by a DVB driver.
+ * @type:	type of the filter, as defined by &enum dvb_dmx_filter_type.
+ * @state:	state of the filter as defined by &enum dvb_dmx_state.
+ * @pid:	PID to be filtered.
+ * @timeout:	feed timeout.
+ * @filter:	pointer to &struct dvb_demux_filter.
+ * @ts_type:	type of TS, as defined by &enum ts_filter_type.
+ * @pes_type:	type of PES, as defined by &enum dmx_ts_pes.
+ * @cc:		MPEG-TS packet continuity counter
+ * @pusi_seen:	if true, indicates that a discontinuity was detected.
+ *		it is used to prevent feeding of garbage from previous section.
+ * @peslen:	length of the PES (Packet Elementary Stream).
+ * @list_head:	head for the list of digital TV demux feeds.
+ * @index:	a unique index for each feed. Can be used as hardware
+ *		pid filter index.
+ */
 struct dvb_demux_feed {
 struct dvb_demux_feed {
 	union {
 	union {
 		struct dmx_ts_feed ts;
 		struct dmx_ts_feed ts;
@@ -73,25 +133,63 @@ struct dvb_demux_feed {
 
 
 	struct dvb_demux *demux;
 	struct dvb_demux *demux;
 	void *priv;
 	void *priv;
-	int type;
-	int state;
+	enum dvb_dmx_filter_type type;
+	enum dvb_dmx_state state;
 	u16 pid;
 	u16 pid;
 
 
 	ktime_t timeout;
 	ktime_t timeout;
 	struct dvb_demux_filter *filter;
 	struct dvb_demux_filter *filter;
 
 
-	int ts_type;
+	enum ts_filter_type ts_type;
 	enum dmx_ts_pes pes_type;
 	enum dmx_ts_pes pes_type;
 
 
 	int cc;
 	int cc;
-	int pusi_seen;		/* prevents feeding of garbage from previous section */
+	bool pusi_seen;
 
 
 	u16 peslen;
 	u16 peslen;
 
 
 	struct list_head list_head;
 	struct list_head list_head;
-	unsigned int index;	/* a unique index for each feed (can be used as hardware pid filter index) */
+	unsigned int index;
 };
 };
 
 
+/**
+ * struct dvb_demux - represents a digital TV demux
+ * @dmx:		embedded &struct dmx_demux with demux capabilities
+ *			and callbacks.
+ * @priv:		private data that can optionally be used by
+ *			a DVB driver.
+ * @filternum:		maximum amount of DVB filters.
+ * @feednum:		maximum amount of DVB feeds.
+ * @start_feed:		callback routine to be called in order to start
+ *			a DVB feed.
+ * @stop_feed:		callback routine to be called in order to stop
+ *			a DVB feed.
+ * @write_to_decoder:	callback routine to be called if the feed is TS and
+ *			it is routed to an A/V decoder, when a new TS packet
+ *			is received.
+ *			Used only on av7110-av.c.
+ * @check_crc32:	callback routine to check CRC. If not initialized,
+ *			dvb_demux will use an internal one.
+ * @memcopy:		callback routine to memcopy received data.
+ *			If not initialized, dvb_demux will default to memcpy().
+ * @users:		counter for the number of demux opened file descriptors.
+ *			Currently, it is limited to 10 users.
+ * @filter:		pointer to &struct dvb_demux_filter.
+ * @feed:		pointer to &struct dvb_demux_feed.
+ * @frontend_list:	&struct list_head with frontends used by the demux.
+ * @pesfilter:		array of &struct dvb_demux_feed with the PES types
+ *			that will be filtered.
+ * @pids:		list of filtered program IDs.
+ * @feed_list:		&struct list_head with feeds.
+ * @tsbuf:		temporary buffer used internally to store TS packets.
+ * @tsbufp:		temporary buffer index used internally.
+ * @mutex:		pointer to &struct mutex used to protect feed set
+ *			logic.
+ * @lock:		pointer to &spinlock_t, used to protect buffer handling.
+ * @cnt_storage:	buffer used for TS/TEI continuity check.
+ * @speed_last_time:	&ktime_t used for TS speed check.
+ * @speed_pkts_cnt:	packets count used for TS speed check.
+ */
 struct dvb_demux {
 struct dvb_demux {
 	struct dmx_demux dmx;
 	struct dmx_demux dmx;
 	void *priv;
 	void *priv;
@@ -115,8 +213,6 @@ struct dvb_demux {
 
 
 	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
 	struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
 	u16 pids[DMX_PES_OTHER];
 	u16 pids[DMX_PES_OTHER];
-	int playing;
-	int recording;
 
 
 #define DMX_MAX_PID 0x2000
 #define DMX_MAX_PID 0x2000
 	struct list_head feed_list;
 	struct list_head feed_list;
@@ -130,15 +226,119 @@ struct dvb_demux {
 
 
 	ktime_t speed_last_time; /* for TS speed check */
 	ktime_t speed_last_time; /* for TS speed check */
 	uint32_t speed_pkts_cnt; /* for TS speed check */
 	uint32_t speed_pkts_cnt; /* for TS speed check */
+
+	/* private: used only on av7110 */
+	int playing;
+	int recording;
 };
 };
 
 
-int dvb_dmx_init(struct dvb_demux *dvbdemux);
-void dvb_dmx_release(struct dvb_demux *dvbdemux);
-void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
+/**
+ * dvb_dmx_init - initialize a digital TV demux struct.
+ *
+ * @demux: &struct dvb_demux to be initialized.
+ *
+ * Before being able to register a digital TV demux struct, drivers
+ * should call this routine. On its typical usage, some fields should
+ * be initialized at the driver before calling it.
+ *
+ * A typical usecase is::
+ *
+ *	dvb->demux.dmx.capabilities =
+ *		DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+ *		DMX_MEMORY_BASED_FILTERING;
+ *	dvb->demux.priv       = dvb;
+ *	dvb->demux.filternum  = 256;
+ *	dvb->demux.feednum    = 256;
+ *	dvb->demux.start_feed = driver_start_feed;
+ *	dvb->demux.stop_feed  = driver_stop_feed;
+ *	ret = dvb_dmx_init(&dvb->demux);
+ *	if (ret < 0)
+ *		return ret;
+ */
+int dvb_dmx_init(struct dvb_demux *demux);
+
+/**
+ * dvb_dmx_release - releases a digital TV demux internal buffers.
+ *
+ * @demux: &struct dvb_demux to be released.
+ *
+ * The DVB core internally allocates data at @demux. This routine
+ * releases those data. Please notice that the struct itelf is not
+ * released, as it can be embedded on other structs.
+ */
+void dvb_dmx_release(struct dvb_demux *demux);
+
+/**
+ * dvb_dmx_swfilter_packets - use dvb software filter for a buffer with
+ *	multiple MPEG-TS packets with 188 bytes each.
+ *
+ * @demux: pointer to &struct dvb_demux
+ * @buf: buffer with data to be filtered
+ * @count: number of MPEG-TS packets with size of 188.
+ *
+ * The routine will discard a DVB packet that don't start with 0x47.
+ *
+ * Use this routine if the DVB demux fills MPEG-TS buffers that are
+ * already aligned.
+ *
+ * NOTE: The @buf size should have size equal to ``count * 188``.
+ */
+void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
 			      size_t count);
 			      size_t count);
+
+/**
+ * dvb_dmx_swfilter -  use dvb software filter for a buffer with
+ *	multiple MPEG-TS packets with 188 bytes each.
+ *
+ * @demux: pointer to &struct dvb_demux
+ * @buf: buffer with data to be filtered
+ * @count: number of MPEG-TS packets with size of 188.
+ *
+ * If a DVB packet doesn't start with 0x47, it will seek for the first
+ * byte that starts with 0x47.
+ *
+ * Use this routine if the DVB demux fill buffers that may not start with
+ * a packet start mark (0x47).
+ *
+ * NOTE: The @buf size should have size equal to ``count * 188``.
+ */
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
+
+/**
+ * dvb_dmx_swfilter_204 -  use dvb software filter for a buffer with
+ *	multiple MPEG-TS packets with 204 bytes each.
+ *
+ * @demux: pointer to &struct dvb_demux
+ * @buf: buffer with data to be filtered
+ * @count: number of MPEG-TS packets with size of 204.
+ *
+ * If a DVB packet doesn't start with 0x47, it will seek for the first
+ * byte that starts with 0x47.
+ *
+ * Use this routine if the DVB demux fill buffers that may not start with
+ * a packet start mark (0x47).
+ *
+ * NOTE: The @buf size should have size equal to ``count * 204``.
+ */
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
 			  size_t count);
 			  size_t count);
+
+/**
+ * dvb_dmx_swfilter_raw -  make the raw data available to userspace without
+ *	filtering
+ *
+ * @demux: pointer to &struct dvb_demux
+ * @buf: buffer with data
+ * @count: number of packets to be passed. The actual size of each packet
+ *	depends on the &dvb_demux->feed->cb.ts logic.
+ *
+ * Use it if the driver needs to deliver the raw payload to userspace without
+ * passing through the kernel demux. That is meant to support some
+ * delivery systems that aren't based on MPEG-TS.
+ *
+ * This function relies on &dvb_demux->feed->cb.ts to actually handle the
+ * buffer.
+ */
 void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
 void dvb_dmx_swfilter_raw(struct dvb_demux *demux, const u8 *buf,
 			  size_t count);
 			  size_t count);
 
 

+ 257 - 261
drivers/media/dvb-core/dvb_frontend.c

@@ -145,15 +145,13 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
 {
 {
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
 
-	if (!fepriv)
-		return;
-
-	dvb_free_device(fepriv->dvbdev);
+	if (fepriv)
+		dvb_free_device(fepriv->dvbdev);
 
 
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 
 
-	kfree(fepriv);
-	fe->frontend_priv = NULL;
+	if (fepriv)
+		kfree(fepriv);
 }
 }
 
 
 static void dvb_frontend_free(struct kref *ref)
 static void dvb_frontend_free(struct kref *ref)
@@ -951,8 +949,6 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 	memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
 	memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
 	c->delivery_system = delsys;
 	c->delivery_system = delsys;
 
 
-	c->state = DTV_CLEAR;
-
 	dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n",
 	dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n",
 			__func__, c->delivery_system);
 			__func__, c->delivery_system);
 
 
@@ -1109,39 +1105,6 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
 	_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
 	_DTV_CMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0, 0),
 };
 };
 
 
-static void dtv_property_dump(struct dvb_frontend *fe,
-			      bool is_set,
-			      struct dtv_property *tvp)
-{
-	int i;
-
-	if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
-		dev_warn(fe->dvb->device, "%s: %s tvp.cmd = 0x%08x undefined\n",
-				__func__,
-				is_set ? "SET" : "GET",
-				tvp->cmd);
-		return;
-	}
-
-	dev_dbg(fe->dvb->device, "%s: %s tvp.cmd    = 0x%08x (%s)\n", __func__,
-		is_set ? "SET" : "GET",
-		tvp->cmd,
-		dtv_cmds[tvp->cmd].name);
-
-	if (dtv_cmds[tvp->cmd].buffer) {
-		dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n",
-			__func__, tvp->u.buffer.len);
-
-		for(i = 0; i < tvp->u.buffer.len; i++)
-			dev_dbg(fe->dvb->device,
-					"%s: tvp.u.buffer.data[0x%02x] = 0x%02x\n",
-					__func__, i, tvp->u.buffer.data[i]);
-	} else {
-		dev_dbg(fe->dvb->device, "%s: tvp.u.data = 0x%08x\n", __func__,
-				tvp->u.data);
-	}
-}
-
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
  * drivers can use a single set_frontend tuning function, regardless of whether
  * drivers can use a single set_frontend tuning function, regardless of whether
  * it's being used for the legacy or new API, reducing code and complexity.
  * it's being used for the legacy or new API, reducing code and complexity.
@@ -1315,17 +1278,15 @@ static int dtv_get_frontend(struct dvb_frontend *fe,
 	return 0;
 	return 0;
 }
 }
 
 
-static int dvb_frontend_ioctl_legacy(struct file *file,
-			unsigned int cmd, void *parg);
-static int dvb_frontend_ioctl_properties(struct file *file,
-			unsigned int cmd, void *parg);
+static int dvb_frontend_handle_ioctl(struct file *file,
+				     unsigned int cmd, void *parg);
 
 
 static int dtv_property_process_get(struct dvb_frontend *fe,
 static int dtv_property_process_get(struct dvb_frontend *fe,
 				    const struct dtv_frontend_properties *c,
 				    const struct dtv_frontend_properties *c,
 				    struct dtv_property *tvp,
 				    struct dtv_property *tvp,
 				    struct file *file)
 				    struct file *file)
 {
 {
-	int r, ncaps;
+	int ncaps;
 
 
 	switch(tvp->cmd) {
 	switch(tvp->cmd) {
 	case DTV_ENUM_DELSYS:
 	case DTV_ENUM_DELSYS:
@@ -1536,14 +1497,18 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	/* Allow the frontend to override outgoing properties */
-	if (fe->ops.get_property) {
-		r = fe->ops.get_property(fe, tvp);
-		if (r < 0)
-			return r;
-	}
-
-	dtv_property_dump(fe, false, tvp);
+	if (!dtv_cmds[tvp->cmd].buffer)
+		dev_dbg(fe->dvb->device,
+			"%s: GET cmd 0x%08x (%s) = 0x%08x\n",
+			__func__, tvp->cmd, dtv_cmds[tvp->cmd].name,
+			tvp->u.data);
+	else
+		dev_dbg(fe->dvb->device,
+			"%s: GET cmd 0x%08x (%s) len %d: %*ph\n",
+			__func__,
+			tvp->cmd, dtv_cmds[tvp->cmd].name,
+			tvp->u.buffer.len,
+			tvp->u.buffer.len, tvp->u.buffer.data);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1766,23 +1731,36 @@ static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
 	return emulate_delivery_system(fe, delsys);
 	return emulate_delivery_system(fe, delsys);
 }
 }
 
 
+/**
+ * dtv_property_process_set -  Sets a single DTV property
+ * @fe:		Pointer to &struct dvb_frontend
+ * @file:	Pointer to &struct file
+ * @cmd:	Digital TV command
+ * @data:	An unsigned 32-bits number
+ *
+ * This routine assigns the property
+ * value to the corresponding member of
+ * &struct dtv_frontend_properties
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
 static int dtv_property_process_set(struct dvb_frontend *fe,
 static int dtv_property_process_set(struct dvb_frontend *fe,
-				    struct dtv_property *tvp,
-				    struct file *file)
+					struct file *file,
+					u32 cmd, u32 data)
 {
 {
 	int r = 0;
 	int r = 0;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
 
-	/* Allow the frontend to validate incoming properties */
-	if (fe->ops.set_property) {
-		r = fe->ops.set_property(fe, tvp);
-		if (r < 0)
-			return r;
-	}
-
-	dtv_property_dump(fe, true, tvp);
-
-	switch(tvp->cmd) {
+	/** Dump DTV command name and value*/
+	if (!cmd || cmd > DTV_MAX_COMMAND)
+		dev_warn(fe->dvb->device, "%s: SET cmd 0x%08x undefined\n",
+				 __func__, cmd);
+	else
+		dev_dbg(fe->dvb->device,
+				"%s: SET cmd 0x%08x (%s) to 0x%08x\n",
+				__func__, cmd, dtv_cmds[cmd].name, data);
+	switch (cmd) {
 	case DTV_CLEAR:
 	case DTV_CLEAR:
 		/*
 		/*
 		 * Reset a cache of data specific to the frontend here. This does
 		 * Reset a cache of data specific to the frontend here. This does
@@ -1791,144 +1769,144 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 		dvb_frontend_clear_cache(fe);
 		dvb_frontend_clear_cache(fe);
 		break;
 		break;
 	case DTV_TUNE:
 	case DTV_TUNE:
-		/* interpret the cache of data, build either a traditional frontend
-		 * tunerequest so we can pass validation in the FE_SET_FRONTEND
-		 * ioctl.
+		/*
+		 * Use the cached Digital TV properties to tune the
+		 * frontend
 		 */
 		 */
-		c->state = tvp->cmd;
-		dev_dbg(fe->dvb->device, "%s: Finalised property cache\n",
-				__func__);
+		dev_dbg(fe->dvb->device,
+			"%s: Setting the frontend from property cache\n",
+			__func__);
 
 
 		r = dtv_set_frontend(fe);
 		r = dtv_set_frontend(fe);
 		break;
 		break;
 	case DTV_FREQUENCY:
 	case DTV_FREQUENCY:
-		c->frequency = tvp->u.data;
+		c->frequency = data;
 		break;
 		break;
 	case DTV_MODULATION:
 	case DTV_MODULATION:
-		c->modulation = tvp->u.data;
+		c->modulation = data;
 		break;
 		break;
 	case DTV_BANDWIDTH_HZ:
 	case DTV_BANDWIDTH_HZ:
-		c->bandwidth_hz = tvp->u.data;
+		c->bandwidth_hz = data;
 		break;
 		break;
 	case DTV_INVERSION:
 	case DTV_INVERSION:
-		c->inversion = tvp->u.data;
+		c->inversion = data;
 		break;
 		break;
 	case DTV_SYMBOL_RATE:
 	case DTV_SYMBOL_RATE:
-		c->symbol_rate = tvp->u.data;
+		c->symbol_rate = data;
 		break;
 		break;
 	case DTV_INNER_FEC:
 	case DTV_INNER_FEC:
-		c->fec_inner = tvp->u.data;
+		c->fec_inner = data;
 		break;
 		break;
 	case DTV_PILOT:
 	case DTV_PILOT:
-		c->pilot = tvp->u.data;
+		c->pilot = data;
 		break;
 		break;
 	case DTV_ROLLOFF:
 	case DTV_ROLLOFF:
-		c->rolloff = tvp->u.data;
+		c->rolloff = data;
 		break;
 		break;
 	case DTV_DELIVERY_SYSTEM:
 	case DTV_DELIVERY_SYSTEM:
-		r = dvbv5_set_delivery_system(fe, tvp->u.data);
+		r = dvbv5_set_delivery_system(fe, data);
 		break;
 		break;
 	case DTV_VOLTAGE:
 	case DTV_VOLTAGE:
-		c->voltage = tvp->u.data;
-		r = dvb_frontend_ioctl_legacy(file, FE_SET_VOLTAGE,
+		c->voltage = data;
+		r = dvb_frontend_handle_ioctl(file, FE_SET_VOLTAGE,
 			(void *)c->voltage);
 			(void *)c->voltage);
 		break;
 		break;
 	case DTV_TONE:
 	case DTV_TONE:
-		c->sectone = tvp->u.data;
-		r = dvb_frontend_ioctl_legacy(file, FE_SET_TONE,
+		c->sectone = data;
+		r = dvb_frontend_handle_ioctl(file, FE_SET_TONE,
 			(void *)c->sectone);
 			(void *)c->sectone);
 		break;
 		break;
 	case DTV_CODE_RATE_HP:
 	case DTV_CODE_RATE_HP:
-		c->code_rate_HP = tvp->u.data;
+		c->code_rate_HP = data;
 		break;
 		break;
 	case DTV_CODE_RATE_LP:
 	case DTV_CODE_RATE_LP:
-		c->code_rate_LP = tvp->u.data;
+		c->code_rate_LP = data;
 		break;
 		break;
 	case DTV_GUARD_INTERVAL:
 	case DTV_GUARD_INTERVAL:
-		c->guard_interval = tvp->u.data;
+		c->guard_interval = data;
 		break;
 		break;
 	case DTV_TRANSMISSION_MODE:
 	case DTV_TRANSMISSION_MODE:
-		c->transmission_mode = tvp->u.data;
+		c->transmission_mode = data;
 		break;
 		break;
 	case DTV_HIERARCHY:
 	case DTV_HIERARCHY:
-		c->hierarchy = tvp->u.data;
+		c->hierarchy = data;
 		break;
 		break;
 	case DTV_INTERLEAVING:
 	case DTV_INTERLEAVING:
-		c->interleaving = tvp->u.data;
+		c->interleaving = data;
 		break;
 		break;
 
 
 	/* ISDB-T Support here */
 	/* ISDB-T Support here */
 	case DTV_ISDBT_PARTIAL_RECEPTION:
 	case DTV_ISDBT_PARTIAL_RECEPTION:
-		c->isdbt_partial_reception = tvp->u.data;
+		c->isdbt_partial_reception = data;
 		break;
 		break;
 	case DTV_ISDBT_SOUND_BROADCASTING:
 	case DTV_ISDBT_SOUND_BROADCASTING:
-		c->isdbt_sb_mode = tvp->u.data;
+		c->isdbt_sb_mode = data;
 		break;
 		break;
 	case DTV_ISDBT_SB_SUBCHANNEL_ID:
 	case DTV_ISDBT_SB_SUBCHANNEL_ID:
-		c->isdbt_sb_subchannel = tvp->u.data;
+		c->isdbt_sb_subchannel = data;
 		break;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_IDX:
 	case DTV_ISDBT_SB_SEGMENT_IDX:
-		c->isdbt_sb_segment_idx = tvp->u.data;
+		c->isdbt_sb_segment_idx = data;
 		break;
 		break;
 	case DTV_ISDBT_SB_SEGMENT_COUNT:
 	case DTV_ISDBT_SB_SEGMENT_COUNT:
-		c->isdbt_sb_segment_count = tvp->u.data;
+		c->isdbt_sb_segment_count = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYER_ENABLED:
 	case DTV_ISDBT_LAYER_ENABLED:
-		c->isdbt_layer_enabled = tvp->u.data;
+		c->isdbt_layer_enabled = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERA_FEC:
 	case DTV_ISDBT_LAYERA_FEC:
-		c->layer[0].fec = tvp->u.data;
+		c->layer[0].fec = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERA_MODULATION:
 	case DTV_ISDBT_LAYERA_MODULATION:
-		c->layer[0].modulation = tvp->u.data;
+		c->layer[0].modulation = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
 	case DTV_ISDBT_LAYERA_SEGMENT_COUNT:
-		c->layer[0].segment_count = tvp->u.data;
+		c->layer[0].segment_count = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
 	case DTV_ISDBT_LAYERA_TIME_INTERLEAVING:
-		c->layer[0].interleaving = tvp->u.data;
+		c->layer[0].interleaving = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERB_FEC:
 	case DTV_ISDBT_LAYERB_FEC:
-		c->layer[1].fec = tvp->u.data;
+		c->layer[1].fec = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERB_MODULATION:
 	case DTV_ISDBT_LAYERB_MODULATION:
-		c->layer[1].modulation = tvp->u.data;
+		c->layer[1].modulation = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
 	case DTV_ISDBT_LAYERB_SEGMENT_COUNT:
-		c->layer[1].segment_count = tvp->u.data;
+		c->layer[1].segment_count = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
 	case DTV_ISDBT_LAYERB_TIME_INTERLEAVING:
-		c->layer[1].interleaving = tvp->u.data;
+		c->layer[1].interleaving = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERC_FEC:
 	case DTV_ISDBT_LAYERC_FEC:
-		c->layer[2].fec = tvp->u.data;
+		c->layer[2].fec = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERC_MODULATION:
 	case DTV_ISDBT_LAYERC_MODULATION:
-		c->layer[2].modulation = tvp->u.data;
+		c->layer[2].modulation = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
 	case DTV_ISDBT_LAYERC_SEGMENT_COUNT:
-		c->layer[2].segment_count = tvp->u.data;
+		c->layer[2].segment_count = data;
 		break;
 		break;
 	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
 	case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
-		c->layer[2].interleaving = tvp->u.data;
+		c->layer[2].interleaving = data;
 		break;
 		break;
 
 
 	/* Multistream support */
 	/* Multistream support */
 	case DTV_STREAM_ID:
 	case DTV_STREAM_ID:
 	case DTV_DVBT2_PLP_ID_LEGACY:
 	case DTV_DVBT2_PLP_ID_LEGACY:
-		c->stream_id = tvp->u.data;
+		c->stream_id = data;
 		break;
 		break;
 
 
 	/* ATSC-MH */
 	/* ATSC-MH */
 	case DTV_ATSCMH_PARADE_ID:
 	case DTV_ATSCMH_PARADE_ID:
-		fe->dtv_property_cache.atscmh_parade_id = tvp->u.data;
+		fe->dtv_property_cache.atscmh_parade_id = data;
 		break;
 		break;
 	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
 	case DTV_ATSCMH_RS_FRAME_ENSEMBLE:
-		fe->dtv_property_cache.atscmh_rs_frame_ensemble = tvp->u.data;
+		fe->dtv_property_cache.atscmh_rs_frame_ensemble = data;
 		break;
 		break;
 
 
 	case DTV_LNA:
 	case DTV_LNA:
-		c->lna = tvp->u.data;
+		c->lna = data;
 		if (fe->ops.set_lna)
 		if (fe->ops.set_lna)
 			r = fe->ops.set_lna(fe);
 			r = fe->ops.set_lna(fe);
 		if (r < 0)
 		if (r < 0)
@@ -1942,14 +1920,12 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
 	return r;
 	return r;
 }
 }
 
 
-static int dvb_frontend_ioctl(struct file *file,
-			unsigned int cmd, void *parg)
+static int dvb_frontend_ioctl(struct file *file, unsigned int cmd, void *parg)
 {
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend *fe = dvbdev->priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int err = -EOPNOTSUPP;
+	int err;
 
 
 	dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd));
 	dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd));
 	if (down_interruptible(&fepriv->sem))
 	if (down_interruptible(&fepriv->sem))
@@ -1960,109 +1936,33 @@ static int dvb_frontend_ioctl(struct file *file,
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
-	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||
-	     cmd == FE_DISEQC_RECV_SLAVE_REPLY)) {
+	/*
+	 * If the frontend is opened in read-only mode, only the ioctls
+	 * that don't interfere with the tune logic should be accepted.
+	 * That allows an external application to monitor the DVB QoS and
+	 * statistics parameters.
+	 *
+	 * That matches all _IOR() ioctls, except for two special cases:
+	 *   - FE_GET_EVENT is part of the tuning logic on a DVB application;
+	 *   - FE_DISEQC_RECV_SLAVE_REPLY is part of DiSEqC 2.0
+	 *     setup
+	 * So, those two ioctls should also return -EPERM, as otherwise
+	 * reading from them would interfere with a DVB tune application
+	 */
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY
+	    && (_IOC_DIR(cmd) != _IOC_READ
+		|| cmd == FE_GET_EVENT
+		|| cmd == FE_DISEQC_RECV_SLAVE_REPLY)) {
 		up(&fepriv->sem);
 		up(&fepriv->sem);
 		return -EPERM;
 		return -EPERM;
 	}
 	}
 
 
-	if ((cmd == FE_SET_PROPERTY) || (cmd == FE_GET_PROPERTY))
-		err = dvb_frontend_ioctl_properties(file, cmd, parg);
-	else {
-		c->state = DTV_UNDEFINED;
-		err = dvb_frontend_ioctl_legacy(file, cmd, parg);
-	}
+	err = dvb_frontend_handle_ioctl(file, cmd, parg);
 
 
 	up(&fepriv->sem);
 	up(&fepriv->sem);
 	return err;
 	return err;
 }
 }
 
 
-static int dvb_frontend_ioctl_properties(struct file *file,
-			unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct dvb_frontend *fe = dvbdev->priv;
-	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int err = 0;
-
-	struct dtv_properties *tvps = parg;
-	struct dtv_property *tvp = NULL;
-	int i;
-
-	dev_dbg(fe->dvb->device, "%s:\n", __func__);
-
-	if (cmd == FE_SET_PROPERTY) {
-		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
-		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
-
-		/* Put an arbitrary limit on the number of messages that can
-		 * be sent at once */
-		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
-			return -EINVAL;
-
-		tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
-		if (IS_ERR(tvp))
-			return PTR_ERR(tvp);
-
-		for (i = 0; i < tvps->num; i++) {
-			err = dtv_property_process_set(fe, tvp + i, file);
-			if (err < 0)
-				goto out;
-			(tvp + i)->result = err;
-		}
-
-		if (c->state == DTV_TUNE)
-			dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
-
-	} else if (cmd == FE_GET_PROPERTY) {
-		struct dtv_frontend_properties getp = fe->dtv_property_cache;
-
-		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
-		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
-
-		/* Put an arbitrary limit on the number of messages that can
-		 * be sent at once */
-		if ((tvps->num == 0) || (tvps->num > DTV_IOCTL_MAX_MSGS))
-			return -EINVAL;
-
-		tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
-		if (IS_ERR(tvp))
-			return PTR_ERR(tvp);
-
-		/*
-		 * Let's use our own copy of property cache, in order to
-		 * avoid mangling with DTV zigzag logic, as drivers might
-		 * return crap, if they don't check if the data is available
-		 * before updating the properties cache.
-		 */
-		if (fepriv->state != FESTATE_IDLE) {
-			err = dtv_get_frontend(fe, &getp, NULL);
-			if (err < 0)
-				goto out;
-		}
-		for (i = 0; i < tvps->num; i++) {
-			err = dtv_property_process_get(fe, &getp, tvp + i, file);
-			if (err < 0)
-				goto out;
-			(tvp + i)->result = err;
-		}
-
-		if (copy_to_user((void __user *)tvps->props, tvp,
-				 tvps->num * sizeof(struct dtv_property))) {
-			err = -EFAULT;
-			goto out;
-		}
-
-	} else
-		err = -EOPNOTSUPP;
-
-out:
-	kfree(tvp);
-	return err;
-}
-
 static int dtv_set_frontend(struct dvb_frontend *fe)
 static int dtv_set_frontend(struct dvb_frontend *fe)
 {
 {
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -2200,16 +2100,102 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
 }
 }
 
 
 
 
-static int dvb_frontend_ioctl_legacy(struct file *file,
-			unsigned int cmd, void *parg)
+static int dvb_frontend_handle_ioctl(struct file *file,
+				     unsigned int cmd, void *parg)
 {
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-	int err = -EOPNOTSUPP;
+	int i, err;
+
+	dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
 
 	switch (cmd) {
 	switch (cmd) {
+	case FE_SET_PROPERTY: {
+		struct dtv_properties *tvps = parg;
+		struct dtv_property *tvp = NULL;
+
+		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n",
+			__func__, tvps->num);
+		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n",
+			__func__, tvps->props);
+
+		/*
+		 * Put an arbitrary limit on the number of messages that can
+		 * be sent at once
+		 */
+		if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
+			return -EINVAL;
+
+		tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
+		if (IS_ERR(tvp))
+			return PTR_ERR(tvp);
+
+		for (i = 0; i < tvps->num; i++) {
+			err = dtv_property_process_set(fe, file,
+							(tvp + i)->cmd,
+							(tvp + i)->u.data);
+			if (err < 0) {
+				kfree(tvp);
+				return err;
+			}
+		}
+		kfree(tvp);
+		break;
+	}
+	case FE_GET_PROPERTY: {
+		struct dtv_properties *tvps = parg;
+		struct dtv_property *tvp = NULL;
+		struct dtv_frontend_properties getp = fe->dtv_property_cache;
+
+		dev_dbg(fe->dvb->device, "%s: properties.num = %d\n",
+			__func__, tvps->num);
+		dev_dbg(fe->dvb->device, "%s: properties.props = %p\n",
+			__func__, tvps->props);
+
+		/*
+		 * Put an arbitrary limit on the number of messages that can
+		 * be sent at once
+		 */
+		if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
+			return -EINVAL;
+
+		tvp = memdup_user(tvps->props, tvps->num * sizeof(*tvp));
+		if (IS_ERR(tvp))
+			return PTR_ERR(tvp);
+
+		/*
+		 * Let's use our own copy of property cache, in order to
+		 * avoid mangling with DTV zigzag logic, as drivers might
+		 * return crap, if they don't check if the data is available
+		 * before updating the properties cache.
+		 */
+		if (fepriv->state != FESTATE_IDLE) {
+			err = dtv_get_frontend(fe, &getp, NULL);
+			if (err < 0) {
+				kfree(tvp);
+				return err;
+			}
+		}
+		for (i = 0; i < tvps->num; i++) {
+			err = dtv_property_process_get(fe, &getp,
+						       tvp + i, file);
+			if (err < 0) {
+				kfree(tvp);
+				return err;
+			}
+		}
+
+		if (copy_to_user((void __user *)tvps->props, tvp,
+				 tvps->num * sizeof(struct dtv_property))) {
+			kfree(tvp);
+			return -EFAULT;
+		}
+		kfree(tvp);
+		break;
+	}
+
 	case FE_GET_INFO: {
 	case FE_GET_INFO: {
 		struct dvb_frontend_info* info = parg;
 		struct dvb_frontend_info* info = parg;
 
 
@@ -2273,42 +2259,6 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		break;
 		break;
 	}
 	}
 
 
-	case FE_READ_BER:
-		if (fe->ops.read_ber) {
-			if (fepriv->thread)
-				err = fe->ops.read_ber(fe, (__u32 *) parg);
-			else
-				err = -EAGAIN;
-		}
-		break;
-
-	case FE_READ_SIGNAL_STRENGTH:
-		if (fe->ops.read_signal_strength) {
-			if (fepriv->thread)
-				err = fe->ops.read_signal_strength(fe, (__u16 *) parg);
-			else
-				err = -EAGAIN;
-		}
-		break;
-
-	case FE_READ_SNR:
-		if (fe->ops.read_snr) {
-			if (fepriv->thread)
-				err = fe->ops.read_snr(fe, (__u16 *) parg);
-			else
-				err = -EAGAIN;
-		}
-		break;
-
-	case FE_READ_UNCORRECTED_BLOCKS:
-		if (fe->ops.read_ucblocks) {
-			if (fepriv->thread)
-				err = fe->ops.read_ucblocks(fe, (__u32 *) parg);
-			else
-				err = -EAGAIN;
-		}
-		break;
-
 	case FE_DISEQC_RESET_OVERLOAD:
 	case FE_DISEQC_RESET_OVERLOAD:
 		if (fe->ops.diseqc_reset_overload) {
 		if (fe->ops.diseqc_reset_overload) {
 			err = fe->ops.diseqc_reset_overload(fe);
 			err = fe->ops.diseqc_reset_overload(fe);
@@ -2360,6 +2310,23 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		}
 		}
 		break;
 		break;
 
 
+	case FE_DISEQC_RECV_SLAVE_REPLY:
+		if (fe->ops.diseqc_recv_slave_reply)
+			err = fe->ops.diseqc_recv_slave_reply(fe, parg);
+		break;
+
+	case FE_ENABLE_HIGH_LNB_VOLTAGE:
+		if (fe->ops.enable_high_lnb_voltage)
+			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
+		break;
+
+	case FE_SET_FRONTEND_TUNE_MODE:
+		fepriv->tune_mode_flags = (unsigned long) parg;
+		err = 0;
+		break;
+
+	/* DEPRECATED dish control ioctls */
+
 	case FE_DISHNETWORK_SEND_LEGACY_CMD:
 	case FE_DISHNETWORK_SEND_LEGACY_CMD:
 		if (fe->ops.dishnetwork_send_legacy_command) {
 		if (fe->ops.dishnetwork_send_legacy_command) {
 			err = fe->ops.dishnetwork_send_legacy_command(fe,
 			err = fe->ops.dishnetwork_send_legacy_command(fe,
@@ -2425,16 +2392,46 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		}
 		}
 		break;
 		break;
 
 
-	case FE_DISEQC_RECV_SLAVE_REPLY:
-		if (fe->ops.diseqc_recv_slave_reply)
-			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+	/* DEPRECATED statistics ioctls */
+
+	case FE_READ_BER:
+		if (fe->ops.read_ber) {
+			if (fepriv->thread)
+				err = fe->ops.read_ber(fe, parg);
+			else
+				err = -EAGAIN;
+		}
 		break;
 		break;
 
 
-	case FE_ENABLE_HIGH_LNB_VOLTAGE:
-		if (fe->ops.enable_high_lnb_voltage)
-			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
+	case FE_READ_SIGNAL_STRENGTH:
+		if (fe->ops.read_signal_strength) {
+			if (fepriv->thread)
+				err = fe->ops.read_signal_strength(fe, parg);
+			else
+				err = -EAGAIN;
+		}
 		break;
 		break;
 
 
+	case FE_READ_SNR:
+		if (fe->ops.read_snr) {
+			if (fepriv->thread)
+				err = fe->ops.read_snr(fe, parg);
+			else
+				err = -EAGAIN;
+		}
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		if (fe->ops.read_ucblocks) {
+			if (fepriv->thread)
+				err = fe->ops.read_ucblocks(fe, parg);
+			else
+				err = -EAGAIN;
+		}
+		break;
+
+	/* DEPRECATED DVBv3 ioctls */
+
 	case FE_SET_FRONTEND:
 	case FE_SET_FRONTEND:
 		err = dvbv3_set_delivery_system(fe);
 		err = dvbv3_set_delivery_system(fe);
 		if (err)
 		if (err)
@@ -2461,11 +2458,10 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 		err = dtv_get_frontend(fe, &getp, parg);
 		err = dtv_get_frontend(fe, &getp, parg);
 		break;
 		break;
 	}
 	}
-	case FE_SET_FRONTEND_TUNE_MODE:
-		fepriv->tune_mode_flags = (unsigned long) parg;
-		err = 0;
-		break;
-	}
+
+	default:
+		return -ENOTSUPP;
+	} /* switch */
 
 
 	return err;
 	return err;
 }
 }

+ 52 - 65
drivers/media/dvb-core/dvb_frontend.h

@@ -180,8 +180,8 @@ enum dvbfe_search {
 /**
 /**
  * struct dvb_tuner_ops - Tuner information and callbacks
  * struct dvb_tuner_ops - Tuner information and callbacks
  *
  *
- * @info:		embedded struct dvb_tuner_info with tuner properties
- * @release:		callback function called when frontend is dettached.
+ * @info:		embedded &struct dvb_tuner_info with tuner properties
+ * @release:		callback function called when frontend is detached.
  *			drivers should free any allocated memory.
  *			drivers should free any allocated memory.
  * @init:		callback function used to initialize the tuner device.
  * @init:		callback function used to initialize the tuner device.
  * @sleep:		callback function used to put the tuner to sleep.
  * @sleep:		callback function used to put the tuner to sleep.
@@ -191,14 +191,14 @@ enum dvbfe_search {
  *			resuming from suspend.
  *			resuming from suspend.
  * @set_params:		callback function used to inform the tuner to tune
  * @set_params:		callback function used to inform the tuner to tune
  *			into a digital TV channel. The properties to be used
  *			into a digital TV channel. The properties to be used
- *			are stored at @dvb_frontend.dtv_property_cache;. The
- *			tuner demod can change the parameters to reflect the
- *			changes needed for the channel to be tuned, and
+ *			are stored at &struct dvb_frontend.dtv_property_cache.
+ *			The tuner demod can change the parameters to reflect
+ *			the changes needed for the channel to be tuned, and
  *			update statistics. This is the recommended way to set
  *			update statistics. This is the recommended way to set
  *			the tuner parameters and should be used on newer
  *			the tuner parameters and should be used on newer
  *			drivers.
  *			drivers.
  * @set_analog_params:	callback function used to tune into an analog TV
  * @set_analog_params:	callback function used to tune into an analog TV
- *			channel on hybrid tuners. It passes @analog_parameters;
+ *			channel on hybrid tuners. It passes @analog_parameters
  *			to the driver.
  *			to the driver.
  * @set_config:		callback function used to send some tuner-specific
  * @set_config:		callback function used to send some tuner-specific
  *			parameters.
  *			parameters.
@@ -207,9 +207,9 @@ enum dvbfe_search {
  * @get_if_frequency:	get the Intermediate Frequency, in Hz. For baseband,
  * @get_if_frequency:	get the Intermediate Frequency, in Hz. For baseband,
  * 			should return 0.
  * 			should return 0.
  * @get_status:		returns the frontend lock status
  * @get_status:		returns the frontend lock status
- * @get_rf_strength:	returns the RF signal strengh. Used mostly to support
+ * @get_rf_strength:	returns the RF signal strength. Used mostly to support
  *			analog TV and radio. Digital TV should report, instead,
  *			analog TV and radio. Digital TV should report, instead,
- *			via DVBv5 API (@dvb_frontend.dtv_property_cache;).
+ *			via DVBv5 API (&struct dvb_frontend.dtv_property_cache).
  * @get_afc:		Used only by analog TV core. Reports the frequency
  * @get_afc:		Used only by analog TV core. Reports the frequency
  *			drift due to AFC.
  *			drift due to AFC.
  * @calc_regs:		callback function used to pass register data settings
  * @calc_regs:		callback function used to pass register data settings
@@ -217,7 +217,7 @@ enum dvbfe_search {
  * @set_frequency:	Set a new frequency. Shouldn't be used on newer drivers.
  * @set_frequency:	Set a new frequency. Shouldn't be used on newer drivers.
  * @set_bandwidth:	Set a new frequency. Shouldn't be used on newer drivers.
  * @set_bandwidth:	Set a new frequency. Shouldn't be used on newer drivers.
  *
  *
- * NOTE: frequencies used on get_frequency and set_frequency are in Hz for
+ * NOTE: frequencies used on @get_frequency and @set_frequency are in Hz for
  * terrestrial/cable or kHz for satellite.
  * terrestrial/cable or kHz for satellite.
  *
  *
  */
  */
@@ -283,14 +283,14 @@ struct analog_demod_info {
  * @set_params:		callback function used to inform the demod to set the
  * @set_params:		callback function used to inform the demod to set the
  *			demodulator parameters needed to decode an analog or
  *			demodulator parameters needed to decode an analog or
  *			radio channel. The properties are passed via
  *			radio channel. The properties are passed via
- *			struct @analog_params;.
+ *			&struct analog_params.
  * @has_signal:		returns 0xffff if has signal, or 0 if it doesn't.
  * @has_signal:		returns 0xffff if has signal, or 0 if it doesn't.
  * @get_afc:		Used only by analog TV core. Reports the frequency
  * @get_afc:		Used only by analog TV core. Reports the frequency
  *			drift due to AFC.
  *			drift due to AFC.
  * @tuner_status:	callback function that returns tuner status bits, e. g.
  * @tuner_status:	callback function that returns tuner status bits, e. g.
- *			TUNER_STATUS_LOCKED and TUNER_STATUS_STEREO.
+ *			%TUNER_STATUS_LOCKED and %TUNER_STATUS_STEREO.
  * @standby:		set the tuner to standby mode.
  * @standby:		set the tuner to standby mode.
- * @release:		callback function called when frontend is dettached.
+ * @release:		callback function called when frontend is detached.
  *			drivers should free any allocated memory.
  *			drivers should free any allocated memory.
  * @i2c_gate_ctrl:	controls the I2C gate. Newer drivers should use I2C
  * @i2c_gate_ctrl:	controls the I2C gate. Newer drivers should use I2C
  *			mux support instead.
  *			mux support instead.
@@ -321,10 +321,10 @@ struct dtv_frontend_properties;
  * struct dvb_frontend_ops - Demodulation information and callbacks for
  * struct dvb_frontend_ops - Demodulation information and callbacks for
  *			      ditialt TV
  *			      ditialt TV
  *
  *
- * @info:		embedded struct dvb_tuner_info with tuner properties
+ * @info:		embedded &struct dvb_tuner_info with tuner properties
  * @delsys:		Delivery systems supported by the frontend
  * @delsys:		Delivery systems supported by the frontend
  * @detach:		callback function called when frontend is detached.
  * @detach:		callback function called when frontend is detached.
- *			drivers should clean up, but not yet free the struct
+ *			drivers should clean up, but not yet free the &struct
  *			dvb_frontend allocation.
  *			dvb_frontend allocation.
  * @release:		callback function called when frontend is ready to be
  * @release:		callback function called when frontend is ready to be
  *			freed.
  *			freed.
@@ -338,57 +338,57 @@ struct dtv_frontend_properties;
  *			allow other drivers to write data into their registers.
  *			allow other drivers to write data into their registers.
  *			Should not be used on new drivers.
  *			Should not be used on new drivers.
  * @tune:		callback function used by demod drivers that use
  * @tune:		callback function used by demod drivers that use
- *			@DVBFE_ALGO_HW; to tune into a frequency.
+ *			@DVBFE_ALGO_HW to tune into a frequency.
  * @get_frontend_algo:	returns the desired hardware algorithm.
  * @get_frontend_algo:	returns the desired hardware algorithm.
  * @set_frontend:	callback function used to inform the demod to set the
  * @set_frontend:	callback function used to inform the demod to set the
  *			parameters for demodulating a digital TV channel.
  *			parameters for demodulating a digital TV channel.
- *			The properties to be used are stored at
- *			@dvb_frontend.dtv_property_cache;. The demod can change
+ *			The properties to be used are stored at &struct
+ *			dvb_frontend.dtv_property_cache. The demod can change
  *			the parameters to reflect the changes needed for the
  *			the parameters to reflect the changes needed for the
  *			channel to be decoded, and update statistics.
  *			channel to be decoded, and update statistics.
  * @get_tune_settings:	callback function
  * @get_tune_settings:	callback function
  * @get_frontend:	callback function used to inform the parameters
  * @get_frontend:	callback function used to inform the parameters
  *			actuall in use. The properties to be used are stored at
  *			actuall in use. The properties to be used are stored at
- *			@dvb_frontend.dtv_property_cache; and update
+ *			&struct dvb_frontend.dtv_property_cache and update
  *			statistics. Please notice that it should not return
  *			statistics. Please notice that it should not return
  *			an error code if the statistics are not available
  *			an error code if the statistics are not available
  *			because the demog is not locked.
  *			because the demog is not locked.
  * @read_status:	returns the locking status of the frontend.
  * @read_status:	returns the locking status of the frontend.
  * @read_ber:		legacy callback function to return the bit error rate.
  * @read_ber:		legacy callback function to return the bit error rate.
  *			Newer drivers should provide such info via DVBv5 API,
  *			Newer drivers should provide such info via DVBv5 API,
- *			e. g. @set_frontend;/@get_frontend;, implementing this
+ *			e. g. @set_frontend;/@get_frontend, implementing this
  *			callback only if DVBv3 API compatibility is wanted.
  *			callback only if DVBv3 API compatibility is wanted.
  * @read_signal_strength: legacy callback function to return the signal
  * @read_signal_strength: legacy callback function to return the signal
  *			strength. Newer drivers should provide such info via
  *			strength. Newer drivers should provide such info via
- *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
+ *			DVBv5 API, e. g. @set_frontend/@get_frontend,
  *			implementing this callback only if DVBv3 API
  *			implementing this callback only if DVBv3 API
  *			compatibility is wanted.
  *			compatibility is wanted.
  * @read_snr:		legacy callback function to return the Signal/Noise
  * @read_snr:		legacy callback function to return the Signal/Noise
  * 			rate. Newer drivers should provide such info via
  * 			rate. Newer drivers should provide such info via
- *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
+ *			DVBv5 API, e. g. @set_frontend/@get_frontend,
  *			implementing this callback only if DVBv3 API
  *			implementing this callback only if DVBv3 API
  *			compatibility is wanted.
  *			compatibility is wanted.
  * @read_ucblocks:	legacy callback function to return the Uncorrected Error
  * @read_ucblocks:	legacy callback function to return the Uncorrected Error
  *			Blocks. Newer drivers should provide such info via
  *			Blocks. Newer drivers should provide such info via
- *			DVBv5 API, e. g. @set_frontend;/@get_frontend;,
+ *			DVBv5 API, e. g. @set_frontend/@get_frontend,
  *			implementing this callback only if DVBv3 API
  *			implementing this callback only if DVBv3 API
  *			compatibility is wanted.
  *			compatibility is wanted.
  * @diseqc_reset_overload: callback function to implement the
  * @diseqc_reset_overload: callback function to implement the
- *			FE_DISEQC_RESET_OVERLOAD ioctl (only Satellite)
+ *			FE_DISEQC_RESET_OVERLOAD() ioctl (only Satellite)
  * @diseqc_send_master_cmd: callback function to implement the
  * @diseqc_send_master_cmd: callback function to implement the
- *			FE_DISEQC_SEND_MASTER_CMD ioctl (only Satellite).
+ *			FE_DISEQC_SEND_MASTER_CMD() ioctl (only Satellite).
  * @diseqc_recv_slave_reply: callback function to implement the
  * @diseqc_recv_slave_reply: callback function to implement the
- *			FE_DISEQC_RECV_SLAVE_REPLY ioctl (only Satellite)
+ *			FE_DISEQC_RECV_SLAVE_REPLY() ioctl (only Satellite)
  * @diseqc_send_burst:	callback function to implement the
  * @diseqc_send_burst:	callback function to implement the
- *			FE_DISEQC_SEND_BURST ioctl (only Satellite).
+ *			FE_DISEQC_SEND_BURST() ioctl (only Satellite).
  * @set_tone:		callback function to implement the
  * @set_tone:		callback function to implement the
- *			FE_SET_TONE ioctl (only Satellite).
+ *			FE_SET_TONE() ioctl (only Satellite).
  * @set_voltage:	callback function to implement the
  * @set_voltage:	callback function to implement the
- *			FE_SET_VOLTAGE ioctl (only Satellite).
+ *			FE_SET_VOLTAGE() ioctl (only Satellite).
  * @enable_high_lnb_voltage: callback function to implement the
  * @enable_high_lnb_voltage: callback function to implement the
- *			FE_ENABLE_HIGH_LNB_VOLTAGE ioctl (only Satellite).
+ *			FE_ENABLE_HIGH_LNB_VOLTAGE() ioctl (only Satellite).
  * @dishnetwork_send_legacy_command: callback function to implement the
  * @dishnetwork_send_legacy_command: callback function to implement the
- *			FE_DISHNETWORK_SEND_LEGACY_CMD ioctl (only Satellite).
+ *			FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl (only Satellite).
  *			Drivers should not use this, except when the DVB
  *			Drivers should not use this, except when the DVB
  *			core emulation fails to provide proper support (e.g.
  *			core emulation fails to provide proper support (e.g.
  *			if @set_voltage takes more than 8ms to work), and
  *			if @set_voltage takes more than 8ms to work), and
@@ -399,15 +399,10 @@ struct dtv_frontend_properties;
  * @ts_bus_ctrl:	callback function used to take control of the TS bus.
  * @ts_bus_ctrl:	callback function used to take control of the TS bus.
  * @set_lna:		callback function to power on/off/auto the LNA.
  * @set_lna:		callback function to power on/off/auto the LNA.
  * @search:		callback function used on some custom algo search algos.
  * @search:		callback function used on some custom algo search algos.
- * @tuner_ops:		pointer to struct dvb_tuner_ops
- * @analog_ops:		pointer to struct analog_demod_ops
- * @set_property:	callback function to allow the frontend to validade
- *			incoming properties. Should not be used on new drivers.
- * @get_property:	callback function to allow the frontend to override
- *			outcoming properties. Should not be used on new drivers.
+ * @tuner_ops:		pointer to &struct dvb_tuner_ops
+ * @analog_ops:		pointer to &struct analog_demod_ops
  */
  */
 struct dvb_frontend_ops {
 struct dvb_frontend_ops {
-
 	struct dvb_frontend_info info;
 	struct dvb_frontend_info info;
 
 
 	u8 delsys[MAX_DELSYS];
 	u8 delsys[MAX_DELSYS];
@@ -466,9 +461,6 @@ struct dvb_frontend_ops {
 
 
 	struct dvb_tuner_ops tuner_ops;
 	struct dvb_tuner_ops tuner_ops;
 	struct analog_demod_ops analog_ops;
 	struct analog_demod_ops analog_ops;
-
-	int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
-	int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
 };
 };
 
 
 #ifdef __DVB_CORE__
 #ifdef __DVB_CORE__
@@ -565,15 +557,15 @@ struct dtv_frontend_properties {
 
 
 	enum fe_sec_voltage	voltage;
 	enum fe_sec_voltage	voltage;
 	enum fe_sec_tone_mode	sectone;
 	enum fe_sec_tone_mode	sectone;
-	enum fe_spectral_inversion	inversion;
-	enum fe_code_rate		fec_inner;
+	enum fe_spectral_inversion inversion;
+	enum fe_code_rate	fec_inner;
 	enum fe_transmit_mode	transmission_mode;
 	enum fe_transmit_mode	transmission_mode;
 	u32			bandwidth_hz;	/* 0 = AUTO */
 	u32			bandwidth_hz;	/* 0 = AUTO */
 	enum fe_guard_interval	guard_interval;
 	enum fe_guard_interval	guard_interval;
-	enum fe_hierarchy		hierarchy;
+	enum fe_hierarchy	hierarchy;
 	u32			symbol_rate;
 	u32			symbol_rate;
-	enum fe_code_rate		code_rate_HP;
-	enum fe_code_rate		code_rate_LP;
+	enum fe_code_rate	code_rate_HP;
+	enum fe_code_rate	code_rate_LP;
 
 
 	enum fe_pilot		pilot;
 	enum fe_pilot		pilot;
 	enum fe_rolloff		rolloff;
 	enum fe_rolloff		rolloff;
@@ -628,11 +620,6 @@ struct dtv_frontend_properties {
 	struct dtv_fe_stats	post_bit_count;
 	struct dtv_fe_stats	post_bit_count;
 	struct dtv_fe_stats	block_error;
 	struct dtv_fe_stats	block_error;
 	struct dtv_fe_stats	block_count;
 	struct dtv_fe_stats	block_count;
-
-	/* private: */
-	/* Cache State */
-	u32			state;
-
 };
 };
 
 
 #define DVB_FE_NO_EXIT  0
 #define DVB_FE_NO_EXIT  0
@@ -643,16 +630,16 @@ struct dtv_frontend_properties {
 /**
 /**
  * struct dvb_frontend - Frontend structure to be used on drivers.
  * struct dvb_frontend - Frontend structure to be used on drivers.
  *
  *
- * @refcount:		refcount to keep track of struct dvb_frontend
+ * @refcount:		refcount to keep track of &struct dvb_frontend
  *			references
  *			references
- * @ops:		embedded struct dvb_frontend_ops
- * @dvb:		pointer to struct dvb_adapter
+ * @ops:		embedded &struct dvb_frontend_ops
+ * @dvb:		pointer to &struct dvb_adapter
  * @demodulator_priv:	demod private data
  * @demodulator_priv:	demod private data
  * @tuner_priv:		tuner private data
  * @tuner_priv:		tuner private data
  * @frontend_priv:	frontend private data
  * @frontend_priv:	frontend private data
  * @sec_priv:		SEC private data
  * @sec_priv:		SEC private data
  * @analog_demod_priv:	Analog demod private data
  * @analog_demod_priv:	Analog demod private data
- * @dtv_property_cache:	embedded struct dtv_frontend_properties
+ * @dtv_property_cache:	embedded &struct dtv_frontend_properties
  * @callback:		callback function used on some drivers to call
  * @callback:		callback function used on some drivers to call
  *			either the tuner or the demodulator.
  *			either the tuner or the demodulator.
  * @id:			Frontend ID
  * @id:			Frontend ID
@@ -681,8 +668,8 @@ struct dvb_frontend {
 /**
 /**
  * dvb_register_frontend() - Registers a DVB frontend at the adapter
  * dvb_register_frontend() - Registers a DVB frontend at the adapter
  *
  *
- * @dvb: pointer to the dvb adapter
- * @fe: pointer to the frontend struct
+ * @dvb: pointer to &struct dvb_adapter
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * Allocate and initialize the private data needed by the frontend core to
  * Allocate and initialize the private data needed by the frontend core to
  * manage the frontend and calls dvb_register_device() to register a new
  * manage the frontend and calls dvb_register_device() to register a new
@@ -695,7 +682,7 @@ int dvb_register_frontend(struct dvb_adapter *dvb,
 /**
 /**
  * dvb_unregister_frontend() - Unregisters a DVB frontend
  * dvb_unregister_frontend() - Unregisters a DVB frontend
  *
  *
- * @fe: pointer to the frontend struct
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * Stops the frontend kthread, calls dvb_unregister_device() and frees the
  * Stops the frontend kthread, calls dvb_unregister_device() and frees the
  * private frontend data allocated by dvb_register_frontend().
  * private frontend data allocated by dvb_register_frontend().
@@ -709,14 +696,14 @@ int dvb_unregister_frontend(struct dvb_frontend *fe);
 /**
 /**
  * dvb_frontend_detach() - Detaches and frees frontend specific data
  * dvb_frontend_detach() - Detaches and frees frontend specific data
  *
  *
- * @fe: pointer to the frontend struct
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * This function should be called after dvb_unregister_frontend(). It
  * This function should be called after dvb_unregister_frontend(). It
  * calls the SEC, tuner and demod release functions:
  * calls the SEC, tuner and demod release functions:
  * &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release,
  * &dvb_frontend_ops.release_sec, &dvb_frontend_ops.tuner_ops.release,
  * &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release.
  * &dvb_frontend_ops.analog_ops.release and &dvb_frontend_ops.release.
  *
  *
- * If the driver is compiled with CONFIG_MEDIA_ATTACH, it also decreases
+ * If the driver is compiled with %CONFIG_MEDIA_ATTACH, it also decreases
  * the module reference count, needed to allow userspace to remove the
  * the module reference count, needed to allow userspace to remove the
  * previously used DVB frontend modules.
  * previously used DVB frontend modules.
  */
  */
@@ -725,7 +712,7 @@ void dvb_frontend_detach(struct dvb_frontend *fe);
 /**
 /**
  * dvb_frontend_suspend() - Suspends a Digital TV frontend
  * dvb_frontend_suspend() - Suspends a Digital TV frontend
  *
  *
- * @fe: pointer to the frontend struct
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * This function prepares a Digital TV frontend to suspend.
  * This function prepares a Digital TV frontend to suspend.
  *
  *
@@ -743,7 +730,7 @@ int dvb_frontend_suspend(struct dvb_frontend *fe);
 /**
 /**
  * dvb_frontend_resume() - Resumes a Digital TV frontend
  * dvb_frontend_resume() - Resumes a Digital TV frontend
  *
  *
- * @fe: pointer to the frontend struct
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * This function resumes the usual operation of the tuner after resume.
  * This function resumes the usual operation of the tuner after resume.
  *
  *
@@ -764,7 +751,7 @@ int dvb_frontend_resume(struct dvb_frontend *fe);
 /**
 /**
  * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend
  * dvb_frontend_reinitialise() - forces a reinitialisation at the frontend
  *
  *
- * @fe: pointer to the frontend struct
+ * @fe: pointer to &struct dvb_frontend
  *
  *
  * Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\),
  * Calls &dvb_frontend_ops.init\(\) and &dvb_frontend_ops.tuner_ops.init\(\),
  * and resets SEC tone and voltage (for Satellite systems).
  * and resets SEC tone and voltage (for Satellite systems).
@@ -779,16 +766,16 @@ void dvb_frontend_reinitialise(struct dvb_frontend *fe);
  * dvb_frontend_sleep_until() - Sleep for the amount of time given by
  * dvb_frontend_sleep_until() - Sleep for the amount of time given by
  *                      add_usec parameter
  *                      add_usec parameter
  *
  *
- * @waketime: pointer to a struct ktime_t
+ * @waketime: pointer to &struct ktime_t
  * @add_usec: time to sleep, in microseconds
  * @add_usec: time to sleep, in microseconds
  *
  *
  * This function is used to measure the time required for the
  * This function is used to measure the time required for the
- * %FE_DISHNETWORK_SEND_LEGACY_CMD ioctl to work. It needs to be as precise
+ * FE_DISHNETWORK_SEND_LEGACY_CMD() ioctl to work. It needs to be as precise
  * as possible, as it affects the detection of the dish tone command at the
  * as possible, as it affects the detection of the dish tone command at the
  * satellite subsystem.
  * satellite subsystem.
  *
  *
  * Its used internally by the DVB frontend core, in order to emulate
  * Its used internally by the DVB frontend core, in order to emulate
- * %FE_DISHNETWORK_SEND_LEGACY_CMD using the &dvb_frontend_ops.set_voltage\(\)
+ * FE_DISHNETWORK_SEND_LEGACY_CMD() using the &dvb_frontend_ops.set_voltage\(\)
  * callback.
  * callback.
  *
  *
  * NOTE: it should not be used at the drivers, as the emulation for the
  * NOTE: it should not be used at the drivers, as the emulation for the

+ 32 - 2
drivers/media/dvb-core/dvb_net.h

@@ -30,6 +30,22 @@
 
 
 #ifdef CONFIG_DVB_NET
 #ifdef CONFIG_DVB_NET
 
 
+/**
+ * struct dvb_net - describes a DVB network interface
+ *
+ * @dvbdev:		pointer to &struct dvb_device.
+ * @device:		array of pointers to &struct net_device.
+ * @state:		array of integers to each net device. A value
+ *			different than zero means that the interface is
+ *			in usage.
+ * @exit:		flag to indicate when the device is being removed.
+ * @demux:		pointer to &struct dmx_demux.
+ * @ioctl_mutex:	protect access to this struct.
+ *
+ * Currently, the core supports up to %DVB_NET_DEVICES_MAX (10) network
+ * devices.
+ */
+
 struct dvb_net {
 struct dvb_net {
 	struct dvb_device *dvbdev;
 	struct dvb_device *dvbdev;
 	struct net_device *device[DVB_NET_DEVICES_MAX];
 	struct net_device *device[DVB_NET_DEVICES_MAX];
@@ -39,8 +55,22 @@ struct dvb_net {
 	struct mutex ioctl_mutex;
 	struct mutex ioctl_mutex;
 };
 };
 
 
-void dvb_net_release(struct dvb_net *);
-int  dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *);
+/**
+ * dvb_net_init - nitializes a digital TV network device and registers it.
+ *
+ * @adap:	pointer to &struct dvb_adapter.
+ * @dvbnet:	pointer to &struct dvb_net.
+ * @dmxdemux:	pointer to &struct dmx_demux.
+ */
+int dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet,
+		  struct dmx_demux *dmxdemux);
+
+/**
+ * dvb_net_release - releases a digital TV network device and unregisters it.
+ *
+ * @dvbnet:	pointer to &struct dvb_net.
+ */
+void dvb_net_release(struct dvb_net *dvbnet);
 
 
 #else
 #else
 
 

+ 27 - 5
drivers/media/dvb-core/dvbdev.c

@@ -51,8 +51,15 @@ static LIST_HEAD(dvb_adapter_list);
 static DEFINE_MUTEX(dvbdev_register_lock);
 static DEFINE_MUTEX(dvbdev_register_lock);
 
 
 static const char * const dnames[] = {
 static const char * const dnames[] = {
-	"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
-	"net", "osd"
+	[DVB_DEVICE_VIDEO] =		"video",
+	[DVB_DEVICE_AUDIO] =		"audio",
+	[DVB_DEVICE_SEC] =		"sec",
+	[DVB_DEVICE_FRONTEND] =		"frontend",
+	[DVB_DEVICE_DEMUX] =		"demux",
+	[DVB_DEVICE_DVR] =		"dvr",
+	[DVB_DEVICE_CA] =		"ca",
+	[DVB_DEVICE_NET] =		"net",
+	[DVB_DEVICE_OSD] =		"osd"
 };
 };
 
 
 #ifdef CONFIG_DVB_DYNAMIC_MINORS
 #ifdef CONFIG_DVB_DYNAMIC_MINORS
@@ -60,7 +67,22 @@ static const char * const dnames[] = {
 #define DVB_MAX_IDS		MAX_DVB_MINORS
 #define DVB_MAX_IDS		MAX_DVB_MINORS
 #else
 #else
 #define DVB_MAX_IDS		4
 #define DVB_MAX_IDS		4
-#define nums2minor(num, type, id)	((num << 6) | (id << 4) | type)
+
+static const u8 minor_type[] = {
+       [DVB_DEVICE_VIDEO]      = 0,
+       [DVB_DEVICE_AUDIO]      = 1,
+       [DVB_DEVICE_SEC]        = 2,
+       [DVB_DEVICE_FRONTEND]   = 3,
+       [DVB_DEVICE_DEMUX]      = 4,
+       [DVB_DEVICE_DVR]        = 5,
+       [DVB_DEVICE_CA]         = 6,
+       [DVB_DEVICE_NET]        = 7,
+       [DVB_DEVICE_OSD]        = 8,
+};
+
+#define nums2minor(num, type, id) \
+       (((num) << 6) | ((id) << 4) | minor_type[type])
+
 #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
 #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
 #endif
 #endif
 
 
@@ -426,8 +448,8 @@ static int dvb_register_media_device(struct dvb_device *dvbdev,
 }
 }
 
 
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
-			const struct dvb_device *template, void *priv, int type,
-			int demux_sink_pads)
+			const struct dvb_device *template, void *priv,
+			enum dvb_device_type type, int demux_sink_pads)
 {
 {
 	struct dvb_device *dvbdev;
 	struct dvb_device *dvbdev;
 	struct file_operations *dvbdevfops;
 	struct file_operations *dvbdevfops;

+ 113 - 24
drivers/media/dvb-core/dvbdev.h

@@ -35,15 +35,37 @@
 
 
 #define DVB_UNSET (-1)
 #define DVB_UNSET (-1)
 
 
-#define DVB_DEVICE_VIDEO      0
-#define DVB_DEVICE_AUDIO      1
-#define DVB_DEVICE_SEC        2
-#define DVB_DEVICE_FRONTEND   3
-#define DVB_DEVICE_DEMUX      4
-#define DVB_DEVICE_DVR        5
-#define DVB_DEVICE_CA         6
-#define DVB_DEVICE_NET        7
-#define DVB_DEVICE_OSD        8
+/* List of DVB device types */
+
+/**
+ * enum dvb_device_type - type of the Digital TV device
+ *
+ * @DVB_DEVICE_SEC:		Digital TV standalone Common Interface (CI)
+ * @DVB_DEVICE_FRONTEND:	Digital TV frontend.
+ * @DVB_DEVICE_DEMUX:		Digital TV demux.
+ * @DVB_DEVICE_DVR:		Digital TV digital video record (DVR).
+ * @DVB_DEVICE_CA:		Digital TV Conditional Access (CA).
+ * @DVB_DEVICE_NET:		Digital TV network.
+ *
+ * @DVB_DEVICE_VIDEO:		Digital TV video decoder.
+ *				Deprecated. Used only on av7110-av.
+ * @DVB_DEVICE_AUDIO:		Digital TV audio decoder.
+ *				Deprecated. Used only on av7110-av.
+ * @DVB_DEVICE_OSD:		Digital TV On Screen Display (OSD).
+ *				Deprecated. Used only on av7110.
+ */
+enum dvb_device_type {
+	DVB_DEVICE_SEC,
+	DVB_DEVICE_FRONTEND,
+	DVB_DEVICE_DEMUX,
+	DVB_DEVICE_DVR,
+	DVB_DEVICE_CA,
+	DVB_DEVICE_NET,
+
+	DVB_DEVICE_VIDEO,
+	DVB_DEVICE_AUDIO,
+	DVB_DEVICE_OSD,
+};
 
 
 #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
 #define DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr) \
 	static short adapter_nr[] = \
 	static short adapter_nr[] = \
@@ -104,8 +126,7 @@ struct dvb_adapter {
  * @list_head:	List head with all DVB devices
  * @list_head:	List head with all DVB devices
  * @fops:	pointer to struct file_operations
  * @fops:	pointer to struct file_operations
  * @adapter:	pointer to the adapter that holds this device node
  * @adapter:	pointer to the adapter that holds this device node
- * @type:	type of the device: DVB_DEVICE_SEC, DVB_DEVICE_FRONTEND,
- *		DVB_DEVICE_DEMUX, DVB_DEVICE_DVR, DVB_DEVICE_CA, DVB_DEVICE_NET
+ * @type:	type of the device, as defined by &enum dvb_device_type.
  * @minor:	devnode minor number. Major number is always DVB_MAJOR.
  * @minor:	devnode minor number. Major number is always DVB_MAJOR.
  * @id:		device ID number, inside the adapter
  * @id:		device ID number, inside the adapter
  * @readers:	Initialized by the caller. Each call to open() in Read Only mode
  * @readers:	Initialized by the caller. Each call to open() in Read Only mode
@@ -135,7 +156,7 @@ struct dvb_device {
 	struct list_head list_head;
 	struct list_head list_head;
 	const struct file_operations *fops;
 	const struct file_operations *fops;
 	struct dvb_adapter *adapter;
 	struct dvb_adapter *adapter;
-	int type;
+	enum dvb_device_type type;
 	int minor;
 	int minor;
 	u32 id;
 	u32 id;
 
 
@@ -194,9 +215,7 @@ int dvb_unregister_adapter(struct dvb_adapter *adap);
  *		stored
  *		stored
  * @template:	Template used to create &pdvbdev;
  * @template:	Template used to create &pdvbdev;
  * @priv:	private data
  * @priv:	private data
- * @type:	type of the device: %DVB_DEVICE_SEC, %DVB_DEVICE_FRONTEND,
- *		%DVB_DEVICE_DEMUX, %DVB_DEVICE_DVR, %DVB_DEVICE_CA,
- *		%DVB_DEVICE_NET
+ * @type:	type of the device, as defined by &enum dvb_device_type.
  * @demux_sink_pads: Number of demux outputs, to be used to create the TS
  * @demux_sink_pads: Number of demux outputs, to be used to create the TS
  *		outputs via the Media Controller.
  *		outputs via the Media Controller.
  */
  */
@@ -204,7 +223,7 @@ int dvb_register_device(struct dvb_adapter *adap,
 			struct dvb_device **pdvbdev,
 			struct dvb_device **pdvbdev,
 			const struct dvb_device *template,
 			const struct dvb_device *template,
 			void *priv,
 			void *priv,
-			int type,
+			enum dvb_device_type type,
 			int demux_sink_pads);
 			int demux_sink_pads);
 
 
 /**
 /**
@@ -242,7 +261,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev);
  * dvb_create_media_graph - Creates media graph for the Digital TV part of the
  * dvb_create_media_graph - Creates media graph for the Digital TV part of the
  * 				device.
  * 				device.
  *
  *
- * @adap:			pointer to struct dvb_adapter
+ * @adap:			pointer to &struct dvb_adapter
  * @create_rf_connector:	if true, it creates the RF connector too
  * @create_rf_connector:	if true, it creates the RF connector too
  *
  *
  * This function checks all DVB-related functions at the media controller
  * This function checks all DVB-related functions at the media controller
@@ -255,12 +274,23 @@ void dvb_unregister_device(struct dvb_device *dvbdev);
 __must_check int dvb_create_media_graph(struct dvb_adapter *adap,
 __must_check int dvb_create_media_graph(struct dvb_adapter *adap,
 					bool create_rf_connector);
 					bool create_rf_connector);
 
 
+/**
+ * dvb_register_media_controller - registers a media controller at DVB adapter
+ *
+ * @adap:			pointer to &struct dvb_adapter
+ * @mdev:			pointer to &struct media_device
+ */
 static inline void dvb_register_media_controller(struct dvb_adapter *adap,
 static inline void dvb_register_media_controller(struct dvb_adapter *adap,
 						 struct media_device *mdev)
 						 struct media_device *mdev)
 {
 {
 	adap->mdev = mdev;
 	adap->mdev = mdev;
 }
 }
 
 
+/**
+ * dvb_get_media_controller - gets the associated media controller
+ *
+ * @adap:			pointer to &struct dvb_adapter
+ */
 static inline struct media_device
 static inline struct media_device
 *dvb_get_media_controller(struct dvb_adapter *adap)
 *dvb_get_media_controller(struct dvb_adapter *adap)
 {
 {
@@ -277,20 +307,71 @@ int dvb_create_media_graph(struct dvb_adapter *adap,
 #define dvb_get_media_controller(a) NULL
 #define dvb_get_media_controller(a) NULL
 #endif
 #endif
 
 
-int dvb_generic_open (struct inode *inode, struct file *file);
-int dvb_generic_release (struct inode *inode, struct file *file);
-long dvb_generic_ioctl (struct file *file,
-			      unsigned int cmd, unsigned long arg);
+/**
+ * dvb_generic_open - Digital TV open function, used by DVB devices
+ *
+ * @inode: pointer to &struct inode.
+ * @file: pointer to &struct file.
+ *
+ * Checks if a DVB devnode is still valid, and if the permissions are
+ * OK and increment negative use count.
+ */
+int dvb_generic_open(struct inode *inode, struct file *file);
 
 
-/* we don't mess with video_usercopy() any more,
-we simply define out own dvb_usercopy(), which will hopefully become
-generic_usercopy()  someday... */
+/**
+ * dvb_generic_close - Digital TV close function, used by DVB devices
+ *
+ * @inode: pointer to &struct inode.
+ * @file: pointer to &struct file.
+ *
+ * Checks if a DVB devnode is still valid, and if the permissions are
+ * OK and decrement negative use count.
+ */
+int dvb_generic_release(struct inode *inode, struct file *file);
 
 
+/**
+ * dvb_generic_ioctl - Digital TV close function, used by DVB devices
+ *
+ * @file: pointer to &struct file.
+ * @cmd: Ioctl name.
+ * @arg: Ioctl argument.
+ *
+ * Checks if a DVB devnode and struct dvbdev.kernel_ioctl is still valid.
+ * If so, calls dvb_usercopy().
+ */
+long dvb_generic_ioctl(struct file *file,
+		       unsigned int cmd, unsigned long arg);
+
+/**
+ * dvb_usercopy - copies data from/to userspace memory when an ioctl is
+ *      issued.
+ *
+ * @file: Pointer to struct &file.
+ * @cmd: Ioctl name.
+ * @arg: Ioctl argument.
+ * @func: function that will actually handle the ioctl
+ *
+ * Ancillary function that uses ioctl direction and size to copy from
+ * userspace. Then, it calls @func, and, if needed, data is copied back
+ * to userspace.
+ */
 int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 		 int (*func)(struct file *file, unsigned int cmd, void *arg));
 		 int (*func)(struct file *file, unsigned int cmd, void *arg));
 
 
 /** generic DVB attach function. */
 /** generic DVB attach function. */
 #ifdef CONFIG_MEDIA_ATTACH
 #ifdef CONFIG_MEDIA_ATTACH
+
+/**
+ * dvb_attach - attaches a DVB frontend into the DVB core.
+ *
+ * @FUNCTION:	function on a frontend module to be called.
+ * @ARGS...:	@FUNCTION arguments.
+ *
+ * This ancillary function loads a frontend module in runtime and runs
+ * the @FUNCTION function there, with @ARGS.
+ * As it increments symbol usage cont, at unregister, dvb_detach()
+ * should be called.
+ */
 #define dvb_attach(FUNCTION, ARGS...) ({ \
 #define dvb_attach(FUNCTION, ARGS...) ({ \
 	void *__r = NULL; \
 	void *__r = NULL; \
 	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
 	typeof(&FUNCTION) __a = symbol_request(FUNCTION); \
@@ -304,6 +385,14 @@ int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
 	__r; \
 	__r; \
 })
 })
 
 
+/**
+ * dvb_detach - detaches a DVB frontend loaded via dvb_attach()
+ *
+ * @FUNC:	attach function
+ *
+ * Decrements usage count for a function previously called via dvb_attach().
+ */
+
 #define dvb_detach(FUNC)	symbol_put_addr(FUNC)
 #define dvb_detach(FUNC)	symbol_put_addr(FUNC)
 
 
 #else
 #else

+ 3 - 3
drivers/media/dvb-frontends/Kconfig

@@ -173,7 +173,7 @@ config DVB_STB6000
 	tristate "ST STB6000 silicon tuner"
 	tristate "ST STB6000 silicon tuner"
 	depends on DVB_CORE && I2C
 	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	default m if !MEDIA_SUBDRV_AUTOSELECT
-	  help
+	help
 	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
 
 config DVB_STV0299
 config DVB_STV0299
@@ -187,7 +187,7 @@ config DVB_STV6110
 	tristate "ST STV6110 silicon tuner"
 	tristate "ST STV6110 silicon tuner"
 	depends on DVB_CORE && I2C
 	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	default m if !MEDIA_SUBDRV_AUTOSELECT
-	  help
+	help
 	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 	  A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
 
 config DVB_STV0900
 config DVB_STV0900
@@ -902,7 +902,7 @@ config DVB_HELENE
 	depends on DVB_CORE && I2C
 	depends on DVB_CORE && I2C
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	default m if !MEDIA_SUBDRV_AUTOSELECT
 	help
 	help
-	Say Y when you want to support this frontend.
+	  Say Y when you want to support this frontend.
 
 
 comment "Tools to develop new frontends"
 comment "Tools to develop new frontends"
 
 

+ 3 - 4
drivers/media/dvb-frontends/as102_fe.c

@@ -455,11 +455,10 @@ struct dvb_frontend *as102_attach(const char *name,
 	struct as102_state *state;
 	struct as102_state *state;
 	struct dvb_frontend *fe;
 	struct dvb_frontend *fe;
 
 
-	state = kzalloc(sizeof(struct as102_state), GFP_KERNEL);
-	if (state == NULL) {
-		pr_err("%s: unable to allocate memory for state\n", __func__);
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
 		return NULL;
 		return NULL;
-	}
+
 	fe = &state->frontend;
 	fe = &state->frontend;
 	fe->demodulator_priv = state;
 	fe->demodulator_priv = state;
 	state->ops = ops;
 	state->ops = ops;

+ 4 - 6
drivers/media/dvb-frontends/cx24113.c

@@ -552,13 +552,11 @@ struct dvb_frontend *cx24113_attach(struct dvb_frontend *fe,
 		const struct cx24113_config *config, struct i2c_adapter *i2c)
 		const struct cx24113_config *config, struct i2c_adapter *i2c)
 {
 {
 	/* allocate memory for the internal state */
 	/* allocate memory for the internal state */
-	struct cx24113_state *state =
-		kzalloc(sizeof(struct cx24113_state), GFP_KERNEL);
+	struct cx24113_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
 	int rc;
 	int rc;
-	if (state == NULL) {
-		cx_err("Unable to kzalloc\n");
-		goto error;
-	}
+
+	if (!state)
+		return NULL;
 
 
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;

+ 8 - 14
drivers/media/dvb-frontends/cx24116.c

@@ -221,16 +221,13 @@ static int cx24116_writereg(struct cx24116_state *state, int reg, int data)
 static int cx24116_writeregN(struct cx24116_state *state, int reg,
 static int cx24116_writeregN(struct cx24116_state *state, int reg,
 			     const u8 *data, u16 len)
 			     const u8 *data, u16 len)
 {
 {
-	int ret = -EREMOTEIO;
+	int ret;
 	struct i2c_msg msg;
 	struct i2c_msg msg;
 	u8 *buf;
 	u8 *buf;
 
 
 	buf = kmalloc(len + 1, GFP_KERNEL);
 	buf = kmalloc(len + 1, GFP_KERNEL);
-	if (buf == NULL) {
-		printk("Unable to kmalloc\n");
-		ret = -ENOMEM;
-		goto error;
-	}
+	if (!buf)
+		return -ENOMEM;
 
 
 	*(buf) = reg;
 	*(buf) = reg;
 	memcpy(buf + 1, data, len);
 	memcpy(buf + 1, data, len);
@@ -251,7 +248,6 @@ static int cx24116_writeregN(struct cx24116_state *state, int reg,
 		ret = -EREMOTEIO;
 		ret = -EREMOTEIO;
 	}
 	}
 
 
-error:
 	kfree(buf);
 	kfree(buf);
 
 
 	return ret;
 	return ret;
@@ -1121,15 +1117,15 @@ static const struct dvb_frontend_ops cx24116_ops;
 struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
 struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
 	struct i2c_adapter *i2c)
 	struct i2c_adapter *i2c)
 {
 {
-	struct cx24116_state *state = NULL;
+	struct cx24116_state *state;
 	int ret;
 	int ret;
 
 
 	dprintk("%s\n", __func__);
 	dprintk("%s\n", __func__);
 
 
 	/* allocate memory for the internal state */
 	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct cx24116_state), GFP_KERNEL);
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
 	if (state == NULL)
 	if (state == NULL)
-		goto error1;
+		return NULL;
 
 
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
@@ -1138,8 +1134,9 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
 	ret = (cx24116_readreg(state, 0xFF) << 8) |
 	ret = (cx24116_readreg(state, 0xFF) << 8) |
 		cx24116_readreg(state, 0xFE);
 		cx24116_readreg(state, 0xFE);
 	if (ret != 0x0501) {
 	if (ret != 0x0501) {
+		kfree(state);
 		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
 		printk(KERN_INFO "Invalid probe, probably not a CX24116 device\n");
-		goto error2;
+		return NULL;
 	}
 	}
 
 
 	/* create dvb_frontend */
 	/* create dvb_frontend */
@@ -1147,9 +1144,6 @@ struct dvb_frontend *cx24116_attach(const struct cx24116_config *config,
 		sizeof(struct dvb_frontend_ops));
 		sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 	return &state->frontend;
-
-error2: kfree(state);
-error1: return NULL;
 }
 }
 EXPORT_SYMBOL(cx24116_attach);
 EXPORT_SYMBOL(cx24116_attach);
 
 

+ 4 - 5
drivers/media/dvb-frontends/drxd_hard.c

@@ -328,7 +328,7 @@ static int WriteTable(struct drxd_state *state, u8 * pTable)
 {
 {
 	int status = 0;
 	int status = 0;
 
 
-	if (pTable == NULL)
+	if (!pTable)
 		return 0;
 		return 0;
 
 
 	while (!status) {
 	while (!status) {
@@ -640,7 +640,7 @@ static int SetCfgIfAgc(struct drxd_state *state, struct SCfgAgc *cfg)
 				const u16 maxRur = 8;
 				const u16 maxRur = 8;
 				static const u16 slowIncrDecLUT[] = {
 				static const u16 slowIncrDecLUT[] = {
 					3, 4, 4, 5, 6 };
 					3, 4, 4, 5, 6 };
-				const u16 fastIncrDecLUT[] = {
+				static const u16 fastIncrDecLUT[] = {
 					14, 15, 15, 16,
 					14, 15, 15, 16,
 					17, 18, 18, 19,
 					17, 18, 18, 19,
 					20, 21, 22, 23,
 					20, 21, 22, 23,
@@ -909,9 +909,8 @@ static int load_firmware(struct drxd_state *state, const char *fw_name)
 	}
 	}
 
 
 	state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
 	state->microcode = kmemdup(fw->data, fw->size, GFP_KERNEL);
-	if (state->microcode == NULL) {
+	if (!state->microcode) {
 		release_firmware(fw);
 		release_firmware(fw);
-		printk(KERN_ERR "drxd: firmware load failure: no memory\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
@@ -2630,7 +2629,7 @@ static int DRXD_init(struct drxd_state *state, const u8 *fw, u32 fw_size)
 			break;
 			break;
 
 
 		/* Apply I2c address patch to B1 */
 		/* Apply I2c address patch to B1 */
-		if (!state->type_A && state->m_HiI2cPatch != NULL) {
+		if (!state->type_A && state->m_HiI2cPatch) {
 			status = WriteTable(state, state->m_HiI2cPatch);
 			status = WriteTable(state, state->m_HiI2cPatch);
 			if (status < 0)
 			if (status < 0)
 				break;
 				break;

+ 7 - 15
drivers/media/dvb-frontends/ds3000.c

@@ -277,10 +277,8 @@ static int ds3000_writeFW(struct ds3000_state *state, int reg,
 	u8 *buf;
 	u8 *buf;
 
 
 	buf = kmalloc(33, GFP_KERNEL);
 	buf = kmalloc(33, GFP_KERNEL);
-	if (buf == NULL) {
-		printk(KERN_ERR "Unable to kmalloc\n");
+	if (!buf)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	*(buf) = reg;
 	*(buf) = reg;
 
 
@@ -835,17 +833,15 @@ static const struct dvb_frontend_ops ds3000_ops;
 struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 				    struct i2c_adapter *i2c)
 				    struct i2c_adapter *i2c)
 {
 {
-	struct ds3000_state *state = NULL;
+	struct ds3000_state *state;
 	int ret;
 	int ret;
 
 
 	dprintk("%s\n", __func__);
 	dprintk("%s\n", __func__);
 
 
 	/* allocate memory for the internal state */
 	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL);
-	if (state == NULL) {
-		printk(KERN_ERR "Unable to kmalloc\n");
-		goto error2;
-	}
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
 
 
 	state->config = config;
 	state->config = config;
 	state->i2c = i2c;
 	state->i2c = i2c;
@@ -854,8 +850,9 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 	/* check if the demod is present */
 	/* check if the demod is present */
 	ret = ds3000_readreg(state, 0x00) & 0xfe;
 	ret = ds3000_readreg(state, 0x00) & 0xfe;
 	if (ret != 0xe0) {
 	if (ret != 0xe0) {
+		kfree(state);
 		printk(KERN_ERR "Invalid probe, probably not a DS3000\n");
 		printk(KERN_ERR "Invalid probe, probably not a DS3000\n");
-		goto error3;
+		return NULL;
 	}
 	}
 
 
 	printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n",
 	printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n",
@@ -873,11 +870,6 @@ struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 	 */
 	 */
 	ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
 	ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
 	return &state->frontend;
 	return &state->frontend;
-
-error3:
-	kfree(state);
-error2:
-	return NULL;
 }
 }
 EXPORT_SYMBOL(ds3000_attach);
 EXPORT_SYMBOL(ds3000_attach);
 
 

+ 0 - 14
drivers/media/dvb-frontends/lg2160.c

@@ -1048,16 +1048,6 @@ fail:
 	return ret;
 	return ret;
 }
 }
 
 
-static int lg216x_get_property(struct dvb_frontend *fe,
-			       struct dtv_property *tvp)
-{
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-
-	return (DTV_ATSCMH_FIC_VER == tvp->cmd) ?
-		lg216x_get_frontend(fe, c) : 0;
-}
-
-
 static int lg2160_set_frontend(struct dvb_frontend *fe)
 static int lg2160_set_frontend(struct dvb_frontend *fe)
 {
 {
 	struct lg216x_state *state = fe->demodulator_priv;
 	struct lg216x_state *state = fe->demodulator_priv;
@@ -1368,8 +1358,6 @@ static const struct dvb_frontend_ops lg2160_ops = {
 	.init                 = lg216x_init,
 	.init                 = lg216x_init,
 	.sleep                = lg216x_sleep,
 	.sleep                = lg216x_sleep,
 #endif
 #endif
-	.get_property         = lg216x_get_property,
-
 	.set_frontend         = lg2160_set_frontend,
 	.set_frontend         = lg2160_set_frontend,
 	.get_frontend         = lg216x_get_frontend,
 	.get_frontend         = lg216x_get_frontend,
 	.get_tune_settings    = lg216x_get_tune_settings,
 	.get_tune_settings    = lg216x_get_tune_settings,
@@ -1396,8 +1384,6 @@ static const struct dvb_frontend_ops lg2161_ops = {
 	.init                 = lg216x_init,
 	.init                 = lg216x_init,
 	.sleep                = lg216x_sleep,
 	.sleep                = lg216x_sleep,
 #endif
 #endif
-	.get_property         = lg216x_get_property,
-
 	.set_frontend         = lg2160_set_frontend,
 	.set_frontend         = lg2160_set_frontend,
 	.get_frontend         = lg216x_get_frontend,
 	.get_frontend         = lg216x_get_frontend,
 	.get_tune_settings    = lg216x_get_tune_settings,
 	.get_tune_settings    = lg216x_get_tune_settings,

+ 2 - 1
drivers/media/dvb-frontends/lgdt3306a.c

@@ -19,6 +19,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 
 #include <asm/div64.h>
 #include <asm/div64.h>
+#include <linux/kernel.h>
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/frontend.h>
 #include "dvb_math.h"
 #include "dvb_math.h"
 #include "lgdt3306a.h"
 #include "lgdt3306a.h"
@@ -2072,7 +2073,7 @@ static const short regtab[] = {
 	0x30aa, /* MPEGLOCK */
 	0x30aa, /* MPEGLOCK */
 };
 };
 
 
-#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0]))
+#define numDumpRegs (ARRAY_SIZE(regtab))
 static u8 regval1[numDumpRegs] = {0, };
 static u8 regval1[numDumpRegs] = {0, };
 static u8 regval2[numDumpRegs] = {0, };
 static u8 regval2[numDumpRegs] = {0, };
 
 

+ 7 - 16
drivers/media/dvb-frontends/mb86a20s.c

@@ -2071,12 +2071,9 @@ struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
 	dev_dbg(&i2c->dev, "%s called.\n", __func__);
 	dev_dbg(&i2c->dev, "%s called.\n", __func__);
 
 
 	/* allocate memory for the internal state */
 	/* allocate memory for the internal state */
-	state = kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL);
-	if (state == NULL) {
-		dev_err(&i2c->dev,
-			"%s: unable to allocate memory for state\n", __func__);
-		goto error;
-	}
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return NULL;
 
 
 	/* setup the state */
 	/* setup the state */
 	state->config = config;
 	state->config = config;
@@ -2089,22 +2086,16 @@ struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
 
 
 	/* Check if it is a mb86a20s frontend */
 	/* Check if it is a mb86a20s frontend */
 	rev = mb86a20s_readreg(state, 0);
 	rev = mb86a20s_readreg(state, 0);
-
-	if (rev == 0x13) {
-		dev_info(&i2c->dev,
-			 "Detected a Fujitsu mb86a20s frontend\n");
-	} else {
+	if (rev != 0x13) {
+		kfree(state);
 		dev_dbg(&i2c->dev,
 		dev_dbg(&i2c->dev,
 			"Frontend revision %d is unknown - aborting.\n",
 			"Frontend revision %d is unknown - aborting.\n",
 		       rev);
 		       rev);
-		goto error;
+		return NULL;
 	}
 	}
 
 
+	dev_info(&i2c->dev, "Detected a Fujitsu mb86a20s frontend\n");
 	return &state->frontend;
 	return &state->frontend;
-
-error:
-	kfree(state);
-	return NULL;
 }
 }
 EXPORT_SYMBOL(mb86a20s_attach);
 EXPORT_SYMBOL(mb86a20s_attach);
 
 

+ 1 - 1
drivers/media/dvb-frontends/mxl5xx.c

@@ -43,7 +43,7 @@
 #define BYTE2(v) ((v >> 16) & 0xff)
 #define BYTE2(v) ((v >> 16) & 0xff)
 #define BYTE3(v) ((v >> 24) & 0xff)
 #define BYTE3(v) ((v >> 24) & 0xff)
 
 
-LIST_HEAD(mxllist);
+static LIST_HEAD(mxllist);
 
 
 struct mxl_base {
 struct mxl_base {
 	struct list_head     mxllist;
 	struct list_head     mxllist;

+ 0 - 1
drivers/media/dvb-frontends/si2168.c

@@ -696,7 +696,6 @@ static int si2168_probe(struct i2c_client *client,
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
 	if (!dev) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		dev_err(&client->dev, "kzalloc() failed\n");
 		goto err;
 		goto err;
 	}
 	}
 
 

+ 4 - 5
drivers/media/dvb-frontends/sp2.c

@@ -357,14 +357,14 @@ static int sp2_exit(struct i2c_client *client)
 
 
 	dev_dbg(&client->dev, "\n");
 	dev_dbg(&client->dev, "\n");
 
 
-	if (client == NULL)
+	if (!client)
 		return 0;
 		return 0;
 
 
 	s = i2c_get_clientdata(client);
 	s = i2c_get_clientdata(client);
-	if (s == NULL)
+	if (!s)
 		return 0;
 		return 0;
 
 
-	if (s->ca.data == NULL)
+	if (!s->ca.data)
 		return 0;
 		return 0;
 
 
 	dvb_ca_en50221_release(&s->ca);
 	dvb_ca_en50221_release(&s->ca);
@@ -381,10 +381,9 @@ static int sp2_probe(struct i2c_client *client,
 
 
 	dev_dbg(&client->dev, "\n");
 	dev_dbg(&client->dev, "\n");
 
 
-	s = kzalloc(sizeof(struct sp2), GFP_KERNEL);
+	s = kzalloc(sizeof(*s), GFP_KERNEL);
 	if (!s) {
 	if (!s) {
 		ret = -ENOMEM;
 		ret = -ENOMEM;
-		dev_err(&client->dev, "kzalloc() failed\n");
 		goto err;
 		goto err;
 	}
 	}
 
 

+ 0 - 7
drivers/media/dvb-frontends/stv0288.c

@@ -447,12 +447,6 @@ static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 	return 0;
 	return 0;
 }
 }
 
 
-static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
-{
-	dprintk("%s(..)\n", __func__);
-	return 0;
-}
-
 static int stv0288_set_frontend(struct dvb_frontend *fe)
 static int stv0288_set_frontend(struct dvb_frontend *fe)
 {
 {
 	struct stv0288_state *state = fe->demodulator_priv;
 	struct stv0288_state *state = fe->demodulator_priv;
@@ -567,7 +561,6 @@ static const struct dvb_frontend_ops stv0288_ops = {
 	.set_tone = stv0288_set_tone,
 	.set_tone = stv0288_set_tone,
 	.set_voltage = stv0288_set_voltage,
 	.set_voltage = stv0288_set_voltage,
 
 
-	.set_property = stv0288_set_property,
 	.set_frontend = stv0288_set_frontend,
 	.set_frontend = stv0288_set_frontend,
 };
 };
 
 

+ 0 - 9
drivers/media/dvb-frontends/stv6110.c

@@ -258,11 +258,9 @@ static int stv6110_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
 static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
 {
 {
 	struct stv6110_priv *priv = fe->tuner_priv;
 	struct stv6110_priv *priv = fe->tuner_priv;
-	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	u8 ret = 0x04;
 	u8 ret = 0x04;
 	u32 divider, ref, p, presc, i, result_freq, vco_freq;
 	u32 divider, ref, p, presc, i, result_freq, vco_freq;
 	s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val;
 	s32 p_calc, p_calc_opt = 1000, r_div, r_div_opt = 0, p_val;
-	s32 srate;
 
 
 	dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__,
 	dprintk("%s, freq=%d kHz, mclk=%d Hz\n", __func__,
 						frequency, priv->mclk);
 						frequency, priv->mclk);
@@ -273,13 +271,6 @@ static int stv6110_set_frequency(struct dvb_frontend *fe, u32 frequency)
 				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
 				((((priv->mclk / 1000000) - 16) & 0x1f) << 3);
 
 
 	/* BB_GAIN = db/2 */
 	/* BB_GAIN = db/2 */
-	if (fe->ops.set_property && fe->ops.get_property) {
-		srate = c->symbol_rate;
-		dprintk("%s: Get Frontend parameters: srate=%d\n",
-							__func__, srate);
-	} else
-		srate = 15000000;
-
 	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
 	priv->regs[RSTV6110_CTRL2] &= ~0x0f;
 	priv->regs[RSTV6110_CTRL2] |= (priv->gain & 0x0f);
 	priv->regs[RSTV6110_CTRL2] |= (priv->gain & 0x0f);
 
 

+ 16 - 0
drivers/media/i2c/Kconfig

@@ -354,6 +354,14 @@ config VIDEO_TC358743
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called tc358743.
 	  module will be called tc358743.
 
 
+config VIDEO_TC358743_CEC
+	bool "Enable Toshiba TC358743 CEC support"
+	depends on VIDEO_TC358743
+	select CEC_CORE
+	---help---
+	  When selected the tc358743 will support the optional
+	  HDMI CEC feature.
+
 config VIDEO_TVP514X
 config VIDEO_TVP514X
 	tristate "Texas Instruments TVP514x video decoder"
 	tristate "Texas Instruments TVP514x video decoder"
 	depends on VIDEO_V4L2 && I2C
 	depends on VIDEO_V4L2 && I2C
@@ -547,6 +555,14 @@ config VIDEO_APTINA_PLL
 config VIDEO_SMIAPP_PLL
 config VIDEO_SMIAPP_PLL
 	tristate
 	tristate
 
 
+config VIDEO_IMX274
+	tristate "Sony IMX274 sensor support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_CAMERA_SUPPORT
+	---help---
+	  This is a V4L2 sensor-level driver for the Sony IMX274
+	  CMOS image sensor.
+
 config VIDEO_OV2640
 config VIDEO_OV2640
 	tristate "OmniVision OV2640 sensor support"
 	tristate "OmniVision OV2640 sensor support"
 	depends on VIDEO_V4L2 && I2C
 	depends on VIDEO_V4L2 && I2C

+ 1 - 0
drivers/media/i2c/Makefile

@@ -93,5 +93,6 @@ obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 obj-$(CONFIG_VIDEO_ML86V7667)	+= ml86v7667.o
 obj-$(CONFIG_VIDEO_ML86V7667)	+= ml86v7667.o
 obj-$(CONFIG_VIDEO_OV2659)	+= ov2659.o
 obj-$(CONFIG_VIDEO_OV2659)	+= ov2659.o
 obj-$(CONFIG_VIDEO_TC358743)	+= tc358743.o
 obj-$(CONFIG_VIDEO_TC358743)	+= tc358743.o
+obj-$(CONFIG_VIDEO_IMX274)	+= imx274.o
 
 
 obj-$(CONFIG_SDR_MAX2175) += max2175.o
 obj-$(CONFIG_SDR_MAX2175) += max2175.o

+ 1 - 1
drivers/media/i2c/adv7180.c

@@ -1328,7 +1328,7 @@ static int adv7180_probe(struct i2c_client *client,
 	state->input = 0;
 	state->input = 0;
 	sd = &state->sd;
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
 	v4l2_i2c_subdev_init(sd, client, &adv7180_ops);
-	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
 
 
 	ret = adv7180_init_controls(state);
 	ret = adv7180_init_controls(state);
 	if (ret)
 	if (ret)

+ 6 - 1
drivers/media/i2c/adv748x/adv748x-afe.c

@@ -217,6 +217,7 @@ static int adv748x_afe_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 {
 {
 	struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
 	struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
 	struct adv748x_state *state = adv748x_afe_to_state(afe);
 	struct adv748x_state *state = adv748x_afe_to_state(afe);
+	int afe_std;
 	int ret;
 	int ret;
 
 
 	mutex_lock(&state->mutex);
 	mutex_lock(&state->mutex);
@@ -235,8 +236,12 @@ static int adv748x_afe_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 	/* Read detected standard */
 	/* Read detected standard */
 	ret = adv748x_afe_status(afe, NULL, std);
 	ret = adv748x_afe_status(afe, NULL, std);
 
 
+	afe_std = adv748x_afe_std(afe->curr_norm);
+	if (afe_std < 0)
+		goto unlock;
+
 	/* Restore original state */
 	/* Restore original state */
-	adv748x_afe_set_video_standard(state, afe->curr_norm);
+	adv748x_afe_set_video_standard(state, afe_std);
 
 
 unlock:
 unlock:
 	mutex_unlock(&state->mutex);
 	mutex_unlock(&state->mutex);

+ 4 - 6
drivers/media/i2c/adv7604.c

@@ -1948,7 +1948,7 @@ static int adv76xx_set_format(struct v4l2_subdev *sd,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	info = adv76xx_format_info(state, format->format.code);
 	info = adv76xx_format_info(state, format->format.code);
-	if (info == NULL)
+	if (!info)
 		info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
 		info = adv76xx_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
 
 
 	adv76xx_fill_format(state, &format->format);
 	adv76xx_fill_format(state, &format->format);
@@ -2256,7 +2256,7 @@ static int adv76xx_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid)
 		return 0;
 		return 0;
 	}
 	}
 
 
-	if (data == NULL)
+	if (!data)
 		return -ENODATA;
 		return -ENODATA;
 
 
 	if (edid->start_block >= state->edid.blocks)
 	if (edid->start_block >= state->edid.blocks)
@@ -3316,10 +3316,8 @@ static int adv76xx_probe(struct i2c_client *client,
 			client->addr << 1);
 			client->addr << 1);
 
 
 	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
 	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
-	if (!state) {
-		v4l_err(client, "Could not allocate adv76xx_state memory!\n");
+	if (!state)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	state->i2c_clients[ADV76XX_PAGE_IO] = client;
 	state->i2c_clients[ADV76XX_PAGE_IO] = client;
 
 
@@ -3482,7 +3480,7 @@ static int adv76xx_probe(struct i2c_client *client,
 		state->i2c_clients[i] =
 		state->i2c_clients[i] =
 			adv76xx_dummy_client(sd, state->pdata.i2c_addresses[i],
 			adv76xx_dummy_client(sd, state->pdata.i2c_addresses[i],
 					     0xf2 + i);
 					     0xf2 + i);
-		if (state->i2c_clients[i] == NULL) {
+		if (!state->i2c_clients[i]) {
 			err = -ENOMEM;
 			err = -ENOMEM;
 			v4l2_err(sd, "failed to create i2c client %u\n", i);
 			v4l2_err(sd, "failed to create i2c client %u\n", i);
 			goto err_i2c;
 			goto err_i2c;

+ 2 - 4
drivers/media/i2c/adv7842.c

@@ -3467,11 +3467,9 @@ static int adv7842_probe(struct i2c_client *client,
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	state = devm_kzalloc(&client->dev, sizeof(struct adv7842_state), GFP_KERNEL);
-	if (!state) {
-		v4l_err(client, "Could not allocate adv7842_state memory!\n");
+	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
+	if (!state)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	/* platform data */
 	/* platform data */
 	state->pdata = *pdata;
 	state->pdata = *pdata;

+ 1 - 1
drivers/media/i2c/cx25840/cx25840-core.c

@@ -1745,7 +1745,7 @@ static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std)
 {
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 
-	v4l2_std_id stds[] = {
+	static const v4l2_std_id stds[] = {
 		/* 0000 */ V4L2_STD_UNKNOWN,
 		/* 0000 */ V4L2_STD_UNKNOWN,
 
 
 		/* 0001 */ V4L2_STD_NTSC_M,
 		/* 0001 */ V4L2_STD_NTSC_M,

+ 6 - 1
drivers/media/i2c/dw9714.c

@@ -20,6 +20,11 @@
 
 
 #define DW9714_NAME		"dw9714"
 #define DW9714_NAME		"dw9714"
 #define DW9714_MAX_FOCUS_POS	1023
 #define DW9714_MAX_FOCUS_POS	1023
+/*
+ * This sets the minimum granularity for the focus positions.
+ * A value of 1 gives maximum accuracy for a desired focus position
+ */
+#define DW9714_FOCUS_STEPS	1
 /*
 /*
  * This acts as the minimum granularity of lens movement.
  * This acts as the minimum granularity of lens movement.
  * Keep this value power of 2, so the control steps can be
  * Keep this value power of 2, so the control steps can be
@@ -137,7 +142,7 @@ static int dw9714_init_controls(struct dw9714_device *dev_vcm)
 	v4l2_ctrl_handler_init(hdl, 1);
 	v4l2_ctrl_handler_init(hdl, 1);
 
 
 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
 	v4l2_ctrl_new_std(hdl, ops, V4L2_CID_FOCUS_ABSOLUTE,
-			  0, DW9714_MAX_FOCUS_POS, DW9714_CTRL_STEPS, 0);
+			  0, DW9714_MAX_FOCUS_POS, DW9714_FOCUS_STEPS, 0);
 
 
 	if (hdl->error)
 	if (hdl->error)
 		dev_err(&client->dev, "%s fail error: 0x%x\n",
 		dev_err(&client->dev, "%s fail error: 0x%x\n",

+ 1 - 1
drivers/media/i2c/et8ek8/et8ek8_driver.c

@@ -1453,7 +1453,7 @@ static int et8ek8_probe(struct i2c_client *client,
 		goto err_mutex;
 		goto err_mutex;
 	}
 	}
 
 
-	ret = v4l2_async_register_subdev(&sensor->subdev);
+	ret = v4l2_async_register_subdev_sensor_common(&sensor->subdev);
 	if (ret < 0)
 	if (ret < 0)
 		goto err_entity;
 		goto err_entity;
 
 

+ 1811 - 0
drivers/media/i2c/imx274.c

@@ -0,0 +1,1811 @@
+/*
+ * imx274.c - IMX274 CMOS Image Sensor driver
+ *
+ * Copyright (C) 2017, Leopard Imaging, Inc.
+ *
+ * Leon Luo <leonl@leopardimaging.com>
+ * Edwin Zou <edwinz@leopardimaging.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-subdev.h>
+
+/*
+ * See "SHR, SVR Setting" in datasheet
+ */
+#define IMX274_DEFAULT_FRAME_LENGTH		(4550)
+#define IMX274_MAX_FRAME_LENGTH			(0x000fffff)
+
+/*
+ * See "Frame Rate Adjustment" in datasheet
+ */
+#define IMX274_PIXCLK_CONST1			(72000000)
+#define IMX274_PIXCLK_CONST2			(1000000)
+
+/*
+ * The input gain is shifted by IMX274_GAIN_SHIFT to get
+ * decimal number. The real gain is
+ * (float)input_gain_value / (1 << IMX274_GAIN_SHIFT)
+ */
+#define IMX274_GAIN_SHIFT			(8)
+#define IMX274_GAIN_SHIFT_MASK			((1 << IMX274_GAIN_SHIFT) - 1)
+
+/*
+ * See "Analog Gain" and "Digital Gain" in datasheet
+ * min gain is 1X
+ * max gain is calculated based on IMX274_GAIN_REG_MAX
+ */
+#define IMX274_GAIN_REG_MAX			(1957)
+#define IMX274_MIN_GAIN				(0x01 << IMX274_GAIN_SHIFT)
+#define IMX274_MAX_ANALOG_GAIN			((2048 << IMX274_GAIN_SHIFT)\
+					/ (2048 - IMX274_GAIN_REG_MAX))
+#define IMX274_MAX_DIGITAL_GAIN			(8)
+#define IMX274_DEF_GAIN				(20 << IMX274_GAIN_SHIFT)
+#define IMX274_GAIN_CONST			(2048) /* for gain formula */
+
+/*
+ * 1 line time in us = (HMAX / 72), minimal is 4 lines
+ */
+#define IMX274_MIN_EXPOSURE_TIME		(4 * 260 / 72)
+
+#define IMX274_DEFAULT_MODE			IMX274_MODE_3840X2160
+#define IMX274_MAX_WIDTH			(3840)
+#define IMX274_MAX_HEIGHT			(2160)
+#define IMX274_MAX_FRAME_RATE			(120)
+#define IMX274_MIN_FRAME_RATE			(5)
+#define IMX274_DEF_FRAME_RATE			(60)
+
+/*
+ * register SHR is limited to (SVR value + 1) x VMAX value - 4
+ */
+#define IMX274_SHR_LIMIT_CONST			(4)
+
+/*
+ * Constants for sensor reset delay
+ */
+#define IMX274_RESET_DELAY1			(2000)
+#define IMX274_RESET_DELAY2			(2200)
+
+/*
+ * shift and mask constants
+ */
+#define IMX274_SHIFT_8_BITS			(8)
+#define IMX274_SHIFT_16_BITS			(16)
+#define IMX274_MASK_LSB_2_BITS			(0x03)
+#define IMX274_MASK_LSB_3_BITS			(0x07)
+#define IMX274_MASK_LSB_4_BITS			(0x0f)
+#define IMX274_MASK_LSB_8_BITS			(0x00ff)
+
+#define DRIVER_NAME "IMX274"
+
+/*
+ * IMX274 register definitions
+ */
+#define IMX274_FRAME_LENGTH_ADDR_1		0x30FA /* VMAX, MSB */
+#define IMX274_FRAME_LENGTH_ADDR_2		0x30F9 /* VMAX */
+#define IMX274_FRAME_LENGTH_ADDR_3		0x30F8 /* VMAX, LSB */
+#define IMX274_SVR_REG_MSB			0x300F /* SVR */
+#define IMX274_SVR_REG_LSB			0x300E /* SVR */
+#define IMX274_HMAX_REG_MSB			0x30F7 /* HMAX */
+#define IMX274_HMAX_REG_LSB			0x30F6 /* HMAX */
+#define IMX274_COARSE_TIME_ADDR_MSB		0x300D /* SHR */
+#define IMX274_COARSE_TIME_ADDR_LSB		0x300C /* SHR */
+#define IMX274_ANALOG_GAIN_ADDR_LSB		0x300A /* ANALOG GAIN LSB */
+#define IMX274_ANALOG_GAIN_ADDR_MSB		0x300B /* ANALOG GAIN MSB */
+#define IMX274_DIGITAL_GAIN_REG			0x3012 /* Digital Gain */
+#define IMX274_VFLIP_REG			0x301A /* VERTICAL FLIP */
+#define IMX274_TEST_PATTERN_REG			0x303D /* TEST PATTERN */
+#define IMX274_STANDBY_REG			0x3000 /* STANDBY */
+
+#define IMX274_TABLE_WAIT_MS			0
+#define IMX274_TABLE_END			1
+
+/*
+ * imx274 I2C operation related structure
+ */
+struct reg_8 {
+	u16 addr;
+	u8 val;
+};
+
+static const struct regmap_config imx274_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+enum imx274_mode {
+	IMX274_MODE_3840X2160,
+	IMX274_MODE_1920X1080,
+	IMX274_MODE_1280X720,
+
+	IMX274_MODE_START_STREAM_1,
+	IMX274_MODE_START_STREAM_2,
+	IMX274_MODE_START_STREAM_3,
+	IMX274_MODE_START_STREAM_4,
+	IMX274_MODE_STOP_STREAM
+};
+
+/*
+ * imx274 format related structure
+ */
+struct imx274_frmfmt {
+	u32 mbus_code;
+	enum v4l2_colorspace colorspace;
+	struct v4l2_frmsize_discrete size;
+	enum imx274_mode mode;
+};
+
+/*
+ * imx274 test pattern related structure
+ */
+enum {
+	TEST_PATTERN_DISABLED = 0,
+	TEST_PATTERN_ALL_000H,
+	TEST_PATTERN_ALL_FFFH,
+	TEST_PATTERN_ALL_555H,
+	TEST_PATTERN_ALL_AAAH,
+	TEST_PATTERN_VSP_5AH, /* VERTICAL STRIPE PATTERN 555H/AAAH */
+	TEST_PATTERN_VSP_A5H, /* VERTICAL STRIPE PATTERN AAAH/555H */
+	TEST_PATTERN_VSP_05H, /* VERTICAL STRIPE PATTERN 000H/555H */
+	TEST_PATTERN_VSP_50H, /* VERTICAL STRIPE PATTERN 555H/000H */
+	TEST_PATTERN_VSP_0FH, /* VERTICAL STRIPE PATTERN 000H/FFFH */
+	TEST_PATTERN_VSP_F0H, /* VERTICAL STRIPE PATTERN FFFH/000H */
+	TEST_PATTERN_H_COLOR_BARS,
+	TEST_PATTERN_V_COLOR_BARS,
+};
+
+static const char * const tp_qmenu[] = {
+	"Disabled",
+	"All 000h Pattern",
+	"All FFFh Pattern",
+	"All 555h Pattern",
+	"All AAAh Pattern",
+	"Vertical Stripe (555h / AAAh)",
+	"Vertical Stripe (AAAh / 555h)",
+	"Vertical Stripe (000h / 555h)",
+	"Vertical Stripe (555h / 000h)",
+	"Vertical Stripe (000h / FFFh)",
+	"Vertical Stripe (FFFh / 000h)",
+	"Horizontal Color Bars",
+	"Vertical Color Bars",
+};
+
+/*
+ * All-pixel scan mode (10-bit)
+ * imx274 mode1(refer to datasheet) register configuration with
+ * 3840x2160 resolution, raw10 data and mipi four lane output
+ */
+static const struct reg_8 imx274_mode1_3840x2160_raw10[] = {
+	{0x3004, 0x01},
+	{0x3005, 0x01},
+	{0x3006, 0x00},
+	{0x3007, 0x02},
+
+	{0x3018, 0xA2}, /* output XVS, HVS */
+
+	{0x306B, 0x05},
+	{0x30E2, 0x01},
+	{0x30F6, 0x07}, /* HMAX, 263 */
+	{0x30F7, 0x01}, /* HMAX */
+
+	{0x30dd, 0x01}, /* crop to 2160 */
+	{0x30de, 0x06},
+	{0x30df, 0x00},
+	{0x30e0, 0x12},
+	{0x30e1, 0x00},
+	{0x3037, 0x01}, /* to crop to 3840 */
+	{0x3038, 0x0c},
+	{0x3039, 0x00},
+	{0x303a, 0x0c},
+	{0x303b, 0x0f},
+
+	{0x30EE, 0x01},
+	{0x3130, 0x86},
+	{0x3131, 0x08},
+	{0x3132, 0x7E},
+	{0x3133, 0x08},
+	{0x3342, 0x0A},
+	{0x3343, 0x00},
+	{0x3344, 0x16},
+	{0x3345, 0x00},
+	{0x33A6, 0x01},
+	{0x3528, 0x0E},
+	{0x3554, 0x1F},
+	{0x3555, 0x01},
+	{0x3556, 0x01},
+	{0x3557, 0x01},
+	{0x3558, 0x01},
+	{0x3559, 0x00},
+	{0x355A, 0x00},
+	{0x35BA, 0x0E},
+	{0x366A, 0x1B},
+	{0x366B, 0x1A},
+	{0x366C, 0x19},
+	{0x366D, 0x17},
+	{0x3A41, 0x08},
+
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * Horizontal/vertical 2/2-line binning
+ * (Horizontal and vertical weightedbinning, 10-bit)
+ * imx274 mode3(refer to datasheet) register configuration with
+ * 1920x1080 resolution, raw10 data and mipi four lane output
+ */
+static const struct reg_8 imx274_mode3_1920x1080_raw10[] = {
+	{0x3004, 0x02},
+	{0x3005, 0x21},
+	{0x3006, 0x00},
+	{0x3007, 0x11},
+
+	{0x3018, 0xA2}, /* output XVS, HVS */
+
+	{0x306B, 0x05},
+	{0x30E2, 0x02},
+
+	{0x30F6, 0x04}, /* HMAX, 260 */
+	{0x30F7, 0x01}, /* HMAX */
+
+	{0x30dd, 0x01}, /* to crop to 1920x1080 */
+	{0x30de, 0x05},
+	{0x30df, 0x00},
+	{0x30e0, 0x04},
+	{0x30e1, 0x00},
+	{0x3037, 0x01},
+	{0x3038, 0x0c},
+	{0x3039, 0x00},
+	{0x303a, 0x0c},
+	{0x303b, 0x0f},
+
+	{0x30EE, 0x01},
+	{0x3130, 0x4E},
+	{0x3131, 0x04},
+	{0x3132, 0x46},
+	{0x3133, 0x04},
+	{0x3342, 0x0A},
+	{0x3343, 0x00},
+	{0x3344, 0x1A},
+	{0x3345, 0x00},
+	{0x33A6, 0x01},
+	{0x3528, 0x0E},
+	{0x3554, 0x00},
+	{0x3555, 0x01},
+	{0x3556, 0x01},
+	{0x3557, 0x01},
+	{0x3558, 0x01},
+	{0x3559, 0x00},
+	{0x355A, 0x00},
+	{0x35BA, 0x0E},
+	{0x366A, 0x1B},
+	{0x366B, 0x1A},
+	{0x366C, 0x19},
+	{0x366D, 0x17},
+	{0x3A41, 0x08},
+
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * Vertical 2/3 subsampling binning horizontal 3 binning
+ * imx274 mode5(refer to datasheet) register configuration with
+ * 1280x720 resolution, raw10 data and mipi four lane output
+ */
+static const struct reg_8 imx274_mode5_1280x720_raw10[] = {
+	{0x3004, 0x03},
+	{0x3005, 0x31},
+	{0x3006, 0x00},
+	{0x3007, 0x09},
+
+	{0x3018, 0xA2}, /* output XVS, HVS */
+
+	{0x306B, 0x05},
+	{0x30E2, 0x03},
+
+	{0x30F6, 0x04}, /* HMAX, 260 */
+	{0x30F7, 0x01}, /* HMAX */
+
+	{0x30DD, 0x01},
+	{0x30DE, 0x07},
+	{0x30DF, 0x00},
+	{0x40E0, 0x04},
+	{0x30E1, 0x00},
+	{0x3030, 0xD4},
+	{0x3031, 0x02},
+	{0x3032, 0xD0},
+	{0x3033, 0x02},
+
+	{0x30EE, 0x01},
+	{0x3130, 0xE2},
+	{0x3131, 0x02},
+	{0x3132, 0xDE},
+	{0x3133, 0x02},
+	{0x3342, 0x0A},
+	{0x3343, 0x00},
+	{0x3344, 0x1B},
+	{0x3345, 0x00},
+	{0x33A6, 0x01},
+	{0x3528, 0x0E},
+	{0x3554, 0x00},
+	{0x3555, 0x01},
+	{0x3556, 0x01},
+	{0x3557, 0x01},
+	{0x3558, 0x01},
+	{0x3559, 0x00},
+	{0x355A, 0x00},
+	{0x35BA, 0x0E},
+	{0x366A, 0x1B},
+	{0x366B, 0x19},
+	{0x366C, 0x17},
+	{0x366D, 0x17},
+	{0x3A41, 0x04},
+
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 first step register configuration for
+ * starting stream
+ */
+static const struct reg_8 imx274_start_1[] = {
+	{IMX274_STANDBY_REG, 0x12},
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 second step register configuration for
+ * starting stream
+ */
+static const struct reg_8 imx274_start_2[] = {
+	{0x3120, 0xF0}, /* clock settings */
+	{0x3121, 0x00}, /* clock settings */
+	{0x3122, 0x02}, /* clock settings */
+	{0x3129, 0x9C}, /* clock settings */
+	{0x312A, 0x02}, /* clock settings */
+	{0x312D, 0x02}, /* clock settings */
+
+	{0x310B, 0x00},
+
+	/* PLSTMG */
+	{0x304C, 0x00}, /* PLSTMG01 */
+	{0x304D, 0x03},
+	{0x331C, 0x1A},
+	{0x331D, 0x00},
+	{0x3502, 0x02},
+	{0x3529, 0x0E},
+	{0x352A, 0x0E},
+	{0x352B, 0x0E},
+	{0x3538, 0x0E},
+	{0x3539, 0x0E},
+	{0x3553, 0x00},
+	{0x357D, 0x05},
+	{0x357F, 0x05},
+	{0x3581, 0x04},
+	{0x3583, 0x76},
+	{0x3587, 0x01},
+	{0x35BB, 0x0E},
+	{0x35BC, 0x0E},
+	{0x35BD, 0x0E},
+	{0x35BE, 0x0E},
+	{0x35BF, 0x0E},
+	{0x366E, 0x00},
+	{0x366F, 0x00},
+	{0x3670, 0x00},
+	{0x3671, 0x00},
+
+	/* PSMIPI */
+	{0x3304, 0x32}, /* PSMIPI1 */
+	{0x3305, 0x00},
+	{0x3306, 0x32},
+	{0x3307, 0x00},
+	{0x3590, 0x32},
+	{0x3591, 0x00},
+	{0x3686, 0x32},
+	{0x3687, 0x00},
+
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 third step register configuration for
+ * starting stream
+ */
+static const struct reg_8 imx274_start_3[] = {
+	{IMX274_STANDBY_REG, 0x00},
+	{0x303E, 0x02}, /* SYS_MODE = 2 */
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 forth step register configuration for
+ * starting stream
+ */
+static const struct reg_8 imx274_start_4[] = {
+	{0x30F4, 0x00},
+	{0x3018, 0xA2}, /* XHS VHS OUTUPT */
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 register configuration for stoping stream
+ */
+static const struct reg_8 imx274_stop[] = {
+	{IMX274_STANDBY_REG, 0x01},
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 disable test pattern register configuration
+ */
+static const struct reg_8 imx274_tp_disabled[] = {
+	{0x303C, 0x00},
+	{0x377F, 0x00},
+	{0x3781, 0x00},
+	{0x370B, 0x00},
+	{IMX274_TABLE_END, 0x00}
+};
+
+/*
+ * imx274 test pattern register configuration
+ * reg 0x303D defines the test pattern modes
+ */
+static const struct reg_8 imx274_tp_regs[] = {
+	{0x303C, 0x11},
+	{0x370E, 0x01},
+	{0x377F, 0x01},
+	{0x3781, 0x01},
+	{0x370B, 0x11},
+	{IMX274_TABLE_END, 0x00}
+};
+
+static const struct reg_8 *mode_table[] = {
+	[IMX274_MODE_3840X2160]		= imx274_mode1_3840x2160_raw10,
+	[IMX274_MODE_1920X1080]		= imx274_mode3_1920x1080_raw10,
+	[IMX274_MODE_1280X720]		= imx274_mode5_1280x720_raw10,
+
+	[IMX274_MODE_START_STREAM_1]	= imx274_start_1,
+	[IMX274_MODE_START_STREAM_2]	= imx274_start_2,
+	[IMX274_MODE_START_STREAM_3]	= imx274_start_3,
+	[IMX274_MODE_START_STREAM_4]	= imx274_start_4,
+	[IMX274_MODE_STOP_STREAM]	= imx274_stop,
+};
+
+/*
+ * imx274 format related structure
+ */
+static const struct imx274_frmfmt imx274_formats[] = {
+	{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {3840, 2160},
+		IMX274_MODE_3840X2160},
+	{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1920, 1080},
+		IMX274_MODE_1920X1080},
+	{MEDIA_BUS_FMT_SRGGB10_1X10, V4L2_COLORSPACE_SRGB, {1280, 720},
+		IMX274_MODE_1280X720},
+};
+
+/*
+ * minimal frame length for each mode
+ * refer to datasheet section "Frame Rate Adjustment (CSI-2)"
+ */
+static const int min_frame_len[] = {
+	4550, /* mode 1, 4K */
+	2310, /* mode 3, 1080p */
+	2310 /* mode 5, 720p */
+};
+
+/*
+ * minimal numbers of SHR register
+ * refer to datasheet table "Shutter Setting (CSI-2)"
+ */
+static const int min_SHR[] = {
+	12, /* mode 1, 4K */
+	8, /* mode 3, 1080p */
+	8 /* mode 5, 720p */
+};
+
+static const int max_frame_rate[] = {
+	60, /* mode 1 , 4K */
+	120, /* mode 3, 1080p */
+	120 /* mode 5, 720p */
+};
+
+/*
+ * Number of clocks per internal offset period
+ * a constant based on mode
+ * refer to section "Integration Time in Each Readout Drive Mode (CSI-2)"
+ * in the datasheet
+ * for the implemented 3 modes, it happens to be the same number
+ */
+static const int nocpiop[] = {
+	112, /* mode 1 , 4K */
+	112, /* mode 3, 1080p */
+	112 /* mode 5, 720p */
+};
+
+/*
+ * struct imx274_ctrls - imx274 ctrl structure
+ * @handler: V4L2 ctrl handler structure
+ * @exposure: Pointer to expsure ctrl structure
+ * @gain: Pointer to gain ctrl structure
+ * @vflip: Pointer to vflip ctrl structure
+ * @test_pattern: Pointer to test pattern ctrl structure
+ */
+struct imx274_ctrls {
+	struct v4l2_ctrl_handler handler;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *gain;
+	struct v4l2_ctrl *vflip;
+	struct v4l2_ctrl *test_pattern;
+};
+
+/*
+ * struct stim274 - imx274 device structure
+ * @sd: V4L2 subdevice structure
+ * @pd: Media pad structure
+ * @client: Pointer to I2C client
+ * @ctrls: imx274 control structure
+ * @format: V4L2 media bus frame format structure
+ * @frame_rate: V4L2 frame rate structure
+ * @regmap: Pointer to regmap structure
+ * @reset_gpio: Pointer to reset gpio
+ * @lock: Mutex structure
+ * @mode_index: Resolution mode index
+ */
+struct stimx274 {
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct i2c_client *client;
+	struct imx274_ctrls ctrls;
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_fract frame_interval;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+	struct mutex lock; /* mutex lock for operations */
+	u32 mode_index;
+};
+
+/*
+ * Function declaration
+ */
+static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl);
+static int imx274_set_exposure(struct stimx274 *priv, int val);
+static int imx274_set_vflip(struct stimx274 *priv, int val);
+static int imx274_set_test_pattern(struct stimx274 *priv, int val);
+static int imx274_set_frame_interval(struct stimx274 *priv,
+				     struct v4l2_fract frame_interval);
+
+static inline void msleep_range(unsigned int delay_base)
+{
+	usleep_range(delay_base * 1000, delay_base * 1000 + 500);
+}
+
+/*
+ * v4l2_ctrl and v4l2_subdev related operations
+ */
+static inline struct v4l2_subdev *ctrl_to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler,
+			     struct stimx274, ctrls.handler)->sd;
+}
+
+static inline struct stimx274 *to_imx274(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct stimx274, sd);
+}
+
+/*
+ * imx274_regmap_util_write_table_8 - Function for writing register table
+ * @regmap: Pointer to device reg map structure
+ * @table: Table containing register values
+ * @wait_ms_addr: Flag for performing delay
+ * @end_addr: Flag for incating end of table
+ *
+ * This is used to write register table into sensor's reg map.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_regmap_util_write_table_8(struct regmap *regmap,
+					    const struct reg_8 table[],
+					    u16 wait_ms_addr, u16 end_addr)
+{
+	int err;
+	const struct reg_8 *next;
+	u8 val;
+
+	int range_start = -1;
+	int range_count = 0;
+	u8 range_vals[16];
+	int max_range_vals = ARRAY_SIZE(range_vals);
+
+	for (next = table;; next++) {
+		if ((next->addr != range_start + range_count) ||
+		    (next->addr == end_addr) ||
+		    (next->addr == wait_ms_addr) ||
+		    (range_count == max_range_vals)) {
+			if (range_count == 1)
+				err = regmap_write(regmap,
+						   range_start, range_vals[0]);
+			else if (range_count > 1)
+				err = regmap_bulk_write(regmap, range_start,
+							&range_vals[0],
+							range_count);
+
+			if (err)
+				return err;
+
+			range_start = -1;
+			range_count = 0;
+
+			/* Handle special address values */
+			if (next->addr == end_addr)
+				break;
+
+			if (next->addr == wait_ms_addr) {
+				msleep_range(next->val);
+				continue;
+			}
+		}
+
+		val = next->val;
+
+		if (range_start == -1)
+			range_start = next->addr;
+
+		range_vals[range_count++] = val;
+	}
+	return 0;
+}
+
+static inline int imx274_read_reg(struct stimx274 *priv, u16 addr, u8 *val)
+{
+	int err;
+
+	err = regmap_read(priv->regmap, addr, (unsigned int *)val);
+	if (err)
+		dev_err(&priv->client->dev,
+			"%s : i2c read failed, addr = %x\n", __func__, addr);
+	else
+		dev_dbg(&priv->client->dev,
+			"%s : addr 0x%x, val=0x%x\n", __func__,
+			addr, *val);
+	return err;
+}
+
+static inline int imx274_write_reg(struct stimx274 *priv, u16 addr, u8 val)
+{
+	int err;
+
+	err = regmap_write(priv->regmap, addr, val);
+	if (err)
+		dev_err(&priv->client->dev,
+			"%s : i2c write failed, %x = %x\n", __func__,
+			addr, val);
+	else
+		dev_dbg(&priv->client->dev,
+			"%s : addr 0x%x, val=0x%x\n", __func__,
+			addr, val);
+	return err;
+}
+
+static int imx274_write_table(struct stimx274 *priv, const struct reg_8 table[])
+{
+	return imx274_regmap_util_write_table_8(priv->regmap,
+		table, IMX274_TABLE_WAIT_MS, IMX274_TABLE_END);
+}
+
+/*
+ * imx274_mode_regs - Function for set mode registers per mode index
+ * @priv: Pointer to device structure
+ * @mode: Mode index value
+ *
+ * This is used to start steam per mode index.
+ * mode = 0, start stream for sensor Mode 1: 4K/raw10
+ * mode = 1, start stream for sensor Mode 3: 1080p/raw10
+ * mode = 2, start stream for sensor Mode 5: 720p/raw10
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_mode_regs(struct stimx274 *priv, int mode)
+{
+	int err = 0;
+
+	err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_1]);
+	if (err)
+		return err;
+
+	err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_2]);
+	if (err)
+		return err;
+
+	err = imx274_write_table(priv, mode_table[mode]);
+
+	return err;
+}
+
+/*
+ * imx274_start_stream - Function for starting stream per mode index
+ * @priv: Pointer to device structure
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_start_stream(struct stimx274 *priv)
+{
+	int err = 0;
+
+	/*
+	 * Refer to "Standby Cancel Sequence when using CSI-2" in
+	 * imx274 datasheet, it should wait 10ms or more here.
+	 * give it 1 extra ms for margin
+	 */
+	msleep_range(11);
+	err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_3]);
+	if (err)
+		return err;
+
+	/*
+	 * Refer to "Standby Cancel Sequence when using CSI-2" in
+	 * imx274 datasheet, it should wait 7ms or more here.
+	 * give it 1 extra ms for margin
+	 */
+	msleep_range(8);
+	err = imx274_write_table(priv, mode_table[IMX274_MODE_START_STREAM_4]);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+/*
+ * imx274_reset - Function called to reset the sensor
+ * @priv: Pointer to device structure
+ * @rst: Input value for determining the sensor's end state after reset
+ *
+ * Set the senor in reset and then
+ * if rst = 0, keep it in reset;
+ * if rst = 1, bring it out of reset.
+ *
+ */
+static void imx274_reset(struct stimx274 *priv, int rst)
+{
+	gpiod_set_value_cansleep(priv->reset_gpio, 0);
+	usleep_range(IMX274_RESET_DELAY1, IMX274_RESET_DELAY2);
+	gpiod_set_value_cansleep(priv->reset_gpio, !!rst);
+	usleep_range(IMX274_RESET_DELAY1, IMX274_RESET_DELAY2);
+}
+
+/**
+ * imx274_s_ctrl - This is used to set the imx274 V4L2 controls
+ * @ctrl: V4L2 control to be set
+ *
+ * This function is used to set the V4L2 controls for the imx274 sensor.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
+	struct stimx274 *imx274 = to_imx274(sd);
+	int ret = -EINVAL;
+
+	dev_dbg(&imx274->client->dev,
+		"%s : s_ctrl: %s, value: %d\n", __func__,
+		ctrl->name, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+		dev_dbg(&imx274->client->dev,
+			"%s : set V4L2_CID_EXPOSURE\n", __func__);
+		ret = imx274_set_exposure(imx274, ctrl->val);
+		break;
+
+	case V4L2_CID_GAIN:
+		dev_dbg(&imx274->client->dev,
+			"%s : set V4L2_CID_GAIN\n", __func__);
+		ret = imx274_set_gain(imx274, ctrl);
+		break;
+
+	case V4L2_CID_VFLIP:
+		dev_dbg(&imx274->client->dev,
+			"%s : set V4L2_CID_VFLIP\n", __func__);
+		ret = imx274_set_vflip(imx274, ctrl->val);
+		break;
+
+	case V4L2_CID_TEST_PATTERN:
+		dev_dbg(&imx274->client->dev,
+			"%s : set V4L2_CID_TEST_PATTERN\n", __func__);
+		ret = imx274_set_test_pattern(imx274, ctrl->val);
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * imx274_get_fmt - Get the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to get the pad format information.
+ *
+ * Return: 0 on success
+ */
+static int imx274_get_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct stimx274 *imx274 = to_imx274(sd);
+
+	mutex_lock(&imx274->lock);
+	fmt->format = imx274->format;
+	mutex_unlock(&imx274->lock);
+	return 0;
+}
+
+/**
+ * imx274_set_fmt - This is used to set the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @format: Pointer to pad level media bus format
+ *
+ * This function is used to set the pad format.
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *format)
+{
+	struct v4l2_mbus_framefmt *fmt = &format->format;
+	struct stimx274 *imx274 = to_imx274(sd);
+	struct i2c_client *client = imx274->client;
+	int index;
+
+	dev_dbg(&client->dev,
+		"%s: width = %d height = %d code = %d mbus_code = %d\n",
+		__func__, fmt->width, fmt->height, fmt->code,
+		imx274_formats[imx274->mode_index].mbus_code);
+
+	mutex_lock(&imx274->lock);
+
+	for (index = 0; index < ARRAY_SIZE(imx274_formats); index++) {
+		if (imx274_formats[index].size.width == fmt->width &&
+		    imx274_formats[index].size.height == fmt->height)
+			break;
+	}
+
+	if (index >= ARRAY_SIZE(imx274_formats)) {
+		/* default to first format */
+		index = 0;
+	}
+
+	imx274->mode_index = index;
+
+	if (fmt->width > IMX274_MAX_WIDTH)
+		fmt->width = IMX274_MAX_WIDTH;
+	if (fmt->height > IMX274_MAX_HEIGHT)
+		fmt->height = IMX274_MAX_HEIGHT;
+	fmt->width = fmt->width & (~IMX274_MASK_LSB_2_BITS);
+	fmt->height = fmt->height & (~IMX274_MASK_LSB_2_BITS);
+	fmt->field = V4L2_FIELD_NONE;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
+		cfg->try_fmt = *fmt;
+	else
+		imx274->format = *fmt;
+
+	mutex_unlock(&imx274->lock);
+	return 0;
+}
+
+/**
+ * imx274_g_frame_interval - Get the frame interval
+ * @sd: Pointer to V4L2 Sub device structure
+ * @fi: Pointer to V4l2 Sub device frame interval structure
+ *
+ * This function is used to get the frame interval.
+ *
+ * Return: 0 on success
+ */
+static int imx274_g_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct stimx274 *imx274 = to_imx274(sd);
+
+	fi->interval = imx274->frame_interval;
+	dev_dbg(&imx274->client->dev, "%s frame rate = %d / %d\n",
+		__func__, imx274->frame_interval.numerator,
+		imx274->frame_interval.denominator);
+
+	return 0;
+}
+
+/**
+ * imx274_s_frame_interval - Set the frame interval
+ * @sd: Pointer to V4L2 Sub device structure
+ * @fi: Pointer to V4l2 Sub device frame interval structure
+ *
+ * This function is used to set the frame intervavl.
+ *
+ * Return: 0 on success
+ */
+static int imx274_s_frame_interval(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_frame_interval *fi)
+{
+	struct stimx274 *imx274 = to_imx274(sd);
+	struct v4l2_ctrl *ctrl = imx274->ctrls.exposure;
+	int min, max, def;
+	int ret;
+
+	mutex_lock(&imx274->lock);
+	ret = imx274_set_frame_interval(imx274, fi->interval);
+
+	if (!ret) {
+		/*
+		 * exposure time range is decided by frame interval
+		 * need to update it after frame interal changes
+		 */
+		min = IMX274_MIN_EXPOSURE_TIME;
+		max = fi->interval.numerator * 1000000
+			/ fi->interval.denominator;
+		def = max;
+		if (__v4l2_ctrl_modify_range(ctrl, min, max, 1, def)) {
+			dev_err(&imx274->client->dev,
+				"Exposure ctrl range update failed\n");
+			goto unlock;
+		}
+
+		/* update exposure time accordingly */
+		imx274_set_exposure(imx274, imx274->ctrls.exposure->val);
+
+		dev_dbg(&imx274->client->dev, "set frame interval to %uus\n",
+			fi->interval.numerator * 1000000
+			/ fi->interval.denominator);
+	}
+
+unlock:
+	mutex_unlock(&imx274->lock);
+
+	return ret;
+}
+
+/**
+ * imx274_load_default - load default control values
+ * @priv: Pointer to device structure
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_load_default(struct stimx274 *priv)
+{
+	int ret;
+
+	/* load default control values */
+	priv->frame_interval.numerator = 1;
+	priv->frame_interval.denominator = IMX274_DEF_FRAME_RATE;
+	priv->ctrls.exposure->val = 1000000 / IMX274_DEF_FRAME_RATE;
+	priv->ctrls.gain->val = IMX274_DEF_GAIN;
+	priv->ctrls.vflip->val = 0;
+	priv->ctrls.test_pattern->val = TEST_PATTERN_DISABLED;
+
+	/* update frame rate */
+	ret = imx274_set_frame_interval(priv,
+					priv->frame_interval);
+	if (ret)
+		return ret;
+
+	/* update exposure time */
+	ret = v4l2_ctrl_s_ctrl(priv->ctrls.exposure, priv->ctrls.exposure->val);
+	if (ret)
+		return ret;
+
+	/* update gain */
+	ret = v4l2_ctrl_s_ctrl(priv->ctrls.gain, priv->ctrls.gain->val);
+	if (ret)
+		return ret;
+
+	/* update vflip */
+	ret = v4l2_ctrl_s_ctrl(priv->ctrls.vflip, priv->ctrls.vflip->val);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+/**
+ * imx274_s_stream - It is used to start/stop the streaming.
+ * @sd: V4L2 Sub device
+ * @on: Flag (True / False)
+ *
+ * This function controls the start or stop of streaming for the
+ * imx274 sensor.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int imx274_s_stream(struct v4l2_subdev *sd, int on)
+{
+	struct stimx274 *imx274 = to_imx274(sd);
+	int ret = 0;
+
+	dev_dbg(&imx274->client->dev, "%s : %s, mode index = %d\n", __func__,
+		on ? "Stream Start" : "Stream Stop", imx274->mode_index);
+
+	mutex_lock(&imx274->lock);
+
+	if (on) {
+		/* load mode registers */
+		ret = imx274_mode_regs(imx274, imx274->mode_index);
+		if (ret)
+			goto fail;
+
+		/*
+		 * update frame rate & expsoure. if the last mode is different,
+		 * HMAX could be changed. As the result, frame rate & exposure
+		 * are changed.
+		 * gain is not affected.
+		 */
+		ret = imx274_set_frame_interval(imx274,
+						imx274->frame_interval);
+		if (ret)
+			goto fail;
+
+		/* update exposure time */
+		ret = __v4l2_ctrl_s_ctrl(imx274->ctrls.exposure,
+					 imx274->ctrls.exposure->val);
+		if (ret)
+			goto fail;
+
+		/* start stream */
+		ret = imx274_start_stream(imx274);
+		if (ret)
+			goto fail;
+	} else {
+		/* stop stream */
+		ret = imx274_write_table(imx274,
+					 mode_table[IMX274_MODE_STOP_STREAM]);
+		if (ret)
+			goto fail;
+	}
+
+	mutex_unlock(&imx274->lock);
+	dev_dbg(&imx274->client->dev,
+		"%s : Done: mode = %d\n", __func__, imx274->mode_index);
+	return 0;
+
+fail:
+	mutex_unlock(&imx274->lock);
+	dev_err(&imx274->client->dev, "s_stream failed\n");
+	return ret;
+}
+
+/*
+ * imx274_get_frame_length - Function for obtaining current frame length
+ * @priv: Pointer to device structure
+ * @val: Pointer to obainted value
+ *
+ * frame_length = vmax x (svr + 1), in unit of hmax.
+ *
+ * Return: 0 on success
+ */
+static int imx274_get_frame_length(struct stimx274 *priv, u32 *val)
+{
+	int err;
+	u16 svr;
+	u32 vmax;
+	u8 reg_val[3];
+
+	/* svr */
+	err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, &reg_val[0]);
+	if (err)
+		goto fail;
+
+	err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, &reg_val[1]);
+	if (err)
+		goto fail;
+
+	svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+
+	/* vmax */
+	err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_3, &reg_val[0]);
+	if (err)
+		goto fail;
+
+	err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_2, &reg_val[1]);
+	if (err)
+		goto fail;
+
+	err = imx274_read_reg(priv, IMX274_FRAME_LENGTH_ADDR_1, &reg_val[2]);
+	if (err)
+		goto fail;
+
+	vmax = ((reg_val[2] & IMX274_MASK_LSB_3_BITS) << IMX274_SHIFT_16_BITS)
+		+ (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+
+	*val = vmax * (svr + 1);
+
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+	return err;
+}
+
+static int imx274_clamp_coarse_time(struct stimx274 *priv, u32 *val,
+				    u32 *frame_length)
+{
+	int err;
+
+	err = imx274_get_frame_length(priv, frame_length);
+	if (err)
+		return err;
+
+	if (*frame_length < min_frame_len[priv->mode_index])
+		*frame_length = min_frame_len[priv->mode_index];
+
+	*val = *frame_length - *val; /* convert to raw shr */
+	if (*val > *frame_length - IMX274_SHR_LIMIT_CONST)
+		*val = *frame_length - IMX274_SHR_LIMIT_CONST;
+	else if (*val < min_SHR[priv->mode_index])
+		*val = min_SHR[priv->mode_index];
+
+	return 0;
+}
+
+/*
+ * imx274_set_digital gain - Function called when setting digital gain
+ * @priv: Pointer to device structure
+ * @dgain: Value of digital gain.
+ *
+ * Digital gain has only 4 steps: 1x, 2x, 4x, and 8x
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_digital_gain(struct stimx274 *priv, u32 dgain)
+{
+	u8 reg_val;
+
+	reg_val = ffs(dgain);
+
+	if (reg_val)
+		reg_val--;
+
+	reg_val = clamp(reg_val, (u8)0, (u8)3);
+
+	return imx274_write_reg(priv, IMX274_DIGITAL_GAIN_REG,
+				reg_val & IMX274_MASK_LSB_4_BITS);
+}
+
+static inline void imx274_calculate_gain_regs(struct reg_8 regs[2], u16 gain)
+{
+	regs->addr = IMX274_ANALOG_GAIN_ADDR_MSB;
+	regs->val = (gain >> IMX274_SHIFT_8_BITS) & IMX274_MASK_LSB_3_BITS;
+
+	(regs + 1)->addr = IMX274_ANALOG_GAIN_ADDR_LSB;
+	(regs + 1)->val = (gain) & IMX274_MASK_LSB_8_BITS;
+}
+
+/*
+ * imx274_set_gain - Function called when setting gain
+ * @priv: Pointer to device structure
+ * @val: Value of gain. the real value = val << IMX274_GAIN_SHIFT;
+ * @ctrl: v4l2 control pointer
+ *
+ * Set the gain based on input value.
+ * The caller should hold the mutex lock imx274->lock if necessary
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_gain(struct stimx274 *priv, struct v4l2_ctrl *ctrl)
+{
+	struct reg_8 reg_list[2];
+	int err;
+	u32 gain, analog_gain, digital_gain, gain_reg;
+	int i;
+
+	gain = (u32)(ctrl->val);
+
+	dev_dbg(&priv->client->dev,
+		"%s : input gain = %d.%d\n", __func__,
+		gain >> IMX274_GAIN_SHIFT,
+		((gain & IMX274_GAIN_SHIFT_MASK) * 100) >> IMX274_GAIN_SHIFT);
+
+	if (gain > IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN)
+		gain = IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN;
+	else if (gain < IMX274_MIN_GAIN)
+		gain = IMX274_MIN_GAIN;
+
+	if (gain <= IMX274_MAX_ANALOG_GAIN)
+		digital_gain = 1;
+	else if (gain <= IMX274_MAX_ANALOG_GAIN * 2)
+		digital_gain = 2;
+	else if (gain <= IMX274_MAX_ANALOG_GAIN * 4)
+		digital_gain = 4;
+	else
+		digital_gain = IMX274_MAX_DIGITAL_GAIN;
+
+	analog_gain = gain / digital_gain;
+
+	dev_dbg(&priv->client->dev,
+		"%s : digital gain = %d, analog gain = %d.%d\n",
+		__func__, digital_gain, analog_gain >> IMX274_GAIN_SHIFT,
+		((analog_gain & IMX274_GAIN_SHIFT_MASK) * 100)
+		>> IMX274_GAIN_SHIFT);
+
+	err = imx274_set_digital_gain(priv, digital_gain);
+	if (err)
+		goto fail;
+
+	/* convert to register value, refer to imx274 datasheet */
+	gain_reg = (u32)IMX274_GAIN_CONST -
+		(IMX274_GAIN_CONST << IMX274_GAIN_SHIFT) / analog_gain;
+	if (gain_reg > IMX274_GAIN_REG_MAX)
+		gain_reg = IMX274_GAIN_REG_MAX;
+
+	imx274_calculate_gain_regs(reg_list, (u16)gain_reg);
+
+	for (i = 0; i < ARRAY_SIZE(reg_list); i++) {
+		err = imx274_write_reg(priv, reg_list[i].addr,
+				       reg_list[i].val);
+		if (err)
+			goto fail;
+	}
+
+	if (IMX274_GAIN_CONST - gain_reg == 0) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	/* convert register value back to gain value */
+	ctrl->val = (IMX274_GAIN_CONST << IMX274_GAIN_SHIFT)
+			/ (IMX274_GAIN_CONST - gain_reg) * digital_gain;
+
+	dev_dbg(&priv->client->dev,
+		"%s : GAIN control success, gain_reg = %d, new gain = %d\n",
+		__func__, gain_reg, ctrl->val);
+
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+	return err;
+}
+
+static inline void imx274_calculate_coarse_time_regs(struct reg_8 regs[2],
+						     u32 coarse_time)
+{
+	regs->addr = IMX274_COARSE_TIME_ADDR_MSB;
+	regs->val = (coarse_time >> IMX274_SHIFT_8_BITS)
+			& IMX274_MASK_LSB_8_BITS;
+	(regs + 1)->addr = IMX274_COARSE_TIME_ADDR_LSB;
+	(regs + 1)->val = (coarse_time) & IMX274_MASK_LSB_8_BITS;
+}
+
+/*
+ * imx274_set_coarse_time - Function called when setting SHR value
+ * @priv: Pointer to device structure
+ * @val: Value for exposure time in number of line_length, or [HMAX]
+ *
+ * Set SHR value based on input value.
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_coarse_time(struct stimx274 *priv, u32 *val)
+{
+	struct reg_8 reg_list[2];
+	int err;
+	u32 coarse_time, frame_length;
+	int i;
+
+	coarse_time = *val;
+
+	/* convert exposure_time to appropriate SHR value */
+	err = imx274_clamp_coarse_time(priv, &coarse_time, &frame_length);
+	if (err)
+		goto fail;
+
+	/* prepare SHR registers */
+	imx274_calculate_coarse_time_regs(reg_list, coarse_time);
+
+	/* write to SHR registers */
+	for (i = 0; i < ARRAY_SIZE(reg_list); i++) {
+		err = imx274_write_reg(priv, reg_list[i].addr,
+				       reg_list[i].val);
+		if (err)
+			goto fail;
+	}
+
+	*val = frame_length - coarse_time;
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+	return err;
+}
+
+/*
+ * imx274_set_exposure - Function called when setting exposure time
+ * @priv: Pointer to device structure
+ * @val: Variable for exposure time, in the unit of micro-second
+ *
+ * Set exposure time based on input value.
+ * The caller should hold the mutex lock imx274->lock if necessary
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_exposure(struct stimx274 *priv, int val)
+{
+	int err;
+	u16 hmax;
+	u8 reg_val[2];
+	u32 coarse_time; /* exposure time in unit of line (HMAX)*/
+
+	dev_dbg(&priv->client->dev,
+		"%s : EXPOSURE control input = %d\n", __func__, val);
+
+	/* step 1: convert input exposure_time (val) into number of 1[HMAX] */
+
+	/* obtain HMAX value */
+	err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, &reg_val[0]);
+	if (err)
+		goto fail;
+	err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, &reg_val[1]);
+	if (err)
+		goto fail;
+	hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+	if (hmax == 0) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	coarse_time = (IMX274_PIXCLK_CONST1 / IMX274_PIXCLK_CONST2 * val
+			- nocpiop[priv->mode_index]) / hmax;
+
+	/* step 2: convert exposure_time into SHR value */
+
+	/* set SHR */
+	err = imx274_set_coarse_time(priv, &coarse_time);
+	if (err)
+		goto fail;
+
+	priv->ctrls.exposure->val =
+			(coarse_time * hmax + nocpiop[priv->mode_index])
+			/ (IMX274_PIXCLK_CONST1 / IMX274_PIXCLK_CONST2);
+
+	dev_dbg(&priv->client->dev,
+		"%s : EXPOSURE control success\n", __func__);
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+
+	return err;
+}
+
+/*
+ * imx274_set_vflip - Function called when setting vertical flip
+ * @priv: Pointer to device structure
+ * @val: Value for vflip setting
+ *
+ * Set vertical flip based on input value.
+ * val = 0: normal, no vertical flip
+ * val = 1: vertical flip enabled
+ * The caller should hold the mutex lock imx274->lock if necessary
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_vflip(struct stimx274 *priv, int val)
+{
+	int err;
+
+	err = imx274_write_reg(priv, IMX274_VFLIP_REG, val);
+	if (err) {
+		dev_err(&priv->client->dev, "VFILP control error\n");
+		return err;
+	}
+
+	dev_dbg(&priv->client->dev,
+		"%s : VFLIP control success\n", __func__);
+
+	return 0;
+}
+
+/*
+ * imx274_set_test_pattern - Function called when setting test pattern
+ * @priv: Pointer to device structure
+ * @val: Variable for test pattern
+ *
+ * Set to different test patterns based on input value.
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_test_pattern(struct stimx274 *priv, int val)
+{
+	int err = 0;
+
+	if (val == TEST_PATTERN_DISABLED) {
+		err = imx274_write_table(priv, imx274_tp_disabled);
+	} else if (val <= TEST_PATTERN_V_COLOR_BARS) {
+		err = imx274_write_reg(priv, IMX274_TEST_PATTERN_REG, val - 1);
+		if (!err)
+			err = imx274_write_table(priv, imx274_tp_regs);
+	} else {
+		err = -EINVAL;
+	}
+
+	if (!err)
+		dev_dbg(&priv->client->dev,
+			"%s : TEST PATTERN control success\n", __func__);
+	else
+		dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+
+	return err;
+}
+
+static inline void imx274_calculate_frame_length_regs(struct reg_8 regs[3],
+						      u32 frame_length)
+{
+	regs->addr = IMX274_FRAME_LENGTH_ADDR_1;
+	regs->val = (frame_length >> IMX274_SHIFT_16_BITS)
+			& IMX274_MASK_LSB_4_BITS;
+	(regs + 1)->addr = IMX274_FRAME_LENGTH_ADDR_2;
+	(regs + 1)->val = (frame_length >> IMX274_SHIFT_8_BITS)
+			& IMX274_MASK_LSB_8_BITS;
+	(regs + 2)->addr = IMX274_FRAME_LENGTH_ADDR_3;
+	(regs + 2)->val = (frame_length) & IMX274_MASK_LSB_8_BITS;
+}
+
+/*
+ * imx274_set_frame_length - Function called when setting frame length
+ * @priv: Pointer to device structure
+ * @val: Variable for frame length (= VMAX, i.e. vertical drive period length)
+ *
+ * Set frame length based on input value.
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_frame_length(struct stimx274 *priv, u32 val)
+{
+	struct reg_8 reg_list[3];
+	int err;
+	u32 frame_length;
+	int i;
+
+	dev_dbg(&priv->client->dev, "%s : input length = %d\n",
+		__func__, val);
+
+	frame_length = (u32)val;
+
+	imx274_calculate_frame_length_regs(reg_list, frame_length);
+	for (i = 0; i < ARRAY_SIZE(reg_list); i++) {
+		err = imx274_write_reg(priv, reg_list[i].addr,
+				       reg_list[i].val);
+		if (err)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+	return err;
+}
+
+/*
+ * imx274_set_frame_interval - Function called when setting frame interval
+ * @priv: Pointer to device structure
+ * @frame_interval: Variable for frame interval
+ *
+ * Change frame interval by updating VMAX value
+ * The caller should hold the mutex lock imx274->lock if necessary
+ *
+ * Return: 0 on success
+ */
+static int imx274_set_frame_interval(struct stimx274 *priv,
+				     struct v4l2_fract frame_interval)
+{
+	int err;
+	u32 frame_length, req_frame_rate;
+	u16 svr;
+	u16 hmax;
+	u8 reg_val[2];
+
+	dev_dbg(&priv->client->dev, "%s: input frame interval = %d / %d",
+		__func__, frame_interval.numerator,
+		frame_interval.denominator);
+
+	if (frame_interval.numerator == 0) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	req_frame_rate = (u32)(frame_interval.denominator
+				/ frame_interval.numerator);
+
+	/* boundary check */
+	if (req_frame_rate > max_frame_rate[priv->mode_index]) {
+		frame_interval.numerator = 1;
+		frame_interval.denominator =
+					max_frame_rate[priv->mode_index];
+	} else if (req_frame_rate < IMX274_MIN_FRAME_RATE) {
+		frame_interval.numerator = 1;
+		frame_interval.denominator = IMX274_MIN_FRAME_RATE;
+	}
+
+	/*
+	 * VMAX = 1/frame_rate x 72M / (SVR+1) / HMAX
+	 * frame_length (i.e. VMAX) = (frame_interval) x 72M /(SVR+1) / HMAX
+	 */
+
+	/* SVR */
+	err = imx274_read_reg(priv, IMX274_SVR_REG_LSB, &reg_val[0]);
+	if (err)
+		goto fail;
+	err = imx274_read_reg(priv, IMX274_SVR_REG_MSB, &reg_val[1]);
+	if (err)
+		goto fail;
+	svr = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+	dev_dbg(&priv->client->dev,
+		"%s : register SVR = %d\n", __func__, svr);
+
+	/* HMAX */
+	err = imx274_read_reg(priv, IMX274_HMAX_REG_LSB, &reg_val[0]);
+	if (err)
+		goto fail;
+	err = imx274_read_reg(priv, IMX274_HMAX_REG_MSB, &reg_val[1]);
+	if (err)
+		goto fail;
+	hmax = (reg_val[1] << IMX274_SHIFT_8_BITS) + reg_val[0];
+	dev_dbg(&priv->client->dev,
+		"%s : register HMAX = %d\n", __func__, hmax);
+
+	if (hmax == 0 || frame_interval.denominator == 0) {
+		err = -EINVAL;
+		goto fail;
+	}
+
+	frame_length = IMX274_PIXCLK_CONST1 / (svr + 1) / hmax
+					* frame_interval.numerator
+					/ frame_interval.denominator;
+
+	err = imx274_set_frame_length(priv, frame_length);
+	if (err)
+		goto fail;
+
+	priv->frame_interval = frame_interval;
+	return 0;
+
+fail:
+	dev_err(&priv->client->dev, "%s error = %d\n", __func__, err);
+	return err;
+}
+
+static const struct v4l2_subdev_pad_ops imx274_pad_ops = {
+	.get_fmt = imx274_get_fmt,
+	.set_fmt = imx274_set_fmt,
+};
+
+static const struct v4l2_subdev_video_ops imx274_video_ops = {
+	.g_frame_interval = imx274_g_frame_interval,
+	.s_frame_interval = imx274_s_frame_interval,
+	.s_stream = imx274_s_stream,
+};
+
+static const struct v4l2_subdev_ops imx274_subdev_ops = {
+	.pad = &imx274_pad_ops,
+	.video = &imx274_video_ops,
+};
+
+static const struct v4l2_ctrl_ops imx274_ctrl_ops = {
+	.s_ctrl	= imx274_s_ctrl,
+};
+
+static const struct of_device_id imx274_of_id_table[] = {
+	{ .compatible = "sony,imx274" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, imx274_of_id_table);
+
+static const struct i2c_device_id imx274_id[] = {
+	{ "IMX274", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, imx274_id);
+
+static int imx274_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct v4l2_subdev *sd;
+	struct stimx274 *imx274;
+	int ret;
+
+	/* initialize imx274 */
+	imx274 = devm_kzalloc(&client->dev, sizeof(*imx274), GFP_KERNEL);
+	if (!imx274)
+		return -ENOMEM;
+
+	mutex_init(&imx274->lock);
+
+	/* initialize regmap */
+	imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config);
+	if (IS_ERR(imx274->regmap)) {
+		dev_err(&client->dev,
+			"regmap init failed: %ld\n", PTR_ERR(imx274->regmap));
+		ret = -ENODEV;
+		goto err_regmap;
+	}
+
+	/* initialize subdevice */
+	imx274->client = client;
+	sd = &imx274->sd;
+	v4l2_i2c_subdev_init(sd, client, &imx274_subdev_ops);
+	strlcpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+
+	/* initialize subdev media pad */
+	imx274->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	ret = media_entity_pads_init(&sd->entity, 1, &imx274->pad);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s : media entity init Failed %d\n", __func__, ret);
+		goto err_regmap;
+	}
+
+	/* initialize sensor reset gpio */
+	imx274->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
+						     GPIOD_OUT_HIGH);
+	if (IS_ERR(imx274->reset_gpio)) {
+		if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER)
+			dev_err(&client->dev, "Reset GPIO not setup in DT");
+		ret = PTR_ERR(imx274->reset_gpio);
+		goto err_me;
+	}
+
+	/* pull sensor out of reset */
+	imx274_reset(imx274, 1);
+
+	/* initialize controls */
+	ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 2);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s : ctrl handler init Failed\n", __func__);
+		goto err_me;
+	}
+
+	imx274->ctrls.handler.lock = &imx274->lock;
+
+	/* add new controls */
+	imx274->ctrls.test_pattern = v4l2_ctrl_new_std_menu_items(
+		&imx274->ctrls.handler, &imx274_ctrl_ops,
+		V4L2_CID_TEST_PATTERN,
+		ARRAY_SIZE(tp_qmenu) - 1, 0, 0, tp_qmenu);
+
+	imx274->ctrls.gain = v4l2_ctrl_new_std(
+		&imx274->ctrls.handler,
+		&imx274_ctrl_ops,
+		V4L2_CID_GAIN, IMX274_MIN_GAIN,
+		IMX274_MAX_DIGITAL_GAIN * IMX274_MAX_ANALOG_GAIN, 1,
+		IMX274_DEF_GAIN);
+
+	imx274->ctrls.exposure = v4l2_ctrl_new_std(
+		&imx274->ctrls.handler,
+		&imx274_ctrl_ops,
+		V4L2_CID_EXPOSURE, IMX274_MIN_EXPOSURE_TIME,
+		1000000 / IMX274_DEF_FRAME_RATE, 1,
+		IMX274_MIN_EXPOSURE_TIME);
+
+	imx274->ctrls.vflip = v4l2_ctrl_new_std(
+		&imx274->ctrls.handler,
+		&imx274_ctrl_ops,
+		V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	imx274->sd.ctrl_handler = &imx274->ctrls.handler;
+	if (imx274->ctrls.handler.error) {
+		ret = imx274->ctrls.handler.error;
+		goto err_ctrls;
+	}
+
+	/* setup default controls */
+	ret = v4l2_ctrl_handler_setup(&imx274->ctrls.handler);
+	if (ret) {
+		dev_err(&client->dev,
+			"Error %d setup default controls\n", ret);
+		goto err_ctrls;
+	}
+
+	/* initialize format */
+	imx274->mode_index = IMX274_MODE_3840X2160;
+	imx274->format.width = imx274_formats[0].size.width;
+	imx274->format.height = imx274_formats[0].size.height;
+	imx274->format.field = V4L2_FIELD_NONE;
+	imx274->format.code = MEDIA_BUS_FMT_SRGGB10_1X10;
+	imx274->format.colorspace = V4L2_COLORSPACE_SRGB;
+	imx274->frame_interval.numerator = 1;
+	imx274->frame_interval.denominator = IMX274_DEF_FRAME_RATE;
+
+	/* load default control values */
+	ret = imx274_load_default(imx274);
+	if (ret) {
+		dev_err(&client->dev,
+			"%s : imx274_load_default failed %d\n",
+			__func__, ret);
+		goto err_ctrls;
+	}
+
+	/* register subdevice */
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"%s : v4l2_async_register_subdev failed %d\n",
+			__func__, ret);
+		goto err_ctrls;
+	}
+
+	dev_info(&client->dev, "imx274 : imx274 probe success !\n");
+	return 0;
+
+err_ctrls:
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+err_me:
+	media_entity_cleanup(&sd->entity);
+err_regmap:
+	mutex_destroy(&imx274->lock);
+	return ret;
+}
+
+static int imx274_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct stimx274 *imx274 = to_imx274(sd);
+
+	/* stop stream */
+	imx274_write_table(imx274, mode_table[IMX274_MODE_STOP_STREAM]);
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(sd->ctrl_handler);
+	media_entity_cleanup(&sd->entity);
+	mutex_destroy(&imx274->lock);
+	return 0;
+}
+
+static struct i2c_driver imx274_i2c_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.of_match_table	= imx274_of_id_table,
+	},
+	.probe		= imx274_probe,
+	.remove		= imx274_remove,
+	.id_table	= imx274_id,
+};
+
+module_i2c_driver(imx274_i2c_driver);
+
+MODULE_AUTHOR("Leon Luo <leonl@leopardimaging.com>");
+MODULE_DESCRIPTION("IMX274 CMOS Image Sensor driver");
+MODULE_LICENSE("GPL v2");

+ 0 - 1
drivers/media/i2c/ir-kbd-i2c.c

@@ -460,7 +460,6 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	 */
 	 */
 	rc->map_name       = ir->ir_codes;
 	rc->map_name       = ir->ir_codes;
 	rc->allowed_protocols = rc_proto;
 	rc->allowed_protocols = rc_proto;
-	rc->enabled_protocols = rc_proto;
 	if (!rc->driver_name)
 	if (!rc->driver_name)
 		rc->driver_name = MODULE_NAME;
 		rc->driver_name = MODULE_NAME;
 
 

+ 1 - 1
drivers/media/i2c/max2175.c

@@ -1345,7 +1345,7 @@ static int max2175_probe(struct i2c_client *client,
 	v4l2_i2c_subdev_init(sd, client, &max2175_ops);
 	v4l2_i2c_subdev_init(sd, client, &max2175_ops);
 	ctx->client = client;
 	ctx->client = client;
 
 
-	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 
 
 	/* Controls */
 	/* Controls */
 	hdl = &ctx->ctrl_hdl;
 	hdl = &ctx->ctrl_hdl;

+ 1 - 1
drivers/media/i2c/mt9m111.c

@@ -945,7 +945,7 @@ static int mt9m111_probe(struct i2c_client *client,
 
 
 	mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
 	mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
 	if (IS_ERR(mt9m111->clk))
 	if (IS_ERR(mt9m111->clk))
-		return -EPROBE_DEFER;
+		return PTR_ERR(mt9m111->clk);
 
 
 	/* Default HIGHPOWER context */
 	/* Default HIGHPOWER context */
 	mt9m111->ctx = &context_b;
 	mt9m111->ctx = &context_b;

+ 38 - 23
drivers/media/i2c/ov13858.c

@@ -104,7 +104,6 @@ struct ov13858_reg_list {
 
 
 /* Link frequency config */
 /* Link frequency config */
 struct ov13858_link_freq_config {
 struct ov13858_link_freq_config {
-	u32 pixel_rate;
 	u32 pixels_per_line;
 	u32 pixels_per_line;
 
 
 	/* PLL registers for this link frequency */
 	/* PLL registers for this link frequency */
@@ -238,11 +237,11 @@ static const struct ov13858_reg mode_4224x3136_regs[] = {
 	{0x3800, 0x00},
 	{0x3800, 0x00},
 	{0x3801, 0x00},
 	{0x3801, 0x00},
 	{0x3802, 0x00},
 	{0x3802, 0x00},
-	{0x3803, 0x00},
+	{0x3803, 0x08},
 	{0x3804, 0x10},
 	{0x3804, 0x10},
 	{0x3805, 0x9f},
 	{0x3805, 0x9f},
 	{0x3806, 0x0c},
 	{0x3806, 0x0c},
-	{0x3807, 0x5f},
+	{0x3807, 0x57},
 	{0x3808, 0x10},
 	{0x3808, 0x10},
 	{0x3809, 0x80},
 	{0x3809, 0x80},
 	{0x380a, 0x0c},
 	{0x380a, 0x0c},
@@ -948,6 +947,18 @@ static const char * const ov13858_test_pattern_menu[] = {
 #define OV13858_LINK_FREQ_INDEX_0	0
 #define OV13858_LINK_FREQ_INDEX_0	0
 #define OV13858_LINK_FREQ_INDEX_1	1
 #define OV13858_LINK_FREQ_INDEX_1	1
 
 
+/*
+ * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
+ * data rate => double data rate; number of lanes => 4; bits per pixel => 10
+ */
+static u64 link_freq_to_pixel_rate(u64 f)
+{
+	f *= 2 * 4;
+	do_div(f, 10);
+
+	return f;
+}
+
 /* Menu items for LINK_FREQ V4L2 control */
 /* Menu items for LINK_FREQ V4L2 control */
 static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = {
 static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = {
 	OV13858_LINK_FREQ_540MHZ,
 	OV13858_LINK_FREQ_540MHZ,
@@ -958,8 +969,6 @@ static const s64 link_freq_menu_items[OV13858_NUM_OF_LINK_FREQS] = {
 static const struct ov13858_link_freq_config
 static const struct ov13858_link_freq_config
 			link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = {
 			link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = {
 	{
 	{
-		/* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
-		.pixel_rate = (OV13858_LINK_FREQ_540MHZ * 2 * 4) / 10,
 		.pixels_per_line = OV13858_PPL_540MHZ,
 		.pixels_per_line = OV13858_PPL_540MHZ,
 		.reg_list = {
 		.reg_list = {
 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps),
 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps),
@@ -967,8 +976,6 @@ static const struct ov13858_link_freq_config
 		}
 		}
 	},
 	},
 	{
 	{
-		/* pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
-		.pixel_rate = (OV13858_LINK_FREQ_270MHZ * 2 * 4) / 10,
 		.pixels_per_line = OV13858_PPL_270MHZ,
 		.pixels_per_line = OV13858_PPL_270MHZ,
 		.reg_list = {
 		.reg_list = {
 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps),
 			.num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps),
@@ -1385,6 +1392,8 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
 	s32 vblank_def;
 	s32 vblank_def;
 	s32 vblank_min;
 	s32 vblank_min;
 	s64 h_blank;
 	s64 h_blank;
+	s64 pixel_rate;
+	s64 link_freq;
 
 
 	mutex_lock(&ov13858->mutex);
 	mutex_lock(&ov13858->mutex);
 
 
@@ -1400,9 +1409,10 @@ ov13858_set_pad_format(struct v4l2_subdev *sd,
 	} else {
 	} else {
 		ov13858->cur_mode = mode;
 		ov13858->cur_mode = mode;
 		__v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index);
 		__v4l2_ctrl_s_ctrl(ov13858->link_freq, mode->link_freq_index);
-		__v4l2_ctrl_s_ctrl_int64(
-			ov13858->pixel_rate,
-			link_freq_configs[mode->link_freq_index].pixel_rate);
+		link_freq = link_freq_menu_items[mode->link_freq_index];
+		pixel_rate = link_freq_to_pixel_rate(link_freq);
+		__v4l2_ctrl_s_ctrl_int64(ov13858->pixel_rate, pixel_rate);
+
 		/* Update limits and set FPS to default */
 		/* Update limits and set FPS to default */
 		vblank_def = ov13858->cur_mode->vts_def -
 		vblank_def = ov13858->cur_mode->vts_def -
 			     ov13858->cur_mode->height;
 			     ov13858->cur_mode->height;
@@ -1617,6 +1627,10 @@ static int ov13858_init_controls(struct ov13858 *ov13858)
 	s64 exposure_max;
 	s64 exposure_max;
 	s64 vblank_def;
 	s64 vblank_def;
 	s64 vblank_min;
 	s64 vblank_min;
+	s64 hblank;
+	s64 pixel_rate_min;
+	s64 pixel_rate_max;
+	const struct ov13858_mode *mode;
 	int ret;
 	int ret;
 
 
 	ctrl_hdlr = &ov13858->ctrl_handler;
 	ctrl_hdlr = &ov13858->ctrl_handler;
@@ -1634,29 +1648,30 @@ static int ov13858_init_controls(struct ov13858 *ov13858)
 				link_freq_menu_items);
 				link_freq_menu_items);
 	ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 
+	pixel_rate_max = link_freq_to_pixel_rate(link_freq_menu_items[0]);
+	pixel_rate_min = link_freq_to_pixel_rate(link_freq_menu_items[1]);
 	/* By default, PIXEL_RATE is read only */
 	/* By default, PIXEL_RATE is read only */
 	ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops,
 	ov13858->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov13858_ctrl_ops,
-					V4L2_CID_PIXEL_RATE, 0,
-					link_freq_configs[0].pixel_rate, 1,
-					link_freq_configs[0].pixel_rate);
+						V4L2_CID_PIXEL_RATE,
+						pixel_rate_min, pixel_rate_max,
+						1, pixel_rate_max);
 
 
-	vblank_def = ov13858->cur_mode->vts_def - ov13858->cur_mode->height;
-	vblank_min = ov13858->cur_mode->vts_min - ov13858->cur_mode->height;
+	mode = ov13858->cur_mode;
+	vblank_def = mode->vts_def - mode->height;
+	vblank_min = mode->vts_min - mode->height;
 	ov13858->vblank = v4l2_ctrl_new_std(
 	ov13858->vblank = v4l2_ctrl_new_std(
 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK,
 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_VBLANK,
-				vblank_min,
-				OV13858_VTS_MAX - ov13858->cur_mode->height, 1,
+				vblank_min, OV13858_VTS_MAX - mode->height, 1,
 				vblank_def);
 				vblank_def);
 
 
+	hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
+		 mode->width;
 	ov13858->hblank = v4l2_ctrl_new_std(
 	ov13858->hblank = v4l2_ctrl_new_std(
 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK,
 				ctrl_hdlr, &ov13858_ctrl_ops, V4L2_CID_HBLANK,
-				OV13858_PPL_540MHZ - ov13858->cur_mode->width,
-				OV13858_PPL_540MHZ - ov13858->cur_mode->width,
-				1,
-				OV13858_PPL_540MHZ - ov13858->cur_mode->width);
+				hblank, hblank, 1, hblank);
 	ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 	ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
 
 
-	exposure_max = ov13858->cur_mode->vts_def - 8;
+	exposure_max = mode->vts_def - 8;
 	ov13858->exposure = v4l2_ctrl_new_std(
 	ov13858->exposure = v4l2_ctrl_new_std(
 				ctrl_hdlr, &ov13858_ctrl_ops,
 				ctrl_hdlr, &ov13858_ctrl_ops,
 				V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN,
 				V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN,
@@ -1746,7 +1761,7 @@ static int ov13858_probe(struct i2c_client *client,
 		goto error_handler_free;
 		goto error_handler_free;
 	}
 	}
 
 
-	ret = v4l2_async_register_subdev(&ov13858->sd);
+	ret = v4l2_async_register_subdev_sensor_common(&ov13858->sd);
 	if (ret < 0)
 	if (ret < 0)
 		goto error_media_entity;
 		goto error_media_entity;
 
 

+ 8 - 9
drivers/media/i2c/ov2640.c

@@ -685,7 +685,7 @@ static int ov2640_mask_set(struct i2c_client *client,
 static int ov2640_reset(struct i2c_client *client)
 static int ov2640_reset(struct i2c_client *client)
 {
 {
 	int ret;
 	int ret;
-	const struct regval_list reset_seq[] = {
+	static const struct regval_list reset_seq[] = {
 		{BANK_SEL, BANK_SEL_SENS},
 		{BANK_SEL, BANK_SEL_SENS},
 		{COM7, COM7_SRST},
 		{COM7, COM7_SRST},
 		ENDMARKER,
 		ENDMARKER,
@@ -1097,18 +1097,17 @@ static int ov2640_probe(struct i2c_client *client,
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
-	priv = devm_kzalloc(&client->dev, sizeof(struct ov2640_priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&adapter->dev,
-			"Failed to allocate memory for private data!\n");
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	if (client->dev.of_node) {
 	if (client->dev.of_node) {
 		priv->clk = devm_clk_get(&client->dev, "xvclk");
 		priv->clk = devm_clk_get(&client->dev, "xvclk");
 		if (IS_ERR(priv->clk))
 		if (IS_ERR(priv->clk))
-			return -EPROBE_DEFER;
-		clk_prepare_enable(priv->clk);
+			return PTR_ERR(priv->clk);
+		ret = clk_prepare_enable(priv->clk);
+		if (ret)
+			return ret;
 	}
 	}
 
 
 	ret = ov2640_probe_dt(client, priv);
 	ret = ov2640_probe_dt(client, priv);
@@ -1116,7 +1115,7 @@ static int ov2640_probe(struct i2c_client *client,
 		goto err_clk;
 		goto err_clk;
 
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov2640_subdev_ops);
-	priv->subdev.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+	priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	v4l2_ctrl_handler_init(&priv->hdl, 2);
 	v4l2_ctrl_handler_init(&priv->hdl, 2);
 	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
 	v4l2_ctrl_new_std(&priv->hdl, &ov2640_ctrl_ops,
 			V4L2_CID_VFLIP, 0, 1, 1, 0);
 			V4L2_CID_VFLIP, 0, 1, 1, 0);

+ 1 - 1
drivers/media/i2c/ov5640.c

@@ -2271,7 +2271,7 @@ static int ov5640_probe(struct i2c_client *client,
 
 
 	v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops);
 	v4l2_i2c_subdev_init(&sensor->sd, client, &ov5640_subdev_ops);
 
 
-	sensor->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
 	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
 	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
 	sensor->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
 	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);
 	ret = media_entity_pads_init(&sensor->sd.entity, 1, &sensor->pad);

+ 36 - 15
drivers/media/i2c/ov5647.c

@@ -35,9 +35,18 @@
 
 
 #define SENSOR_NAME "ov5647"
 #define SENSOR_NAME "ov5647"
 
 
-#define OV5647_SW_RESET		0x0103
-#define OV5647_REG_CHIPID_H	0x300A
-#define OV5647_REG_CHIPID_L	0x300B
+#define MIPI_CTRL00_CLOCK_LANE_GATE		BIT(5)
+#define MIPI_CTRL00_BUS_IDLE			BIT(2)
+#define MIPI_CTRL00_CLOCK_LANE_DISABLE		BIT(0)
+
+#define OV5647_SW_STANDBY		0x0100
+#define OV5647_SW_RESET			0x0103
+#define OV5647_REG_CHIPID_H		0x300A
+#define OV5647_REG_CHIPID_L		0x300B
+#define OV5640_REG_PAD_OUT		0x300D
+#define OV5647_REG_FRAME_OFF_NUMBER	0x4202
+#define OV5647_REG_MIPI_CTRL00		0x4800
+#define OV5647_REG_MIPI_CTRL14		0x4814
 
 
 #define REG_TERM 0xfffe
 #define REG_TERM 0xfffe
 #define VAL_TERM 0xfe
 #define VAL_TERM 0xfe
@@ -241,34 +250,43 @@ static int ov5647_set_virtual_channel(struct v4l2_subdev *sd, int channel)
 	u8 channel_id;
 	u8 channel_id;
 	int ret;
 	int ret;
 
 
-	ret = ov5647_read(sd, 0x4814, &channel_id);
+	ret = ov5647_read(sd, OV5647_REG_MIPI_CTRL14, &channel_id);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
 	channel_id &= ~(3 << 6);
 	channel_id &= ~(3 << 6);
-	return ov5647_write(sd, 0x4814, channel_id | (channel << 6));
+	return ov5647_write(sd, OV5647_REG_MIPI_CTRL14, channel_id | (channel << 6));
 }
 }
 
 
 static int ov5647_stream_on(struct v4l2_subdev *sd)
 static int ov5647_stream_on(struct v4l2_subdev *sd)
 {
 {
 	int ret;
 	int ret;
 
 
-	ret = ov5647_write(sd, 0x4202, 0x00);
+	ret = ov5647_write(sd, OV5647_REG_MIPI_CTRL00, MIPI_CTRL00_BUS_IDLE);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	return ov5647_write(sd, 0x300D, 0x00);
+	ret = ov5647_write(sd, OV5647_REG_FRAME_OFF_NUMBER, 0x00);
+	if (ret < 0)
+		return ret;
+
+	return ov5647_write(sd, OV5640_REG_PAD_OUT, 0x00);
 }
 }
 
 
 static int ov5647_stream_off(struct v4l2_subdev *sd)
 static int ov5647_stream_off(struct v4l2_subdev *sd)
 {
 {
 	int ret;
 	int ret;
 
 
-	ret = ov5647_write(sd, 0x4202, 0x0f);
+	ret = ov5647_write(sd, OV5647_REG_MIPI_CTRL00, MIPI_CTRL00_CLOCK_LANE_GATE
+			   | MIPI_CTRL00_BUS_IDLE | MIPI_CTRL00_CLOCK_LANE_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	ret = ov5647_write(sd, OV5647_REG_FRAME_OFF_NUMBER, 0x0f);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	return ov5647_write(sd, 0x300D, 0x01);
+	return ov5647_write(sd, OV5640_REG_PAD_OUT, 0x01);
 }
 }
 
 
 static int set_sw_standby(struct v4l2_subdev *sd, bool standby)
 static int set_sw_standby(struct v4l2_subdev *sd, bool standby)
@@ -276,7 +294,7 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby)
 	int ret;
 	int ret;
 	u8 rdval;
 	u8 rdval;
 
 
-	ret = ov5647_read(sd, 0x0100, &rdval);
+	ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -285,7 +303,7 @@ static int set_sw_standby(struct v4l2_subdev *sd, bool standby)
 	else
 	else
 		rdval |= 0x01;
 		rdval |= 0x01;
 
 
-	return ov5647_write(sd, 0x0100, rdval);
+	return ov5647_write(sd, OV5647_SW_STANDBY, rdval);
 }
 }
 
 
 static int __sensor_init(struct v4l2_subdev *sd)
 static int __sensor_init(struct v4l2_subdev *sd)
@@ -294,7 +312,7 @@ static int __sensor_init(struct v4l2_subdev *sd)
 	u8 resetval, rdval;
 	u8 resetval, rdval;
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
 
-	ret = ov5647_read(sd, 0x0100, &rdval);
+	ret = ov5647_read(sd, OV5647_SW_STANDBY, &rdval);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
@@ -309,18 +327,21 @@ static int __sensor_init(struct v4l2_subdev *sd)
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
-	ret = ov5647_read(sd, 0x0100, &resetval);
+	ret = ov5647_read(sd, OV5647_SW_STANDBY, &resetval);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 
 	if (!(resetval & 0x01)) {
 	if (!(resetval & 0x01)) {
 		dev_err(&client->dev, "Device was in SW standby");
 		dev_err(&client->dev, "Device was in SW standby");
-		ret = ov5647_write(sd, 0x0100, 0x01);
+		ret = ov5647_write(sd, OV5647_SW_STANDBY, 0x01);
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
 	}
 	}
 
 
-	return ov5647_write(sd, 0x4800, 0x04);
+	/*
+	 * stream off to make the clock lane into LP-11 state.
+	 */
+	return ov5647_stream_off(sd);
 }
 }
 
 
 static int ov5647_sensor_power(struct v4l2_subdev *sd, int on)
 static int ov5647_sensor_power(struct v4l2_subdev *sd, int on)

+ 26 - 11
drivers/media/i2c/ov5670.c

@@ -390,7 +390,10 @@ static const struct ov5670_reg mode_2592x1944_regs[] = {
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
 	{0x5794, 0xa3},
 	{0x5794, 0xa3},
-	{0x3503, 0x00}
+	{0x3503, 0x00},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const struct ov5670_reg mode_1296x972_regs[] = {
 static const struct ov5670_reg mode_1296x972_regs[] = {
@@ -653,7 +656,10 @@ static const struct ov5670_reg mode_1296x972_regs[] = {
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
 	{0x5794, 0xa3},
 	{0x5794, 0xa3},
-	{0x3503, 0x00}
+	{0x3503, 0x00},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const struct ov5670_reg mode_648x486_regs[] = {
 static const struct ov5670_reg mode_648x486_regs[] = {
@@ -916,7 +922,10 @@ static const struct ov5670_reg mode_648x486_regs[] = {
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
 	{0x5794, 0xa3},
 	{0x5794, 0xa3},
-	{0x3503, 0x00}
+	{0x3503, 0x00},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const struct ov5670_reg mode_2560x1440_regs[] = {
 static const struct ov5670_reg mode_2560x1440_regs[] = {
@@ -1178,7 +1187,10 @@ static const struct ov5670_reg mode_2560x1440_regs[] = {
 	{0x5791, 0x06},
 	{0x5791, 0x06},
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
-	{0x5794, 0xa3}
+	{0x5794, 0xa3},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const struct ov5670_reg mode_1280x720_regs[] = {
 static const struct ov5670_reg mode_1280x720_regs[] = {
@@ -1441,7 +1453,10 @@ static const struct ov5670_reg mode_1280x720_regs[] = {
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
 	{0x5794, 0xa3},
 	{0x5794, 0xa3},
-	{0x3503, 0x00}
+	{0x3503, 0x00},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const struct ov5670_reg mode_640x360_regs[] = {
 static const struct ov5670_reg mode_640x360_regs[] = {
@@ -1704,7 +1719,10 @@ static const struct ov5670_reg mode_640x360_regs[] = {
 	{0x5792, 0x00},
 	{0x5792, 0x00},
 	{0x5793, 0x52},
 	{0x5793, 0x52},
 	{0x5794, 0xa3},
 	{0x5794, 0xa3},
-	{0x3503, 0x00}
+	{0x3503, 0x00},
+	{0x5045, 0x05},
+	{0x4003, 0x40},
+	{0x5048, 0x40}
 };
 };
 
 
 static const char * const ov5670_test_pattern_menu[] = {
 static const char * const ov5670_test_pattern_menu[] = {
@@ -2323,8 +2341,6 @@ static int ov5670_start_streaming(struct ov5670 *ov5670)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	ov5670->streaming = true;
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2338,8 +2354,6 @@ static int ov5670_stop_streaming(struct ov5670 *ov5670)
 	if (ret)
 	if (ret)
 		dev_err(&client->dev, "%s failed to set stream\n", __func__);
 		dev_err(&client->dev, "%s failed to set stream\n", __func__);
 
 
-	ov5670->streaming = false;
-
 	/* Return success even if it was an error, as there is nothing the
 	/* Return success even if it was an error, as there is nothing the
 	 * caller can do about it.
 	 * caller can do about it.
 	 */
 	 */
@@ -2370,6 +2384,7 @@ static int ov5670_set_stream(struct v4l2_subdev *sd, int enable)
 		ret = ov5670_stop_streaming(ov5670);
 		ret = ov5670_stop_streaming(ov5670);
 		pm_runtime_put(&client->dev);
 		pm_runtime_put(&client->dev);
 	}
 	}
+	ov5670->streaming = enable;
 	goto unlock_and_return;
 	goto unlock_and_return;
 
 
 error:
 error:
@@ -2514,7 +2529,7 @@ static int ov5670_probe(struct i2c_client *client)
 	}
 	}
 
 
 	/* Async register for subdev */
 	/* Async register for subdev */
-	ret = v4l2_async_register_subdev(&ov5670->sd);
+	ret = v4l2_async_register_subdev_sensor_common(&ov5670->sd);
 	if (ret < 0) {
 	if (ret < 0) {
 		err_msg = "v4l2_async_register_subdev() error";
 		err_msg = "v4l2_async_register_subdev() error";
 		goto error_entity_cleanup;
 		goto error_entity_cleanup;

+ 1 - 4
drivers/media/i2c/ov6650.c

@@ -951,11 +951,8 @@ static int ov6650_probe(struct i2c_client *client,
 	int ret;
 	int ret;
 
 
 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&client->dev,
-			"Failed to allocate memory for private data!\n");
+	if (!priv)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops);
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov6650_subdev_ops);
 	v4l2_ctrl_handler_init(&priv->hdl, 13);
 	v4l2_ctrl_handler_init(&priv->hdl, 13);

+ 122 - 7
drivers/media/i2c/ov7670.c

@@ -213,6 +213,9 @@ struct ov7670_devtype {
 struct ov7670_format_struct;  /* coming later */
 struct ov7670_format_struct;  /* coming later */
 struct ov7670_info {
 struct ov7670_info {
 	struct v4l2_subdev sd;
 	struct v4l2_subdev sd;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct media_pad pad;
+#endif
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_ctrl_handler hdl;
 	struct {
 	struct {
 		/* gain cluster */
 		/* gain cluster */
@@ -229,6 +232,7 @@ struct ov7670_info {
 		struct v4l2_ctrl *saturation;
 		struct v4l2_ctrl *saturation;
 		struct v4l2_ctrl *hue;
 		struct v4l2_ctrl *hue;
 	};
 	};
+	struct v4l2_mbus_framefmt format;
 	struct ov7670_format_struct *fmt;  /* Current format */
 	struct ov7670_format_struct *fmt;  /* Current format */
 	struct clk *clk;
 	struct clk *clk;
 	struct gpio_desc *resetb_gpio;
 	struct gpio_desc *resetb_gpio;
@@ -972,6 +976,9 @@ static int ov7670_try_fmt_internal(struct v4l2_subdev *sd,
 	fmt->width = wsize->width;
 	fmt->width = wsize->width;
 	fmt->height = wsize->height;
 	fmt->height = wsize->height;
 	fmt->colorspace = ov7670_formats[index].colorspace;
 	fmt->colorspace = ov7670_formats[index].colorspace;
+
+	info->format = *fmt;
+
 	return 0;
 	return 0;
 }
 }
 
 
@@ -985,6 +992,9 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
 	struct ov7670_format_struct *ovfmt;
 	struct ov7670_format_struct *ovfmt;
 	struct ov7670_win_size *wsize;
 	struct ov7670_win_size *wsize;
 	struct ov7670_info *info = to_state(sd);
 	struct ov7670_info *info = to_state(sd);
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+	struct v4l2_mbus_framefmt *mbus_fmt;
+#endif
 	unsigned char com7;
 	unsigned char com7;
 	int ret;
 	int ret;
 
 
@@ -995,8 +1005,13 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
 		ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL);
 		ret = ov7670_try_fmt_internal(sd, &format->format, NULL, NULL);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
-		cfg->try_fmt = format->format;
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+		mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, format->pad);
+		*mbus_fmt = format->format;
 		return 0;
 		return 0;
+#else
+		return -ENOTTY;
+#endif
 	}
 	}
 
 
 	ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize);
 	ret = ov7670_try_fmt_internal(sd, &format->format, &ovfmt, &wsize);
@@ -1038,6 +1053,30 @@ static int ov7670_set_fmt(struct v4l2_subdev *sd,
 	return 0;
 	return 0;
 }
 }
 
 
+static int ov7670_get_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *format)
+{
+	struct ov7670_info *info = to_state(sd);
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+	struct v4l2_mbus_framefmt *mbus_fmt;
+#endif
+
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+		mbus_fmt = v4l2_subdev_get_try_format(sd, cfg, 0);
+		format->format = *mbus_fmt;
+		return 0;
+#else
+		return -ENOTTY;
+#endif
+	} else {
+		format->format = info->format;
+	}
+
+	return 0;
+}
+
 /*
 /*
  * Implement G/S_PARM.  There is a "high quality" mode we could try
  * Implement G/S_PARM.  There is a "high quality" mode we could try
  * to do someday; for now, we just do the frame rate tweak.
  * to do someday; for now, we just do the frame rate tweak.
@@ -1505,6 +1544,46 @@ static int ov7670_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regis
 }
 }
 #endif
 #endif
 
 
+static int ov7670_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct ov7670_info *info = to_state(sd);
+
+	if (info->pwdn_gpio)
+		gpiod_set_value(info->pwdn_gpio, !on);
+	if (on && info->resetb_gpio) {
+		gpiod_set_value(info->resetb_gpio, 1);
+		usleep_range(500, 1000);
+		gpiod_set_value(info->resetb_gpio, 0);
+		usleep_range(3000, 5000);
+	}
+
+	return 0;
+}
+
+static void ov7670_get_default_format(struct v4l2_subdev *sd,
+				      struct v4l2_mbus_framefmt *format)
+{
+	struct ov7670_info *info = to_state(sd);
+
+	format->width = info->devtype->win_sizes[0].width;
+	format->height = info->devtype->win_sizes[0].height;
+	format->colorspace = info->fmt->colorspace;
+	format->code = info->fmt->mbus_code;
+	format->field = V4L2_FIELD_NONE;
+}
+
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+static int ov7670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format =
+				v4l2_subdev_get_try_format(sd, fh->pad, 0);
+
+	ov7670_get_default_format(sd, format);
+
+	return 0;
+}
+#endif
+
 /* ----------------------------------------------------------------------- */
 /* ----------------------------------------------------------------------- */
 
 
 static const struct v4l2_subdev_core_ops ov7670_core_ops = {
 static const struct v4l2_subdev_core_ops ov7670_core_ops = {
@@ -1525,6 +1604,7 @@ static const struct v4l2_subdev_pad_ops ov7670_pad_ops = {
 	.enum_frame_interval = ov7670_enum_frame_interval,
 	.enum_frame_interval = ov7670_enum_frame_interval,
 	.enum_frame_size = ov7670_enum_frame_size,
 	.enum_frame_size = ov7670_enum_frame_size,
 	.enum_mbus_code = ov7670_enum_mbus_code,
 	.enum_mbus_code = ov7670_enum_mbus_code,
+	.get_fmt = ov7670_get_fmt,
 	.set_fmt = ov7670_set_fmt,
 	.set_fmt = ov7670_set_fmt,
 };
 };
 
 
@@ -1534,6 +1614,12 @@ static const struct v4l2_subdev_ops ov7670_ops = {
 	.pad = &ov7670_pad_ops,
 	.pad = &ov7670_pad_ops,
 };
 };
 
 
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+static const struct v4l2_subdev_internal_ops ov7670_subdev_internal_ops = {
+	.open = ov7670_open,
+};
+#endif
+
 /* ----------------------------------------------------------------------- */
 /* ----------------------------------------------------------------------- */
 
 
 static const struct ov7670_devtype ov7670_devdata[] = {
 static const struct ov7670_devtype ov7670_devdata[] = {
@@ -1586,6 +1672,11 @@ static int ov7670_probe(struct i2c_client *client,
 	sd = &info->sd;
 	sd = &info->sd;
 	v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
 	v4l2_i2c_subdev_init(sd, client, &ov7670_ops);
 
 
+#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
+	sd->internal_ops = &ov7670_subdev_internal_ops;
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+#endif
+
 	info->clock_speed = 30; /* default: a guess */
 	info->clock_speed = 30; /* default: a guess */
 	if (client->dev.platform_data) {
 	if (client->dev.platform_data) {
 		struct ov7670_config *config = client->dev.platform_data;
 		struct ov7670_config *config = client->dev.platform_data;
@@ -1619,29 +1710,34 @@ static int ov7670_probe(struct i2c_client *client,
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
-	ret = ov7670_init_gpio(client, info);
-	if (ret)
-		goto clk_disable;
-
 	info->clock_speed = clk_get_rate(info->clk) / 1000000;
 	info->clock_speed = clk_get_rate(info->clk) / 1000000;
 	if (info->clock_speed < 10 || info->clock_speed > 48) {
 	if (info->clock_speed < 10 || info->clock_speed > 48) {
 		ret = -EINVAL;
 		ret = -EINVAL;
 		goto clk_disable;
 		goto clk_disable;
 	}
 	}
 
 
+	ret = ov7670_init_gpio(client, info);
+	if (ret)
+		goto clk_disable;
+
+	ov7670_s_power(sd, 1);
+
 	/* Make sure it's an ov7670 */
 	/* Make sure it's an ov7670 */
 	ret = ov7670_detect(sd);
 	ret = ov7670_detect(sd);
 	if (ret) {
 	if (ret) {
 		v4l_dbg(1, debug, client,
 		v4l_dbg(1, debug, client,
 			"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
 			"chip found @ 0x%x (%s) is not an ov7670 chip.\n",
 			client->addr << 1, client->adapter->name);
 			client->addr << 1, client->adapter->name);
-		goto clk_disable;
+		goto power_off;
 	}
 	}
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 			client->addr << 1, client->adapter->name);
 			client->addr << 1, client->adapter->name);
 
 
 	info->devtype = &ov7670_devdata[id->driver_data];
 	info->devtype = &ov7670_devdata[id->driver_data];
 	info->fmt = &ov7670_formats[0];
 	info->fmt = &ov7670_formats[0];
+
+	ov7670_get_default_format(sd, &info->format);
+
 	info->clkrc = 0;
 	info->clkrc = 0;
 
 
 	/* Set default frame rate to 30 fps */
 	/* Set default frame rate to 30 fps */
@@ -1688,16 +1784,31 @@ static int ov7670_probe(struct i2c_client *client,
 	v4l2_ctrl_auto_cluster(2, &info->auto_exposure,
 	v4l2_ctrl_auto_cluster(2, &info->auto_exposure,
 			       V4L2_EXPOSURE_MANUAL, false);
 			       V4L2_EXPOSURE_MANUAL, false);
 	v4l2_ctrl_cluster(2, &info->saturation);
 	v4l2_ctrl_cluster(2, &info->saturation);
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	info->pad.flags = MEDIA_PAD_FL_SOURCE;
+	info->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	ret = media_entity_pads_init(&info->sd.entity, 1, &info->pad);
+	if (ret < 0)
+		goto hdl_free;
+#endif
+
 	v4l2_ctrl_handler_setup(&info->hdl);
 	v4l2_ctrl_handler_setup(&info->hdl);
 
 
 	ret = v4l2_async_register_subdev(&info->sd);
 	ret = v4l2_async_register_subdev(&info->sd);
 	if (ret < 0)
 	if (ret < 0)
-		goto hdl_free;
+		goto entity_cleanup;
 
 
 	return 0;
 	return 0;
 
 
+entity_cleanup:
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	media_entity_cleanup(&info->sd.entity);
+#endif
 hdl_free:
 hdl_free:
 	v4l2_ctrl_handler_free(&info->hdl);
 	v4l2_ctrl_handler_free(&info->hdl);
+power_off:
+	ov7670_s_power(sd, 0);
 clk_disable:
 clk_disable:
 	clk_disable_unprepare(info->clk);
 	clk_disable_unprepare(info->clk);
 	return ret;
 	return ret;
@@ -1712,6 +1823,10 @@ static int ov7670_remove(struct i2c_client *client)
 	v4l2_device_unregister_subdev(sd);
 	v4l2_device_unregister_subdev(sd);
 	v4l2_ctrl_handler_free(&info->hdl);
 	v4l2_ctrl_handler_free(&info->hdl);
 	clk_disable_unprepare(info->clk);
 	clk_disable_unprepare(info->clk);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	media_entity_cleanup(&info->sd.entity);
+#endif
+	ov7670_s_power(sd, 0);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 1
drivers/media/i2c/ov9650.c

@@ -985,7 +985,6 @@ static const struct v4l2_ctrl_ops ov965x_ctrl_ops = {
 static const char * const test_pattern_menu[] = {
 static const char * const test_pattern_menu[] = {
 	"Disabled",
 	"Disabled",
 	"Color bars",
 	"Color bars",
-	NULL
 };
 };
 
 
 static int ov965x_initialize_controls(struct ov965x *ov965x)
 static int ov965x_initialize_controls(struct ov965x *ov965x)

+ 75 - 74
drivers/media/i2c/smiapp/smiapp-core.c

@@ -1239,6 +1239,10 @@ static int smiapp_power_on(struct device *dev)
 	sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk);
 	sleep = SMIAPP_RESET_DELAY(sensor->hwcfg->ext_clk);
 	usleep_range(sleep, sleep);
 	usleep_range(sleep, sleep);
 
 
+	mutex_lock(&sensor->mutex);
+
+	sensor->active = true;
+
 	/*
 	/*
 	 * Failures to respond to the address change command have been noticed.
 	 * Failures to respond to the address change command have been noticed.
 	 * Those failures seem to be caused by the sensor requiring a longer
 	 * Those failures seem to be caused by the sensor requiring a longer
@@ -1313,7 +1317,7 @@ static int smiapp_power_on(struct device *dev)
 	rval = smiapp_write(sensor, SMIAPP_REG_U8_DPHY_CTRL,
 	rval = smiapp_write(sensor, SMIAPP_REG_U8_DPHY_CTRL,
 			    SMIAPP_DPHY_CTRL_UI);
 			    SMIAPP_DPHY_CTRL_UI);
 	if (rval < 0)
 	if (rval < 0)
-		return rval;
+		goto out_cci_addr_fail;
 
 
 	rval = smiapp_call_quirk(sensor, post_poweron);
 	rval = smiapp_call_quirk(sensor, post_poweron);
 	if (rval) {
 	if (rval) {
@@ -1321,28 +1325,28 @@ static int smiapp_power_on(struct device *dev)
 		goto out_cci_addr_fail;
 		goto out_cci_addr_fail;
 	}
 	}
 
 
-	/* Are we still initialising...? If yes, return here. */
-	if (!sensor->pixel_array)
-		return 0;
+	/* Are we still initialising...? If not, proceed with control setup. */
+	if (sensor->pixel_array) {
+		rval = __v4l2_ctrl_handler_setup(
+			&sensor->pixel_array->ctrl_handler);
+		if (rval)
+			goto out_cci_addr_fail;
 
 
-	rval = v4l2_ctrl_handler_setup(&sensor->pixel_array->ctrl_handler);
-	if (rval)
-		goto out_cci_addr_fail;
+		rval = __v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
+		if (rval)
+			goto out_cci_addr_fail;
 
 
-	rval = v4l2_ctrl_handler_setup(&sensor->src->ctrl_handler);
-	if (rval)
-		goto out_cci_addr_fail;
+		rval = smiapp_update_mode(sensor);
+		if (rval < 0)
+			goto out_cci_addr_fail;
+	}
 
 
-	mutex_lock(&sensor->mutex);
-	rval = smiapp_update_mode(sensor);
 	mutex_unlock(&sensor->mutex);
 	mutex_unlock(&sensor->mutex);
-	if (rval < 0)
-		goto out_cci_addr_fail;
 
 
 	return 0;
 	return 0;
 
 
 out_cci_addr_fail:
 out_cci_addr_fail:
-
+	mutex_unlock(&sensor->mutex);
 	gpiod_set_value(sensor->xshutdown, 0);
 	gpiod_set_value(sensor->xshutdown, 0);
 	clk_disable_unprepare(sensor->ext_clk);
 	clk_disable_unprepare(sensor->ext_clk);
 
 
@@ -1360,6 +1364,8 @@ static int smiapp_power_off(struct device *dev)
 	struct smiapp_sensor *sensor =
 	struct smiapp_sensor *sensor =
 		container_of(ssd, struct smiapp_sensor, ssds[0]);
 		container_of(ssd, struct smiapp_sensor, ssds[0]);
 
 
+	mutex_lock(&sensor->mutex);
+
 	/*
 	/*
 	 * Currently power/clock to lens are enable/disabled separately
 	 * Currently power/clock to lens are enable/disabled separately
 	 * but they are essentially the same signals. So if the sensor is
 	 * but they are essentially the same signals. So if the sensor is
@@ -1372,6 +1378,10 @@ static int smiapp_power_off(struct device *dev)
 			     SMIAPP_REG_U8_SOFTWARE_RESET,
 			     SMIAPP_REG_U8_SOFTWARE_RESET,
 			     SMIAPP_SOFTWARE_RESET);
 			     SMIAPP_SOFTWARE_RESET);
 
 
+	sensor->active = false;
+
+	mutex_unlock(&sensor->mutex);
+
 	gpiod_set_value(sensor->xshutdown, 0);
 	gpiod_set_value(sensor->xshutdown, 0);
 	clk_disable_unprepare(sensor->ext_clk);
 	clk_disable_unprepare(sensor->ext_clk);
 	usleep_range(5000, 5000);
 	usleep_range(5000, 5000);
@@ -1381,29 +1391,6 @@ static int smiapp_power_off(struct device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int smiapp_set_power(struct v4l2_subdev *subdev, int on)
-{
-	int rval;
-
-	if (!on) {
-		pm_runtime_mark_last_busy(subdev->dev);
-		pm_runtime_put_autosuspend(subdev->dev);
-
-		return 0;
-	}
-
-	rval = pm_runtime_get_sync(subdev->dev);
-	if (rval >= 0)
-		return 0;
-
-	if (rval != -EBUSY && rval != -EAGAIN)
-		pm_runtime_set_active(subdev->dev);
-
-	pm_runtime_put(subdev->dev);
-
-	return rval;
-}
-
 /* -----------------------------------------------------------------------------
 /* -----------------------------------------------------------------------------
  * Video stream management
  * Video stream management
  */
  */
@@ -1560,19 +1547,31 @@ out:
 static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
 static int smiapp_set_stream(struct v4l2_subdev *subdev, int enable)
 {
 {
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
 	struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
 	int rval;
 	int rval;
 
 
 	if (sensor->streaming == enable)
 	if (sensor->streaming == enable)
 		return 0;
 		return 0;
 
 
 	if (enable) {
 	if (enable) {
+		rval = pm_runtime_get_sync(&client->dev);
+		if (rval < 0) {
+			if (rval != -EBUSY && rval != -EAGAIN)
+				pm_runtime_set_active(&client->dev);
+			pm_runtime_put(&client->dev);
+			return rval;
+		}
+
 		sensor->streaming = true;
 		sensor->streaming = true;
+
 		rval = smiapp_start_streaming(sensor);
 		rval = smiapp_start_streaming(sensor);
 		if (rval < 0)
 		if (rval < 0)
 			sensor->streaming = false;
 			sensor->streaming = false;
 	} else {
 	} else {
 		rval = smiapp_stop_streaming(sensor);
 		rval = smiapp_stop_streaming(sensor);
 		sensor->streaming = false;
 		sensor->streaming = false;
+		pm_runtime_mark_last_busy(&client->dev);
+		pm_runtime_put_autosuspend(&client->dev);
 	}
 	}
 
 
 	return rval;
 	return rval;
@@ -2650,7 +2649,6 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
 	struct smiapp_subdev *ssd = to_smiapp_subdev(sd);
 	struct smiapp_sensor *sensor = ssd->sensor;
 	struct smiapp_sensor *sensor = ssd->sensor;
 	unsigned int i;
 	unsigned int i;
-	int rval;
 
 
 	mutex_lock(&sensor->mutex);
 	mutex_lock(&sensor->mutex);
 
 
@@ -2677,22 +2675,6 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 
 
 	mutex_unlock(&sensor->mutex);
 	mutex_unlock(&sensor->mutex);
 
 
-	rval = pm_runtime_get_sync(sd->dev);
-	if (rval >= 0)
-		return 0;
-
-	if (rval != -EBUSY && rval != -EAGAIN)
-		pm_runtime_set_active(sd->dev);
-	pm_runtime_put(sd->dev);
-
-	return rval;
-}
-
-static int smiapp_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
-{
-	pm_runtime_mark_last_busy(sd->dev);
-	pm_runtime_put_autosuspend(sd->dev);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -2700,10 +2682,6 @@ static const struct v4l2_subdev_video_ops smiapp_video_ops = {
 	.s_stream = smiapp_set_stream,
 	.s_stream = smiapp_set_stream,
 };
 };
 
 
-static const struct v4l2_subdev_core_ops smiapp_core_ops = {
-	.s_power = smiapp_set_power,
-};
-
 static const struct v4l2_subdev_pad_ops smiapp_pad_ops = {
 static const struct v4l2_subdev_pad_ops smiapp_pad_ops = {
 	.enum_mbus_code = smiapp_enum_mbus_code,
 	.enum_mbus_code = smiapp_enum_mbus_code,
 	.get_fmt = smiapp_get_format,
 	.get_fmt = smiapp_get_format,
@@ -2718,7 +2696,6 @@ static const struct v4l2_subdev_sensor_ops smiapp_sensor_ops = {
 };
 };
 
 
 static const struct v4l2_subdev_ops smiapp_ops = {
 static const struct v4l2_subdev_ops smiapp_ops = {
-	.core = &smiapp_core_ops,
 	.video = &smiapp_video_ops,
 	.video = &smiapp_video_ops,
 	.pad = &smiapp_pad_ops,
 	.pad = &smiapp_pad_ops,
 	.sensor = &smiapp_sensor_ops,
 	.sensor = &smiapp_sensor_ops,
@@ -2732,12 +2709,10 @@ static const struct v4l2_subdev_internal_ops smiapp_internal_src_ops = {
 	.registered = smiapp_registered,
 	.registered = smiapp_registered,
 	.unregistered = smiapp_unregistered,
 	.unregistered = smiapp_unregistered,
 	.open = smiapp_open,
 	.open = smiapp_open,
-	.close = smiapp_close,
 };
 };
 
 
 static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
 static const struct v4l2_subdev_internal_ops smiapp_internal_ops = {
 	.open = smiapp_open,
 	.open = smiapp_open,
-	.close = smiapp_close,
 };
 };
 
 
 /* -----------------------------------------------------------------------------
 /* -----------------------------------------------------------------------------
@@ -2829,12 +2804,10 @@ static struct smiapp_hwconfig *smiapp_get_hwconfig(struct device *dev)
 	/* NVM size is not mandatory */
 	/* NVM size is not mandatory */
 	fwnode_property_read_u32(fwnode, "nokia,nvm-size", &hwcfg->nvm_size);
 	fwnode_property_read_u32(fwnode, "nokia,nvm-size", &hwcfg->nvm_size);
 
 
-	rval = fwnode_property_read_u32(fwnode, "clock-frequency",
+	rval = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
 					&hwcfg->ext_clk);
 					&hwcfg->ext_clk);
-	if (rval) {
-		dev_warn(dev, "can't get clock-frequency\n");
-		goto out_err;
-	}
+	if (rval)
+		dev_info(dev, "can't get clock-frequency\n");
 
 
 	dev_dbg(dev, "nvm %d, clk %d, mode %d\n",
 	dev_dbg(dev, "nvm %d, clk %d, mode %d\n",
 		hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode);
 		hwcfg->nvm_size, hwcfg->ext_clk, hwcfg->csi_signalling_mode);
@@ -2894,18 +2867,46 @@ static int smiapp_probe(struct i2c_client *client,
 	}
 	}
 
 
 	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
 	sensor->ext_clk = devm_clk_get(&client->dev, NULL);
-	if (IS_ERR(sensor->ext_clk)) {
+	if (PTR_ERR(sensor->ext_clk) == -ENOENT) {
+		dev_info(&client->dev, "no clock defined, continuing...\n");
+		sensor->ext_clk = NULL;
+	} else if (IS_ERR(sensor->ext_clk)) {
 		dev_err(&client->dev, "could not get clock (%ld)\n",
 		dev_err(&client->dev, "could not get clock (%ld)\n",
 			PTR_ERR(sensor->ext_clk));
 			PTR_ERR(sensor->ext_clk));
 		return -EPROBE_DEFER;
 		return -EPROBE_DEFER;
 	}
 	}
 
 
-	rval = clk_set_rate(sensor->ext_clk, sensor->hwcfg->ext_clk);
-	if (rval < 0) {
-		dev_err(&client->dev,
-			"unable to set clock freq to %u\n",
+	if (sensor->ext_clk) {
+		if (sensor->hwcfg->ext_clk) {
+			unsigned long rate;
+
+			rval = clk_set_rate(sensor->ext_clk,
+					    sensor->hwcfg->ext_clk);
+			if (rval < 0) {
+				dev_err(&client->dev,
+					"unable to set clock freq to %u\n",
+					sensor->hwcfg->ext_clk);
+				return rval;
+			}
+
+			rate = clk_get_rate(sensor->ext_clk);
+			if (rate != sensor->hwcfg->ext_clk) {
+				dev_err(&client->dev,
+					"can't set clock freq, asked for %u but got %lu\n",
+					sensor->hwcfg->ext_clk, rate);
+				return rval;
+			}
+		} else {
+			sensor->hwcfg->ext_clk = clk_get_rate(sensor->ext_clk);
+			dev_dbg(&client->dev, "obtained clock freq %u\n",
+				sensor->hwcfg->ext_clk);
+		}
+	} else if (sensor->hwcfg->ext_clk) {
+		dev_dbg(&client->dev, "assuming clock freq %u\n",
 			sensor->hwcfg->ext_clk);
 			sensor->hwcfg->ext_clk);
-		return rval;
+	} else {
+		dev_err(&client->dev, "unable to obtain clock freq\n");
+		return -EINVAL;
 	}
 	}
 
 
 	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
 	sensor->xshutdown = devm_gpiod_get_optional(&client->dev, "xshutdown",
@@ -3092,7 +3093,7 @@ static int smiapp_probe(struct i2c_client *client,
 	if (rval < 0)
 	if (rval < 0)
 		goto out_media_entity_cleanup;
 		goto out_media_entity_cleanup;
 
 
-	rval = v4l2_async_register_subdev(&sensor->src->sd);
+	rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd);
 	if (rval < 0)
 	if (rval < 0)
 		goto out_media_entity_cleanup;
 		goto out_media_entity_cleanup;
 
 

+ 3 - 0
drivers/media/i2c/smiapp/smiapp-regs.c

@@ -231,6 +231,9 @@ int smiapp_write_no_quirk(struct smiapp_sensor *sensor, u32 reg, u32 val)
 	     len != SMIAPP_REG_32BIT) || flags)
 	     len != SMIAPP_REG_32BIT) || flags)
 		return -EINVAL;
 		return -EINVAL;
 
 
+	if (!sensor->active)
+		return 0;
+
 	msg.addr = client->addr;
 	msg.addr = client->addr;
 	msg.flags = 0; /* Write */
 	msg.flags = 0; /* Write */
 	msg.len = 2 + len;
 	msg.len = 2 + len;

+ 1 - 0
drivers/media/i2c/smiapp/smiapp.h

@@ -206,6 +206,7 @@ struct smiapp_sensor {
 
 
 	u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
 	u8 hvflip_inv_mask; /* H/VFLIP inversion due to sensor orientation */
 	u8 frame_skip;
 	u8 frame_skip;
+	bool active; /* is the sensor powered on? */
 	u16 embedded_start; /* embedded data start line */
 	u16 embedded_start; /* embedded data start line */
 	u16 embedded_end;
 	u16 embedded_end;
 	u16 image_start; /* image data start line */
 	u16 image_start; /* image data start line */

+ 4 - 7
drivers/media/i2c/soc_camera/ov9640.c

@@ -335,8 +335,8 @@ static void ov9640_res_roundup(u32 *width, u32 *height)
 {
 {
 	int i;
 	int i;
 	enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA };
 	enum { QQCIF, QQVGA, QCIF, QVGA, CIF, VGA, SXGA };
-	int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 };
-	int res_y[] = { 72, 120, 144, 240, 288, 480, 960 };
+	static const int res_x[] = { 88, 160, 176, 320, 352, 640, 1280 };
+	static const int res_y[] = { 72, 120, 144, 240, 288, 480, 960 };
 
 
 	for (i = 0; i < ARRAY_SIZE(res_x); i++) {
 	for (i = 0; i < ARRAY_SIZE(res_x); i++) {
 		if (res_x[i] >= *width && res_y[i] >= *height) {
 		if (res_x[i] >= *width && res_y[i] >= *height) {
@@ -675,12 +675,9 @@ static int ov9640_probe(struct i2c_client *client,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	priv = devm_kzalloc(&client->dev, sizeof(struct ov9640_priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&client->dev,
-			"Failed to allocate memory for private data!\n");
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9640_subdev_ops);
 
 

+ 2 - 4
drivers/media/i2c/soc_camera/ov9740.c

@@ -935,11 +935,9 @@ static int ov9740_probe(struct i2c_client *client,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	priv = devm_kzalloc(&client->dev, sizeof(struct ov9740_priv), GFP_KERNEL);
-	if (!priv) {
-		dev_err(&client->dev, "Failed to allocate private data!\n");
+	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
 	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
 	v4l2_ctrl_handler_init(&priv->hdl, 13);
 	v4l2_ctrl_handler_init(&priv->hdl, 13);

+ 209 - 11
drivers/media/i2c/tc358743.c

@@ -39,6 +39,7 @@
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
 #include <linux/v4l2-dv-timings.h>
 #include <linux/v4l2-dv-timings.h>
 #include <linux/hdmi.h>
 #include <linux/hdmi.h>
+#include <media/cec.h>
 #include <media/v4l2-dv-timings.h>
 #include <media/v4l2-dv-timings.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-ctrls.h>
@@ -63,6 +64,7 @@ MODULE_LICENSE("GPL");
 
 
 #define I2C_MAX_XFER_SIZE  (EDID_BLOCK_SIZE + 2)
 #define I2C_MAX_XFER_SIZE  (EDID_BLOCK_SIZE + 2)
 
 
+#define POLL_INTERVAL_CEC_MS	10
 #define POLL_INTERVAL_MS	1000
 #define POLL_INTERVAL_MS	1000
 
 
 static const struct v4l2_dv_timings_cap tc358743_timings_cap = {
 static const struct v4l2_dv_timings_cap tc358743_timings_cap = {
@@ -106,6 +108,8 @@ struct tc358743_state {
 	u8 csi_lanes_in_use;
 	u8 csi_lanes_in_use;
 
 
 	struct gpio_desc *reset_gpio;
 	struct gpio_desc *reset_gpio;
+
+	struct cec_adapter *cec_adap;
 };
 };
 
 
 static void tc358743_enable_interrupts(struct v4l2_subdev *sd,
 static void tc358743_enable_interrupts(struct v4l2_subdev *sd,
@@ -595,6 +599,7 @@ static void tc358743_set_ref_clk(struct v4l2_subdev *sd)
 	struct tc358743_platform_data *pdata = &state->pdata;
 	struct tc358743_platform_data *pdata = &state->pdata;
 	u32 sys_freq;
 	u32 sys_freq;
 	u32 lockdet_ref;
 	u32 lockdet_ref;
+	u32 cec_freq;
 	u16 fh_min;
 	u16 fh_min;
 	u16 fh_max;
 	u16 fh_max;
 
 
@@ -626,6 +631,15 @@ static void tc358743_set_ref_clk(struct v4l2_subdev *sd)
 	i2c_wr8_and_or(sd, NCO_F0_MOD, ~MASK_NCO_F0_MOD,
 	i2c_wr8_and_or(sd, NCO_F0_MOD, ~MASK_NCO_F0_MOD,
 			(pdata->refclk_hz == 27000000) ?
 			(pdata->refclk_hz == 27000000) ?
 			MASK_NCO_F0_MOD_27MHZ : 0x0);
 			MASK_NCO_F0_MOD_27MHZ : 0x0);
+
+	/*
+	 * Trial and error suggests that the default register value
+	 * of 656 is for a 42 MHz reference clock. Use that to derive
+	 * a new value based on the actual reference clock.
+	 */
+	cec_freq = (656 * sys_freq) / 4200;
+	i2c_wr16(sd, CECHCLK, cec_freq);
+	i2c_wr16(sd, CECLCLK, cec_freq);
 }
 }
 
 
 static void tc358743_set_csi_color_space(struct v4l2_subdev *sd)
 static void tc358743_set_csi_color_space(struct v4l2_subdev *sd)
@@ -814,11 +828,17 @@ static void tc358743_initial_setup(struct v4l2_subdev *sd)
 	struct tc358743_state *state = to_state(sd);
 	struct tc358743_state *state = to_state(sd);
 	struct tc358743_platform_data *pdata = &state->pdata;
 	struct tc358743_platform_data *pdata = &state->pdata;
 
 
-	/* CEC and IR are not supported by this driver */
-	i2c_wr16_and_or(sd, SYSCTL, ~(MASK_CECRST | MASK_IRRST),
-			(MASK_CECRST | MASK_IRRST));
+	/*
+	 * IR is not supported by this driver.
+	 * CEC is only enabled if needed.
+	 */
+	i2c_wr16_and_or(sd, SYSCTL, ~(MASK_IRRST | MASK_CECRST),
+				     (MASK_IRRST | MASK_CECRST));
 
 
 	tc358743_reset(sd, MASK_CTXRST | MASK_HDMIRST);
 	tc358743_reset(sd, MASK_CTXRST | MASK_HDMIRST);
+#ifdef CONFIG_VIDEO_TC358743_CEC
+	tc358743_reset(sd, MASK_CECRST);
+#endif
 	tc358743_sleep_mode(sd, false);
 	tc358743_sleep_mode(sd, false);
 
 
 	i2c_wr16(sd, FIFOCTL, pdata->fifo_level);
 	i2c_wr16(sd, FIFOCTL, pdata->fifo_level);
@@ -842,6 +862,133 @@ static void tc358743_initial_setup(struct v4l2_subdev *sd)
 	i2c_wr8(sd, VOUT_SET3, MASK_VOUT_EXTCNT);
 	i2c_wr8(sd, VOUT_SET3, MASK_VOUT_EXTCNT);
 }
 }
 
 
+/* --------------- CEC --------------- */
+
+#ifdef CONFIG_VIDEO_TC358743_CEC
+static int tc358743_cec_adap_enable(struct cec_adapter *adap, bool enable)
+{
+	struct tc358743_state *state = adap->priv;
+	struct v4l2_subdev *sd = &state->sd;
+
+	i2c_wr32(sd, CECIMSK, enable ? MASK_CECTIM | MASK_CECRIM : 0);
+	i2c_wr32(sd, CECICLR, MASK_CECTICLR | MASK_CECRICLR);
+	i2c_wr32(sd, CECEN, enable);
+	if (enable)
+		i2c_wr32(sd, CECREN, MASK_CECREN);
+	return 0;
+}
+
+static int tc358743_cec_adap_monitor_all_enable(struct cec_adapter *adap,
+						bool enable)
+{
+	struct tc358743_state *state = adap->priv;
+	struct v4l2_subdev *sd = &state->sd;
+	u32 reg;
+
+	reg = i2c_rd32(sd, CECRCTL1);
+	if (enable)
+		reg |= MASK_CECOTH;
+	else
+		reg &= ~MASK_CECOTH;
+	i2c_wr32(sd, CECRCTL1, reg);
+	return 0;
+}
+
+static int tc358743_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr)
+{
+	struct tc358743_state *state = adap->priv;
+	struct v4l2_subdev *sd = &state->sd;
+	unsigned int la = 0;
+
+	if (log_addr != CEC_LOG_ADDR_INVALID) {
+		la = i2c_rd32(sd, CECADD);
+		la |= 1 << log_addr;
+	}
+	i2c_wr32(sd, CECADD, la);
+	return 0;
+}
+
+static int tc358743_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
+				   u32 signal_free_time, struct cec_msg *msg)
+{
+	struct tc358743_state *state = adap->priv;
+	struct v4l2_subdev *sd = &state->sd;
+	unsigned int i;
+
+	i2c_wr32(sd, CECTCTL,
+		 (cec_msg_is_broadcast(msg) ? MASK_CECBRD : 0) |
+		 (signal_free_time - 1));
+	for (i = 0; i < msg->len; i++)
+		i2c_wr32(sd, CECTBUF1 + i * 4,
+			msg->msg[i] | ((i == msg->len - 1) ? MASK_CECTEOM : 0));
+	i2c_wr32(sd, CECTEN, MASK_CECTEN);
+	return 0;
+}
+
+static const struct cec_adap_ops tc358743_cec_adap_ops = {
+	.adap_enable = tc358743_cec_adap_enable,
+	.adap_log_addr = tc358743_cec_adap_log_addr,
+	.adap_transmit = tc358743_cec_adap_transmit,
+	.adap_monitor_all_enable = tc358743_cec_adap_monitor_all_enable,
+};
+
+static void tc358743_cec_isr(struct v4l2_subdev *sd, u16 intstatus,
+			     bool *handled)
+{
+	struct tc358743_state *state = to_state(sd);
+	unsigned int cec_rxint, cec_txint;
+	unsigned int clr = 0;
+
+	cec_rxint = i2c_rd32(sd, CECRSTAT);
+	cec_txint = i2c_rd32(sd, CECTSTAT);
+
+	if (intstatus & MASK_CEC_RINT)
+		clr |= MASK_CECRICLR;
+	if (intstatus & MASK_CEC_TINT)
+		clr |= MASK_CECTICLR;
+	i2c_wr32(sd, CECICLR, clr);
+
+	if ((intstatus & MASK_CEC_TINT) && cec_txint) {
+		if (cec_txint & MASK_CECTIEND)
+			cec_transmit_attempt_done(state->cec_adap,
+						  CEC_TX_STATUS_OK);
+		else if (cec_txint & MASK_CECTIAL)
+			cec_transmit_attempt_done(state->cec_adap,
+						  CEC_TX_STATUS_ARB_LOST);
+		else if (cec_txint & MASK_CECTIACK)
+			cec_transmit_attempt_done(state->cec_adap,
+						  CEC_TX_STATUS_NACK);
+		else if (cec_txint & MASK_CECTIUR) {
+			/*
+			 * Not sure when this bit is set. Treat
+			 * it as an error for now.
+			 */
+			cec_transmit_attempt_done(state->cec_adap,
+						  CEC_TX_STATUS_ERROR);
+		}
+		*handled = true;
+	}
+	if ((intstatus & MASK_CEC_RINT) &&
+	    (cec_rxint & MASK_CECRIEND)) {
+		struct cec_msg msg = {};
+		unsigned int i;
+		unsigned int v;
+
+		v = i2c_rd32(sd, CECRCTR);
+		msg.len = v & 0x1f;
+		for (i = 0; i < msg.len; i++) {
+			v = i2c_rd32(sd, CECRBUF1 + i * 4);
+			msg.msg[i] = v & 0xff;
+		}
+		cec_received_msg(state->cec_adap, &msg);
+		*handled = true;
+	}
+	i2c_wr16(sd, INTSTATUS,
+		 intstatus & (MASK_CEC_RINT | MASK_CEC_TINT));
+}
+
+#endif
+
 /* --------------- IRQ --------------- */
 /* --------------- IRQ --------------- */
 
 
 static void tc358743_format_change(struct v4l2_subdev *sd)
 static void tc358743_format_change(struct v4l2_subdev *sd)
@@ -1296,6 +1443,15 @@ static int tc358743_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
 		intstatus &= ~MASK_HDMI_INT;
 		intstatus &= ~MASK_HDMI_INT;
 	}
 	}
 
 
+#ifdef CONFIG_VIDEO_TC358743_CEC
+	if (intstatus & (MASK_CEC_RINT | MASK_CEC_TINT)) {
+		tc358743_cec_isr(sd, intstatus, handled);
+		i2c_wr16(sd, INTSTATUS,
+			 intstatus & (MASK_CEC_RINT | MASK_CEC_TINT));
+		intstatus &= ~(MASK_CEC_RINT | MASK_CEC_TINT);
+	}
+#endif
+
 	if (intstatus & MASK_CSI_INT) {
 	if (intstatus & MASK_CSI_INT) {
 		u32 csi_int = i2c_rd32(sd, CSI_INT);
 		u32 csi_int = i2c_rd32(sd, CSI_INT);
 
 
@@ -1325,13 +1481,18 @@ static irqreturn_t tc358743_irq_handler(int irq, void *dev_id)
 	return handled ? IRQ_HANDLED : IRQ_NONE;
 	return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 }
 
 
-static void tc358743_irq_poll_timer(unsigned long arg)
+static void tc358743_irq_poll_timer(struct timer_list *t)
 {
 {
-	struct tc358743_state *state = (struct tc358743_state *)arg;
+	struct tc358743_state *state = from_timer(state, t, timer);
+	unsigned int msecs;
 
 
 	schedule_work(&state->work_i2c_poll);
 	schedule_work(&state->work_i2c_poll);
-
-	mod_timer(&state->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
+	/*
+	 * If CEC is present, then we need to poll more frequently,
+	 * otherwise we will miss CEC messages.
+	 */
+	msecs = state->cec_adap ? POLL_INTERVAL_CEC_MS : POLL_INTERVAL_MS;
+	mod_timer(&state->timer, jiffies + msecs_to_jiffies(msecs));
 }
 }
 
 
 static void tc358743_work_i2c_poll(struct work_struct *work)
 static void tc358743_work_i2c_poll(struct work_struct *work)
@@ -1488,7 +1649,7 @@ static int tc358743_s_stream(struct v4l2_subdev *sd, int enable)
 {
 {
 	enable_stream(sd, enable);
 	enable_stream(sd, enable);
 	if (!enable) {
 	if (!enable) {
-		/* Put all lanes in PL-11 state (STOPSTATE) */
+		/* Put all lanes in LP-11 state (STOPSTATE) */
 		tc358743_set_csi(sd);
 		tc358743_set_csi(sd);
 	}
 	}
 
 
@@ -1621,6 +1782,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd,
 {
 {
 	struct tc358743_state *state = to_state(sd);
 	struct tc358743_state *state = to_state(sd);
 	u16 edid_len = edid->blocks * EDID_BLOCK_SIZE;
 	u16 edid_len = edid->blocks * EDID_BLOCK_SIZE;
+	u16 pa;
+	int err;
 	int i;
 	int i;
 
 
 	v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n",
 	v4l2_dbg(2, debug, sd, "%s, pad %d, start block %d, blocks %d\n",
@@ -1638,6 +1801,12 @@ static int tc358743_s_edid(struct v4l2_subdev *sd,
 		edid->blocks = EDID_NUM_BLOCKS_MAX;
 		edid->blocks = EDID_NUM_BLOCKS_MAX;
 		return -E2BIG;
 		return -E2BIG;
 	}
 	}
+	pa = cec_get_edid_phys_addr(edid->edid, edid->blocks * 128, NULL);
+	err = cec_phys_addr_validate(pa, &pa, NULL);
+	if (err)
+		return err;
+
+	cec_phys_addr_invalidate(state->cec_adap);
 
 
 	tc358743_disable_edid(sd);
 	tc358743_disable_edid(sd);
 
 
@@ -1654,6 +1823,8 @@ static int tc358743_s_edid(struct v4l2_subdev *sd,
 
 
 	state->edid_blocks_written = edid->blocks;
 	state->edid_blocks_written = edid->blocks;
 
 
+	cec_s_phys_addr(state->cec_adap, pa, false);
+
 	if (tx_5v_power_present(sd))
 	if (tx_5v_power_present(sd))
 		tc358743_enable_edid(sd);
 		tc358743_enable_edid(sd);
 
 
@@ -1770,6 +1941,11 @@ static int tc358743_probe_of(struct tc358743_state *state)
 		goto free_endpoint;
 		goto free_endpoint;
 	}
 	}
 
 
+	if (endpoint->bus.mipi_csi2.num_data_lanes > 4) {
+		dev_err(dev, "invalid number of lanes\n");
+		goto free_endpoint;
+	}
+
 	state->bus = endpoint->bus.mipi_csi2;
 	state->bus = endpoint->bus.mipi_csi2;
 
 
 	ret = clk_prepare_enable(refclk);
 	ret = clk_prepare_enable(refclk);
@@ -1867,6 +2043,7 @@ static int tc358743_probe(struct i2c_client *client,
 	struct tc358743_state *state;
 	struct tc358743_state *state;
 	struct tc358743_platform_data *pdata = client->dev.platform_data;
 	struct tc358743_platform_data *pdata = client->dev.platform_data;
 	struct v4l2_subdev *sd;
 	struct v4l2_subdev *sd;
+	u16 irq_mask = MASK_HDMI_MSK | MASK_CSI_MSK;
 	int err;
 	int err;
 
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -1929,6 +2106,7 @@ static int tc358743_probe(struct i2c_client *client,
 	}
 	}
 
 
 	state->pad.flags = MEDIA_PAD_FL_SOURCE;
 	state->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
 	err = media_entity_pads_init(&sd->entity, 1, &state->pad);
 	err = media_entity_pads_init(&sd->entity, 1, &state->pad);
 	if (err < 0)
 	if (err < 0)
 		goto err_hdl;
 		goto err_hdl;
@@ -1945,6 +2123,17 @@ static int tc358743_probe(struct i2c_client *client,
 	INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
 	INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
 			tc358743_delayed_work_enable_hotplug);
 			tc358743_delayed_work_enable_hotplug);
 
 
+#ifdef CONFIG_VIDEO_TC358743_CEC
+	state->cec_adap = cec_allocate_adapter(&tc358743_cec_adap_ops,
+		state, dev_name(&client->dev),
+		CEC_CAP_DEFAULTS | CEC_CAP_MONITOR_ALL, CEC_MAX_LOG_ADDRS);
+	if (IS_ERR(state->cec_adap)) {
+		err = PTR_ERR(state->cec_adap);
+		goto err_hdl;
+	}
+	irq_mask |= MASK_CEC_RMSK | MASK_CEC_TMSK;
+#endif
+
 	tc358743_initial_setup(sd);
 	tc358743_initial_setup(sd);
 
 
 	tc358743_s_dv_timings(sd, &default_timing);
 	tc358743_s_dv_timings(sd, &default_timing);
@@ -1964,15 +2153,22 @@ static int tc358743_probe(struct i2c_client *client,
 	} else {
 	} else {
 		INIT_WORK(&state->work_i2c_poll,
 		INIT_WORK(&state->work_i2c_poll,
 			  tc358743_work_i2c_poll);
 			  tc358743_work_i2c_poll);
-		state->timer.data = (unsigned long)state;
-		state->timer.function = tc358743_irq_poll_timer;
+		timer_setup(&state->timer, tc358743_irq_poll_timer, 0);
 		state->timer.expires = jiffies +
 		state->timer.expires = jiffies +
 				       msecs_to_jiffies(POLL_INTERVAL_MS);
 				       msecs_to_jiffies(POLL_INTERVAL_MS);
 		add_timer(&state->timer);
 		add_timer(&state->timer);
 	}
 	}
 
 
+	err = cec_register_adapter(state->cec_adap, &client->dev);
+	if (err < 0) {
+		pr_err("%s: failed to register the cec device\n", __func__);
+		cec_delete_adapter(state->cec_adap);
+		state->cec_adap = NULL;
+		goto err_work_queues;
+	}
+
 	tc358743_enable_interrupts(sd, tx_5v_power_present(sd));
 	tc358743_enable_interrupts(sd, tx_5v_power_present(sd));
-	i2c_wr16(sd, INTMASK, ~(MASK_HDMI_MSK | MASK_CSI_MSK) & 0xffff);
+	i2c_wr16(sd, INTMASK, ~irq_mask);
 
 
 	err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
 	err = v4l2_ctrl_handler_setup(sd->ctrl_handler);
 	if (err)
 	if (err)
@@ -1984,6 +2180,7 @@ static int tc358743_probe(struct i2c_client *client,
 	return 0;
 	return 0;
 
 
 err_work_queues:
 err_work_queues:
+	cec_unregister_adapter(state->cec_adap);
 	if (!state->i2c_client->irq)
 	if (!state->i2c_client->irq)
 		flush_work(&state->work_i2c_poll);
 		flush_work(&state->work_i2c_poll);
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
@@ -2004,6 +2201,7 @@ static int tc358743_remove(struct i2c_client *client)
 		flush_work(&state->work_i2c_poll);
 		flush_work(&state->work_i2c_poll);
 	}
 	}
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	cec_unregister_adapter(state->cec_adap);
 	v4l2_async_unregister_subdev(sd);
 	v4l2_async_unregister_subdev(sd);
 	v4l2_device_unregister_subdev(sd);
 	v4l2_device_unregister_subdev(sd);
 	mutex_destroy(&state->confctl_mutex);
 	mutex_destroy(&state->confctl_mutex);

+ 92 - 2
drivers/media/i2c/tc358743_regs.h

@@ -193,8 +193,98 @@
 #define CSI_START                             0x0518
 #define CSI_START                             0x0518
 #define MASK_STRT                             0x00000001
 #define MASK_STRT                             0x00000001
 
 
-#define CECEN                                 0x0600
-#define MASK_CECEN                            0x0001
+/* *** CEC (32 bit) *** */
+#define CECHCLK				      0x0028	/* 16 bits */
+#define MASK_CECHCLK			      (0x7ff << 0)
+
+#define CECLCLK				      0x002a	/* 16 bits */
+#define MASK_CECLCLK			      (0x7ff << 0)
+
+#define CECEN				      0x0600
+#define MASK_CECEN			      0x0001
+
+#define CECADD				      0x0604
+#define CECRST				      0x0608
+#define MASK_CECRESET			      0x0001
+
+#define CECREN				      0x060c
+#define MASK_CECREN			      0x0001
+
+#define CECRCTL1			      0x0614
+#define MASK_CECACKDIS			      (1 << 24)
+#define MASK_CECHNC			      (3 << 20)
+#define MASK_CECLNC			      (7 << 16)
+#define MASK_CECMIN			      (7 << 12)
+#define MASK_CECMAX			      (7 << 8)
+#define MASK_CECDAT			      (7 << 4)
+#define MASK_CECTOUT			      (3 << 2)
+#define MASK_CECRIHLD			      (1 << 1)
+#define MASK_CECOTH			      (1 << 0)
+
+#define CECRCTL2			      0x0618
+#define MASK_CECSWAV3			      (7 << 12)
+#define MASK_CECSWAV2			      (7 << 8)
+#define MASK_CECSWAV1			      (7 << 4)
+#define MASK_CECSWAV0			      (7 << 0)
+
+#define CECRCTL3			      0x061c
+#define MASK_CECWAV3			      (7 << 20)
+#define MASK_CECWAV2			      (7 << 16)
+#define MASK_CECWAV1			      (7 << 12)
+#define MASK_CECWAV0			      (7 << 8)
+#define MASK_CECACKEI			      (1 << 4)
+#define MASK_CECMINEI			      (1 << 3)
+#define MASK_CECMAXEI			      (1 << 2)
+#define MASK_CECRSTEI			      (1 << 1)
+#define MASK_CECWAVEI			      (1 << 0)
+
+#define CECTEN				      0x0620
+#define MASK_CECTBUSY			      (1 << 1)
+#define MASK_CECTEN			      (1 << 0)
+
+#define CECTCTL				      0x0628
+#define MASK_CECSTRS			      (7 << 20)
+#define MASK_CECSPRD			      (7 << 16)
+#define MASK_CECDTRS			      (7 << 12)
+#define MASK_CECDPRD			      (15 << 8)
+#define MASK_CECBRD			      (1 << 4)
+#define MASK_CECFREE			      (15 << 0)
+
+#define CECRSTAT			      0x062c
+#define MASK_CECRIWA			      (1 << 6)
+#define MASK_CECRIOR			      (1 << 5)
+#define MASK_CECRIACK			      (1 << 4)
+#define MASK_CECRIMIN			      (1 << 3)
+#define MASK_CECRIMAX			      (1 << 2)
+#define MASK_CECRISTA			      (1 << 1)
+#define MASK_CECRIEND			      (1 << 0)
+
+#define CECTSTAT			      0x0630
+#define MASK_CECTIUR			      (1 << 4)
+#define MASK_CECTIACK			      (1 << 3)
+#define MASK_CECTIAL			      (1 << 2)
+#define MASK_CECTIEND			      (1 << 1)
+
+#define CECRBUF1			      0x0634
+#define MASK_CECRACK			      (1 << 9)
+#define MASK_CECEOM			      (1 << 8)
+#define MASK_CECRBYTE			      (0xff << 0)
+
+#define CECTBUF1			      0x0674
+#define MASK_CECTEOM			      (1 << 8)
+#define MASK_CECTBYTE			      (0xff << 0)
+
+#define CECRCTR				      0x06b4
+#define MASK_CECRCTR			      (0x1f << 0)
+
+#define CECIMSK				      0x06c0
+#define MASK_CECTIM			      (1 << 1)
+#define MASK_CECRIM			      (1 << 0)
+
+#define CECICLR				      0x06cc
+#define MASK_CECTICLR			      (1 << 1)
+#define MASK_CECRICLR			      (1 << 0)
+
 
 
 #define HDMI_INT0                             0x8500
 #define HDMI_INT0                             0x8500
 #define MASK_I_KEY                            0x80
 #define MASK_I_KEY                            0x80

+ 3 - 5
drivers/media/i2c/tvaudio.c

@@ -300,9 +300,9 @@ static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd)
  *   if available, ...
  *   if available, ...
  */
  */
 
 
-static void chip_thread_wake(unsigned long data)
+static void chip_thread_wake(struct timer_list *t)
 {
 {
-	struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+	struct CHIPSTATE *chip = from_timer(chip, t, wt);
 	wake_up_process(chip->thread);
 	wake_up_process(chip->thread);
 }
 }
 
 
@@ -1995,7 +1995,7 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
 	v4l2_ctrl_handler_setup(&chip->hdl);
 	v4l2_ctrl_handler_setup(&chip->hdl);
 
 
 	chip->thread = NULL;
 	chip->thread = NULL;
-	init_timer(&chip->wt);
+	timer_setup(&chip->wt, chip_thread_wake, 0);
 	if (desc->flags & CHIP_NEED_CHECKMODE) {
 	if (desc->flags & CHIP_NEED_CHECKMODE) {
 		if (!desc->getrxsubchans || !desc->setaudmode) {
 		if (!desc->getrxsubchans || !desc->setaudmode) {
 			/* This shouldn't be happen. Warn user, but keep working
 			/* This shouldn't be happen. Warn user, but keep working
@@ -2005,8 +2005,6 @@ static int tvaudio_probe(struct i2c_client *client, const struct i2c_device_id *
 			return 0;
 			return 0;
 		}
 		}
 		/* start async thread */
 		/* start async thread */
-		chip->wt.function = chip_thread_wake;
-		chip->wt.data     = (unsigned long)chip;
 		chip->thread = kthread_run(chip_thread, chip, "%s",
 		chip->thread = kthread_run(chip_thread, chip, "%s",
 					   client->name);
 					   client->name);
 		if (IS_ERR(chip->thread)) {
 		if (IS_ERR(chip->thread)) {

+ 8 - 5
drivers/media/media-entity.c

@@ -214,12 +214,20 @@ void media_gobj_destroy(struct media_gobj *gobj)
 	gobj->mdev = NULL;
 	gobj->mdev = NULL;
 }
 }
 
 
+/*
+ * TODO: Get rid of this.
+ */
+#define MEDIA_ENTITY_MAX_PADS		512
+
 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
 int media_entity_pads_init(struct media_entity *entity, u16 num_pads,
 			   struct media_pad *pads)
 			   struct media_pad *pads)
 {
 {
 	struct media_device *mdev = entity->graph_obj.mdev;
 	struct media_device *mdev = entity->graph_obj.mdev;
 	unsigned int i;
 	unsigned int i;
 
 
+	if (num_pads >= MEDIA_ENTITY_MAX_PADS)
+		return -E2BIG;
+
 	entity->num_pads = num_pads;
 	entity->num_pads = num_pads;
 	entity->pads = pads;
 	entity->pads = pads;
 
 
@@ -280,11 +288,6 @@ static struct media_entity *stack_pop(struct media_graph *graph)
 #define link_top(en)	((en)->stack[(en)->top].link)
 #define link_top(en)	((en)->stack[(en)->top].link)
 #define stack_top(en)	((en)->stack[(en)->top].entity)
 #define stack_top(en)	((en)->stack[(en)->top].entity)
 
 
-/*
- * TODO: Get rid of this.
- */
-#define MEDIA_ENTITY_MAX_PADS		512
-
 /**
 /**
  * media_graph_walk_init - Allocate resources for graph walk
  * media_graph_walk_init - Allocate resources for graph walk
  * @graph: Media graph structure that will be used to walk the graph
  * @graph: Media graph structure that will be used to walk the graph

+ 2 - 2
drivers/media/pci/b2c2/Kconfig

@@ -11,5 +11,5 @@ config DVB_B2C2_FLEXCOP_PCI_DEBUG
 	depends on DVB_B2C2_FLEXCOP_PCI
 	depends on DVB_B2C2_FLEXCOP_PCI
 	select DVB_B2C2_FLEXCOP_DEBUG
 	select DVB_B2C2_FLEXCOP_DEBUG
 	help
 	help
-	Say Y if you want to enable the module option to control debug messages
-	of all B2C2 FlexCop drivers.
+	  Say Y if you want to enable the module option to control debug messages
+	  of all B2C2 FlexCop drivers.

+ 3 - 3
drivers/media/pci/bt8xx/bttv-driver.c

@@ -3652,9 +3652,9 @@ bttv_irq_wakeup_vbi(struct bttv *btv, struct bttv_buffer *wakeup,
 	wake_up(&wakeup->vb.done);
 	wake_up(&wakeup->vb.done);
 }
 }
 
 
-static void bttv_irq_timeout(unsigned long data)
+static void bttv_irq_timeout(struct timer_list *t)
 {
 {
-	struct bttv *btv = (struct bttv *)data;
+	struct bttv *btv = from_timer(btv, t, timeout);
 	struct bttv_buffer_set old,new;
 	struct bttv_buffer_set old,new;
 	struct bttv_buffer *ovbi;
 	struct bttv_buffer *ovbi;
 	struct bttv_buffer *item;
 	struct bttv_buffer *item;
@@ -4043,7 +4043,7 @@ static int bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 	INIT_LIST_HEAD(&btv->capture);
 	INIT_LIST_HEAD(&btv->capture);
 	INIT_LIST_HEAD(&btv->vcapture);
 	INIT_LIST_HEAD(&btv->vcapture);
 
 
-	setup_timer(&btv->timeout, bttv_irq_timeout, (unsigned long)btv);
+	timer_setup(&btv->timeout, bttv_irq_timeout, 0);
 
 
 	btv->i2c_rc = -1;
 	btv->i2c_rc = -1;
 	btv->tuner_type  = UNSET;
 	btv->tuner_type  = UNSET;

+ 10 - 9
drivers/media/pci/bt8xx/bttv-input.c

@@ -133,10 +133,10 @@ void bttv_input_irq(struct bttv *btv)
 		ir_handle_key(btv);
 		ir_handle_key(btv);
 }
 }
 
 
-static void bttv_input_timer(unsigned long data)
+static void bttv_input_timer(struct timer_list *t)
 {
 {
-	struct bttv *btv = (struct bttv*)data;
-	struct bttv_ir *ir = btv->remote;
+	struct bttv_ir *ir = from_timer(ir, t, timer);
+	struct bttv *btv = ir->btv;
 
 
 	if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
 	if (btv->c.type == BTTV_BOARD_ENLTV_FM_2)
 		ir_enltv_handle_key(btv);
 		ir_enltv_handle_key(btv);
@@ -189,9 +189,9 @@ static u32 bttv_rc5_decode(unsigned int code)
 	return rc5;
 	return rc5;
 }
 }
 
 
-static void bttv_rc5_timer_end(unsigned long data)
+static void bttv_rc5_timer_end(struct timer_list *t)
 {
 {
-	struct bttv_ir *ir = (struct bttv_ir *)data;
+	struct bttv_ir *ir = from_timer(ir, t, timer);
 	ktime_t tv;
 	ktime_t tv;
 	u32 gap, rc5, scancode;
 	u32 gap, rc5, scancode;
 	u8 toggle, command, system;
 	u8 toggle, command, system;
@@ -296,15 +296,15 @@ static int bttv_rc5_irq(struct bttv *btv)
 
 
 /* ---------------------------------------------------------------------- */
 /* ---------------------------------------------------------------------- */
 
 
-static void bttv_ir_start(struct bttv *btv, struct bttv_ir *ir)
+static void bttv_ir_start(struct bttv_ir *ir)
 {
 {
 	if (ir->polling) {
 	if (ir->polling) {
-		setup_timer(&ir->timer, bttv_input_timer, (unsigned long)btv);
+		timer_setup(&ir->timer, bttv_input_timer, 0);
 		ir->timer.expires  = jiffies + msecs_to_jiffies(1000);
 		ir->timer.expires  = jiffies + msecs_to_jiffies(1000);
 		add_timer(&ir->timer);
 		add_timer(&ir->timer);
 	} else if (ir->rc5_gpio) {
 	} else if (ir->rc5_gpio) {
 		/* set timer_end for code completion */
 		/* set timer_end for code completion */
-		setup_timer(&ir->timer, bttv_rc5_timer_end, (unsigned long)ir);
+		timer_setup(&ir->timer, bttv_rc5_timer_end, 0);
 		ir->shift_by = 1;
 		ir->shift_by = 1;
 		ir->rc5_remote_gap = ir_rc5_remote_gap;
 		ir->rc5_remote_gap = ir_rc5_remote_gap;
 	}
 	}
@@ -531,6 +531,7 @@ int bttv_input_init(struct bttv *btv)
 
 
 	/* init input device */
 	/* init input device */
 	ir->dev = rc;
 	ir->dev = rc;
+	ir->btv = btv;
 
 
 	snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
 	snprintf(ir->name, sizeof(ir->name), "bttv IR (card=%d)",
 		 btv->c.type);
 		 btv->c.type);
@@ -553,7 +554,7 @@ int bttv_input_init(struct bttv *btv)
 	rc->driver_name = MODULE_NAME;
 	rc->driver_name = MODULE_NAME;
 
 
 	btv->remote = ir;
 	btv->remote = ir;
-	bttv_ir_start(btv, ir);
+	bttv_ir_start(ir);
 
 
 	/* all done */
 	/* all done */
 	err = rc_register_device(rc);
 	err = rc_register_device(rc);

+ 1 - 1
drivers/media/pci/bt8xx/bttv-vbi.c

@@ -233,7 +233,7 @@ static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer
 	bttv_dma_free(q,fh->btv,buf);
 	bttv_dma_free(q,fh->btv,buf);
 }
 }
 
 
-struct videobuf_queue_ops bttv_vbi_qops = {
+const struct videobuf_queue_ops bttv_vbi_qops = {
 	.buf_setup    = vbi_buffer_setup,
 	.buf_setup    = vbi_buffer_setup,
 	.buf_prepare  = vbi_buffer_prepare,
 	.buf_prepare  = vbi_buffer_prepare,
 	.buf_queue    = vbi_buffer_queue,
 	.buf_queue    = vbi_buffer_queue,

+ 2 - 1
drivers/media/pci/bt8xx/bttvp.h

@@ -122,6 +122,7 @@ struct bttv_format {
 
 
 struct bttv_ir {
 struct bttv_ir {
 	struct rc_dev           *dev;
 	struct rc_dev           *dev;
+	struct bttv		*btv;
 	struct timer_list       timer;
 	struct timer_list       timer;
 
 
 	char                    name[32];
 	char                    name[32];
@@ -281,7 +282,7 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
 int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
 int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
 int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
 int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
 
 
-extern struct videobuf_queue_ops bttv_vbi_qops;
+extern const struct videobuf_queue_ops bttv_vbi_qops;
 
 
 /* ---------------------------------------------------------- */
 /* ---------------------------------------------------------- */
 /* bttv-gpio.c */
 /* bttv-gpio.c */

+ 0 - 5
drivers/media/pci/cobalt/cobalt-driver.c

@@ -738,9 +738,6 @@ static int cobalt_probe(struct pci_dev *pci_dev,
 			goto err_i2c;
 			goto err_i2c;
 	}
 	}
 
 
-	retval = v4l2_device_register_subdev_nodes(&cobalt->v4l2_dev);
-	if (retval)
-		goto err_i2c;
 	retval = cobalt_nodes_register(cobalt);
 	retval = cobalt_nodes_register(cobalt);
 	if (retval) {
 	if (retval) {
 		cobalt_err("Error %d registering device nodes\n", retval);
 		cobalt_err("Error %d registering device nodes\n", retval);
@@ -767,8 +764,6 @@ err_pci:
 err_wq:
 err_wq:
 	destroy_workqueue(cobalt->irq_work_queues);
 	destroy_workqueue(cobalt->irq_work_queues);
 err:
 err:
-	if (retval == 0)
-		retval = -ENODEV;
 	cobalt_err("error %d on initialization\n", retval);
 	cobalt_err("error %d on initialization\n", retval);
 
 
 	v4l2_device_unregister(&cobalt->v4l2_dev);
 	v4l2_device_unregister(&cobalt->v4l2_dev);

+ 13 - 15
drivers/media/pci/cx18/cx18-driver.c

@@ -255,7 +255,7 @@ static void request_module_async(struct work_struct *work)
 	request_module("cx18-alsa");
 	request_module("cx18-alsa");
 
 
 	/* Initialize cx18-alsa for this instance of the cx18 device */
 	/* Initialize cx18-alsa for this instance of the cx18 device */
-	if (cx18_ext_init != NULL)
+	if (cx18_ext_init)
 		cx18_ext_init(dev);
 		cx18_ext_init(dev);
 }
 }
 
 
@@ -291,11 +291,11 @@ int cx18_msleep_timeout(unsigned int msecs, int intr)
 /* Release ioremapped memory */
 /* Release ioremapped memory */
 static void cx18_iounmap(struct cx18 *cx)
 static void cx18_iounmap(struct cx18 *cx)
 {
 {
-	if (cx == NULL)
+	if (!cx)
 		return;
 		return;
 
 
 	/* Release io memory */
 	/* Release io memory */
-	if (cx->enc_mem != NULL) {
+	if (cx->enc_mem) {
 		CX18_DEBUG_INFO("releasing enc_mem\n");
 		CX18_DEBUG_INFO("releasing enc_mem\n");
 		iounmap(cx->enc_mem);
 		iounmap(cx->enc_mem);
 		cx->enc_mem = NULL;
 		cx->enc_mem = NULL;
@@ -649,15 +649,15 @@ static void cx18_process_options(struct cx18 *cx)
 		CX18_INFO("User specified %s card\n", cx->card->name);
 		CX18_INFO("User specified %s card\n", cx->card->name);
 	else if (cx->options.cardtype != 0)
 	else if (cx->options.cardtype != 0)
 		CX18_ERR("Unknown user specified type, trying to autodetect card\n");
 		CX18_ERR("Unknown user specified type, trying to autodetect card\n");
-	if (cx->card == NULL) {
+	if (!cx->card) {
 		if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
 		if (cx->pci_dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
 			cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 			cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 			CX18_INFO("Autodetected Hauppauge card\n");
 			CX18_INFO("Autodetected Hauppauge card\n");
 		}
 		}
 	}
 	}
-	if (cx->card == NULL) {
+	if (!cx->card) {
 		for (i = 0; (cx->card = cx18_get_card(i)); i++) {
 		for (i = 0; (cx->card = cx18_get_card(i)); i++) {
-			if (cx->card->pci_list == NULL)
+			if (!cx->card->pci_list)
 				continue;
 				continue;
 			for (j = 0; cx->card->pci_list[j].device; j++) {
 			for (j = 0; cx->card->pci_list[j].device; j++) {
 				if (cx->pci_dev->device !=
 				if (cx->pci_dev->device !=
@@ -676,7 +676,7 @@ static void cx18_process_options(struct cx18 *cx)
 	}
 	}
 done:
 done:
 
 
-	if (cx->card == NULL) {
+	if (!cx->card) {
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
 		CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
 		CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
 			 cx->pci_dev->vendor, cx->pci_dev->device);
 			 cx->pci_dev->vendor, cx->pci_dev->device);
@@ -698,7 +698,7 @@ static int cx18_create_in_workq(struct cx18 *cx)
 	snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
 	snprintf(cx->in_workq_name, sizeof(cx->in_workq_name), "%s-in",
 		 cx->v4l2_dev.name);
 		 cx->v4l2_dev.name);
 	cx->in_work_queue = alloc_ordered_workqueue("%s", 0, cx->in_workq_name);
 	cx->in_work_queue = alloc_ordered_workqueue("%s", 0, cx->in_workq_name);
-	if (cx->in_work_queue == NULL) {
+	if (!cx->in_work_queue) {
 		CX18_ERR("Unable to create incoming mailbox handler thread\n");
 		CX18_ERR("Unable to create incoming mailbox handler thread\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -909,12 +909,10 @@ static int cx18_probe(struct pci_dev *pci_dev,
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 
 
-	cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
-	if (cx == NULL) {
-		printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
-		       i);
+	cx = kzalloc(sizeof(*cx), GFP_ATOMIC);
+	if (!cx)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
+
 	cx->pci_dev = pci_dev;
 	cx->pci_dev = pci_dev;
 	cx->instance = i;
 	cx->instance = i;
 
 
@@ -1256,7 +1254,7 @@ static void cx18_cancel_out_work_orders(struct cx18 *cx)
 {
 {
 	int i;
 	int i;
 	for (i = 0; i < CX18_MAX_STREAMS; i++)
 	for (i = 0; i < CX18_MAX_STREAMS; i++)
-		if (&cx->streams[i].video_dev != NULL)
+		if (&cx->streams[i].video_dev)
 			cancel_work_sync(&cx->streams[i].out_work_order);
 			cancel_work_sync(&cx->streams[i].out_work_order);
 }
 }
 
 
@@ -1301,7 +1299,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
 
 
 	pci_disable_device(cx->pci_dev);
 	pci_disable_device(cx->pci_dev);
 
 
-	if (cx->vbi.sliced_mpeg_data[0] != NULL)
+	if (cx->vbi.sliced_mpeg_data[0])
 		for (i = 0; i < CX18_VBI_FRAMES; i++)
 		for (i = 0; i < CX18_VBI_FRAMES; i++)
 			kfree(cx->vbi.sliced_mpeg_data[i]);
 			kfree(cx->vbi.sliced_mpeg_data[i]);
 
 

+ 2 - 2
drivers/media/pci/cx18/cx18-fileops.c

@@ -684,9 +684,9 @@ int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-void cx18_vb_timeout(unsigned long data)
+void cx18_vb_timeout(struct timer_list *t)
 {
 {
-	struct cx18_stream *s = (struct cx18_stream *)data;
+	struct cx18_stream *s = from_timer(s, t, vb_timeout);
 	struct cx18_videobuf_buffer *buf;
 	struct cx18_videobuf_buffer *buf;
 	unsigned long flags;
 	unsigned long flags;
 
 

+ 1 - 1
drivers/media/pci/cx18/cx18-fileops.h

@@ -29,7 +29,7 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end);
 void cx18_mute(struct cx18 *cx);
 void cx18_mute(struct cx18 *cx);
 void cx18_unmute(struct cx18 *cx);
 void cx18_unmute(struct cx18 *cx);
 int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
 int cx18_v4l2_mmap(struct file *file, struct vm_area_struct *vma);
-void cx18_vb_timeout(unsigned long data);
+void cx18_vb_timeout(struct timer_list *t);
 
 
 /* Shared with cx18-alsa module */
 /* Shared with cx18-alsa module */
 int cx18_claim_stream(struct cx18_open_id *id, int type);
 int cx18_claim_stream(struct cx18_open_id *id, int type);

部分文件因为文件数量过多而无法显示