瀏覽代碼

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

Pull media updates from Mauro Carvalho Chehab:

 - a new frontend driver for new ATSC devices: lgdt3306a

 - a new sensor driver: ov2659

 - a new platform driver: xilinx

 - the m88ts2022 tuner driver was merged at ts2020 driver

 - the media controller gained experimental support for DVB and hybrid
   devices

 - lots of random cleanups, fixes and improvements on media drivers

* tag 'media/v4.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (404 commits)
  [media] uvcvideo: add support for VIDIOC_QUERY_EXT_CTRL
  [media] uvcvideo: fix cropcap v4l2-compliance failure
  [media] media: omap3isp: remove unused clkdev
  [media] coda: Add tracing support
  [media] coda: drop dma_sync_single_for_device in coda_bitstream_queue
  [media] coda: fix fill bitstream errors in nonstreaming case
  [media] coda: call SEQ_END when the first queue is stopped
  [media] coda: fail to start streaming if userspace set invalid formats
  [media] coda: remove duplicate error messages for buffer allocations
  [media] coda: move parameter buffer in together with context buffer allocation
  [media] coda: allocate bitstream buffer from REQBUFS, size depends on the format
  [media] coda: allocate per-context buffers from REQBUFS
  [media] coda: use strlcpy instead of snprintf
  [media] coda: bitstream payload is unsigned
  [media] coda: fix double call to debugfs_remove
  [media] coda: check kasprintf return value in coda_open
  [media] coda: bitrate can only be set in kbps steps
  [media] v4l2-mem2mem: no need to initialize b in v4l2_m2m_next_buf and v4l2_m2m_buf_remove
  [media] s5p-mfc: set allow_zero_bytesused flag for vb2_queue_init
  [media] coda: set allow_zero_bytesused flag for vb2_queue_init
  ...
Linus Torvalds 10 年之前
父節點
當前提交
0c8027d50c
共有 100 個文件被更改,包括 4338 次插入1059 次删除
  1. 1 1
      Documentation/DocBook/media/v4l/compat.xml
  2. 27 65
      Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml
  3. 40 39
      Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
  4. 8 8
      Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml
  5. 1 1
      Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml
  6. 2 2
      Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
  7. 52 58
      Documentation/DocBook/media/v4l/pixfmt.xml
  8. 434 337
      Documentation/DocBook/media/v4l/subdev-formats.xml
  9. 9 0
      Documentation/DocBook/media/v4l/v4l2.xml
  10. 6 3
      Documentation/DocBook/media/v4l/vidioc-cropcap.xml
  11. 114 7
      Documentation/DocBook/media/v4l/vidioc-dqevent.xml
  12. 5 0
      Documentation/DocBook/media/v4l/vidioc-g-crop.xml
  13. 14 4
      Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml
  14. 2 2
      Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
  15. 2 2
      Documentation/DocBook/media/v4l/vidioc-g-selection.xml
  16. 4 4
      Documentation/DocBook/media/v4l/vidioc-querycap.xml
  17. 11 1
      Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
  18. 9 4
      Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml
  19. 9 4
      Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml
  20. 8 3
      Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml
  21. 3 108
      Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
  22. 1 1
      Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt
  23. 39 0
      Documentation/devicetree/bindings/media/i2c/mt9v032.txt
  24. 46 0
      Documentation/devicetree/bindings/media/i2c/ov2640.txt
  25. 38 0
      Documentation/devicetree/bindings/media/i2c/ov2659.txt
  26. 6 0
      Documentation/devicetree/bindings/media/video-interfaces.txt
  27. 35 0
      Documentation/devicetree/bindings/media/xilinx/video.txt
  28. 33 0
      Documentation/devicetree/bindings/media/xilinx/xlnx,v-tc.txt
  29. 71 0
      Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt
  30. 55 0
      Documentation/devicetree/bindings/media/xilinx/xlnx,video.txt
  31. 1 0
      Documentation/devicetree/bindings/vendor-prefixes.txt
  32. 3 1
      Documentation/video4linux/v4l2-controls.txt
  33. 3 3
      Documentation/video4linux/v4l2-framework.txt
  34. 5 0
      Documentation/video4linux/vivid.txt
  35. 22 11
      MAINTAINERS
  36. 21 36
      arch/arm/mach-omap2/board-cm-t35.c
  37. 3 73
      arch/arm/mach-omap2/devices.c
  38. 3 33
      arch/arm/mach-omap2/omap34xx.h
  39. 15 3
      drivers/input/ff-memless.c
  40. 2 0
      drivers/input/touchscreen/Kconfig
  41. 422 12
      drivers/input/touchscreen/sur40.c
  42. 9 1
      drivers/media/Kconfig
  43. 4 15
      drivers/media/common/saa7146/saa7146_fops.c
  44. 2 2
      drivers/media/common/saa7146/saa7146_vbi.c
  45. 2 6
      drivers/media/common/siano/sms-cards.c
  46. 2 1
      drivers/media/common/siano/sms-cards.h
  47. 81 83
      drivers/media/common/siano/smscoreapi.c
  48. 10 22
      drivers/media/common/siano/smscoreapi.h
  49. 2 4
      drivers/media/common/siano/smsdvb-debugfs.c
  50. 43 31
      drivers/media/common/siano/smsdvb-main.c
  51. 9 9
      drivers/media/common/siano/smsir.c
  52. 8 3
      drivers/media/dvb-core/dmxdev.c
  53. 3 0
      drivers/media/dvb-core/dvb-usb-ids.h
  54. 16 14
      drivers/media/dvb-core/dvb_ca_en50221.c
  55. 123 1
      drivers/media/dvb-core/dvb_frontend.c
  56. 4 2
      drivers/media/dvb-core/dvb_net.c
  57. 143 1
      drivers/media/dvb-core/dvbdev.c
  58. 27 0
      drivers/media/dvb-core/dvbdev.h
  59. 8 0
      drivers/media/dvb-frontends/Kconfig
  60. 1 0
      drivers/media/dvb-frontends/Makefile
  61. 1 1
      drivers/media/dvb-frontends/a8293.h
  62. 1 1
      drivers/media/dvb-frontends/af9013.h
  63. 1 1
      drivers/media/dvb-frontends/atbm8830.h
  64. 1 1
      drivers/media/dvb-frontends/au8522.h
  65. 1 1
      drivers/media/dvb-frontends/bcm3510.h
  66. 1 1
      drivers/media/dvb-frontends/cx22700.h
  67. 1 1
      drivers/media/dvb-frontends/cx22702.h
  68. 1 1
      drivers/media/dvb-frontends/cx24110.h
  69. 1 1
      drivers/media/dvb-frontends/cx24113.h
  70. 1 1
      drivers/media/dvb-frontends/cx24116.h
  71. 1 1
      drivers/media/dvb-frontends/cx24117.h
  72. 1 1
      drivers/media/dvb-frontends/cx24123.h
  73. 1 1
      drivers/media/dvb-frontends/cxd2820r.h
  74. 1 1
      drivers/media/dvb-frontends/dib0070.h
  75. 1 1
      drivers/media/dvb-frontends/dib0090.h
  76. 1 1
      drivers/media/dvb-frontends/dib3000.h
  77. 1 1
      drivers/media/dvb-frontends/dib3000mc.h
  78. 1 1
      drivers/media/dvb-frontends/dib7000m.h
  79. 1 1
      drivers/media/dvb-frontends/dib7000p.h
  80. 1 1
      drivers/media/dvb-frontends/dib8000.h
  81. 1 1
      drivers/media/dvb-frontends/dib9000.h
  82. 1 1
      drivers/media/dvb-frontends/drx39xyj/drx39xxj.h
  83. 1 1
      drivers/media/dvb-frontends/drxd.h
  84. 1 1
      drivers/media/dvb-frontends/drxk.h
  85. 1 1
      drivers/media/dvb-frontends/ds3000.h
  86. 1 1
      drivers/media/dvb-frontends/dvb-pll.h
  87. 1 1
      drivers/media/dvb-frontends/dvb_dummy_fe.h
  88. 1 1
      drivers/media/dvb-frontends/ec100.h
  89. 1 1
      drivers/media/dvb-frontends/hd29l2.h
  90. 1 1
      drivers/media/dvb-frontends/isl6405.h
  91. 1 1
      drivers/media/dvb-frontends/isl6421.h
  92. 1 1
      drivers/media/dvb-frontends/isl6423.h
  93. 1 1
      drivers/media/dvb-frontends/itd1000.h
  94. 1 1
      drivers/media/dvb-frontends/ix2505v.h
  95. 1 1
      drivers/media/dvb-frontends/l64781.h
  96. 1 1
      drivers/media/dvb-frontends/lg2160.h
  97. 1 1
      drivers/media/dvb-frontends/lgdt3305.h
  98. 2144 0
      drivers/media/dvb-frontends/lgdt3306a.c
  99. 74 0
      drivers/media/dvb-frontends/lgdt3306a.h
  100. 1 1
      drivers/media/dvb-frontends/lgdt330x.h

+ 1 - 1
Documentation/DocBook/media/v4l/compat.xml

@@ -2491,7 +2491,7 @@ that used it. It was originally scheduled for removal in 2.6.35.
         </listitem>
         <listitem>
 	  <para>Added <constant>V4L2_EVENT_CTRL_CH_RANGE</constant> control event
-	  changes flag. See <xref linkend="changes-flags"/>.</para>
+	  changes flag. See <xref linkend="ctrl-changes-flags"/>.</para>
         </listitem>
       </orderedlist>
     </section>

+ 27 - 65
Documentation/DocBook/media/v4l/media-ioc-enum-entities.xml

@@ -143,86 +143,28 @@
 	  <row>
 	    <entry></entry>
 	    <entry>struct</entry>
-	    <entry><structfield>v4l</structfield></entry>
+	    <entry><structfield>dev</structfield></entry>
 	    <entry></entry>
-	    <entry>Valid for V4L sub-devices and nodes only.</entry>
+	    <entry>Valid for (sub-)devices that create a single device node.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry></entry>
 	    <entry>__u32</entry>
 	    <entry><structfield>major</structfield></entry>
-	    <entry>V4L device node major number. For V4L sub-devices with no
-	    device node, set by the driver to 0.</entry>
+	    <entry>Device node major number.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry></entry>
 	    <entry>__u32</entry>
 	    <entry><structfield>minor</structfield></entry>
-	    <entry>V4L device node minor number. For V4L sub-devices with no
-	    device node, set by the driver to 0.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>struct</entry>
-	    <entry><structfield>fb</structfield></entry>
-	    <entry></entry>
-	    <entry>Valid for frame buffer nodes only.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry>__u32</entry>
-	    <entry><structfield>major</structfield></entry>
-	    <entry>Frame buffer device node major number.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry>__u32</entry>
-	    <entry><structfield>minor</structfield></entry>
-	    <entry>Frame buffer device node minor number.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>struct</entry>
-	    <entry><structfield>alsa</structfield></entry>
-	    <entry></entry>
-	    <entry>Valid for ALSA devices only.</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry>__u32</entry>
-	    <entry><structfield>card</structfield></entry>
-	    <entry>ALSA card number</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry>__u32</entry>
-	    <entry><structfield>device</structfield></entry>
-	    <entry>ALSA device number</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry>__u32</entry>
-	    <entry><structfield>subdevice</structfield></entry>
-	    <entry>ALSA sub-device number</entry>
-	  </row>
-	  <row>
-	    <entry></entry>
-	    <entry>int</entry>
-	    <entry><structfield>dvb</structfield></entry>
-	    <entry></entry>
-	    <entry>DVB card number</entry>
+	    <entry>Device node minor number.</entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>__u8</entry>
-	    <entry><structfield>raw</structfield>[180]</entry>
+	    <entry><structfield>raw</structfield>[184]</entry>
 	    <entry></entry>
 	    <entry></entry>
 	  </row>
@@ -253,8 +195,24 @@
 	    <entry>ALSA card</entry>
 	  </row>
 	  <row>
-	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB</constant></entry>
-	    <entry>DVB card</entry>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_FE</constant></entry>
+	    <entry>DVB frontend devnode</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DEMUX</constant></entry>
+	    <entry>DVB demux devnode</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_DVR</constant></entry>
+	    <entry>DVB DVR devnode</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_CA</constant></entry>
+	    <entry>DVB CAM devnode</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB_NET</constant></entry>
+	    <entry>DVB network devnode</entry>
 	  </row>
 	  <row>
 	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry>
@@ -282,6 +240,10 @@
 	    it in some digital video standard, with appropriate embedded timing
 	    signals.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_TUNER</constant></entry>
+	    <entry>TV and/or radio tuner</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 40 - 39
Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml

@@ -303,45 +303,6 @@ for a pixel lie next to each other in memory.</para>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
-	  <row id="V4L2-PIX-FMT-BGR666">
-	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
-	    <entry>'BGRH'</entry>
-	    <entry></entry>
-	    <entry>b<subscript>5</subscript></entry>
-	    <entry>b<subscript>4</subscript></entry>
-	    <entry>b<subscript>3</subscript></entry>
-	    <entry>b<subscript>2</subscript></entry>
-	    <entry>b<subscript>1</subscript></entry>
-	    <entry>b<subscript>0</subscript></entry>
-	    <entry>g<subscript>5</subscript></entry>
-	    <entry>g<subscript>4</subscript></entry>
-	    <entry></entry>
-	    <entry>g<subscript>3</subscript></entry>
-	    <entry>g<subscript>2</subscript></entry>
-	    <entry>g<subscript>1</subscript></entry>
-	    <entry>g<subscript>0</subscript></entry>
-	    <entry>r<subscript>5</subscript></entry>
-	    <entry>r<subscript>4</subscript></entry>
-	    <entry>r<subscript>3</subscript></entry>
-	    <entry>r<subscript>2</subscript></entry>
-	    <entry></entry>
-	    <entry>r<subscript>1</subscript></entry>
-	    <entry>r<subscript>0</subscript></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	    <entry></entry>
-	  </row>
 	  <row id="V4L2-PIX-FMT-BGR24">
 	    <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
 	    <entry>'BGR3'</entry>
@@ -404,6 +365,46 @@ for a pixel lie next to each other in memory.</para>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
+	  <row id="V4L2-PIX-FMT-BGR666">
+	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
+	    <entry>'BGRH'</entry>
+	    <entry></entry>
+	    <entry>b<subscript>5</subscript></entry>
+	    <entry>b<subscript>4</subscript></entry>
+	    <entry>b<subscript>3</subscript></entry>
+	    <entry>b<subscript>2</subscript></entry>
+	    <entry>b<subscript>1</subscript></entry>
+	    <entry>b<subscript>0</subscript></entry>
+	    <entry>g<subscript>5</subscript></entry>
+	    <entry>g<subscript>4</subscript></entry>
+	    <entry></entry>
+	    <entry>g<subscript>3</subscript></entry>
+	    <entry>g<subscript>2</subscript></entry>
+	    <entry>g<subscript>1</subscript></entry>
+	    <entry>g<subscript>0</subscript></entry>
+	    <entry>r<subscript>5</subscript></entry>
+	    <entry>r<subscript>4</subscript></entry>
+	    <entry>r<subscript>3</subscript></entry>
+	    <entry>r<subscript>2</subscript></entry>
+	    <entry></entry>
+	    <entry>r<subscript>1</subscript></entry>
+	    <entry>r<subscript>0</subscript></entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry></entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	    <entry>-</entry>
+	  </row>
 	  <row id="V4L2-PIX-FMT-ABGR32">
 	    <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
 	    <entry>'AR24'</entry>

+ 8 - 8
Documentation/DocBook/media/v4l/pixfmt-sgrbg8.xml

@@ -38,10 +38,10 @@ columns and rows.</para>
 		    </row>
 		    <row>
 		      <entry>start&nbsp;+&nbsp;4:</entry>
-		      <entry>R<subscript>10</subscript></entry>
-		      <entry>B<subscript>11</subscript></entry>
-		      <entry>R<subscript>12</subscript></entry>
-		      <entry>B<subscript>13</subscript></entry>
+		      <entry>B<subscript>10</subscript></entry>
+		      <entry>G<subscript>11</subscript></entry>
+		      <entry>B<subscript>12</subscript></entry>
+		      <entry>G<subscript>13</subscript></entry>
 		    </row>
 		    <row>
 		      <entry>start&nbsp;+&nbsp;8:</entry>
@@ -52,10 +52,10 @@ columns and rows.</para>
 		    </row>
 		    <row>
 		      <entry>start&nbsp;+&nbsp;12:</entry>
-		      <entry>R<subscript>30</subscript></entry>
-		      <entry>B<subscript>31</subscript></entry>
-		      <entry>R<subscript>32</subscript></entry>
-		      <entry>B<subscript>33</subscript></entry>
+		      <entry>B<subscript>30</subscript></entry>
+		      <entry>G<subscript>31</subscript></entry>
+		      <entry>B<subscript>32</subscript></entry>
+		      <entry>G<subscript>33</subscript></entry>
 		    </row>
 		  </tbody>
 		</tgroup>

+ 1 - 1
Documentation/DocBook/media/v4l/pixfmt-srggb10p.xml

@@ -38,7 +38,7 @@
 	<title>Byte Order.</title>
 	<para>Each cell is one byte.
 	  <informaltable frame="topbot" colsep="1" rowsep="1">
-	    <tgroup cols="5" align="center" border="1">
+	    <tgroup cols="5" align="center">
 	      <colspec align="left" colwidth="2*" />
 	      <tbody valign="top">
 		<row>

+ 2 - 2
Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml

@@ -29,12 +29,12 @@ and Cr planes have half as many pad bytes after their rows. In other
 words, two Cx rows (including padding) is exactly as long as one Y row
 (including padding).</para>
 
-	<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
+	<para><constant>V4L2_PIX_FMT_YUV420M</constant> is intended to be
 used only in drivers and applications that support the multi-planar API,
 described in <xref linkend="planar-apis"/>. </para>
 
 	<example>
-	  <title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
+	  <title><constant>V4L2_PIX_FMT_YUV420M</constant> 4 &times; 4
 pixel image</title>
 
 	  <formalpara>

+ 52 - 58
Documentation/DocBook/media/v4l/pixfmt.xml

@@ -80,9 +80,9 @@ padding bytes after the last line of an image cross a system page
 boundary. Input devices may write padding bytes, the value is
 undefined. Output devices ignore the contents of padding
 bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the largest
+<structfield>bytesperline</structfield> value applies to the first
 plane and is divided by the same factor as the
-<structfield>width</structfield> field for any smaller planes. For
+<structfield>width</structfield> field for the other planes. For
 example the Cb and Cr planes of a YUV 4:2:0 image have half as many
 padding bytes following each line as the Y plane. To avoid ambiguities
 drivers must return a <structfield>bytesperline</structfield> value
@@ -182,14 +182,14 @@ see <xref linkend="colorspaces" />.</entry>
           </entry>
         </row>
         <row>
-          <entry>__u16</entry>
+          <entry>__u32</entry>
           <entry><structfield>bytesperline</structfield></entry>
           <entry>Distance in bytes between the leftmost pixels in two adjacent
             lines. See &v4l2-pix-format;.</entry>
         </row>
         <row>
           <entry>__u16</entry>
-          <entry><structfield>reserved[7]</structfield></entry>
+          <entry><structfield>reserved[6]</structfield></entry>
           <entry>Reserved for future extensions. Should be zeroed by the
            application.</entry>
         </row>
@@ -483,8 +483,8 @@ is the Y'CbCr encoding identifier (&v4l2-ycbcr-encoding;) to specify non-standar
 Y'CbCr encodings and the third is the quantization identifier (&v4l2-quantization;)
 to specify non-standard quantization methods. Most of the time only the colorspace
 field of &v4l2-pix-format; or &v4l2-pix-format-mplane; needs to be filled in. Note
-that the default R'G'B' quantization is always full range for all colorspaces,
-so this won't be mentioned explicitly for each colorspace description.</para>
+that the default R'G'B' quantization is full range for all colorspaces except for
+BT.2020 which uses limited range R'G'B' quantization.</para>
 
     <table pgwide="1" frame="none" id="v4l2-colorspace">
       <title>V4L2 Colorspaces</title>
@@ -598,7 +598,8 @@ so this won't be mentioned explicitly for each colorspace description.</para>
 	  <row>
 	    <entry><constant>V4L2_QUANTIZATION_DEFAULT</constant></entry>
 	    <entry>Use the default quantization encoding as defined by the colorspace.
-This is always full range for R'G'B' and usually limited range for Y'CbCr.</entry>
+This is always full range for R'G'B' (except for the BT.2020 colorspace) and usually
+limited range for Y'CbCr.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_QUANTIZATION_FULL_RANGE</constant></entry>
@@ -620,8 +621,8 @@ is mapped to [16&hellip;235]. Cb and Cr are mapped from [-0.5&hellip;0.5] to [16
 
   <section>
     <title>Detailed Colorspace Descriptions</title>
-    <section>
-      <title id="col-smpte-170m">Colorspace SMPTE 170M (<constant>V4L2_COLORSPACE_SMPTE170M</constant>)</title>
+    <section id="col-smpte-170m">
+      <title>Colorspace SMPTE 170M (<constant>V4L2_COLORSPACE_SMPTE170M</constant>)</title>
       <para>The <xref linkend="smpte170m" /> standard defines the colorspace used by NTSC and PAL and by SDTV
 in general. The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>.
 The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and
@@ -666,8 +667,7 @@ as the SMPTE C set, so this colorspace is sometimes called SMPTE C as well.</par
       <variablelist>
 	<varlistentry>
           <term>The transfer function defined for SMPTE 170M is the same as the
-one defined in Rec. 709. Normally L is in the range [0&hellip;1], but for the extended
-gamut xvYCC encoding values outside that range are allowed.</term>
+one defined in Rec. 709.</term>
 	  <listitem>
             <para>L' = -1.099(-L)<superscript>0.45</superscript>&nbsp;+&nbsp;0.099&nbsp;for&nbsp;L&nbsp;&le;&nbsp;-0.018</para>
             <para>L' = 4.5L&nbsp;for&nbsp;-0.018&nbsp;&lt;&nbsp;L&nbsp;&lt;&nbsp;0.018</para>
@@ -702,29 +702,10 @@ defined in the <xref linkend="itu601" /> standard and this colorspace is sometim
 though BT.601 does not mention any color primaries.</para>
       <para>The default quantization is limited range, but full range is possible although
 rarely seen.</para>
-      <para>The <constant>V4L2_YCBCR_ENC_601</constant> encoding as described above is the
-default for this colorspace, but it can be overridden with <constant>V4L2_YCBCR_ENC_709</constant>,
-in which case the Rec. 709 Y'CbCr encoding is used.</para>
-      <variablelist>
-	<varlistentry>
-      	  <term>The xvYCC 601 encoding (<constant>V4L2_YCBCR_ENC_XV601</constant>, <xref linkend="xvycc" />) is similar
-to the BT.601 encoding, but it allows for R', G' and B' values that are outside the range
-[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
-	  <listitem>
-            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;255)</para>
-            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B')</para>
-            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B')</para>
-	  </listitem>
-	</varlistentry>
-      </variablelist>
-      <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The non-standard xvYCC 709 encoding can also be used by selecting
-<constant>V4L2_YCBCR_ENC_XV709</constant>. The xvYCC encodings always use full range
-quantization.</para>
     </section>
 
-    <section>
-      <title id="col-rec709">Colorspace Rec. 709 (<constant>V4L2_COLORSPACE_REC709</constant>)</title>
+    <section id="col-rec709">
+      <title>Colorspace Rec. 709 (<constant>V4L2_COLORSPACE_REC709</constant>)</title>
       <para>The <xref linkend="itu709" /> standard defines the colorspace used by HDTV in general. The default
 Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_709</constant>. The default Y'CbCr quantization is
 limited range. The chromaticities of the primary colors and the white reference are:</para>
@@ -803,26 +784,39 @@ rarely seen.</para>
       <para>The <constant>V4L2_YCBCR_ENC_709</constant> encoding described above is the default
 for this colorspace, but it can be overridden with <constant>V4L2_YCBCR_ENC_601</constant>, in which
 case the BT.601 Y'CbCr encoding is used.</para>
+      <para>Two additional extended gamut Y'CbCr encodings are also possible with this colorspace:</para>
       <variablelist>
 	<varlistentry>
       	  <term>The xvYCC 709 encoding (<constant>V4L2_YCBCR_ENC_XV709</constant>, <xref linkend="xvycc" />)
 is similar to the Rec. 709 encoding, but it allows for R', G' and B' values that are outside the range
 [0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
 	  <listitem>
-            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;255)</para>
-            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B')</para>
-            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;255)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B')</para>
+            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.2126R'&nbsp;+&nbsp;0.7152G'&nbsp;+&nbsp;0.0722B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
+            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.1146R'&nbsp;-&nbsp;0.3854G'&nbsp;+&nbsp;0.5B')</para>
+            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.4542G'&nbsp;-&nbsp;0.0458B')</para>
+	  </listitem>
+	</varlistentry>
+      </variablelist>
+      <variablelist>
+	<varlistentry>
+         <term>The xvYCC 601 encoding (<constant>V4L2_YCBCR_ENC_XV601</constant>, <xref linkend="xvycc" />) is similar
+to the BT.601 encoding, but it allows for R', G' and B' values that are outside the range
+[0&hellip;1]. The resulting Y', Cb and Cr values are scaled and offset:</term>
+	  <listitem>
+            <para>Y'&nbsp;=&nbsp;(219&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.299R'&nbsp;+&nbsp;0.587G'&nbsp;+&nbsp;0.114B')&nbsp;+&nbsp;(16&nbsp;/&nbsp;256)</para>
+            <para>Cb&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(-0.169R'&nbsp;-&nbsp;0.331G'&nbsp;+&nbsp;0.5B')</para>
+            <para>Cr&nbsp;=&nbsp;(224&nbsp;/&nbsp;256)&nbsp;*&nbsp;(0.5R'&nbsp;-&nbsp;0.419G'&nbsp;-&nbsp;0.081B')</para>
 	  </listitem>
 	</varlistentry>
       </variablelist>
       <para>Y' is clamped to the range [0&hellip;1] and Cb and Cr are clamped
-to the range [-0.5&hellip;0.5]. The non-standard xvYCC 601 encoding can also be used by
-selecting <constant>V4L2_YCBCR_ENC_XV601</constant>. The xvYCC encodings always use full
-range quantization.</para>
+to the range [-0.5&hellip;0.5]. The non-standard xvYCC 709 or xvYCC 601 encodings can be used by
+selecting <constant>V4L2_YCBCR_ENC_XV709</constant> or <constant>V4L2_YCBCR_ENC_XV601</constant>.
+The xvYCC encodings always use full range quantization.</para>
     </section>
 
-    <section>
-      <title id="col-srgb">Colorspace sRGB (<constant>V4L2_COLORSPACE_SRGB</constant>)</title>
+    <section id="col-srgb">
+      <title>Colorspace sRGB (<constant>V4L2_COLORSPACE_SRGB</constant>)</title>
       <para>The <xref linkend="srgb" /> standard defines the colorspace used by most webcams and computer graphics. The
 default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SYCC</constant>. The default Y'CbCr quantization
 is full range. The chromaticities of the primary colors and the white reference are:</para>
@@ -898,8 +892,8 @@ encoding, it is not. The <constant>V4L2_YCBCR_ENC_XV601</constant> scales and of
 values before quantization, but this encoding does not do that.</para>
     </section>
 
-    <section>
-      <title id="col-adobergb">Colorspace Adobe RGB (<constant>V4L2_COLORSPACE_ADOBERGB</constant>)</title>
+    <section id="col-adobergb">
+      <title>Colorspace Adobe RGB (<constant>V4L2_COLORSPACE_ADOBERGB</constant>)</title>
       <para>The <xref linkend="adobergb" /> standard defines the colorspace used by computer graphics
 that use the AdobeRGB colorspace. This is also known as the <xref linkend="oprgb" /> standard.
 The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr
@@ -970,12 +964,12 @@ clamped to the range [-0.5&hellip;0.5]. This transform is identical to one defin
 SMPTE 170M/BT.601. The Y'CbCr quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-bt2020">Colorspace BT.2020 (<constant>V4L2_COLORSPACE_BT2020</constant>)</title>
+    <section id="col-bt2020">
+      <title>Colorspace BT.2020 (<constant>V4L2_COLORSPACE_BT2020</constant>)</title>
       <para>The <xref linkend="itu2020" /> standard defines the colorspace used by Ultra-high definition
 television (UHDTV). The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_BT2020</constant>.
-The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and
-the white reference are:</para>
+The default R'G'B' quantization is limited range (!), and so is the default Y'CbCr quantization.
+The chromaticities of the primary colors and the white reference are:</para>
       <table frame="none">
         <title>BT.2020 Chromaticities</title>
         <tgroup cols="3" align="left">
@@ -1032,7 +1026,7 @@ the white reference are:</para>
       	  <term>The luminance (Y') and color difference (Cb and Cr) are obtained with the
 following <constant>V4L2_YCBCR_ENC_BT2020</constant> encoding:</term>
 	  <listitem>
-            <para>Y'&nbsp;=&nbsp;0.2627R'&nbsp;+&nbsp;0.6789G'&nbsp;+&nbsp;0.0593B'</para>
+            <para>Y'&nbsp;=&nbsp;0.2627R'&nbsp;+&nbsp;0.6780G'&nbsp;+&nbsp;0.0593B'</para>
             <para>Cb&nbsp;=&nbsp;-0.1396R'&nbsp;-&nbsp;0.3604G'&nbsp;+&nbsp;0.5B'</para>
             <para>Cr&nbsp;=&nbsp;0.5R'&nbsp;-&nbsp;0.4598G'&nbsp;-&nbsp;0.0402B'</para>
 	  </listitem>
@@ -1046,7 +1040,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 	<varlistentry>
       	  <term>Luma:</term>
 	  <listitem>
-            <para>Yc'&nbsp;=&nbsp;(0.2627R&nbsp;+&nbsp;0.6789G&nbsp;+&nbsp;0.0593B)'</para>
+            <para>Yc'&nbsp;=&nbsp;(0.2627R&nbsp;+&nbsp;0.6780G&nbsp;+&nbsp;0.0593B)'</para>
 	  </listitem>
 	</varlistentry>
       </variablelist>
@@ -1054,7 +1048,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 	<varlistentry>
       	  <term>B'&nbsp;-&nbsp;Yc'&nbsp;&le;&nbsp;0:</term>
 	  <listitem>
-            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;1.9404</para>
+            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.9404</para>
 	  </listitem>
 	</varlistentry>
       </variablelist>
@@ -1062,7 +1056,7 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 	<varlistentry>
       	  <term>B'&nbsp;-&nbsp;Yc'&nbsp;&gt;&nbsp;0:</term>
 	  <listitem>
-            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Y')&nbsp;/&nbsp;1.5816</para>
+            <para>Cbc&nbsp;=&nbsp;(B'&nbsp;-&nbsp;Yc')&nbsp;/&nbsp;1.5816</para>
 	  </listitem>
 	</varlistentry>
       </variablelist>
@@ -1086,8 +1080,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 clamped to the range [-0.5&hellip;0.5]. The Yc'CbcCrc quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-smpte-240m">Colorspace SMPTE 240M (<constant>V4L2_COLORSPACE_SMPTE240M</constant>)</title>
+    <section id="col-smpte-240m">
+      <title>Colorspace SMPTE 240M (<constant>V4L2_COLORSPACE_SMPTE240M</constant>)</title>
       <para>The <xref linkend="smpte240m" /> standard was an interim standard used during the early days of HDTV (1988-1998).
 It has been superseded by Rec. 709. The default Y'CbCr encoding is <constant>V4L2_YCBCR_ENC_SMPTE240M</constant>.
 The default Y'CbCr quantization is limited range. The chromaticities of the primary colors and the
@@ -1159,8 +1153,8 @@ following <constant>V4L2_YCBCR_ENC_SMPTE240M</constant> encoding:</term>
 clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range.</para>
     </section>
 
-    <section>
-      <title id="col-sysm">Colorspace NTSC 1953 (<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant>)</title>
+    <section id="col-sysm">
+      <title>Colorspace NTSC 1953 (<constant>V4L2_COLORSPACE_470_SYSTEM_M</constant>)</title>
       <para>This standard defines the colorspace used by NTSC in 1953. In practice this
 colorspace is obsolete and SMPTE 170M should be used instead. The default Y'CbCr encoding
 is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr quantization is limited range.
@@ -1237,8 +1231,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 This transform is identical to one defined in SMPTE 170M/BT.601.</para>
     </section>
 
-    <section>
-      <title id="col-sysbg">Colorspace EBU Tech. 3213 (<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant>)</title>
+    <section id="col-sysbg">
+      <title>Colorspace EBU Tech. 3213 (<constant>V4L2_COLORSPACE_470_SYSTEM_BG</constant>)</title>
       <para>The <xref linkend="tech3213" /> standard defines the colorspace used by PAL/SECAM in 1975. In practice this
 colorspace is obsolete and SMPTE 170M should be used instead. The default Y'CbCr encoding
 is <constant>V4L2_YCBCR_ENC_601</constant>. The default Y'CbCr quantization is limited range.
@@ -1311,8 +1305,8 @@ clamped to the range [-0.5&hellip;0.5]. The Y'CbCr quantization is limited range
 This transform is identical to one defined in SMPTE 170M/BT.601.</para>
     </section>
 
-    <section>
-      <title id="col-jpeg">Colorspace JPEG (<constant>V4L2_COLORSPACE_JPEG</constant>)</title>
+    <section id="col-jpeg">
+      <title>Colorspace JPEG (<constant>V4L2_COLORSPACE_JPEG</constant>)</title>
       <para>This colorspace defines the colorspace used by most (Motion-)JPEG formats. The chromaticities
 of the primary colors and the white reference are identical to sRGB. The Y'CbCr encoding is
 <constant>V4L2_YCBCR_ENC_601</constant> with full range quantization where

+ 434 - 337
Documentation/DocBook/media/v4l/subdev-formats.xml

@@ -482,6 +482,36 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>b<subscript>1</subscript></entry>
 	      <entry>b<subscript>0</subscript></entry>
 	    </row>
+	    <row id="MEDIA-BUS-FMT-RBG888-1X24">
+	      <entry>MEDIA_BUS_FMT_RBG888_1X24</entry>
+	      <entry>0x100e</entry>
+	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
 	    <row id="MEDIA-BUS-FMT-RGB666-1X24_CPADHI">
 	      <entry>MEDIA_BUS_FMT_RGB666_1X24_CPADHI</entry>
 	      <entry>0x1015</entry>
@@ -711,6 +741,43 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>b<subscript>1</subscript></entry>
 	      <entry>b<subscript>0</subscript></entry>
 	    </row>
+	    <row id="MEDIA-BUS-FMT-RGB888-1X32-PADHI">
+	      <entry>MEDIA_BUS_FMT_RGB888_1X32_PADHI</entry>
+	      <entry>0x100f</entry>
+	      <entry></entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
 	  </tbody>
 	</tgroup>
       </table>
@@ -2575,11 +2642,15 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-UYVY8-1X16">
-	      <entry>MEDIA_BUS_FMT_UYVY8_1X16</entry>
-	      <entry>0x200f</entry>
+	    <row id="MEDIA-BUS-FMT-UYVY12-2X12">
+	      <entry>MEDIA_BUS_FMT_UYVY12_2X12</entry>
+	      <entry>0x201c</entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2588,6 +2659,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2601,7 +2682,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2610,6 +2695,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>2</subscript></entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2619,11 +2714,15 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-VYUY8-1X16">
-	      <entry>MEDIA_BUS_FMT_VYUY8_1X16</entry>
-	      <entry>0x2010</entry>
+	    <row id="MEDIA-BUS-FMT-VYUY12-2X12">
+	      <entry>MEDIA_BUS_FMT_VYUY12_2X12</entry>
+	      <entry>0x201d</entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2632,6 +2731,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>2</subscript></entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2645,7 +2754,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2654,6 +2767,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2663,11 +2786,15 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YUYV8-1X16">
-	      <entry>MEDIA_BUS_FMT_YUYV8_1X16</entry>
-	      <entry>0x2011</entry>
+	    <row id="MEDIA-BUS-FMT-YUYV12-2X12">
+	      <entry>MEDIA_BUS_FMT_YUYV12_2X12</entry>
+	      <entry>0x201e</entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2676,6 +2803,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2689,7 +2826,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2698,6 +2839,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2707,11 +2858,15 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YVYU8-1X16">
-	      <entry>MEDIA_BUS_FMT_YVYU8_1X16</entry>
-	      <entry>0x2012</entry>
+	    <row id="MEDIA-BUS-FMT-YVYU12-2X12">
+	      <entry>MEDIA_BUS_FMT_YVYU12_2X12</entry>
+	      <entry>0x201f</entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2720,6 +2875,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>v<subscript>11</subscript></entry>
+	      <entry>v<subscript>10</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2733,7 +2898,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-16;
+	      &dash-ent-20;
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2742,6 +2911,16 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-20;
+	      <entry>u<subscript>11</subscript></entry>
+	      <entry>u<subscript>10</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2751,11 +2930,19 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YDYUYDYV8-1X16">
-	      <entry>MEDIA_BUS_FMT_YDYUYDYV8_1X16</entry>
-	      <entry>0x2014</entry>
+	    <row id="MEDIA-BUS-FMT-UYVY8-1X16">
+	      <entry>MEDIA_BUS_FMT_UYVY8_1X16</entry>
+	      <entry>0x200f</entry>
 	      <entry></entry>
 	      &dash-ent-16;
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2764,20 +2951,20 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
 	    </row>
 	    <row>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
 	      &dash-ent-16;
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2786,50 +2973,12 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>7</subscript></entry>
-	      <entry>u<subscript>6</subscript></entry>
-	      <entry>u<subscript>5</subscript></entry>
-	      <entry>u<subscript>4</subscript></entry>
-	      <entry>u<subscript>3</subscript></entry>
-	      <entry>u<subscript>2</subscript></entry>
-	      <entry>u<subscript>1</subscript></entry>
-	      <entry>u<subscript>0</subscript></entry>
 	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-16;
-	      <entry>y<subscript>7</subscript></entry>
-	      <entry>y<subscript>6</subscript></entry>
-	      <entry>y<subscript>5</subscript></entry>
-	      <entry>y<subscript>4</subscript></entry>
-	      <entry>y<subscript>3</subscript></entry>
-	      <entry>y<subscript>2</subscript></entry>
-	      <entry>y<subscript>1</subscript></entry>
-	      <entry>y<subscript>0</subscript></entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	      <entry>d</entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
+	    <row id="MEDIA-BUS-FMT-VYUY8-1X16">
+	      <entry>MEDIA_BUS_FMT_VYUY8_1X16</entry>
+	      <entry>0x2010</entry>
 	      <entry></entry>
 	      &dash-ent-16;
-	      <entry>y<subscript>7</subscript></entry>
-	      <entry>y<subscript>6</subscript></entry>
-	      <entry>y<subscript>5</subscript></entry>
-	      <entry>y<subscript>4</subscript></entry>
-	      <entry>y<subscript>3</subscript></entry>
-	      <entry>y<subscript>2</subscript></entry>
-	      <entry>y<subscript>1</subscript></entry>
-	      <entry>y<subscript>0</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2838,24 +2987,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>2</subscript></entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
-	    </row>
-	    <row id="MEDIA-BUS-FMT-UYVY10-1X20">
-	      <entry>MEDIA_BUS_FMT_UYVY10_1X20</entry>
-	      <entry>0x201a</entry>
-	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
-	      <entry>u<subscript>7</subscript></entry>
-	      <entry>u<subscript>6</subscript></entry>
-	      <entry>u<subscript>5</subscript></entry>
-	      <entry>u<subscript>4</subscript></entry>
-	      <entry>u<subscript>3</subscript></entry>
-	      <entry>u<subscript>2</subscript></entry>
-	      <entry>u<subscript>1</subscript></entry>
-	      <entry>u<subscript>0</subscript></entry>
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2869,61 +3000,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>v<subscript>9</subscript></entry>
-	      <entry>v<subscript>8</subscript></entry>
-	      <entry>v<subscript>7</subscript></entry>
-	      <entry>v<subscript>6</subscript></entry>
-	      <entry>v<subscript>5</subscript></entry>
-	      <entry>v<subscript>4</subscript></entry>
-	      <entry>v<subscript>3</subscript></entry>
-	      <entry>v<subscript>2</subscript></entry>
-	      <entry>v<subscript>1</subscript></entry>
-	      <entry>v<subscript>0</subscript></entry>
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
-	      <entry>y<subscript>7</subscript></entry>
-	      <entry>y<subscript>6</subscript></entry>
-	      <entry>y<subscript>5</subscript></entry>
-	      <entry>y<subscript>4</subscript></entry>
-	      <entry>y<subscript>3</subscript></entry>
-	      <entry>y<subscript>2</subscript></entry>
-	      <entry>y<subscript>1</subscript></entry>
-	      <entry>y<subscript>0</subscript></entry>
-	    </row>
-	    <row id="MEDIA-BUS-FMT-VYUY10-1X20">
-	      <entry>MEDIA_BUS_FMT_VYUY10_1X20</entry>
-	      <entry>0x201b</entry>
-	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>v<subscript>9</subscript></entry>
-	      <entry>v<subscript>8</subscript></entry>
-	      <entry>v<subscript>7</subscript></entry>
-	      <entry>v<subscript>6</subscript></entry>
-	      <entry>v<subscript>5</subscript></entry>
-	      <entry>v<subscript>4</subscript></entry>
-	      <entry>v<subscript>3</subscript></entry>
-	      <entry>v<subscript>2</subscript></entry>
-	      <entry>v<subscript>1</subscript></entry>
-	      <entry>v<subscript>0</subscript></entry>
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
-	      <entry>y<subscript>7</subscript></entry>
-	      <entry>y<subscript>6</subscript></entry>
-	      <entry>y<subscript>5</subscript></entry>
-	      <entry>y<subscript>4</subscript></entry>
-	      <entry>y<subscript>3</subscript></entry>
-	      <entry>y<subscript>2</subscript></entry>
-	      <entry>y<subscript>1</subscript></entry>
-	      <entry>y<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
+	      &dash-ent-16;
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2932,8 +3009,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2943,13 +3018,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YUYV10-1X20">
-	      <entry>MEDIA_BUS_FMT_YUYV10_1X20</entry>
-	      <entry>0x200d</entry>
+	    <row id="MEDIA-BUS-FMT-YUYV8-1X16">
+	      <entry>MEDIA_BUS_FMT_YUYV8_1X16</entry>
+	      <entry>0x2011</entry>
 	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2958,8 +3031,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -2973,9 +3044,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -2984,8 +3053,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>v<subscript>9</subscript></entry>
-	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -2995,13 +3062,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YVYU10-1X20">
-	      <entry>MEDIA_BUS_FMT_YVYU10_1X20</entry>
-	      <entry>0x200e</entry>
+	    <row id="MEDIA-BUS-FMT-YVYU8-1X16">
+	      <entry>MEDIA_BUS_FMT_YVYU8_1X16</entry>
+	      <entry>0x2012</entry>
 	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -3010,8 +3075,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>v<subscript>9</subscript></entry>
-	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -3025,9 +3088,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-12;
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -3036,8 +3097,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -3047,18 +3106,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YUV8-1X24">
-	      <entry>MEDIA_BUS_FMT_YUV8_1X24</entry>
-	      <entry>0x2025</entry>
+	    <row id="MEDIA-BUS-FMT-YDYUYDYV8-1X16">
+	      <entry>MEDIA_BUS_FMT_YDYUYDYV8_1X16</entry>
+	      <entry>0x2014</entry>
 	      <entry></entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -3067,31 +3119,20 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>7</subscript></entry>
-	      <entry>u<subscript>6</subscript></entry>
-	      <entry>u<subscript>5</subscript></entry>
-	      <entry>u<subscript>4</subscript></entry>
-	      <entry>u<subscript>3</subscript></entry>
-	      <entry>u<subscript>2</subscript></entry>
-	      <entry>u<subscript>1</subscript></entry>
-	      <entry>u<subscript>0</subscript></entry>
-	      <entry>v<subscript>7</subscript></entry>
-	      <entry>v<subscript>6</subscript></entry>
-	      <entry>v<subscript>5</subscript></entry>
-	      <entry>v<subscript>4</subscript></entry>
-	      <entry>v<subscript>3</subscript></entry>
-	      <entry>v<subscript>2</subscript></entry>
-	      <entry>v<subscript>1</subscript></entry>
-	      <entry>v<subscript>0</subscript></entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YUV10-1X30">
-	      <entry>MEDIA_BUS_FMT_YUV10_1X30</entry>
-	      <entry>0x2016</entry>
+	    <row>
 	      <entry></entry>
-	      <entry>-</entry>
-	      <entry>-</entry>
-	      <entry>y<subscript>9</subscript></entry>
-	      <entry>y<subscript>8</subscript></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -3100,8 +3141,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -3110,29 +3149,34 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
-	      <entry>v<subscript>9</subscript></entry>
-	      <entry>v<subscript>8</subscript></entry>
-	      <entry>v<subscript>7</subscript></entry>
-	      <entry>v<subscript>6</subscript></entry>
-	      <entry>v<subscript>5</subscript></entry>
-	      <entry>v<subscript>4</subscript></entry>
-	      <entry>v<subscript>3</subscript></entry>
-	      <entry>v<subscript>2</subscript></entry>
-	      <entry>v<subscript>1</subscript></entry>
-	      <entry>v<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-AYUV8-1X32">
-	      <entry>MEDIA_BUS_FMT_AYUV8_1X32</entry>
-	      <entry>0x2017</entry>
+	    <row>
 	      <entry></entry>
-	      <entry>a<subscript>7</subscript></entry>
-	      <entry>a<subscript>6</subscript></entry>
-	      <entry>a<subscript>5</subscript></entry>
-	      <entry>a<subscript>4</subscript></entry>
-	      <entry>a<subscript>3</subscript></entry>
-	      <entry>a<subscript>2</subscript></entry>
-	      <entry>a<subscript>1</subscript></entry>
-	      <entry>a<subscript>0</subscript></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-16;
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	      <entry>d</entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      &dash-ent-16;
 	      <entry>y<subscript>7</subscript></entry>
 	      <entry>y<subscript>6</subscript></entry>
 	      <entry>y<subscript>5</subscript></entry>
@@ -3141,14 +3185,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	      <entry>u<subscript>7</subscript></entry>
-	      <entry>u<subscript>6</subscript></entry>
-	      <entry>u<subscript>5</subscript></entry>
-	      <entry>u<subscript>4</subscript></entry>
-	      <entry>u<subscript>3</subscript></entry>
-	      <entry>u<subscript>2</subscript></entry>
-	      <entry>u<subscript>1</subscript></entry>
-	      <entry>u<subscript>0</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
 	      <entry>v<subscript>6</subscript></entry>
 	      <entry>v<subscript>5</subscript></entry>
@@ -3158,13 +3194,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-UYVY12-2X12">
-	      <entry>MEDIA_BUS_FMT_UYVY12_2X12</entry>
-	      <entry>0x201c</entry>
+	    <row id="MEDIA-BUS-FMT-UYVY10-1X20">
+	      <entry>MEDIA_BUS_FMT_UYVY10_1X20</entry>
+	      <entry>0x201a</entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>u<subscript>11</subscript></entry>
-	      <entry>u<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>u<subscript>9</subscript></entry>
 	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
@@ -3175,14 +3209,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3198,9 +3224,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>v<subscript>11</subscript></entry>
-	      <entry>v<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>v<subscript>9</subscript></entry>
 	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
@@ -3211,14 +3235,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>2</subscript></entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3230,13 +3246,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-VYUY12-2X12">
-	      <entry>MEDIA_BUS_FMT_VYUY12_2X12</entry>
-	      <entry>0x201d</entry>
+	    <row id="MEDIA-BUS-FMT-VYUY10-1X20">
+	      <entry>MEDIA_BUS_FMT_VYUY10_1X20</entry>
+	      <entry>0x201b</entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>v<subscript>11</subscript></entry>
-	      <entry>v<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>v<subscript>9</subscript></entry>
 	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
@@ -3247,14 +3261,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>2</subscript></entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3270,9 +3276,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>u<subscript>11</subscript></entry>
-	      <entry>u<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>u<subscript>9</subscript></entry>
 	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
@@ -3283,14 +3287,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3302,13 +3298,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YUYV12-2X12">
-	      <entry>MEDIA_BUS_FMT_YUYV12_2X12</entry>
-	      <entry>0x201e</entry>
+	    <row id="MEDIA-BUS-FMT-YUYV10-1X20">
+	      <entry>MEDIA_BUS_FMT_YUYV10_1X20</entry>
+	      <entry>0x200d</entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3319,14 +3313,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>u<subscript>11</subscript></entry>
-	      <entry>u<subscript>10</subscript></entry>
 	      <entry>u<subscript>9</subscript></entry>
 	      <entry>u<subscript>8</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
@@ -3342,9 +3328,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3355,14 +3339,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>v<subscript>11</subscript></entry>
-	      <entry>v<subscript>10</subscript></entry>
 	      <entry>v<subscript>9</subscript></entry>
 	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
@@ -3374,13 +3350,11 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>v<subscript>1</subscript></entry>
 	      <entry>v<subscript>0</subscript></entry>
 	    </row>
-	    <row id="MEDIA-BUS-FMT-YVYU12-2X12">
-	      <entry>MEDIA_BUS_FMT_YVYU12_2X12</entry>
-	      <entry>0x201f</entry>
+	    <row id="MEDIA-BUS-FMT-YVYU10-1X20">
+	      <entry>MEDIA_BUS_FMT_YVYU10_1X20</entry>
+	      <entry>0x200e</entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3391,14 +3365,6 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
-	    </row>
-	    <row>
-	      <entry></entry>
-	      <entry></entry>
-	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>v<subscript>11</subscript></entry>
-	      <entry>v<subscript>10</subscript></entry>
 	      <entry>v<subscript>9</subscript></entry>
 	      <entry>v<subscript>8</subscript></entry>
 	      <entry>v<subscript>7</subscript></entry>
@@ -3414,9 +3380,7 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry></entry>
 	      <entry></entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>y<subscript>11</subscript></entry>
-	      <entry>y<subscript>10</subscript></entry>
+	      &dash-ent-12;
 	      <entry>y<subscript>9</subscript></entry>
 	      <entry>y<subscript>8</subscript></entry>
 	      <entry>y<subscript>7</subscript></entry>
@@ -3427,16 +3391,67 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>y<subscript>2</subscript></entry>
 	      <entry>y<subscript>1</subscript></entry>
 	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
 	    </row>
-	    <row>
-	      <entry></entry>
+	    <row id="MEDIA-BUS-FMT-VUY8-1X24">
+	      <entry>MEDIA_BUS_FMT_VUY8_1X24</entry>
+	      <entry>0x201a</entry>
 	      <entry></entry>
+	      &dash-ent-8;
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="MEDIA-BUS-FMT-YUV8-1X24">
+	      <entry>MEDIA_BUS_FMT_YUV8_1X24</entry>
+	      <entry>0x2025</entry>
 	      <entry></entry>
-	      &dash-ent-20;
-	      <entry>u<subscript>11</subscript></entry>
-	      <entry>u<subscript>10</subscript></entry>
-	      <entry>u<subscript>9</subscript></entry>
-	      <entry>u<subscript>8</subscript></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
 	      <entry>u<subscript>7</subscript></entry>
 	      <entry>u<subscript>6</subscript></entry>
 	      <entry>u<subscript>5</subscript></entry>
@@ -3445,6 +3460,14 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>2</subscript></entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
 	    </row>
 	    <row id="MEDIA-BUS-FMT-UYVY12-1X24">
 	      <entry>MEDIA_BUS_FMT_UYVY12_1X24</entry>
@@ -3686,6 +3709,80 @@ see <xref linkend="colorspaces" />.</entry>
 	      <entry>u<subscript>1</subscript></entry>
 	      <entry>u<subscript>0</subscript></entry>
 	    </row>
+	    <row id="MEDIA-BUS-FMT-YUV10-1X30">
+	      <entry>MEDIA_BUS_FMT_YUV10_1X30</entry>
+	      <entry>0x2016</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="MEDIA-BUS-FMT-AYUV8-1X32">
+	      <entry>MEDIA_BUS_FMT_AYUV8_1X32</entry>
+	      <entry>0x2017</entry>
+	      <entry></entry>
+	      <entry>a<subscript>7</subscript></entry>
+	      <entry>a<subscript>6</subscript></entry>
+	      <entry>a<subscript>5</subscript></entry>
+	      <entry>a<subscript>4</subscript></entry>
+	      <entry>a<subscript>3</subscript></entry>
+	      <entry>a<subscript>2</subscript></entry>
+	      <entry>a<subscript>1</subscript></entry>
+	      <entry>a<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
 	  </tbody>
 	</tgroup>
       </table>

+ 9 - 0
Documentation/DocBook/media/v4l/v4l2.xml

@@ -136,6 +136,7 @@ Remote Controller chapter.</contrib>
       <year>2012</year>
       <year>2013</year>
       <year>2014</year>
+      <year>2015</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
 	Pawel Osciak</holder>
@@ -151,6 +152,14 @@ structs, ioctls) must be noted in more detail in the history chapter
 (compat.xml), along with the possible impact on existing drivers and
 applications. -->
 
+      <revision>
+	<revnumber>3.21</revnumber>
+	<date>2015-02-13</date>
+	<authorinitials>mcc</authorinitials>
+	<revremark>Fix documentation for media controller device nodes and add support for DVB device nodes.
+Add support for Tuner sub-device.
+	</revremark>
+      </revision>
       <revision>
 	<revnumber>3.19</revnumber>
 	<date>2014-12-05</date>

+ 6 - 3
Documentation/DocBook/media/v4l/vidioc-cropcap.xml

@@ -59,6 +59,11 @@ constant except when switching the video standard. Remember this
 switch can occur implicit when switching the video input or
 output.</para>
 
+<para>Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
+and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
+
     <para>This ioctl must be implemented for video capture or output devices that
 support cropping and/or scaling and/or have non-square pixels, and for overlay devices.</para>
 
@@ -73,9 +78,7 @@ support cropping and/or scaling and/or have non-square pixels, and for overlay d
 	    <entry>Type of the data stream, set by the application.
 Only these types are valid here:
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and
 <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
 	  </row>
 	  <row>

+ 114 - 7
Documentation/DocBook/media/v4l/vidioc-dqevent.xml

@@ -64,7 +64,7 @@
 	    <entry>__u32</entry>
 	    <entry><structfield>type</structfield></entry>
             <entry></entry>
-	    <entry>Type of the event.</entry>
+	    <entry>Type of the event, see <xref linkend="event-type" />.</entry>
 	  </row>
 	  <row>
 	    <entry>union</entry>
@@ -154,6 +154,113 @@
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="event-type">
+      <title>Event Types</title>
+      <tgroup cols="3">
+	&cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>V4L2_EVENT_ALL</constant></entry>
+	    <entry>0</entry>
+	    <entry>All events. V4L2_EVENT_ALL is valid only for
+	    VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
+	    <entry>1</entry>
+	    <entry>This event is triggered on the vertical sync.
+	    This event has a &v4l2-event-vsync; associated with it.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_EOS</constant></entry>
+	    <entry>2</entry>
+	    <entry>This event is triggered when the end of a stream is reached.
+	    This is typically used with MPEG decoders to report to the application
+	    when the last of the MPEG stream has been decoded.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_CTRL</constant></entry>
+	    <entry>3</entry>
+	    <entry><para>This event requires that the <structfield>id</structfield>
+		matches the control ID from which you want to receive events.
+		This event is triggered if the control's value changes, if a
+		button control is pressed or if the control's flags change.
+	    	This event has a &v4l2-event-ctrl; associated with it. This struct
+		contains much of the same information as &v4l2-queryctrl; and
+		&v4l2-control;.</para>
+
+		<para>If the event is generated due to a call to &VIDIOC-S-CTRL; or
+		&VIDIOC-S-EXT-CTRLS;, then the event will <emphasis>not</emphasis> be sent to
+		the file handle that called the ioctl function. This prevents
+		nasty feedback loops. If you <emphasis>do</emphasis> want to get the
+		event, then set the <constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant>
+		flag.
+		</para>
+
+		<para>This event type will ensure that no information is lost when
+		more events are raised than there is room internally. In that
+		case the &v4l2-event-ctrl; of the second-oldest event is kept,
+		but the <structfield>changes</structfield> field of the
+		second-oldest event is ORed with the <structfield>changes</structfield>
+		field of the oldest event.</para>
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
+	    <entry>4</entry>
+	    <entry>
+	      <para>Triggered immediately when the reception of a
+	      frame has begun. This event has a
+	      &v4l2-event-frame-sync; associated with it.</para>
+
+	      <para>If the hardware needs to be stopped in the case of a
+	      buffer underrun it might not be able to generate this event.
+	      In such cases the <structfield>frame_sequence</structfield>
+	      field in &v4l2-event-frame-sync; will not be incremented. This
+	      causes two consecutive frame sequence numbers to have n times
+	      frame interval in between them.</para>
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
+	    <entry>5</entry>
+	    <entry>
+	      <para>This event is triggered when a source parameter change is
+	       detected during runtime by the video device. It can be a
+	       runtime resolution change triggered by a video decoder or the
+	       format change happening on an input connector.
+	       This event requires that the <structfield>id</structfield>
+	       matches the input index (when used with a video device node)
+	       or the pad index (when used with a subdevice node) from which
+	       you want to receive events.</para>
+
+              <para>This event has a &v4l2-event-src-change; associated
+	      with it. The <structfield>changes</structfield> bitfield denotes
+	      what has changed for the subscribed pad. If multiple events
+	      occurred before application could dequeue them, then the changes
+	      will have the ORed value of all the events generated.</para>
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
+	    <entry>6</entry>
+	    <entry>
+	      <para>Triggered whenever the motion detection state for one or more of the regions
+	      changes. This event has a &v4l2-event-motion-det; associated with it.</para>
+	    </entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
+	    <entry>0x08000000</entry>
+	    <entry>Base event number for driver-private events.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
     <table frame="none" pgwide="1" id="v4l2-event-vsync">
       <title>struct <structname>v4l2_event_vsync</structname></title>
       <tgroup cols="3">
@@ -177,7 +284,7 @@
 	    <entry>__u32</entry>
 	    <entry><structfield>changes</structfield></entry>
 	    <entry></entry>
-	    <entry>A bitmask that tells what has changed. See <xref linkend="changes-flags" />.</entry>
+	    <entry>A bitmask that tells what has changed. See <xref linkend="ctrl-changes-flags" />.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -309,8 +416,8 @@
       </tgroup>
     </table>
 
-    <table pgwide="1" frame="none" id="changes-flags">
-      <title>Changes</title>
+    <table pgwide="1" frame="none" id="ctrl-changes-flags">
+      <title>Control Changes</title>
       <tgroup cols="3">
 	&cs-def;
 	<tbody valign="top">
@@ -318,9 +425,9 @@
 	    <entry><constant>V4L2_EVENT_CTRL_CH_VALUE</constant></entry>
 	    <entry>0x0001</entry>
 	    <entry>This control event was triggered because the value of the control
-		changed. Special case: if a button control is pressed, then this
-		event is sent as well, even though there is not explicit value
-		associated with a button control.</entry>
+		changed. Special cases: Volatile controls do no generate this event;
+		If a control has the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant>
+		flag set, then this event is sent as well, regardless its value.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_EVENT_CTRL_CH_FLAGS</constant></entry>

+ 5 - 0
Documentation/DocBook/media/v4l/vidioc-g-crop.xml

@@ -70,6 +70,11 @@ structure or returns the &EINVAL; if cropping is not supported.</para>
 <constant>VIDIOC_S_CROP</constant> ioctl with a pointer to this
 structure.</para>
 
+<para>Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
+and use <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.</para>
+
     <para>The driver first adjusts the requested dimensions against
 hardware limits, &ie; the bounds given by the capture/output window,
 and it rounds to the closest possible values of horizontal and

+ 14 - 4
Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml

@@ -318,10 +318,20 @@ can't generate such frequencies, then the flag will also be cleared.
 	  </row>
 	  <row>
 	    <entry>V4L2_DV_FL_HALF_LINE</entry>
-	    <entry>Specific to interlaced formats: if set, then field 1 (aka the odd field)
-is really one half-line longer and field 2 (aka the even field) is really one half-line
-shorter, so each field has exactly the same number of half-lines. Whether half-lines can be
-detected or used depends on the hardware.
+	    <entry>Specific to interlaced formats: if set, then the vertical frontporch
+of field 1 (aka the odd field) is really one half-line longer and the vertical backporch
+of field 2 (aka the even field) is really one half-line shorter, so each field has exactly
+the same number of half-lines. Whether half-lines can be detected or used depends on
+the hardware.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_DV_FL_IS_CE_VIDEO</entry>
+	    <entry>If set, then this is a Consumer Electronics (CE) video format.
+Such formats differ from other formats (commonly called IT formats) in that if
+R'G'B' encoding is used then by default the R'G'B' values use limited range
+(i.e. 16-235) as opposed to full range (i.e. 0-255). All formats defined in CEA-861
+except for the 640x480p59.94 format are CE formats.
 	    </entry>
 	  </row>
 	</tbody>

+ 2 - 2
Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml

@@ -240,9 +240,9 @@ where padding bytes after the last line of an image cross a system
 page boundary. Capture devices may write padding bytes, the value is
 undefined. Output devices ignore the contents of padding
 bytes.</para><para>When the image format is planar the
-<structfield>bytesperline</structfield> value applies to the largest
+<structfield>bytesperline</structfield> value applies to the first
 plane and is divided by the same factor as the
-<structfield>width</structfield> field for any smaller planes. For
+<structfield>width</structfield> field for the other planes. For
 example the Cb and Cr planes of a YUV 4:2:0 image have half as many
 padding bytes following each line as the Y plane. To avoid ambiguities
 drivers must return a <structfield>bytesperline</structfield> value

+ 2 - 2
Documentation/DocBook/media/v4l/vidioc-g-selection.xml

@@ -60,8 +60,8 @@
 
 <para>To query the cropping (composing) rectangle set &v4l2-selection;
 <structfield> type </structfield> field to the respective buffer type.
-Do not use multiplanar buffers.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
-instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>.  Use
+Do not use the multiplanar buffer types.  Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and use
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>.  The next step is
 setting the value of &v4l2-selection; <structfield>target</structfield> field

+ 4 - 4
Documentation/DocBook/media/v4l/vidioc-querycap.xml

@@ -102,10 +102,10 @@ The bus_info must start with "PCI:" for PCI boards, "PCIe:" for PCI Express boar
 	    <entry>__u32</entry>
 	    <entry><structfield>version</structfield></entry>
 	    <entry><para>Version number of the driver.</para>
-<para>Starting on kernel 3.1, the version reported is provided per
-V4L2 subsystem, following the same Kernel numberation scheme. However, it
-should not always return the same version as the kernel, if, for example,
-an stable or distribution-modified kernel uses the V4L2 stack from a
+<para>Starting with kernel 3.1, the version reported is provided by the
+V4L2 subsystem following the kernel numbering scheme. However, it
+may not always return the same version as the kernel if, for example,
+a stable or distribution-modified kernel uses the V4L2 stack from a
 newer kernel.</para>
 <para>The version number is formatted using the
 <constant>KERNEL_VERSION()</constant> macro:</para></entry>

+ 11 - 1
Documentation/DocBook/media/v4l/vidioc-queryctrl.xml

@@ -600,7 +600,9 @@ writing a value will cause the device to carry out a given action
 changes continuously. A typical example would be the current gain value if the device
 is in auto-gain mode. In such a case the hardware calculates the gain value based on
 the lighting conditions which can change over time. Note that setting a new value for
-a volatile control will have no effect. The new value will just be ignored.</entry>
+a volatile control will have no effect and no <constant>V4L2_EVENT_CTRL_CH_VALUE</constant>
+will be sent, unless the <constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant> flag
+(see below) is also set. Otherwise the new value will just be ignored.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
@@ -610,6 +612,14 @@ using one of the pointer fields of &v4l2-ext-control;. This flag is set for cont
 that are an array, string, or have a compound type. In all cases you have to set a
 pointer to memory containing the payload of the control.</entry>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CTRL_FLAG_EXECUTE_ON_WRITE</constant></entry>
+	    <entry>0x0200</entry>
+	    <entry>The value provided to the control will be propagated to the driver
+even if remains constant. This is required when the control represents an action
+on the hardware. For example: clearing an error flag or triggering the flash. All the
+controls of the type <constant>V4L2_CTRL_TYPE_BUTTON</constant> have this flag set.</entry>
+	  </row>
 	</tbody>
       </tgroup>
     </table>

+ 9 - 4
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-interval.xml

@@ -67,9 +67,9 @@
 
     <para>To enumerate frame intervals applications initialize the
     <structfield>index</structfield>, <structfield>pad</structfield>,
-    <structfield>code</structfield>, <structfield>width</structfield> and
-    <structfield>height</structfield> fields of
-    &v4l2-subdev-frame-interval-enum; and call the
+    <structfield>which</structfield>, <structfield>code</structfield>,
+    <structfield>width</structfield> and <structfield>height</structfield>
+    fields of &v4l2-subdev-frame-interval-enum; and call the
     <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
     to this structure. Drivers fill the rest of the structure or return
     an &EINVAL; if one of the input fields is invalid. All frame intervals are
@@ -123,7 +123,12 @@
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry><structfield>which</structfield></entry>
+	    <entry>Frame intervals to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
 	    <entry>Reserved for future extensions. Applications and drivers must
 	    set the array to zero.</entry>
 	  </row>

+ 9 - 4
Documentation/DocBook/media/v4l/vidioc-subdev-enum-frame-size.xml

@@ -61,9 +61,9 @@
     ioctl.</para>
 
     <para>To enumerate frame sizes applications initialize the
-    <structfield>pad</structfield>, <structfield>code</structfield> and
-    <structfield>index</structfield> fields of the
-    &v4l2-subdev-mbus-code-enum; and call the
+    <structfield>pad</structfield>, <structfield>which</structfield> ,
+    <structfield>code</structfield> and <structfield>index</structfield>
+    fields of the &v4l2-subdev-mbus-code-enum; and call the
     <constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant> ioctl with a pointer to
     the structure. Drivers fill the minimum and maximum frame sizes or return
     an &EINVAL; if one of the input parameters is invalid.</para>
@@ -127,7 +127,12 @@
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry><structfield>which</structfield></entry>
+	    <entry>Frame sizes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
 	    <entry>Reserved for future extensions. Applications and drivers must
 	    set the array to zero.</entry>
 	  </row>

+ 8 - 3
Documentation/DocBook/media/v4l/vidioc-subdev-enum-mbus-code.xml

@@ -56,8 +56,8 @@
     </note>
 
     <para>To enumerate media bus formats available at a given sub-device pad
-    applications initialize the <structfield>pad</structfield> and
-    <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
+    applications initialize the <structfield>pad</structfield>, <structfield>which</structfield>
+    and <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
     call the <constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant> ioctl with a
     pointer to this structure. Drivers fill the rest of the structure or return
     an &EINVAL; if either the <structfield>pad</structfield> or
@@ -93,7 +93,12 @@
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry><structfield>which</structfield></entry>
+	    <entry>Media bus format codes to be enumerated, from &v4l2-subdev-format-whence;.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
 	    <entry>Reserved for future extensions. Applications and drivers must
 	    set the array to zero.</entry>
 	  </row>

+ 3 - 108
Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml

@@ -60,7 +60,9 @@
 	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>type</structfield></entry>
-	    <entry>Type of the event.</entry>
+	    <entry>Type of the event, see <xref linkend="event-type" />. Note that
+<constant>V4L2_EVENT_ALL</constant> can be used with VIDIOC_UNSUBSCRIBE_EVENT
+for unsubscribing all events at once.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -84,113 +86,6 @@
       </tgroup>
     </table>
 
-    <table frame="none" pgwide="1" id="event-type">
-      <title>Event Types</title>
-      <tgroup cols="3">
-	&cs-def;
-	<tbody valign="top">
-	  <row>
-	    <entry><constant>V4L2_EVENT_ALL</constant></entry>
-	    <entry>0</entry>
-	    <entry>All events. V4L2_EVENT_ALL is valid only for
-	    VIDIOC_UNSUBSCRIBE_EVENT for unsubscribing all events at once.
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_VSYNC</constant></entry>
-	    <entry>1</entry>
-	    <entry>This event is triggered on the vertical sync.
-	    This event has a &v4l2-event-vsync; associated with it.
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_EOS</constant></entry>
-	    <entry>2</entry>
-	    <entry>This event is triggered when the end of a stream is reached.
-	    This is typically used with MPEG decoders to report to the application
-	    when the last of the MPEG stream has been decoded.
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_CTRL</constant></entry>
-	    <entry>3</entry>
-	    <entry><para>This event requires that the <structfield>id</structfield>
-		matches the control ID from which you want to receive events.
-		This event is triggered if the control's value changes, if a
-		button control is pressed or if the control's flags change.
-	    	This event has a &v4l2-event-ctrl; associated with it. This struct
-		contains much of the same information as &v4l2-queryctrl; and
-		&v4l2-control;.</para>
-
-		<para>If the event is generated due to a call to &VIDIOC-S-CTRL; or
-		&VIDIOC-S-EXT-CTRLS;, then the event will <emphasis>not</emphasis> be sent to
-		the file handle that called the ioctl function. This prevents
-		nasty feedback loops. If you <emphasis>do</emphasis> want to get the
-		event, then set the <constant>V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK</constant>
-		flag.
-		</para>
-
-		<para>This event type will ensure that no information is lost when
-		more events are raised than there is room internally. In that
-		case the &v4l2-event-ctrl; of the second-oldest event is kept,
-		but the <structfield>changes</structfield> field of the
-		second-oldest event is ORed with the <structfield>changes</structfield>
-		field of the oldest event.</para>
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_FRAME_SYNC</constant></entry>
-	    <entry>4</entry>
-	    <entry>
-	      <para>Triggered immediately when the reception of a
-	      frame has begun. This event has a
-	      &v4l2-event-frame-sync; associated with it.</para>
-
-	      <para>If the hardware needs to be stopped in the case of a
-	      buffer underrun it might not be able to generate this event.
-	      In such cases the <structfield>frame_sequence</structfield>
-	      field in &v4l2-event-frame-sync; will not be incremented. This
-	      causes two consecutive frame sequence numbers to have n times
-	      frame interval in between them.</para>
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_SOURCE_CHANGE</constant></entry>
-	    <entry>5</entry>
-	    <entry>
-	      <para>This event is triggered when a source parameter change is
-	       detected during runtime by the video device. It can be a
-	       runtime resolution change triggered by a video decoder or the
-	       format change happening on an input connector.
-	       This event requires that the <structfield>id</structfield>
-	       matches the input index (when used with a video device node)
-	       or the pad index (when used with a subdevice node) from which
-	       you want to receive events.</para>
-
-              <para>This event has a &v4l2-event-src-change; associated
-	      with it. The <structfield>changes</structfield> bitfield denotes
-	      what has changed for the subscribed pad. If multiple events
-	      occurred before application could dequeue them, then the changes
-	      will have the ORed value of all the events generated.</para>
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
-	    <entry>6</entry>
-	    <entry>
-	      <para>Triggered whenever the motion detection state for one or more of the regions
-	      changes. This event has a &v4l2-event-motion-det; associated with it.</para>
-	    </entry>
-	  </row>
-	  <row>
-	    <entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
-	    <entry>0x08000000</entry>
-	    <entry>Base event number for driver-private events.</entry>
-	  </row>
-	</tbody>
-      </tgroup>
-    </table>
-
     <table pgwide="1" frame="none" id="event-flags">
       <title>Event Flags</title>
       <tgroup cols="3">

+ 1 - 1
Documentation/devicetree/bindings/media/exynos-jpeg-codec.txt

@@ -4,7 +4,7 @@ Required properties:
 
 - compatible	: should be one of:
 		  "samsung,s5pv210-jpeg", "samsung,exynos4210-jpeg",
-		  "samsung,exynos3250-jpeg";
+		  "samsung,exynos3250-jpeg", "samsung,exynos5420-jpeg";
 - reg		: address and length of the JPEG codec IP register set;
 - interrupts	: specifies the JPEG codec IP interrupt;
 - clock-names   : should contain:

+ 39 - 0
Documentation/devicetree/bindings/media/i2c/mt9v032.txt

@@ -0,0 +1,39 @@
+* Aptina 1/3-Inch WVGA CMOS Digital Image Sensor
+
+The Aptina MT9V032 is a 1/3-inch CMOS active pixel digital image sensor with
+an active array size of 752H x 480V. It is programmable through a simple
+two-wire serial interface.
+
+Required Properties:
+
+- compatible: value should be either one among the following
+	(a) "aptina,mt9v022" for MT9V022 color sensor
+	(b) "aptina,mt9v022m" for MT9V022 monochrome sensor
+	(c) "aptina,mt9v024" for MT9V024 color sensor
+	(d) "aptina,mt9v024m" for MT9V024 monochrome sensor
+	(e) "aptina,mt9v032" for MT9V032 color sensor
+	(f) "aptina,mt9v032m" for MT9V032 monochrome sensor
+	(g) "aptina,mt9v034" for MT9V034 color sensor
+	(h) "aptina,mt9v034m" for MT9V034 monochrome sensor
+
+Optional Properties:
+
+- link-frequencies: List of allowed link frequencies in Hz. Each frequency is
+	expressed as a 64-bit big-endian integer.
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+	mt9v032@5c {
+		compatible = "aptina,mt9v032";
+		reg = <0x5c>;
+
+		port {
+			mt9v032_out: endpoint {
+				link-frequencies = /bits/ 64
+					<13000000 26600000 27000000>;
+			};
+		};
+	};

+ 46 - 0
Documentation/devicetree/bindings/media/i2c/ov2640.txt

@@ -0,0 +1,46 @@
+* Omnivision OV2640 CMOS sensor
+
+The Omnivision OV2640 sensor support multiple resolutions output, such as
+CIF, SVGA, UXGA. It also can support YUV422/420, RGB565/555 or raw RGB
+output format.
+
+Required Properties:
+- compatible: should be "ovti,ov2640"
+- clocks: reference to the xvclk input clock.
+- clock-names: should be "xvclk".
+
+Optional Properties:
+- resetb-gpios: reference to the GPIO connected to the resetb pin, if any.
+- pwdn-gpios: reference to the GPIO connected to the pwdn pin, if any.
+
+The device node must contain one 'port' child node for its digital output
+video port, in accordance with the video interface bindings defined in
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+	i2c1: i2c@f0018000 {
+		ov2640: camera@0x30 {
+			compatible = "ovti,ov2640";
+			reg = <0x30>;
+
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_pck1 &pinctrl_ov2640_pwdn &pinctrl_ov2640_resetb>;
+
+			resetb-gpios = <&pioE 24 GPIO_ACTIVE_LOW>;
+			pwdn-gpios = <&pioE 29 GPIO_ACTIVE_HIGH>;
+
+			clocks = <&pck1>;
+			clock-names = "xvclk";
+
+			assigned-clocks = <&pck1>;
+			assigned-clock-rates = <25000000>;
+
+			port {
+				ov2640_0: endpoint {
+					remote-endpoint = <&isi_0>;
+					bus-width = <8>;
+				};
+			};
+		};
+	};

+ 38 - 0
Documentation/devicetree/bindings/media/i2c/ov2659.txt

@@ -0,0 +1,38 @@
+* OV2659 1/5-Inch 2Mp SOC Camera
+
+The Omnivision OV2659 is a 1/5-inch SOC camera, with an active array size of
+1632H x 1212V. It is programmable through a SCCB. The OV2659 sensor supports
+multiple resolutions output, such as UXGA, SVGA, 720p. It also can support
+YUV422, RGB565/555 or raw RGB output formats.
+
+Required Properties:
+- compatible: Must be "ovti,ov2659"
+- reg: I2C slave address
+- clocks: reference to the xvclk input clock.
+- clock-names: should be "xvclk".
+- link-frequencies: target pixel clock frequency.
+
+For further reading on port node refer to
+Documentation/devicetree/bindings/media/video-interfaces.txt.
+
+Example:
+
+	i2c0@1c22000 {
+		...
+		...
+		 ov2659@30 {
+			compatible = "ovti,ov2659";
+			reg = <0x30>;
+
+			clocks = <&clk_ov2659 0>;
+			clock-names = "xvclk";
+
+			port {
+				ov2659_0: endpoint {
+					remote-endpoint = <&vpfe_ep>;
+					link-frequencies = /bits/ 64 <70000000>;
+				};
+			};
+		};
+		...
+	};

+ 6 - 0
Documentation/devicetree/bindings/media/video-interfaces.txt

@@ -106,6 +106,12 @@ Optional endpoint properties
 - link-frequencies: Allowed data bus frequencies. For MIPI CSI-2, for
   instance, this is the actual frequency of the bus, not bits per clock per
   lane value. An array of 64-bit unsigned integers.
+- lane-polarities: an array of polarities of the lanes starting from the clock
+  lane and followed by the data lanes in the same order as in data-lanes.
+  Valid values are 0 (normal) and 1 (inverted). The length of the array
+  should be the combined length of data-lanes and clock-lanes properties.
+  If the lane-polarities property is omitted, the value must be interpreted
+  as 0 (normal). This property is valid for serial busses only.
 
 
 Example

+ 35 - 0
Documentation/devicetree/bindings/media/xilinx/video.txt

@@ -0,0 +1,35 @@
+DT bindings for Xilinx video IP cores
+-------------------------------------
+
+Xilinx video IP cores process video streams by acting as video sinks and/or
+sources. They are connected by links through their input and output ports,
+creating a video pipeline.
+
+Each video IP core is represented by an AMBA bus child node in the device
+tree using bindings documented in this directory. Connections between the IP
+cores are represented as defined in ../video-interfaces.txt.
+
+The whole  pipeline is represented by an AMBA bus child node in the device
+tree using bindings documented in ./xlnx,video.txt.
+
+Common properties
+-----------------
+
+The following properties are common to all Xilinx video IP cores.
+
+- xlnx,video-format: This property represents a video format transmitted on an
+  AXI bus between video IP cores, using its VF code as defined in "AXI4-Stream
+  Video IP and System Design Guide" [UG934]. How the format relates to the IP
+  core is decribed in the IP core bindings documentation.
+
+- xlnx,video-width: This property qualifies the video format with the sample
+  width expressed as a number of bits per pixel component. All components must
+  use the same width.
+
+- xlnx,cfa-pattern: When the video format is set to Mono/Sensor, this property
+  describes the sensor's color filter array pattern. Supported values are
+  "bggr", "gbrg", "grbg", "rggb" and "mono". If not specified, the pattern
+  defaults to "mono".
+
+
+[UG934] http://www.xilinx.com/support/documentation/ip_documentation/axi_videoip/v1_0/ug934_axi_videoIP.pdf

+ 33 - 0
Documentation/devicetree/bindings/media/xilinx/xlnx,v-tc.txt

@@ -0,0 +1,33 @@
+Xilinx Video Timing Controller (VTC)
+------------------------------------
+
+The Video Timing Controller is a general purpose video timing generator and
+detector.
+
+Required properties:
+
+  - compatible: Must be "xlnx,v-tc-6.1".
+
+  - reg: Physical base address and length of the registers set for the device.
+
+  - clocks: Must contain a clock specifier for the VTC core and timing
+    interfaces clock.
+
+Optional properties:
+
+  - xlnx,detector: The VTC has a timing detector
+  - xlnx,generator: The VTC has a timing generator
+
+  At least one of the xlnx,detector and xlnx,generator properties must be
+  specified.
+
+
+Example:
+
+	vtc: vtc@43c40000 {
+		compatible = "xlnx,v-tc-6.1";
+		reg = <0x43c40000 0x10000>;
+
+		clocks = <&clkc 15>;
+		xlnx,generator;
+	};

+ 71 - 0
Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt

@@ -0,0 +1,71 @@
+Xilinx Video Test Pattern Generator (TPG)
+-----------------------------------------
+
+Required properties:
+
+- compatible: Must contain at least one of
+
+    "xlnx,v-tpg-5.0" (TPG version 5.0)
+    "xlnx,v-tpg-6.0" (TPG version 6.0)
+
+  TPG versions backward-compatible with previous versions should list all
+  compatible versions in the newer to older order.
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- xlnx,video-format, xlnx,video-width: Video format and width, as defined in
+  video.txt.
+
+- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
+  The TPG has a single output port numbered 0.
+
+Optional properties:
+
+- xlnx,vtc: A phandle referencing the Video Timing Controller that generates
+  video timings for the TPG test patterns.
+
+- timing-gpios: Specifier for a GPIO that controls the timing mux at the TPG
+  input. The GPIO active level corresponds to the selection of VTC-generated
+  video timings.
+
+The xlnx,vtc and timing-gpios properties are mandatory when the TPG is
+synthesized with two ports and forbidden when synthesized with one port.
+
+Example:
+
+	tpg_0: tpg@40050000 {
+		compatible = "xlnx,v-tpg-6.0", "xlnx,v-tpg-5.0";
+		reg = <0x40050000 0x10000>;
+		clocks = <&clkc 15>;
+
+		xlnx,vtc = <&vtc_3>;
+		timing-gpios = <&ps7_gpio_0 55 GPIO_ACTIVE_LOW>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				tpg_in: endpoint {
+					remote-endpoint = <&adv7611_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				tpg1_out: endpoint {
+					remote-endpoint = <&switch_in0>;
+				};
+			}:
+		};
+	};

+ 55 - 0
Documentation/devicetree/bindings/media/xilinx/xlnx,video.txt

@@ -0,0 +1,55 @@
+Xilinx Video IP Pipeline (VIPP)
+-------------------------------
+
+General concept
+---------------
+
+Xilinx video IP pipeline processes video streams through one or more Xilinx
+video IP cores. Each video IP core is represented as documented in video.txt
+and IP core specific documentation, xlnx,v-*.txt, in this directory. The DT
+node of the VIPP represents as a top level node of the pipeline and defines
+mappings between DMAs and the video IP cores.
+
+Required properties:
+
+- compatible: Must be "xlnx,video".
+
+- dmas, dma-names: List of one DMA specifier and identifier string (as defined
+  in Documentation/devicetree/bindings/dma/dma.txt) per port. Each port
+  requires a DMA channel with the identifier string set to "port" followed by
+  the port index.
+
+- ports: Video port, using the DT bindings defined in ../video-interfaces.txt.
+
+Required port properties:
+
+- direction: should be either "input" or "output" depending on the direction
+  of stream.
+
+Example:
+
+	video_cap {
+		compatible = "xlnx,video";
+		dmas = <&vdma_1 1>, <&vdma_3 1>;
+		dma-names = "port0", "port1";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				direction = "input";
+				vcap0_in0: endpoint {
+					remote-endpoint = <&scaler0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				direction = "input";
+				vcap0_in1: endpoint {
+					remote-endpoint = <&switch_out1>;
+				};
+			};
+		};
+	};

+ 1 - 0
Documentation/devicetree/bindings/vendor-prefixes.txt

@@ -21,6 +21,7 @@ ampire	Ampire Co., Ltd.
 ams	AMS AG
 amstaos	AMS-Taos Inc.
 apm	Applied Micro Circuits Corporation (APM)
+aptina	Aptina Imaging
 arasan	Arasan Chip Systems
 arm	ARM Ltd.
 armadeus	ARMadeus Systems SARL

+ 3 - 1
Documentation/video4linux/v4l2-controls.txt

@@ -344,7 +344,9 @@ implement g_volatile_ctrl like this:
 	}
 
 Note that you use the 'new value' union as well in g_volatile_ctrl. In general
-controls that need to implement g_volatile_ctrl are read-only controls.
+controls that need to implement g_volatile_ctrl are read-only controls. If they
+are not, a V4L2_EVENT_CTRL_CH_VALUE will not be generated when the control
+changes.
 
 To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
 

+ 3 - 3
Documentation/video4linux/v4l2-framework.txt

@@ -793,8 +793,8 @@ video_register_device_no_warn() instead.
 
 Whenever a device node is created some attributes are also created for you.
 If you look in /sys/class/video4linux you see the devices. Go into e.g.
-video0 and you will see 'name', 'debug' and 'index' attributes. The 'name'
-attribute is the 'name' field of the video_device struct. The 'debug' attribute
+video0 and you will see 'name', 'dev_debug' and 'index' attributes. The 'name'
+attribute is the 'name' field of the video_device struct. The 'dev_debug' attribute
 can be used to enable core debugging. See the next section for more detailed
 information on this.
 
@@ -821,7 +821,7 @@ unregister the device if the registration failed.
 video device debugging
 ----------------------
 
-The 'debug' attribute that is created for each video, vbi, radio or swradio
+The 'dev_debug' attribute that is created for each video, vbi, radio or swradio
 device in /sys/class/video4linux/<devX>/ allows you to enable logging of
 file operations.
 

+ 5 - 0
Documentation/video4linux/vivid.txt

@@ -912,6 +912,11 @@ looped to the video input provided that:
   sequence and field counting in struct v4l2_buffer on the capture side may not
   be 100% accurate.
 
+- field settings V4L2_FIELD_SEQ_TB/BT are not supported. While it is possible to
+  implement this, it would mean a lot of work to get this right. Since these
+  field values are rarely used the decision was made not to implement this for
+  now.
+
 - on the input side the "Standard Signal Mode" for the S-Video input or the
   "DV Timings Signal Mode" for the HDMI input should be configured so that a
   valid signal is passed to the video input.

+ 22 - 11
MAINTAINERS

@@ -4474,7 +4474,7 @@ S:	Maintained
 F:	block/partitions/efi.*
 
 STK1160 USB VIDEO CAPTURE DRIVER
-M:	Ezequiel Garcia <elezegarcia@gmail.com>
+M:	Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
 L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
@@ -6166,16 +6166,6 @@ Q:	http://patchwork.linuxtv.org/project/linux-media/list/
 S:	Maintained
 F:	drivers/media/dvb-frontends/m88rs2000*
 
-M88TS2022 MEDIA DRIVER
-M:	Antti Palosaari <crope@iki.fi>
-L:	linux-media@vger.kernel.org
-W:	http://linuxtv.org/
-W:	http://palosaari.fi/linux/
-Q:	http://patchwork.linuxtv.org/project/linux-media/list/
-T:	git git://linuxtv.org/anttip/media_tree.git
-S:	Maintained
-F:	drivers/media/tuners/m88ts2022*
-
 MA901 MASTERKIT USB FM RADIO DRIVER
 M:	Alexey Klimov <klimov.linux@gmail.com>
 L:	linux-media@vger.kernel.org
@@ -6599,6 +6589,7 @@ M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:	linux-media@vger.kernel.org
 T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
+F:	Documentation/devicetree/bindings/media/i2c/mt9v032.txt
 F:	drivers/media/i2c/mt9v032.c
 F:	include/media/mt9v032.h
 
@@ -8992,6 +8983,16 @@ T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
 S:	Maintained
 F:	drivers/media/platform/am437x/
 
+OV2659 OMNIVISION SENSOR DRIVER
+M:	Lad, Prabhakar <prabhakar.csengg@gmail.com>
+L:	linux-media@vger.kernel.org
+W:	http://linuxtv.org/
+Q:	http://patchwork.linuxtv.org/project/linux-media/list/
+T:	git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
+S:	Maintained
+F:	drivers/media/i2c/ov2659.c
+F:	include/media/ov2659.h
+
 SIS 190 ETHERNET DRIVER
 M:	Francois Romieu <romieu@fr.zoreil.com>
 L:	netdev@vger.kernel.org
@@ -10921,6 +10922,16 @@ L:	linux-serial@vger.kernel.org
 S:	Maintained
 F:	drivers/tty/serial/uartlite.c
 
+XILINX VIDEO IP CORES
+M:	Hyun Kwon <hyun.kwon@xilinx.com>
+M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:	linux-media@vger.kernel.org
+T:	git git://linuxtv.org/media_tree.git
+S:	Supported
+F:	Documentation/devicetree/bindings/media/xilinx/
+F:	drivers/media/platform/xilinx/
+F:	include/uapi/linux/xilinx-v4l2-controls.h
+
 XILLYBUS DRIVER
 M:	Eli Billauer <eli.billauer@gmail.com>
 L:	linux-kernel@vger.kernel.org

+ 21 - 36
arch/arm/mach-omap2/board-cm-t35.c

@@ -492,51 +492,36 @@ static struct twl4030_platform_data cm_t35_twldata = {
 #include <media/omap3isp.h>
 #include "devices.h"
 
-static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = {
+static struct isp_platform_subdev cm_t35_isp_subdevs[] = {
 	{
-		I2C_BOARD_INFO("mt9t001", 0x5d),
-	},
-	{
-		I2C_BOARD_INFO("tvp5150", 0x5c),
-	},
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = {
-	{
-		.board_info = &cm_t35_isp_i2c_boardinfo[0],
-		.i2c_adapter_id = 3,
-	},
-	{ NULL, 0, },
-};
-
-static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = {
-	{
-		.board_info = &cm_t35_isp_i2c_boardinfo[1],
+		.board_info = &(struct i2c_board_info){
+			I2C_BOARD_INFO("mt9t001", 0x5d)
+		},
 		.i2c_adapter_id = 3,
-	},
-	{ NULL, 0, },
-};
-
-static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = {
-	{
-		.subdevs = cm_t35_isp_primary_subdevs,
-		.interface = ISP_INTERFACE_PARALLEL,
-		.bus = {
-			.parallel = {
-				.clk_pol = 1,
+		.bus = &(struct isp_bus_cfg){
+			.interface = ISP_INTERFACE_PARALLEL,
+			.bus = {
+				.parallel = {
+					.clk_pol = 1,
+				},
 			},
 		},
 	},
 	{
-		.subdevs = cm_t35_isp_secondary_subdevs,
-		.interface = ISP_INTERFACE_PARALLEL,
-		.bus = {
-			.parallel = {
-				.clk_pol = 0,
+		.board_info = &(struct i2c_board_info){
+			I2C_BOARD_INFO("tvp5150", 0x5c),
+		},
+		.i2c_adapter_id = 3,
+		.bus = &(struct isp_bus_cfg){
+			.interface = ISP_INTERFACE_PARALLEL,
+			.bus = {
+				.parallel = {
+					.clk_pol = 0,
+				},
 			},
 		},
 	},
-	{ NULL, 0, },
+	{ 0 },
 };
 
 static struct isp_platform_data cm_t35_isp_pdata = {

+ 3 - 73
arch/arm/mach-omap2/devices.c

@@ -74,82 +74,12 @@ omap_postcore_initcall(omap3_l3_init);
 static struct resource omap3isp_resources[] = {
 	{
 		.start		= OMAP3430_ISP_BASE,
-		.end		= OMAP3430_ISP_END,
+		.end		= OMAP3430_ISP_BASE + 0x12fc,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= OMAP3430_ISP_CCP2_BASE,
-		.end		= OMAP3430_ISP_CCP2_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_CCDC_BASE,
-		.end		= OMAP3430_ISP_CCDC_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_HIST_BASE,
-		.end		= OMAP3430_ISP_HIST_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_H3A_BASE,
-		.end		= OMAP3430_ISP_H3A_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_PREV_BASE,
-		.end		= OMAP3430_ISP_PREV_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_RESZ_BASE,
-		.end		= OMAP3430_ISP_RESZ_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_SBL_BASE,
-		.end		= OMAP3430_ISP_SBL_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_CSI2A_REGS1_BASE,
-		.end		= OMAP3430_ISP_CSI2A_REGS1_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3430_ISP_CSIPHY2_BASE,
-		.end		= OMAP3430_ISP_CSIPHY2_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3630_ISP_CSI2A_REGS2_BASE,
-		.end		= OMAP3630_ISP_CSI2A_REGS2_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3630_ISP_CSI2C_REGS1_BASE,
-		.end		= OMAP3630_ISP_CSI2C_REGS1_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3630_ISP_CSIPHY1_BASE,
-		.end		= OMAP3630_ISP_CSIPHY1_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP3630_ISP_CSI2C_REGS2_BASE,
-		.end		= OMAP3630_ISP_CSI2C_REGS2_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE,
-		.end		= OMAP343X_CTRL_BASE + OMAP343X_CONTROL_CSIRXFE + 3,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL,
-		.end		= OMAP343X_CTRL_BASE + OMAP3630_CONTROL_CAMERA_PHY_CTRL + 3,
+		.start		= OMAP3430_ISP_BASE2,
+		.end		= OMAP3430_ISP_BASE2 + 0x0600,
 		.flags		= IORESOURCE_MEM,
 	},
 	{

+ 3 - 33
arch/arm/mach-omap2/omap34xx.h

@@ -46,39 +46,9 @@
 
 #define OMAP34XX_IC_BASE	0x48200000
 
-#define OMAP3430_ISP_BASE		(L4_34XX_BASE + 0xBC000)
-#define OMAP3430_ISP_CBUFF_BASE		(OMAP3430_ISP_BASE + 0x0100)
-#define OMAP3430_ISP_CCP2_BASE		(OMAP3430_ISP_BASE + 0x0400)
-#define OMAP3430_ISP_CCDC_BASE		(OMAP3430_ISP_BASE + 0x0600)
-#define OMAP3430_ISP_HIST_BASE		(OMAP3430_ISP_BASE + 0x0A00)
-#define OMAP3430_ISP_H3A_BASE		(OMAP3430_ISP_BASE + 0x0C00)
-#define OMAP3430_ISP_PREV_BASE		(OMAP3430_ISP_BASE + 0x0E00)
-#define OMAP3430_ISP_RESZ_BASE		(OMAP3430_ISP_BASE + 0x1000)
-#define OMAP3430_ISP_SBL_BASE		(OMAP3430_ISP_BASE + 0x1200)
-#define OMAP3430_ISP_MMU_BASE		(OMAP3430_ISP_BASE + 0x1400)
-#define OMAP3430_ISP_CSI2A_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1800)
-#define OMAP3430_ISP_CSIPHY2_BASE	(OMAP3430_ISP_BASE + 0x1970)
-#define OMAP3630_ISP_CSI2A_REGS2_BASE	(OMAP3430_ISP_BASE + 0x19C0)
-#define OMAP3630_ISP_CSI2C_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1C00)
-#define OMAP3630_ISP_CSIPHY1_BASE	(OMAP3430_ISP_BASE + 0x1D70)
-#define OMAP3630_ISP_CSI2C_REGS2_BASE	(OMAP3430_ISP_BASE + 0x1DC0)
-
-#define OMAP3430_ISP_END		(OMAP3430_ISP_BASE         + 0x06F)
-#define OMAP3430_ISP_CBUFF_END		(OMAP3430_ISP_CBUFF_BASE   + 0x077)
-#define OMAP3430_ISP_CCP2_END		(OMAP3430_ISP_CCP2_BASE    + 0x1EF)
-#define OMAP3430_ISP_CCDC_END		(OMAP3430_ISP_CCDC_BASE    + 0x0A7)
-#define OMAP3430_ISP_HIST_END		(OMAP3430_ISP_HIST_BASE    + 0x047)
-#define OMAP3430_ISP_H3A_END		(OMAP3430_ISP_H3A_BASE     + 0x05F)
-#define OMAP3430_ISP_PREV_END		(OMAP3430_ISP_PREV_BASE    + 0x09F)
-#define OMAP3430_ISP_RESZ_END		(OMAP3430_ISP_RESZ_BASE    + 0x0AB)
-#define OMAP3430_ISP_SBL_END		(OMAP3430_ISP_SBL_BASE     + 0x0FB)
-#define OMAP3430_ISP_MMU_END		(OMAP3430_ISP_MMU_BASE     + 0x06F)
-#define OMAP3430_ISP_CSI2A_REGS1_END	(OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
-#define OMAP3430_ISP_CSIPHY2_END	(OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2A_REGS2_END	(OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
-#define OMAP3630_ISP_CSI2C_REGS1_END	(OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
-#define OMAP3630_ISP_CSIPHY1_END	(OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
-#define OMAP3630_ISP_CSI2C_REGS2_END	(OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
+#define OMAP3430_ISP_BASE	(L4_34XX_BASE + 0xBC000)
+#define OMAP3430_ISP_MMU_BASE	(OMAP3430_ISP_BASE + 0x1400)
+#define OMAP3430_ISP_BASE2	(OMAP3430_ISP_BASE + 0x1800)
 
 #define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
 #define OMAP34XX_USBTLL_BASE	(L4_34XX_BASE + 0x62000)

+ 15 - 3
drivers/input/ff-memless.c

@@ -237,6 +237,18 @@ static u16 ml_calculate_direction(u16 direction, u16 force,
 		(force + new_force)) << 1;
 }
 
+#define FRAC_N 8
+static inline s16 fixp_new16(s16 a)
+{
+	return ((s32)a) >> (16 - FRAC_N);
+}
+
+static inline s16 fixp_mult(s16 a, s16 b)
+{
+	a = ((s32)a * 0x100) / 0x7fff;
+	return ((s32)(a * b)) >> FRAC_N;
+}
+
 /*
  * Combine two effects and apply gain.
  */
@@ -247,7 +259,7 @@ static void ml_combine_effects(struct ff_effect *effect,
 	struct ff_effect *new = state->effect;
 	unsigned int strong, weak, i;
 	int x, y;
-	fixp_t level;
+	s16 level;
 
 	switch (new->type) {
 	case FF_CONSTANT:
@@ -255,8 +267,8 @@ static void ml_combine_effects(struct ff_effect *effect,
 		level = fixp_new16(apply_envelope(state,
 					new->u.constant.level,
 					&new->u.constant.envelope));
-		x = fixp_mult(fixp_sin(i), level) * gain / 0xffff;
-		y = fixp_mult(-fixp_cos(i), level) * gain / 0xffff;
+		x = fixp_mult(fixp_sin16(i), level) * gain / 0xffff;
+		y = fixp_mult(-fixp_cos16(i), level) * gain / 0xffff;
 		/*
 		 * here we abuse ff_ramp to hold x and y of constant force
 		 * If in future any driver wants something else than x and y

+ 2 - 0
drivers/input/touchscreen/Kconfig

@@ -980,7 +980,9 @@ config TOUCHSCREEN_SUN4I
 config TOUCHSCREEN_SUR40
 	tristate "Samsung SUR40 (Surface 2.0/PixelSense) touchscreen"
 	depends on USB
+	depends on MEDIA_USB_SUPPORT
 	select INPUT_POLLDEV
+	select VIDEOBUF2_DMA_SG
 	help
 	  Say Y here if you want support for the Samsung SUR40 touchscreen
 	  (also known as Microsoft Surface 2.0 or Microsoft PixelSense).

+ 422 - 12
drivers/input/touchscreen/sur40.c

@@ -1,7 +1,7 @@
 /*
  * Surface2.0/SUR40/PixelSense input driver
  *
- * Copyright (c) 2013 by Florian 'floe' Echtler <floe@butterbrot.org>
+ * Copyright (c) 2014 by Florian 'floe' Echtler <floe@butterbrot.org>
  *
  * Derived from the USB Skeleton driver 1.1,
  * Copyright (c) 2003 Greg Kroah-Hartman (greg@kroah.com)
@@ -12,6 +12,9 @@
  * and from the generic hid-multitouch driver,
  * Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
  *
+ * and from the v4l2-pci-skeleton driver,
+ * Copyright (c) Copyright 2014 Cisco Systems, Inc.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -31,6 +34,11 @@
 #include <linux/input-polldev.h>
 #include <linux/input/mt.h>
 #include <linux/usb/input.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-sg.h>
 
 /* read 512 bytes from endpoint 0x86 -> get header + blobs */
 struct sur40_header {
@@ -82,9 +90,19 @@ struct sur40_data {
 	struct sur40_blob   blobs[];
 } __packed;
 
+/* read 512 bytes from endpoint 0x82 -> get header below
+ * continue reading 16k blocks until header.size bytes read */
+struct sur40_image_header {
+	__le32 magic;     /* "SUBF" */
+	__le32 packet_id;
+	__le32 size;      /* always 0x0007e900 = 960x540 */
+	__le32 timestamp; /* milliseconds (increases by 16 or 17 each frame) */
+	__le32 unknown;   /* "epoch?" always 02/03 00 00 00 */
+} __packed;
 
 /* version information */
 #define DRIVER_SHORT   "sur40"
+#define DRIVER_LONG    "Samsung SUR40"
 #define DRIVER_AUTHOR  "Florian 'floe' Echtler <floe@butterbrot.org>"
 #define DRIVER_DESC    "Surface2.0/SUR40/PixelSense input driver"
 
@@ -99,6 +117,13 @@ struct sur40_data {
 /* touch data endpoint */
 #define TOUCH_ENDPOINT 0x86
 
+/* video data endpoint */
+#define VIDEO_ENDPOINT 0x82
+
+/* video header fields */
+#define VIDEO_HEADER_MAGIC 0x46425553
+#define VIDEO_PACKET_SIZE  16384
+
 /* polling interval (ms) */
 #define POLL_INTERVAL 10
 
@@ -113,21 +138,23 @@ struct sur40_data {
 #define SUR40_GET_STATE   0xc5 /*  4 bytes state (?) */
 #define SUR40_GET_SENSORS 0xb1 /*  8 bytes sensors   */
 
-/*
- * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
- * here by mistake which is very likely to have corrupted the firmware EEPROM
- * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
- * Should you ever run into a similar problem, the background story to this
- * incident and instructions on how to fix the corrupted EEPROM are available
- * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
-*/
-
+/* master device state */
 struct sur40_state {
 
 	struct usb_device *usbdev;
 	struct device *dev;
 	struct input_polled_dev *input;
 
+	struct v4l2_device v4l2;
+	struct video_device vdev;
+	struct mutex lock;
+
+	struct vb2_queue queue;
+	struct vb2_alloc_ctx *alloc_ctx;
+	struct list_head buf_list;
+	spinlock_t qlock;
+	int sequence;
+
 	struct sur40_data *bulk_in_buffer;
 	size_t bulk_in_size;
 	u8 bulk_in_epaddr;
@@ -135,6 +162,27 @@ struct sur40_state {
 	char phys[64];
 };
 
+struct sur40_buffer {
+	struct vb2_buffer vb;
+	struct list_head list;
+};
+
+/* forward declarations */
+static const struct video_device sur40_video_device;
+static const struct v4l2_pix_format sur40_video_format;
+static const struct vb2_queue sur40_queue;
+static void sur40_process_video(struct sur40_state *sur40);
+
+/*
+ * Note: an earlier, non-public version of this driver used USB_RECIP_ENDPOINT
+ * here by mistake which is very likely to have corrupted the firmware EEPROM
+ * on two separate SUR40 devices. Thanks to Alan Stern who spotted this bug.
+ * Should you ever run into a similar problem, the background story to this
+ * incident and instructions on how to fix the corrupted EEPROM are available
+ * at https://floe.butterbrot.org/matrix/hacking/surface/brick.html
+*/
+
+/* command wrapper */
 static int sur40_command(struct sur40_state *dev,
 			 u8 command, u16 index, void *buffer, u16 size)
 {
@@ -247,7 +295,6 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input)
 /* core function: poll for new input data */
 static void sur40_poll(struct input_polled_dev *polldev)
 {
-
 	struct sur40_state *sur40 = polldev->private;
 	struct input_dev *input = polldev->input;
 	int result, bulk_read, need_blobs, packet_blobs, i;
@@ -314,6 +361,86 @@ static void sur40_poll(struct input_polled_dev *polldev)
 
 	input_mt_sync_frame(input);
 	input_sync(input);
+
+	sur40_process_video(sur40);
+}
+
+/* deal with video data */
+static void sur40_process_video(struct sur40_state *sur40)
+{
+
+	struct sur40_image_header *img = (void *)(sur40->bulk_in_buffer);
+	struct sur40_buffer *new_buf;
+	struct usb_sg_request sgr;
+	struct sg_table *sgt;
+	int result, bulk_read;
+
+	if (!vb2_start_streaming_called(&sur40->queue))
+		return;
+
+	/* get a new buffer from the list */
+	spin_lock(&sur40->qlock);
+	if (list_empty(&sur40->buf_list)) {
+		dev_dbg(sur40->dev, "buffer queue empty\n");
+		spin_unlock(&sur40->qlock);
+		return;
+	}
+	new_buf = list_entry(sur40->buf_list.next, struct sur40_buffer, list);
+	list_del(&new_buf->list);
+	spin_unlock(&sur40->qlock);
+
+	/* retrieve data via bulk read */
+	result = usb_bulk_msg(sur40->usbdev,
+			usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT),
+			sur40->bulk_in_buffer, sur40->bulk_in_size,
+			&bulk_read, 1000);
+
+	if (result < 0) {
+		dev_err(sur40->dev, "error in usb_bulk_read\n");
+		goto err_poll;
+	}
+
+	if (bulk_read != sizeof(struct sur40_image_header)) {
+		dev_err(sur40->dev, "received %d bytes (%zd expected)\n",
+			bulk_read, sizeof(struct sur40_image_header));
+		goto err_poll;
+	}
+
+	if (le32_to_cpu(img->magic) != VIDEO_HEADER_MAGIC) {
+		dev_err(sur40->dev, "image magic mismatch\n");
+		goto err_poll;
+	}
+
+	if (le32_to_cpu(img->size) != sur40_video_format.sizeimage) {
+		dev_err(sur40->dev, "image size mismatch\n");
+		goto err_poll;
+	}
+
+	sgt = vb2_dma_sg_plane_desc(&new_buf->vb, 0);
+
+	result = usb_sg_init(&sgr, sur40->usbdev,
+		usb_rcvbulkpipe(sur40->usbdev, VIDEO_ENDPOINT), 0,
+		sgt->sgl, sgt->nents, sur40_video_format.sizeimage, 0);
+	if (result < 0) {
+		dev_err(sur40->dev, "error %d in usb_sg_init\n", result);
+		goto err_poll;
+	}
+
+	usb_sg_wait(&sgr);
+	if (sgr.status < 0) {
+		dev_err(sur40->dev, "error %d in usb_sg_wait\n", sgr.status);
+		goto err_poll;
+	}
+
+	/* mark as finished */
+	v4l2_get_timestamp(&new_buf->vb.v4l2_buf.timestamp);
+	new_buf->vb.v4l2_buf.sequence = sur40->sequence++;
+	new_buf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+	vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_DONE);
+	return;
+
+err_poll:
+	vb2_buffer_done(&new_buf->vb, VB2_BUF_STATE_ERROR);
 }
 
 /* Initialize input device parameters. */
@@ -377,6 +504,11 @@ static int sur40_probe(struct usb_interface *interface,
 		goto err_free_dev;
 	}
 
+	/* initialize locks/lists */
+	INIT_LIST_HEAD(&sur40->buf_list);
+	spin_lock_init(&sur40->qlock);
+	mutex_init(&sur40->lock);
+
 	/* Set up polled input device control structure */
 	poll_dev->private = sur40;
 	poll_dev->poll_interval = POLL_INTERVAL;
@@ -387,7 +519,7 @@ static int sur40_probe(struct usb_interface *interface,
 	/* Set up regular input device structure */
 	sur40_input_setup(poll_dev->input);
 
-	poll_dev->input->name = "Samsung SUR40";
+	poll_dev->input->name = DRIVER_LONG;
 	usb_to_input_id(usbdev, &poll_dev->input->id);
 	usb_make_path(usbdev, sur40->phys, sizeof(sur40->phys));
 	strlcat(sur40->phys, "/input0", sizeof(sur40->phys));
@@ -408,6 +540,7 @@ static int sur40_probe(struct usb_interface *interface,
 		goto err_free_polldev;
 	}
 
+	/* register the polled input device */
 	error = input_register_polled_device(poll_dev);
 	if (error) {
 		dev_err(&interface->dev,
@@ -415,12 +548,54 @@ static int sur40_probe(struct usb_interface *interface,
 		goto err_free_buffer;
 	}
 
+	/* register the video master device */
+	snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG);
+	error = v4l2_device_register(sur40->dev, &sur40->v4l2);
+	if (error) {
+		dev_err(&interface->dev,
+			"Unable to register video master device.");
+		goto err_unreg_v4l2;
+	}
+
+	/* initialize the lock and subdevice */
+	sur40->queue = sur40_queue;
+	sur40->queue.drv_priv = sur40;
+	sur40->queue.lock = &sur40->lock;
+
+	/* initialize the queue */
+	error = vb2_queue_init(&sur40->queue);
+	if (error)
+		goto err_unreg_v4l2;
+
+	sur40->alloc_ctx = vb2_dma_sg_init_ctx(sur40->dev);
+	if (IS_ERR(sur40->alloc_ctx)) {
+		dev_err(sur40->dev, "Can't allocate buffer context");
+		goto err_unreg_v4l2;
+	}
+
+	sur40->vdev = sur40_video_device;
+	sur40->vdev.v4l2_dev = &sur40->v4l2;
+	sur40->vdev.lock = &sur40->lock;
+	sur40->vdev.queue = &sur40->queue;
+	video_set_drvdata(&sur40->vdev, sur40);
+
+	error = video_register_device(&sur40->vdev, VFL_TYPE_GRABBER, -1);
+	if (error) {
+		dev_err(&interface->dev,
+			"Unable to register video subdevice.");
+		goto err_unreg_video;
+	}
+
 	/* we can register the device now, as it is ready */
 	usb_set_intfdata(interface, sur40);
 	dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);
 
 	return 0;
 
+err_unreg_video:
+	video_unregister_device(&sur40->vdev);
+err_unreg_v4l2:
+	v4l2_device_unregister(&sur40->v4l2);
 err_free_buffer:
 	kfree(sur40->bulk_in_buffer);
 err_free_polldev:
@@ -436,6 +611,10 @@ static void sur40_disconnect(struct usb_interface *interface)
 {
 	struct sur40_state *sur40 = usb_get_intfdata(interface);
 
+	video_unregister_device(&sur40->vdev);
+	v4l2_device_unregister(&sur40->v4l2);
+	vb2_dma_sg_cleanup_ctx(sur40->alloc_ctx);
+
 	input_unregister_polled_device(sur40->input);
 	input_free_polled_device(sur40->input);
 	kfree(sur40->bulk_in_buffer);
@@ -445,12 +624,243 @@ static void sur40_disconnect(struct usb_interface *interface)
 	dev_dbg(&interface->dev, "%s is now disconnected\n", DRIVER_DESC);
 }
 
+/*
+ * Setup the constraints of the queue: besides setting the number of planes
+ * per buffer and the size and allocation context of each plane, it also
+ * checks if sufficient buffers have been allocated. Usually 3 is a good
+ * minimum number: many DMA engines need a minimum of 2 buffers in the
+ * queue and you need to have another available for userspace processing.
+ */
+static int sur40_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
+		       unsigned int *nbuffers, unsigned int *nplanes,
+		       unsigned int sizes[], void *alloc_ctxs[])
+{
+	struct sur40_state *sur40 = vb2_get_drv_priv(q);
+
+	if (q->num_buffers + *nbuffers < 3)
+		*nbuffers = 3 - q->num_buffers;
+
+	if (fmt && fmt->fmt.pix.sizeimage < sur40_video_format.sizeimage)
+		return -EINVAL;
+
+	*nplanes = 1;
+	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : sur40_video_format.sizeimage;
+	alloc_ctxs[0] = sur40->alloc_ctx;
+
+	return 0;
+}
+
+/*
+ * Prepare the buffer for queueing to the DMA engine: check and set the
+ * payload size.
+ */
+static int sur40_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = sur40_video_format.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(&sur40->usbdev->dev, "buffer too small (%lu < %lu)\n",
+			 vb2_plane_size(vb, 0), size);
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	return 0;
+}
+
+/*
+ * Queue this buffer to the DMA engine.
+ */
+static void sur40_buffer_queue(struct vb2_buffer *vb)
+{
+	struct sur40_state *sur40 = vb2_get_drv_priv(vb->vb2_queue);
+	struct sur40_buffer *buf = (struct sur40_buffer *)vb;
+
+	spin_lock(&sur40->qlock);
+	list_add_tail(&buf->list, &sur40->buf_list);
+	spin_unlock(&sur40->qlock);
+}
+
+static void return_all_buffers(struct sur40_state *sur40,
+			       enum vb2_buffer_state state)
+{
+	struct sur40_buffer *buf, *node;
+
+	spin_lock(&sur40->qlock);
+	list_for_each_entry_safe(buf, node, &sur40->buf_list, list) {
+		vb2_buffer_done(&buf->vb, state);
+		list_del(&buf->list);
+	}
+	spin_unlock(&sur40->qlock);
+}
+
+/*
+ * Start streaming. First check if the minimum number of buffers have been
+ * queued. If not, then return -ENOBUFS and the vb2 framework will call
+ * this function again the next time a buffer has been queued until enough
+ * buffers are available to actually start the DMA engine.
+ */
+static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+
+	sur40->sequence = 0;
+	return 0;
+}
+
+/*
+ * Stop the DMA engine. Any remaining buffers in the DMA queue are dequeued
+ * and passed on to the vb2 framework marked as STATE_ERROR.
+ */
+static void sur40_stop_streaming(struct vb2_queue *vq)
+{
+	struct sur40_state *sur40 = vb2_get_drv_priv(vq);
+
+	/* Release all active buffers */
+	return_all_buffers(sur40, VB2_BUF_STATE_ERROR);
+}
+
+/* V4L ioctl */
+static int sur40_vidioc_querycap(struct file *file, void *priv,
+				 struct v4l2_capability *cap)
+{
+	struct sur40_state *sur40 = video_drvdata(file);
+
+	strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
+	strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
+	usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
+	cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+		V4L2_CAP_READWRITE |
+		V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int sur40_vidioc_enum_input(struct file *file, void *priv,
+				   struct v4l2_input *i)
+{
+	if (i->index != 0)
+		return -EINVAL;
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	i->std = V4L2_STD_UNKNOWN;
+	strlcpy(i->name, "In-Cell Sensor", sizeof(i->name));
+	i->capabilities = 0;
+	return 0;
+}
+
+static int sur40_vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+	return (i == 0) ? 0 : -EINVAL;
+}
+
+static int sur40_vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int sur40_vidioc_fmt(struct file *file, void *priv,
+			    struct v4l2_format *f)
+{
+	f->fmt.pix = sur40_video_format;
+	return 0;
+}
+
+static int sur40_vidioc_enum_fmt(struct file *file, void *priv,
+				 struct v4l2_fmtdesc *f)
+{
+	if (f->index != 0)
+		return -EINVAL;
+	strlcpy(f->description, "8-bit greyscale", sizeof(f->description));
+	f->pixelformat = V4L2_PIX_FMT_GREY;
+	f->flags = 0;
+	return 0;
+}
+
 static const struct usb_device_id sur40_table[] = {
 	{ USB_DEVICE(ID_MICROSOFT, ID_SUR40) },  /* Samsung SUR40 */
 	{ }                                      /* terminating null entry */
 };
 MODULE_DEVICE_TABLE(usb, sur40_table);
 
+/* V4L2 structures */
+static const struct vb2_ops sur40_queue_ops = {
+	.queue_setup		= sur40_queue_setup,
+	.buf_prepare		= sur40_buffer_prepare,
+	.buf_queue		= sur40_buffer_queue,
+	.start_streaming	= sur40_start_streaming,
+	.stop_streaming		= sur40_stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+static const struct vb2_queue sur40_queue = {
+	.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+	/*
+	 * VB2_USERPTR in currently not enabled: passing a user pointer to
+	 * dma-sg will result in segment sizes that are not a multiple of
+	 * 512 bytes, which is required by the host controller.
+	*/
+	.io_modes = VB2_MMAP | VB2_READ | VB2_DMABUF,
+	.buf_struct_size = sizeof(struct sur40_buffer),
+	.ops = &sur40_queue_ops,
+	.mem_ops = &vb2_dma_sg_memops,
+	.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC,
+	.min_buffers_needed = 3,
+};
+
+static const struct v4l2_file_operations sur40_video_fops = {
+	.owner = THIS_MODULE,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.unlocked_ioctl = video_ioctl2,
+	.read = vb2_fop_read,
+	.mmap = vb2_fop_mmap,
+	.poll = vb2_fop_poll,
+};
+
+static const struct v4l2_ioctl_ops sur40_video_ioctl_ops = {
+
+	.vidioc_querycap	= sur40_vidioc_querycap,
+
+	.vidioc_enum_fmt_vid_cap = sur40_vidioc_enum_fmt,
+	.vidioc_try_fmt_vid_cap	= sur40_vidioc_fmt,
+	.vidioc_s_fmt_vid_cap	= sur40_vidioc_fmt,
+	.vidioc_g_fmt_vid_cap	= sur40_vidioc_fmt,
+
+	.vidioc_enum_input	= sur40_vidioc_enum_input,
+	.vidioc_g_input		= sur40_vidioc_g_input,
+	.vidioc_s_input		= sur40_vidioc_s_input,
+
+	.vidioc_reqbufs		= vb2_ioctl_reqbufs,
+	.vidioc_create_bufs	= vb2_ioctl_create_bufs,
+	.vidioc_querybuf	= vb2_ioctl_querybuf,
+	.vidioc_qbuf		= vb2_ioctl_qbuf,
+	.vidioc_dqbuf		= vb2_ioctl_dqbuf,
+	.vidioc_expbuf		= vb2_ioctl_expbuf,
+
+	.vidioc_streamon	= vb2_ioctl_streamon,
+	.vidioc_streamoff	= vb2_ioctl_streamoff,
+};
+
+static const struct video_device sur40_video_device = {
+	.name = DRIVER_LONG,
+	.fops = &sur40_video_fops,
+	.ioctl_ops = &sur40_video_ioctl_ops,
+	.release = video_device_release_empty,
+};
+
+static const struct v4l2_pix_format sur40_video_format = {
+	.pixelformat = V4L2_PIX_FMT_GREY,
+	.width  = SENSOR_RES_X / 2,
+	.height = SENSOR_RES_Y / 2,
+	.field = V4L2_FIELD_NONE,
+	.colorspace = V4L2_COLORSPACE_SRGB,
+	.bytesperline = SENSOR_RES_X / 2,
+	.sizeimage = (SENSOR_RES_X/2) * (SENSOR_RES_Y/2),
+};
+
 /* USB-specific object needed to register this driver with the USB subsystem. */
 static struct usb_driver sur40_driver = {
 	.name = DRIVER_SHORT,

+ 9 - 1
drivers/media/Kconfig

@@ -87,13 +87,21 @@ config MEDIA_RC_SUPPORT
 
 config MEDIA_CONTROLLER
 	bool "Media Controller API"
-	depends on MEDIA_CAMERA_SUPPORT
+	depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
 	---help---
 	  Enable the media controller API used to query media devices internal
 	  topology and configure it dynamically.
 
 	  This API is mostly used by camera interfaces in embedded platforms.
 
+config MEDIA_CONTROLLER_DVB
+	bool "Enable Media controller for DVB"
+	depends on MEDIA_CONTROLLER
+	---help---
+	  Enable the media controller API support for DVB.
+
+	  This is currently experimental.
+
 #
 # Video4Linux support
 #	Only enables if one of the V4L2 types (ATV, webcam, radio) is selected

+ 4 - 15
drivers/media/common/saa7146/saa7146_fops.c

@@ -587,26 +587,20 @@ int saa7146_vv_release(struct saa7146_dev* dev)
 }
 EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
-int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
+int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
 			    char *name, int type)
 {
-	struct video_device *vfd;
 	int err;
 	int i;
 
 	DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 
-	// released by vfd->release
-	vfd = video_device_alloc();
-	if (vfd == NULL)
-		return -ENOMEM;
-
 	vfd->fops = &video_fops;
 	if (type == VFL_TYPE_GRABBER)
 		vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
 	else
 		vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
-	vfd->release = video_device_release;
+	vfd->release = video_device_release_empty;
 	vfd->lock = &dev->v4l2_lock;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 	vfd->tvnorms = 0;
@@ -618,25 +612,20 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 	err = video_register_device(vfd, type, -1);
 	if (err < 0) {
 		ERR("cannot register v4l2 device. skipping.\n");
-		video_device_release(vfd);
 		return err;
 	}
 
 	pr_info("%s: registered device %s [v4l2]\n",
 		dev->name, video_device_node_name(vfd));
-
-	*vid = vfd;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(saa7146_register_device);
 
-int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
+int saa7146_unregister_device(struct video_device *vfd, struct saa7146_dev *dev)
 {
 	DEB_EE("dev:%p\n", dev);
 
-	video_unregister_device(*vid);
-	*vid = NULL;
-
+	video_unregister_device(vfd);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(saa7146_unregister_device);

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

@@ -95,7 +95,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
 
 		/* prepare to wait to be woken up by the irq-handler */
 		add_wait_queue(&vv->vbi_wq, &wait);
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 
 		/* start rps1 to enable workaround */
 		saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle);
@@ -106,7 +106,7 @@ static int vbi_workaround(struct saa7146_dev *dev)
 		DEB_VBI("brs bug workaround %d/1\n", i);
 
 		remove_wait_queue(&vv->vbi_wq, &wait);
-		current->state = TASK_RUNNING;
+		__set_current_state(TASK_RUNNING);
 
 		/* disable rps1 irqs */
 		SAA7146_IER_DISABLE(dev,MASK_28);

+ 2 - 6
drivers/media/common/siano/sms-cards.c

@@ -21,10 +21,6 @@
 #include "smsir.h"
 #include <linux/module.h>
 
-static int sms_dbg;
-module_param_named(cards_dbg, sms_dbg, int, 0644);
-MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
-
 static struct sms_board sms_boards[] = {
 	[SMS_BOARD_UNKNOWN] = {
 		.name	= "Unknown board",
@@ -232,7 +228,7 @@ int sms_board_event(struct smscore_device_t *coredev,
 		break; /* BOARD_EVENT_MULTIPLEX_ERRORS */
 
 	default:
-		sms_err("Unknown SMS board event");
+		pr_err("Unknown SMS board event\n");
 		break;
 	}
 	return 0;
@@ -342,7 +338,7 @@ int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
 	int board_id = smscore_get_board_id(coredev);
 	struct sms_board *board = sms_get_board(board_id);
 
-	sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled");
+	pr_debug("%s: LNA %s\n", __func__, onoff ? "enabled" : "disabled");
 
 	switch (board_id) {
 	case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:

+ 2 - 1
drivers/media/common/siano/sms-cards.h

@@ -20,8 +20,9 @@
 #ifndef __SMS_CARDS_H__
 #define __SMS_CARDS_H__
 
-#include <linux/usb.h>
 #include "smscoreapi.h"
+
+#include <linux/usb.h>
 #include "smsir.h"
 
 #define SMS_BOARD_UNKNOWN 0

+ 81 - 83
drivers/media/common/siano/smscoreapi.c

@@ -21,6 +21,8 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "smscoreapi.h"
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -34,14 +36,9 @@
 #include <linux/wait.h>
 #include <asm/byteorder.h>
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 #include "smsir.h"
 
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
 struct smscore_device_notifyee_t {
 	struct list_head entry;
 	hotplug_t hotplug;
@@ -460,7 +457,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
 		strcpy(entry->devpath, devpath);
 		list_add(&entry->entry, &g_smscore_registry);
 	} else
-		sms_err("failed to create smscore_registry.");
+		pr_err("failed to create smscore_registry.\n");
 	kmutex_unlock(&g_smscore_registrylock);
 	return entry;
 }
@@ -473,7 +470,7 @@ int smscore_registry_getmode(char *devpath)
 	if (entry)
 		return entry->mode;
 	else
-		sms_err("No registry found.");
+		pr_err("No registry found.\n");
 
 	return default_mode;
 }
@@ -487,7 +484,7 @@ static enum sms_device_type_st smscore_registry_gettype(char *devpath)
 	if (entry)
 		return entry->type;
 	else
-		sms_err("No registry found.");
+		pr_err("No registry found.\n");
 
 	return -EINVAL;
 }
@@ -500,7 +497,7 @@ static void smscore_registry_setmode(char *devpath, int mode)
 	if (entry)
 		entry->mode = mode;
 	else
-		sms_err("No registry found.");
+		pr_err("No registry found.\n");
 }
 
 static void smscore_registry_settype(char *devpath,
@@ -512,7 +509,7 @@ static void smscore_registry_settype(char *devpath,
 	if (entry)
 		entry->type = type;
 	else
-		sms_err("No registry found.");
+		pr_err("No registry found.\n");
 }
 
 
@@ -635,10 +632,8 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
 	struct smscore_buffer_t *cb;
 
 	cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);
-	if (!cb) {
-		sms_info("kzalloc(...) failed");
+	if (!cb)
 		return NULL;
-	}
 
 	cb->p = buffer;
 	cb->offset_in_common = buffer - (u8 *) common_buffer;
@@ -658,16 +653,19 @@ smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,
  * @return 0 on success, <0 on error.
  */
 int smscore_register_device(struct smsdevice_params_t *params,
-			    struct smscore_device_t **coredev)
+			    struct smscore_device_t **coredev,
+			    void *mdev)
 {
 	struct smscore_device_t *dev;
 	u8 *buffer;
 
 	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);
-	if (!dev) {
-		sms_info("kzalloc(...) failed");
+	if (!dev)
 		return -ENOMEM;
-	}
+
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	dev->media_dev = mdev;
+#endif
 
 	/* init list entry so it could be safe in smscore_unregister_device */
 	INIT_LIST_HEAD(&dev->entry);
@@ -722,7 +720,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 		smscore_putbuffer(dev, cb);
 	}
 
-	sms_info("allocated %d buffers", dev->num_buffers);
+	pr_debug("allocated %d buffers\n", dev->num_buffers);
 
 	dev->mode = DEVICE_MODE_NONE;
 	dev->board_id = SMS_BOARD_UNKNOWN;
@@ -746,7 +744,7 @@ int smscore_register_device(struct smsdevice_params_t *params,
 
 	*coredev = dev;
 
-	sms_info("device %p created", dev);
+	pr_debug("device %p created\n", dev);
 
 	return 0;
 }
@@ -763,7 +761,7 @@ static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,
 
 	rc = coredev->sendrequest_handler(coredev->context, buffer, size);
 	if (rc < 0) {
-		sms_info("sendrequest returned error %d", rc);
+		pr_info("sendrequest returned error %d\n", rc);
 		return rc;
 	}
 
@@ -786,11 +784,11 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 	coredev->ir.dev = NULL;
 	ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir;
 	if (ir_io) {/* only if IR port exist we use IR sub-module */
-		sms_info("IR loading");
+		pr_debug("IR loading\n");
 		rc = sms_ir_init(coredev);
 
 		if	(rc != 0)
-			sms_err("Error initialization DTV IR sub-module");
+			pr_err("Error initialization DTV IR sub-module\n");
 		else {
 			buffer = kmalloc(sizeof(struct sms_msg_data2) +
 						SMS_DMA_ALIGNMENT,
@@ -812,11 +810,10 @@ static int smscore_init_ir(struct smscore_device_t *coredev)
 
 				kfree(buffer);
 			} else
-				sms_err
-				("Sending IR initialization message failed");
+				pr_err("Sending IR initialization message failed\n");
 		}
 	} else
-		sms_info("IR port has not been detected");
+		pr_info("IR port has not been detected\n");
 
 	return 0;
 }
@@ -835,13 +832,13 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
 
 	board = sms_get_board(coredev->board_id);
 	if (!board) {
-		sms_err("no board configuration exist.");
+		pr_err("no board configuration exist.\n");
 		return -EINVAL;
 	}
 
 	if (board->mtu) {
 		struct sms_msg_data mtu_msg;
-		sms_debug("set max transmit unit %d", board->mtu);
+		pr_debug("set max transmit unit %d\n", board->mtu);
 
 		mtu_msg.x_msg_header.msg_src_id = 0;
 		mtu_msg.x_msg_header.msg_dst_id = HIF_TASK;
@@ -856,7 +853,7 @@ static int smscore_configure_board(struct smscore_device_t *coredev)
 
 	if (board->crystal) {
 		struct sms_msg_data crys_msg;
-		sms_debug("set crystal value %d", board->crystal);
+		pr_debug("set crystal value %d\n", board->crystal);
 
 		SMS_INIT_MSG(&crys_msg.x_msg_header,
 				MSG_SMS_NEW_CRYSTAL_REQ,
@@ -890,12 +887,12 @@ int smscore_start_device(struct smscore_device_t *coredev)
 
 	rc = smscore_set_device_mode(coredev, mode);
 	if (rc < 0) {
-		sms_info("set device mode faile , rc %d", rc);
+		pr_info("set device mode failed , rc %d\n", rc);
 		return rc;
 	}
 	rc = smscore_configure_board(coredev);
 	if (rc < 0) {
-		sms_info("configure board failed , rc %d", rc);
+		pr_info("configure board failed , rc %d\n", rc);
 		return rc;
 	}
 
@@ -904,7 +901,7 @@ int smscore_start_device(struct smscore_device_t *coredev)
 	rc = smscore_notify_callbacks(coredev, coredev->device, 1);
 	smscore_init_ir(coredev);
 
-	sms_info("device %p started, rc %d", coredev, rc);
+	pr_debug("device %p started, rc %d\n", coredev, rc);
 
 	kmutex_unlock(&g_smscore_deviceslock);
 
@@ -927,7 +924,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 
 	mem_address = firmware->start_address;
 
-	sms_info("loading FW to addr 0x%x size %d",
+	pr_debug("loading FW to addr 0x%x size %d\n",
 		 mem_address, firmware->length);
 	if (coredev->preload_handler) {
 		rc = coredev->preload_handler(coredev->context);
@@ -941,14 +938,14 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 		return -ENOMEM;
 
 	if (coredev->mode != DEVICE_MODE_NONE) {
-		sms_debug("sending reload command.");
+		pr_debug("sending reload command.\n");
 		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_START_REQ,
 			     sizeof(struct sms_msg_hdr));
 		rc = smscore_sendrequest_and_wait(coredev, msg,
 						  msg->x_msg_header.msg_length,
 						  &coredev->reload_start_done);
 		if (rc < 0) {
-			sms_err("device reload failed, rc %d", rc);
+			pr_err("device reload failed, rc %d\n", rc);
 			goto exit_fw_download;
 		}
 		mem_address = *(u32 *) &payload[20];
@@ -982,7 +979,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 	if (rc < 0)
 		goto exit_fw_download;
 
-	sms_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x",
+	pr_debug("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x\n",
 		calc_checksum);
 	SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_DATA_VALIDITY_REQ,
 			sizeof(msg->x_msg_header) +
@@ -1001,7 +998,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev,
 		struct sms_msg_data *trigger_msg =
 			(struct sms_msg_data *) msg;
 
-		sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ");
+		pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n");
 		SMS_INIT_MSG(&msg->x_msg_header,
 				MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
 				sizeof(struct sms_msg_hdr) +
@@ -1037,12 +1034,13 @@ exit_fw_download:
 	kfree(msg);
 
 	if (coredev->postload_handler) {
-		sms_debug("rc=%d, postload=0x%p", rc, coredev->postload_handler);
+		pr_debug("rc=%d, postload=0x%p\n",
+			 rc, coredev->postload_handler);
 		if (rc >= 0)
 			return coredev->postload_handler(coredev->context);
 	}
 
-	sms_debug("rc=%d", rc);
+	pr_debug("rc=%d\n", rc);
 	return rc;
 }
 
@@ -1121,11 +1119,11 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
 	if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX)
 		return NULL;
 
-	sms_debug("trying to get fw name from sms_boards board_id %d mode %d",
+	pr_debug("trying to get fw name from sms_boards board_id %d mode %d\n",
 		  board_id, mode);
 	fw = sms_get_board(board_id)->fw;
 	if (!fw || !fw[mode]) {
-		sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d",
+		pr_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d\n",
 			  mode, type);
 		return smscore_fw_lkup[type][mode];
 	}
@@ -1154,10 +1152,10 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
 
 	char *fw_filename = smscore_get_fw_filename(coredev, mode);
 	if (!fw_filename) {
-		sms_err("mode %d not supported on this device", mode);
+		pr_err("mode %d not supported on this device\n", mode);
 		return -ENOENT;
 	}
-	sms_debug("Firmware name: %s", fw_filename);
+	pr_debug("Firmware name: %s\n", fw_filename);
 
 	if (loadfirmware_handler == NULL && !(coredev->device_flags
 			& SMS_DEVICE_FAMILY2))
@@ -1165,14 +1163,14 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
 
 	rc = request_firmware(&fw, fw_filename, coredev->device);
 	if (rc < 0) {
-		sms_err("failed to open firmware file \"%s\"", fw_filename);
+		pr_err("failed to open firmware file '%s'\n", fw_filename);
 		return rc;
 	}
-	sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size);
+	pr_debug("read fw %s, buffer size=0x%zx\n", fw_filename, fw->size);
 	fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),
 			 GFP_KERNEL | GFP_DMA);
 	if (!fw_buf) {
-		sms_err("failed to allocate firmware buffer");
+		pr_err("failed to allocate firmware buffer\n");
 		rc = -ENOMEM;
 	} else {
 		memcpy(fw_buf, fw->data, fw->size);
@@ -1226,18 +1224,18 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 		if (num_buffers == coredev->num_buffers)
 			break;
 		if (++retry > 10) {
-			sms_info("exiting although not all buffers released.");
+			pr_info("exiting although not all buffers released.\n");
 			break;
 		}
 
-		sms_info("waiting for %d buffer(s)",
+		pr_debug("waiting for %d buffer(s)\n",
 			 coredev->num_buffers - num_buffers);
 		kmutex_unlock(&g_smscore_deviceslock);
 		msleep(100);
 		kmutex_lock(&g_smscore_deviceslock);
 	}
 
-	sms_info("freed %d buffers", num_buffers);
+	pr_debug("freed %d buffers\n", num_buffers);
 
 	if (coredev->common_buffer)
 		dma_free_coherent(NULL, coredev->common_buffer_size,
@@ -1250,7 +1248,7 @@ void smscore_unregister_device(struct smscore_device_t *coredev)
 
 	kmutex_unlock(&g_smscore_deviceslock);
 
-	sms_info("device %p destroyed", coredev);
+	pr_debug("device %p destroyed\n", coredev);
 }
 EXPORT_SYMBOL_GPL(smscore_unregister_device);
 
@@ -1271,7 +1269,7 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msg_length,
 					  &coredev->version_ex_done);
 	if (rc == -ETIME) {
-		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");
+		pr_err("MSG_SMS_GET_VERSION_EX_REQ failed first try\n");
 
 		if (wait_for_completion_timeout(&coredev->resume_done,
 						msecs_to_jiffies(5000))) {
@@ -1279,7 +1277,7 @@ static int smscore_detect_mode(struct smscore_device_t *coredev)
 				coredev, msg, msg->msg_length,
 				&coredev->version_ex_done);
 			if (rc < 0)
-				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d",
+				pr_err("MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d\n",
 					rc);
 		} else
 			rc = -ETIME;
@@ -1308,7 +1306,7 @@ static int smscore_init_device(struct smscore_device_t *coredev, int mode)
 	buffer = kmalloc(sizeof(struct sms_msg_data) +
 			SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
 	if (!buffer) {
-		sms_err("Could not allocate buffer for init device message.");
+		pr_err("Could not allocate buffer for init device message.\n");
 		return -ENOMEM;
 	}
 
@@ -1339,10 +1337,10 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 {
 	int rc = 0;
 
-	sms_debug("set device mode to %d", mode);
+	pr_debug("set device mode to %d\n", mode);
 	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {
 		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
-			sms_err("invalid mode specified %d", mode);
+			pr_err("invalid mode specified %d\n", mode);
 			return -EINVAL;
 		}
 
@@ -1351,13 +1349,13 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 		if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {
 			rc = smscore_detect_mode(coredev);
 			if (rc < 0) {
-				sms_err("mode detect failed %d", rc);
+				pr_err("mode detect failed %d\n", rc);
 				return rc;
 			}
 		}
 
 		if (coredev->mode == mode) {
-			sms_info("device mode %d already set", mode);
+			pr_debug("device mode %d already set\n", mode);
 			return 0;
 		}
 
@@ -1365,19 +1363,19 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 			rc = smscore_load_firmware_from_file(coredev,
 							     mode, NULL);
 			if (rc >= 0)
-				sms_info("firmware download success");
+				pr_debug("firmware download success\n");
 		} else {
-			sms_info("mode %d is already supported by running firmware",
+			pr_debug("mode %d is already supported by running firmware\n",
 				 mode);
 		}
 		if (coredev->fw_version >= 0x800) {
 			rc = smscore_init_device(coredev, mode);
 			if (rc < 0)
-				sms_err("device init failed, rc %d.", rc);
+				pr_err("device init failed, rc %d.\n", rc);
 		}
 	} else {
 		if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) {
-			sms_err("invalid mode specified %d", mode);
+			pr_err("invalid mode specified %d\n", mode);
 			return -EINVAL;
 		}
 
@@ -1414,9 +1412,9 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
 	}
 
 	if (rc < 0)
-		sms_err("return error code %d.", rc);
+		pr_err("return error code %d.\n", rc);
 	else
-		sms_debug("Success setting device mode.");
+		pr_debug("Success setting device mode.\n");
 
 	return rc;
 }
@@ -1495,7 +1493,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		last_sample_time = time_now;
 
 	if (time_now - last_sample_time > 10000) {
-		sms_debug("data rate %d bytes/secs",
+		pr_debug("data rate %d bytes/secs\n",
 			  (int)((data_total * 1000) /
 				(time_now - last_sample_time)));
 
@@ -1539,7 +1537,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		{
 			struct sms_version_res *ver =
 				(struct sms_version_res *) phdr;
-			sms_debug("Firmware id %d prots 0x%x ver %d.%d",
+			pr_debug("Firmware id %d prots 0x%x ver %d.%d\n",
 				  ver->firmware_id, ver->supported_protocols,
 				  ver->rom_ver_major, ver->rom_ver_minor);
 
@@ -1562,7 +1560,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		{
 			struct sms_msg_data *validity = (struct sms_msg_data *) phdr;
 
-			sms_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x",
+			pr_debug("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x\n",
 				validity->msg_data[0]);
 			complete(&coredev->data_validity_done);
 			break;
@@ -1588,7 +1586,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 		{
 			u32 *msgdata = (u32 *) phdr;
 			coredev->gpio_get_res = msgdata[1];
-			sms_debug("gpio level %d",
+			pr_debug("gpio level %d\n",
 					coredev->gpio_get_res);
 			complete(&coredev->gpio_get_level_done);
 			break;
@@ -1615,7 +1613,7 @@ void smscore_onresponse(struct smscore_device_t *coredev,
 			break;
 
 		default:
-			sms_debug("message %s(%d) not handled.",
+			pr_debug("message %s(%d) not handled.\n",
 				  smscore_translate_msg(phdr->msg_type),
 				  phdr->msg_type);
 			break;
@@ -1681,7 +1679,7 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
 	struct smscore_client_t *registered_client;
 
 	if (!client) {
-		sms_err("bad parameter.");
+		pr_err("bad parameter.\n");
 		return -EINVAL;
 	}
 	registered_client = smscore_find_client(coredev, data_type, id);
@@ -1689,12 +1687,12 @@ static int smscore_validate_client(struct smscore_device_t *coredev,
 		return 0;
 
 	if (registered_client) {
-		sms_err("The msg ID already registered to another client.");
+		pr_err("The msg ID already registered to another client.\n");
 		return -EEXIST;
 	}
 	listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL);
 	if (!listentry) {
-		sms_err("Can't allocate memory for client id.");
+		pr_err("Can't allocate memory for client id.\n");
 		return -ENOMEM;
 	}
 	listentry->id = id;
@@ -1726,13 +1724,13 @@ int smscore_register_client(struct smscore_device_t *coredev,
 	/* check that no other channel with same parameters exists */
 	if (smscore_find_client(coredev, params->data_type,
 				params->initial_id)) {
-		sms_err("Client already exist.");
+		pr_err("Client already exist.\n");
 		return -EEXIST;
 	}
 
 	newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL);
 	if (!newclient) {
-		sms_err("Failed to allocate memory for client.");
+		pr_err("Failed to allocate memory for client.\n");
 		return -ENOMEM;
 	}
 
@@ -1746,7 +1744,7 @@ int smscore_register_client(struct smscore_device_t *coredev,
 	smscore_validate_client(coredev, newclient, params->data_type,
 				params->initial_id);
 	*client = newclient;
-	sms_debug("%p %d %d", params->context, params->data_type,
+	pr_debug("%p %d %d\n", params->context, params->data_type,
 		  params->initial_id);
 
 	return 0;
@@ -1775,7 +1773,7 @@ void smscore_unregister_client(struct smscore_client_t *client)
 		kfree(identry);
 	}
 
-	sms_info("%p", client->context);
+	pr_debug("%p\n", client->context);
 
 	list_del(&client->entry);
 	kfree(client);
@@ -1803,7 +1801,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 	int rc;
 
 	if (client == NULL) {
-		sms_err("Got NULL client");
+		pr_err("Got NULL client\n");
 		return -EINVAL;
 	}
 
@@ -1811,7 +1809,7 @@ int smsclient_sendrequest(struct smscore_client_t *client,
 
 	/* check that no other channel with same id exists */
 	if (coredev == NULL) {
-		sms_err("Got NULL coredev");
+		pr_err("Got NULL coredev\n");
 		return -EINVAL;
 	}
 
@@ -2016,9 +2014,9 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 pin_num,
 
 	if (rc != 0) {
 		if (rc == -ETIME)
-			sms_err("smscore_gpio_configure timeout");
+			pr_err("smscore_gpio_configure timeout\n");
 		else
-			sms_err("smscore_gpio_configure error");
+			pr_err("smscore_gpio_configure error\n");
 	}
 free:
 	kfree(buffer);
@@ -2065,9 +2063,9 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 pin_num,
 
 	if (rc != 0) {
 		if (rc == -ETIME)
-			sms_err("smscore_gpio_set_level timeout");
+			pr_err("smscore_gpio_set_level timeout\n");
 		else
-			sms_err("smscore_gpio_set_level error");
+			pr_err("smscore_gpio_set_level error\n");
 	}
 	kfree(buffer);
 
@@ -2113,9 +2111,9 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 pin_num,
 
 	if (rc != 0) {
 		if (rc == -ETIME)
-			sms_err("smscore_gpio_get_level timeout");
+			pr_err("smscore_gpio_get_level timeout\n");
 		else
-			sms_err("smscore_gpio_get_level error");
+			pr_err("smscore_gpio_get_level error\n");
 	}
 	kfree(buffer);
 
@@ -2163,7 +2161,7 @@ static void __exit smscore_module_exit(void)
 	}
 	kmutex_unlock(&g_smscore_registrylock);
 
-	sms_debug("");
+	pr_debug("\n");
 }
 
 module_init(smscore_module_init);

+ 10 - 22
drivers/media/common/siano/smscoreapi.h

@@ -22,6 +22,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #ifndef __SMS_CORE_API_H__
 #define __SMS_CORE_API_H__
 
+#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
+
 #include <linux/device.h>
 #include <linux/list.h>
 #include <linux/mm.h>
@@ -31,6 +33,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <linux/wait.h>
 #include <linux/timer.h>
 
+#include <media/media-device.h>
+
 #include <asm/page.h>
 
 #include "smsir.h"
@@ -215,6 +219,10 @@ struct smscore_device_t {
 	bool is_usb_device;
 
 	int led_state;
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	struct media_device *media_dev;
+#endif
 };
 
 /* GPIO definitions for antenna frequency domain control (SMS8021) */
@@ -1115,7 +1123,8 @@ extern int smscore_register_hotplug(hotplug_t hotplug);
 extern void smscore_unregister_hotplug(hotplug_t hotplug);
 
 extern int smscore_register_device(struct smsdevice_params_t *params,
-				   struct smscore_device_t **coredev);
+				   struct smscore_device_t **coredev,
+				   void *mdev);
 extern void smscore_unregister_device(struct smscore_device_t *coredev);
 
 extern int smscore_start_device(struct smscore_device_t *coredev);
@@ -1168,25 +1177,4 @@ int smscore_led_state(struct smscore_device_t *core, int led);
 
 /* ------------------------------------------------------------------------ */
 
-#define DBG_INFO 1
-#define DBG_ADV  2
-
-#define sms_printk(kern, fmt, arg...) \
-	printk(kern "%s: " fmt "\n", __func__, ##arg)
-
-#define dprintk(kern, lvl, fmt, arg...) do {\
-	if (sms_dbg & lvl) \
-		sms_printk(kern, fmt, ##arg); \
-} while (0)
-
-#define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg)
-#define sms_err(fmt, arg...) \
-	sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg)
-#define sms_warn(fmt, arg...)  sms_printk(KERN_WARNING, fmt, ##arg)
-#define sms_info(fmt, arg...) \
-	dprintk(KERN_INFO, DBG_INFO, fmt, ##arg)
-#define sms_debug(fmt, arg...) \
-	dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg)
-
-
 #endif /* __SMS_CORE_API_H__ */

+ 2 - 4
drivers/media/common/siano/smsdvb-debugfs.c

@@ -17,7 +17,7 @@
  *
  ***********************************************************************/
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include "smscoreapi.h"
 
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -31,8 +31,6 @@
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
 
-#include "smscoreapi.h"
-
 #include "smsdvb.h"
 
 static struct dentry *smsdvb_debugfs_usb_root;
@@ -536,7 +534,7 @@ int smsdvb_debugfs_register(void)
 	 */
 	d = debugfs_create_dir("smsdvb", usb_debug_root);
 	if (IS_ERR_OR_NULL(d)) {
-		sms_err("Couldn't create sysfs node for smsdvb");
+		pr_err("Couldn't create sysfs node for smsdvb\n");
 		return PTR_ERR(d);
 	} else {
 		smsdvb_debugfs_usb_root = d;

+ 43 - 31
drivers/media/common/siano/smsdvb-main.c

@@ -19,6 +19,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 ****************************************************************/
 
+#include "smscoreapi.h"
+
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -29,7 +31,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "dvb_demux.h"
 #include "dvb_frontend.h"
 
-#include "smscoreapi.h"
 #include "sms-cards.h"
 
 #include "smsdvb.h"
@@ -39,11 +40,6 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 static struct list_head g_smsdvb_clients;
 static struct mutex g_smsdvb_clientslock;
 
-static int sms_dbg;
-module_param_named(debug, sms_dbg, int, 0644);
-MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
-
-
 static u32 sms_to_guard_interval_table[] = {
 	[0] = GUARD_INTERVAL_1_32,
 	[1] = GUARD_INTERVAL_1_16,
@@ -82,48 +78,48 @@ static void sms_board_dvb3_event(struct smsdvb_client_t *client,
 	struct smscore_device_t *coredev = client->coredev;
 	switch (event) {
 	case DVB3_EVENT_INIT:
-		sms_debug("DVB3_EVENT_INIT");
+		pr_debug("DVB3_EVENT_INIT\n");
 		sms_board_event(coredev, BOARD_EVENT_BIND);
 		break;
 	case DVB3_EVENT_SLEEP:
-		sms_debug("DVB3_EVENT_SLEEP");
+		pr_debug("DVB3_EVENT_SLEEP\n");
 		sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND);
 		break;
 	case DVB3_EVENT_HOTPLUG:
-		sms_debug("DVB3_EVENT_HOTPLUG");
+		pr_debug("DVB3_EVENT_HOTPLUG\n");
 		sms_board_event(coredev, BOARD_EVENT_POWER_INIT);
 		break;
 	case DVB3_EVENT_FE_LOCK:
 		if (client->event_fe_state != DVB3_EVENT_FE_LOCK) {
 			client->event_fe_state = DVB3_EVENT_FE_LOCK;
-			sms_debug("DVB3_EVENT_FE_LOCK");
+			pr_debug("DVB3_EVENT_FE_LOCK\n");
 			sms_board_event(coredev, BOARD_EVENT_FE_LOCK);
 		}
 		break;
 	case DVB3_EVENT_FE_UNLOCK:
 		if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) {
 			client->event_fe_state = DVB3_EVENT_FE_UNLOCK;
-			sms_debug("DVB3_EVENT_FE_UNLOCK");
+			pr_debug("DVB3_EVENT_FE_UNLOCK\n");
 			sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK);
 		}
 		break;
 	case DVB3_EVENT_UNC_OK:
 		if (client->event_unc_state != DVB3_EVENT_UNC_OK) {
 			client->event_unc_state = DVB3_EVENT_UNC_OK;
-			sms_debug("DVB3_EVENT_UNC_OK");
+			pr_debug("DVB3_EVENT_UNC_OK\n");
 			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK);
 		}
 		break;
 	case DVB3_EVENT_UNC_ERR:
 		if (client->event_unc_state != DVB3_EVENT_UNC_ERR) {
 			client->event_unc_state = DVB3_EVENT_UNC_ERR;
-			sms_debug("DVB3_EVENT_UNC_ERR");
+			pr_debug("DVB3_EVENT_UNC_ERR\n");
 			sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS);
 		}
 		break;
 
 	default:
-		sms_err("Unknown dvb3 api event");
+		pr_err("Unknown dvb3 api event\n");
 		break;
 	}
 }
@@ -590,7 +586,7 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 		is_status_update = true;
 		break;
 	default:
-		sms_info("message not handled");
+		pr_debug("message not handled\n");
 	}
 	smscore_putbuffer(client->coredev, cb);
 
@@ -613,6 +609,19 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb)
 	return 0;
 }
 
+static void smsdvb_media_device_unregister(struct smsdvb_client_t *client)
+{
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	struct smscore_device_t *coredev = client->coredev;
+
+	if (!coredev->media_dev)
+		return;
+	media_device_unregister(coredev->media_dev);
+	kfree(coredev->media_dev);
+	coredev->media_dev = NULL;
+#endif
+}
+
 static void smsdvb_unregister_client(struct smsdvb_client_t *client)
 {
 	/* must be called under clientslock */
@@ -624,6 +633,7 @@ static void smsdvb_unregister_client(struct smsdvb_client_t *client)
 	dvb_unregister_frontend(&client->frontend);
 	dvb_dmxdev_release(&client->dmxdev);
 	dvb_dmx_release(&client->demux);
+	smsdvb_media_device_unregister(client);
 	dvb_unregister_adapter(&client->adapter);
 	kfree(client);
 }
@@ -643,7 +653,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed)
 		container_of(feed->demux, struct smsdvb_client_t, demux);
 	struct sms_msg_data pid_msg;
 
-	sms_debug("add pid %d(%x)",
+	pr_debug("add pid %d(%x)\n",
 		  feed->pid, feed->pid);
 
 	client->feed_users++;
@@ -665,7 +675,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed)
 		container_of(feed->demux, struct smsdvb_client_t, demux);
 	struct sms_msg_data pid_msg;
 
-	sms_debug("remove pid %d(%x)",
+	pr_debug("remove pid %d(%x)\n",
 		  feed->pid, feed->pid);
 
 	client->feed_users--;
@@ -835,7 +845,7 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 static int smsdvb_get_tune_settings(struct dvb_frontend *fe,
 				    struct dvb_frontend_tune_settings *tune)
 {
-	sms_debug("");
+	pr_debug("\n");
 
 	tune->min_delay_ms = 400;
 	tune->step_size = 250000;
@@ -869,7 +879,7 @@ static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe)
 	msg.Data[0] = c->frequency;
 	msg.Data[2] = 12000000;
 
-	sms_info("%s: freq %d band %d", __func__, c->frequency,
+	pr_debug("%s: freq %d band %d\n", __func__, c->frequency,
 		 c->bandwidth_hz);
 
 	switch (c->bandwidth_hz / 1000000) {
@@ -954,7 +964,7 @@ static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe)
 
 	c->bandwidth_hz = 6000000;
 
-	sms_info("%s: freq %d segwidth %d segindex %d", __func__,
+	pr_debug("freq %d segwidth %d segindex %d\n",
 		 c->frequency, c->isdbt_sb_segment_count,
 		 c->isdbt_sb_segment_idx);
 
@@ -1082,10 +1092,8 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 	if (!arrival)
 		return 0;
 	client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL);
-	if (!client) {
-		sms_err("kmalloc() failed");
+	if (!client)
 		return -ENOMEM;
-	}
 
 	/* register dvb adapter */
 	rc = dvb_register_adapter(&client->adapter,
@@ -1093,9 +1101,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 					smscore_get_board_id(coredev))->name,
 				  THIS_MODULE, device, adapter_nr);
 	if (rc < 0) {
-		sms_err("dvb_register_adapter() failed %d", rc);
+		pr_err("dvb_register_adapter() failed %d\n", rc);
 		goto adapter_error;
 	}
+	dvb_register_media_controller(&client->adapter, coredev->media_dev);
 
 	/* init dvb demux */
 	client->demux.dmx.capabilities = DMX_TS_FILTERING;
@@ -1106,7 +1115,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
 	rc = dvb_dmx_init(&client->demux);
 	if (rc < 0) {
-		sms_err("dvb_dmx_init failed %d", rc);
+		pr_err("dvb_dmx_init failed %d\n", rc);
 		goto dvbdmx_error;
 	}
 
@@ -1117,7 +1126,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
 	rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter);
 	if (rc < 0) {
-		sms_err("dvb_dmxdev_init failed %d", rc);
+		pr_err("dvb_dmxdev_init failed %d\n", rc);
 		goto dmxdev_error;
 	}
 
@@ -1138,7 +1147,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
 	rc = dvb_register_frontend(&client->adapter, &client->frontend);
 	if (rc < 0) {
-		sms_err("frontend registration failed %d", rc);
+		pr_err("frontend registration failed %d\n", rc);
 		goto frontend_error;
 	}
 
@@ -1150,7 +1159,7 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 
 	rc = smscore_register_client(coredev, &params, &client->smsclient);
 	if (rc < 0) {
-		sms_err("smscore_register_client() failed %d", rc);
+		pr_err("smscore_register_client() failed %d\n", rc);
 		goto client_error;
 	}
 
@@ -1169,12 +1178,14 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev,
 	client->event_unc_state = -1;
 	sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG);
 
-	sms_info("success");
 	sms_board_setup(coredev);
 
 	if (smsdvb_debugfs_create(client) < 0)
-		sms_info("failed to create debugfs node");
+		pr_info("failed to create debugfs node\n");
+
+	dvb_create_media_graph(&client->adapter);
 
+	pr_info("DVB interface registered.\n");
 	return 0;
 
 client_error:
@@ -1187,6 +1198,7 @@ dmxdev_error:
 	dvb_dmx_release(&client->demux);
 
 dvbdmx_error:
+	smsdvb_media_device_unregister(client);
 	dvb_unregister_adapter(&client->adapter);
 
 adapter_error:
@@ -1205,7 +1217,7 @@ static int __init smsdvb_module_init(void)
 
 	rc = smscore_register_hotplug(smsdvb_hotplug);
 
-	sms_debug("");
+	pr_debug("\n");
 
 	return rc;
 }

+ 9 - 9
drivers/media/common/siano/smsir.c

@@ -25,10 +25,11 @@
  ****************************************************************/
 
 
+#include "smscoreapi.h"
+
 #include <linux/types.h>
 #include <linux/input.h>
 
-#include "smscoreapi.h"
 #include "smsir.h"
 #include "sms-cards.h"
 
@@ -56,16 +57,14 @@ int sms_ir_init(struct smscore_device_t *coredev)
 	int board_id = smscore_get_board_id(coredev);
 	struct rc_dev *dev;
 
-	sms_log("Allocating rc device");
+	pr_debug("Allocating rc device\n");
 	dev = rc_allocate_device();
-	if (!dev) {
-		sms_err("Not enough memory");
+	if (!dev)
 		return -ENOMEM;
-	}
 
 	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
 	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
-	sms_log("IR port %d, timeout %d ms",
+	pr_debug("IR port %d, timeout %d ms\n",
 			coredev->ir.controller, coredev->ir.timeout);
 
 	snprintf(coredev->ir.name, sizeof(coredev->ir.name),
@@ -92,11 +91,12 @@ int sms_ir_init(struct smscore_device_t *coredev)
 	dev->map_name = sms_get_board(board_id)->rc_codes;
 	dev->driver_name = MODULE_NAME;
 
-	sms_log("Input device (IR) %s is set for key events", dev->input_name);
+	pr_debug("Input device (IR) %s is set for key events\n",
+		 dev->input_name);
 
 	err = rc_register_device(dev);
 	if (err < 0) {
-		sms_err("Failed to register device");
+		pr_err("Failed to register device\n");
 		rc_free_device(dev);
 		return err;
 	}
@@ -109,5 +109,5 @@ void sms_ir_exit(struct smscore_device_t *coredev)
 {
 	rc_unregister_device(coredev->ir.dev);
 
-	sms_log("");
+	pr_debug("\n");
 }

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

@@ -1136,10 +1136,13 @@ static const struct file_operations dvb_demux_fops = {
 	.llseek = default_llseek,
 };
 
-static struct dvb_device dvbdev_demux = {
+static const struct dvb_device dvbdev_demux = {
 	.priv = NULL,
 	.users = 1,
 	.writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	.name = "dvb-demux",
+#endif
 	.fops = &dvb_demux_fops
 };
 
@@ -1209,13 +1212,15 @@ static const struct file_operations dvb_dvr_fops = {
 	.llseek = default_llseek,
 };
 
-static struct dvb_device dvbdev_dvr = {
+static const struct dvb_device dvbdev_dvr = {
 	.priv = NULL,
 	.readers = 1,
 	.users = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	.name = "dvb-dvr",
+#endif
 	.fops = &dvb_dvr_fops
 };
-
 int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 {
 	int i;

+ 3 - 0
drivers/media/dvb-core/dvb-usb-ids.h

@@ -245,6 +245,7 @@
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM	0x3009
 #define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d
+#define USB_PID_TECHNOTREND_CONNECT_S2_4600             0x3011
 #define USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI		0x3012
 #define USB_PID_TECHNOTREND_TVSTICK_CT2_4400		0x3014
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a
@@ -318,6 +319,7 @@
 #define USB_PID_GRANDTEC_DVBT_USB2_COLD			0x0bc6
 #define USB_PID_GRANDTEC_DVBT_USB2_WARM			0x0bc7
 #define USB_PID_WINFAST_DTV2000DS			0x6a04
+#define USB_PID_WINFAST_DTV2000DS_PLUS			0x6f12
 #define USB_PID_WINFAST_DTV_DONGLE_COLD			0x6025
 #define USB_PID_WINFAST_DTV_DONGLE_WARM			0x6026
 #define USB_PID_WINFAST_DTV_DONGLE_STK7700P		0x6f00
@@ -385,4 +387,5 @@
 #define USB_PID_PCTV_2002E                              0x025c
 #define USB_PID_PCTV_2002E_SE                           0x025d
 #define USB_PID_SVEON_STV27                             0xd3af
+#define USB_PID_TURBOX_DTT_2000                         0xd3a4
 #endif

+ 16 - 14
drivers/media/dvb-core/dvb_ca_en50221.c

@@ -1638,15 +1638,17 @@ static const struct file_operations dvb_ca_fops = {
 	.llseek = noop_llseek,
 };
 
-static struct dvb_device dvbdev_ca = {
+static const struct dvb_device dvbdev_ca = {
 	.priv = NULL,
 	.users = 1,
 	.readers = 1,
 	.writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	.name = "dvb-ca-en50221",
+#endif
 	.fops = &dvb_ca_fops,
 };
 
-
 /* ******************************************************************************** */
 /* Initialisation/shutdown functions */
 
@@ -1676,14 +1678,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 	/* initialise the system data */
 	if ((ca = kzalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
 		ret = -ENOMEM;
-		goto error;
+		goto exit;
 	}
 	ca->pub = pubca;
 	ca->flags = flags;
 	ca->slot_count = slot_count;
 	if ((ca->slot_info = kcalloc(slot_count, sizeof(struct dvb_ca_slot), GFP_KERNEL)) == NULL) {
 		ret = -ENOMEM;
-		goto error;
+		goto free_ca;
 	}
 	init_waitqueue_head(&ca->wait_queue);
 	ca->open = 0;
@@ -1694,7 +1696,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 	/* register the DVB device */
 	ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
 	if (ret)
-		goto error;
+		goto free_slot_info;
 
 	/* now initialise each slot */
 	for (i = 0; i < slot_count; i++) {
@@ -1709,7 +1711,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 
 	if (signal_pending(current)) {
 		ret = -EINTR;
-		goto error;
+		goto unregister_device;
 	}
 	mb();
 
@@ -1720,17 +1722,17 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
 		ret = PTR_ERR(ca->thread);
 		printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
 			ret);
-		goto error;
+		goto unregister_device;
 	}
 	return 0;
 
-error:
-	if (ca != NULL) {
-		if (ca->dvbdev != NULL)
-			dvb_unregister_device(ca->dvbdev);
-		kfree(ca->slot_info);
-		kfree(ca);
-	}
+unregister_device:
+	dvb_unregister_device(ca->dvbdev);
+free_slot_info:
+	kfree(ca->slot_info);
+free_ca:
+	kfree(ca);
+exit:
 	pubca->private = NULL;
 	return ret;
 }

+ 123 - 1
drivers/media/dvb-core/dvb_frontend.c

@@ -131,6 +131,11 @@ struct dvb_frontend_private {
 	int quality;
 	unsigned int check_wrapped;
 	enum dvbfe_search algo_status;
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	struct media_pipeline pipe;
+	struct media_entity *pipe_start_entity;
+#endif
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
@@ -590,12 +595,106 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
 	wake_up_interruptible(&fepriv->wait_queue);
 }
 
+/**
+ * dvb_enable_media_tuner() - tries to enable the DVB tuner
+ *
+ * @fe:		struct dvb_frontend pointer
+ *
+ * This function ensures that just one media tuner is enabled for a given
+ * frontend. It has two different behaviors:
+ * - For trivial devices with just one tuner:
+ *   it just enables the existing tuner->fe link
+ * - For devices with more than one tuner:
+ *   It is up to the driver to implement the logic that will enable one tuner
+ *   and disable the other ones. However, if more than one tuner is enabled for
+ *   the same frontend, it will print an error message and return -EINVAL.
+ *
+ * At return, it will return the error code returned by media_entity_setup_link,
+ * or 0 if everything is OK, if no tuner is linked to the frontend or if the
+ * mdev is NULL.
+ */
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+static int dvb_enable_media_tuner(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_adapter *adapter = fe->dvb;
+	struct media_device *mdev = adapter->mdev;
+	struct media_entity  *entity, *source;
+	struct media_link *link, *found_link = NULL;
+	int i, ret, n_links = 0, active_links = 0;
+
+	fepriv->pipe_start_entity = NULL;
+
+	if (!mdev)
+		return 0;
+
+	entity = fepriv->dvbdev->entity;
+	fepriv->pipe_start_entity = entity;
+
+	for (i = 0; i < entity->num_links; i++) {
+		link = &entity->links[i];
+		if (link->sink->entity == entity) {
+			found_link = link;
+			n_links++;
+			if (link->flags & MEDIA_LNK_FL_ENABLED)
+				active_links++;
+		}
+	}
+
+	if (!n_links || active_links == 1 || !found_link)
+		return 0;
+
+	/*
+	 * If a frontend has more than one tuner linked, it is up to the driver
+	 * to select with one will be the active one, as the frontend core can't
+	 * guess. If the driver doesn't do that, it is a bug.
+	 */
+	if (n_links > 1 && active_links != 1) {
+		dev_err(fe->dvb->device,
+			"WARNING: there are %d active links among %d tuners. This is a driver's bug!\n",
+			active_links, n_links);
+		return -EINVAL;
+	}
+
+	source = found_link->source->entity;
+	fepriv->pipe_start_entity = source;
+	for (i = 0; i < source->num_links; i++) {
+		struct media_entity *sink;
+		int flags = 0;
+
+		link = &source->links[i];
+		sink = link->sink->entity;
+
+		if (sink == entity)
+			flags = MEDIA_LNK_FL_ENABLED;
+
+		ret = media_entity_setup_link(link, flags);
+		if (ret) {
+			dev_err(fe->dvb->device,
+				"Couldn't change link %s->%s to %s. Error %d\n",
+				source->name, sink->name,
+				flags ? "enabled" : "disabled",
+				ret);
+			return ret;
+		} else
+			dev_dbg(fe->dvb->device,
+				"link %s->%s was %s\n",
+				source->name, sink->name,
+				flags ? "ENABLED" : "disabled");
+	}
+	return 0;
+}
+#endif
+
 static int dvb_frontend_thread(void *data)
 {
 	struct dvb_frontend *fe = data;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	fe_status_t s;
 	enum dvbfe_algo algo;
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	int ret;
+#endif
 
 	bool re_tune = false;
 	bool semheld = false;
@@ -609,6 +708,20 @@ static int dvb_frontend_thread(void *data)
 	fepriv->wakeup = 0;
 	fepriv->reinitialise = 0;
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	ret = dvb_enable_media_tuner(fe);
+	if (ret) {
+		/* FIXME: return an error if it fails */
+		dev_info(fe->dvb->device,
+			"proceeding with FE task\n");
+	} else if (fepriv->pipe_start_entity) {
+		ret = media_entity_pipeline_start(fepriv->pipe_start_entity,
+						  &fepriv->pipe);
+		if (ret)
+			return ret;
+	}
+#endif
+
 	dvb_frontend_init(fe);
 
 	set_freezable();
@@ -718,6 +831,12 @@ restart:
 		}
 	}
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	if (fepriv->pipe_start_entity)
+		media_entity_pipeline_stop(fepriv->pipe_start_entity);
+	fepriv->pipe_start_entity = NULL;
+#endif
+
 	if (dvb_powerdown_on_sleep) {
 		if (fe->ops.set_voltage)
 			fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
@@ -2612,11 +2731,14 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 			  struct dvb_frontend* fe)
 {
 	struct dvb_frontend_private *fepriv;
-	static const struct dvb_device dvbdev_template = {
+	const struct dvb_device dvbdev_template = {
 		.users = ~0,
 		.writers = 1,
 		.readers = (~0)-1,
 		.fops = &dvb_frontend_fops,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+		.name = fe->ops.info.name,
+#endif
 		.kernel_ioctl = dvb_frontend_ioctl
 	};
 

+ 4 - 2
drivers/media/dvb-core/dvb_net.c

@@ -1461,14 +1461,16 @@ static const struct file_operations dvb_net_fops = {
 	.llseek = noop_llseek,
 };
 
-static struct dvb_device dvbdev_net = {
+static const struct dvb_device dvbdev_net = {
 	.priv = NULL,
 	.users = 1,
 	.writers = 1,
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	.name = "dvb-net",
+#endif
 	.fops = &dvb_net_fops,
 };
 
-
 void dvb_net_release (struct dvb_net *dvbnet)
 {
 	int i;

+ 143 - 1
drivers/media/dvb-core/dvbdev.c

@@ -180,6 +180,93 @@ skip:
 	return -ENFILE;
 }
 
+static void dvb_register_media_device(struct dvb_device *dvbdev,
+				      int type, int minor)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	int ret = 0, npads;
+
+	if (!dvbdev->adapter->mdev)
+		return;
+
+	dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
+	if (!dvbdev->entity)
+		return;
+
+	dvbdev->entity->info.dev.major = DVB_MAJOR;
+	dvbdev->entity->info.dev.minor = minor;
+	dvbdev->entity->name = dvbdev->name;
+
+	switch (type) {
+	case DVB_DEVICE_CA:
+	case DVB_DEVICE_DEMUX:
+	case DVB_DEVICE_FRONTEND:
+		npads = 2;
+		break;
+	case DVB_DEVICE_NET:
+		npads = 0;
+		break;
+	default:
+		npads = 1;
+	}
+
+	if (npads) {
+		dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
+				       GFP_KERNEL);
+		if (!dvbdev->pads) {
+			kfree(dvbdev->entity);
+			return;
+		}
+	}
+
+	switch (type) {
+	case DVB_DEVICE_FRONTEND:
+		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
+		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+		break;
+	case DVB_DEVICE_DEMUX:
+		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
+		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+		break;
+	case DVB_DEVICE_DVR:
+		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR;
+		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+		break;
+	case DVB_DEVICE_CA:
+		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
+		dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
+		dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+		break;
+	case DVB_DEVICE_NET:
+		dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET;
+		break;
+	default:
+		kfree(dvbdev->entity);
+		dvbdev->entity = NULL;
+		return;
+	}
+
+	if (npads)
+		ret = media_entity_init(dvbdev->entity, npads, dvbdev->pads, 0);
+	if (!ret)
+		ret = media_device_register_entity(dvbdev->adapter->mdev,
+						   dvbdev->entity);
+	if (ret < 0) {
+		printk(KERN_ERR
+			"%s: media_device_register_entity failed for %s\n",
+			__func__, dvbdev->entity->name);
+		kfree(dvbdev->pads);
+		kfree(dvbdev->entity);
+		dvbdev->entity = NULL;
+		return;
+	}
+
+	printk(KERN_DEBUG "%s: media device '%s' registered.\n",
+		__func__, dvbdev->entity->name);
+#endif
+}
 
 int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 			const struct dvb_device *template, void *priv, int type)
@@ -258,10 +345,11 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
 		return PTR_ERR(clsdev);
 	}
-
 	dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, minor, minor);
 
+	dvb_register_media_device(dvbdev, type, minor);
+
 	return 0;
 }
 EXPORT_SYMBOL(dvb_register_device);
@@ -278,12 +366,66 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
 
 	device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	if (dvbdev->entity) {
+		media_device_unregister_entity(dvbdev->entity);
+		kfree(dvbdev->entity);
+		kfree(dvbdev->pads);
+	}
+#endif
+
 	list_del (&dvbdev->list_head);
 	kfree (dvbdev->fops);
 	kfree (dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
+
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+void dvb_create_media_graph(struct dvb_adapter *adap)
+{
+	struct media_device *mdev = adap->mdev;
+	struct media_entity *entity, *tuner = NULL, *fe = NULL;
+	struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
+
+	if (!mdev)
+		return;
+
+	media_device_for_each_entity(entity, mdev) {
+		switch (entity->type) {
+		case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
+			tuner = entity;
+			break;
+		case MEDIA_ENT_T_DEVNODE_DVB_FE:
+			fe = entity;
+			break;
+		case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
+			demux = entity;
+			break;
+		case MEDIA_ENT_T_DEVNODE_DVB_DVR:
+			dvr = entity;
+			break;
+		case MEDIA_ENT_T_DEVNODE_DVB_CA:
+			ca = entity;
+			break;
+		}
+	}
+
+	if (tuner && fe)
+		media_entity_create_link(tuner, 0, fe, 0, 0);
+
+	if (fe && demux)
+		media_entity_create_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
+
+	if (demux && dvr)
+		media_entity_create_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
+
+	if (demux && ca)
+		media_entity_create_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
+}
+EXPORT_SYMBOL_GPL(dvb_create_media_graph);
+#endif
+
 static int dvbdev_check_free_adapter_num(int num)
 {
 	struct list_head *entry;

+ 27 - 0
drivers/media/dvb-core/dvbdev.h

@@ -27,6 +27,7 @@
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/list.h>
+#include <media/media-device.h>
 
 #define DVB_MAJOR 212
 
@@ -71,6 +72,10 @@ struct dvb_adapter {
 	int mfe_shared;			/* indicates mutually exclusive frontends */
 	struct dvb_device *mfe_dvbdev;	/* frontend device in use */
 	struct mutex mfe_lock;		/* access lock for thread creation */
+
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	struct media_device *mdev;
+#endif
 };
 
 
@@ -92,6 +97,15 @@ struct dvb_device {
 	/* don't really need those !? -- FIXME: use video_usercopy  */
 	int (*kernel_ioctl)(struct file *file, unsigned int cmd, void *arg);
 
+	/* Needed for media controller register/unregister */
+#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
+	const char *name;
+
+	/* Allocated and filled inside dvbdev.c */
+	struct media_entity *entity;
+	struct media_pad *pads;
+#endif
+
 	void *priv;
 };
 
@@ -109,6 +123,19 @@ extern int dvb_register_device (struct dvb_adapter *adap,
 
 extern void dvb_unregister_device (struct dvb_device *dvbdev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+void dvb_create_media_graph(struct dvb_adapter *adap);
+static inline void dvb_register_media_controller(struct dvb_adapter *adap,
+						 struct media_device *mdev)
+{
+	adap->mdev = mdev;
+}
+
+#else
+static inline void dvb_create_media_graph(struct dvb_adapter *adap) {}
+#define dvb_register_media_controller(a, b) {}
+#endif
+
 extern int dvb_generic_open (struct inode *inode, struct file *file);
 extern int dvb_generic_release (struct inode *inode, struct file *file);
 extern long dvb_generic_ioctl (struct file *file,

+ 8 - 0
drivers/media/dvb-frontends/Kconfig

@@ -577,6 +577,14 @@ config DVB_LGDT3305
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+config DVB_LGDT3306A
+	tristate "LG Electronics LGDT3306A based"
+	depends on DVB_CORE && I2C
+	default m if !MEDIA_SUBDRV_AUTOSELECT
+	help
+	  An ATSC 8VSB and QAM-B 64/256 demodulator module. Say Y when you want
+	  to support this frontend.
+
 config DVB_LG2160
 	tristate "LG Electronics LG216x based"
 	depends on DVB_CORE && I2C

+ 1 - 0
drivers/media/dvb-frontends/Makefile

@@ -54,6 +54,7 @@ obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
+obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o
 obj-$(CONFIG_DVB_LG2160) += lg2160.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
 obj-$(CONFIG_DVB_LNBP21) += lnbp21.o

+ 1 - 1
drivers/media/dvb-frontends/a8293.h

@@ -27,7 +27,7 @@ struct a8293_config {
 	u8 i2c_addr;
 };
 
-#if IS_ENABLED(CONFIG_DVB_A8293)
+#if IS_REACHABLE(CONFIG_DVB_A8293)
 extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
 	struct i2c_adapter *i2c, const struct a8293_config *cfg);
 #else

+ 1 - 1
drivers/media/dvb-frontends/af9013.h

@@ -103,7 +103,7 @@ struct af9013_config {
 	u8 gpio[4];
 };
 
-#if IS_ENABLED(CONFIG_DVB_AF9013)
+#if IS_REACHABLE(CONFIG_DVB_AF9013)
 extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/atbm8830.h

@@ -61,7 +61,7 @@ struct atbm8830_config {
 	u8 agc_hold_loop;
 };
 
-#if IS_ENABLED(CONFIG_DVB_ATBM8830)
+#if IS_REACHABLE(CONFIG_DVB_ATBM8830)
 extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
 		struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/au8522.h

@@ -61,7 +61,7 @@ struct au8522_config {
 	enum au8522_if_freq qam_if;
 };
 
-#if IS_ENABLED(CONFIG_DVB_AU8522_DTV)
+#if IS_REACHABLE(CONFIG_DVB_AU8522_DTV)
 extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
 					  struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/bcm3510.h

@@ -34,7 +34,7 @@ struct bcm3510_config
 	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
 
-#if IS_ENABLED(CONFIG_DVB_BCM3510)
+#if IS_REACHABLE(CONFIG_DVB_BCM3510)
 extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
 					   struct i2c_adapter* i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/cx22700.h

@@ -31,7 +31,7 @@ struct cx22700_config
 	u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX22700)
+#if IS_REACHABLE(CONFIG_DVB_CX22700)
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
 					   struct i2c_adapter* i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/cx22702.h

@@ -41,7 +41,7 @@ struct cx22702_config {
 	u8 output_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX22702)
+#if IS_REACHABLE(CONFIG_DVB_CX22702)
 extern struct dvb_frontend *cx22702_attach(
 	const struct cx22702_config *config,
 	struct i2c_adapter *i2c);

+ 1 - 1
drivers/media/dvb-frontends/cx24110.h

@@ -46,7 +46,7 @@ static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val)
 	return 0;
 }
 
-#if IS_ENABLED(CONFIG_DVB_CX24110)
+#if IS_REACHABLE(CONFIG_DVB_CX24110)
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
 					   struct i2c_adapter* i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/cx24113.h

@@ -32,7 +32,7 @@ struct cx24113_config {
 	u32 xtal_khz;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_CX24113)
 extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
 	const struct cx24113_config *config, struct i2c_adapter *i2c);
 

+ 1 - 1
drivers/media/dvb-frontends/cx24116.h

@@ -41,7 +41,7 @@ struct cx24116_config {
 	u16 i2c_wr_max;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24116)
+#if IS_REACHABLE(CONFIG_DVB_CX24116)
 extern struct dvb_frontend *cx24116_attach(
 	const struct cx24116_config *config,
 	struct i2c_adapter *i2c);

+ 1 - 1
drivers/media/dvb-frontends/cx24117.h

@@ -30,7 +30,7 @@ struct cx24117_config {
 	u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24117)
+#if IS_REACHABLE(CONFIG_DVB_CX24117)
 extern struct dvb_frontend *cx24117_attach(
 	const struct cx24117_config *config,
 	struct i2c_adapter *i2c);

+ 1 - 1
drivers/media/dvb-frontends/cx24123.h

@@ -39,7 +39,7 @@ struct cx24123_config {
 	void (*agc_callback) (struct dvb_frontend *);
 };
 
-#if IS_ENABLED(CONFIG_DVB_CX24123)
+#if IS_REACHABLE(CONFIG_DVB_CX24123)
 extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
 					   struct i2c_adapter *i2c);
 extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);

+ 1 - 1
drivers/media/dvb-frontends/cxd2820r.h

@@ -72,7 +72,7 @@ struct cxd2820r_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_CXD2820R)
+#if IS_REACHABLE(CONFIG_DVB_CXD2820R)
 extern struct dvb_frontend *cxd2820r_attach(
 	const struct cxd2820r_config *config,
 	struct i2c_adapter *i2c,

+ 1 - 1
drivers/media/dvb-frontends/dib0070.h

@@ -48,7 +48,7 @@ struct dib0070_config {
 	u8 vga_filter;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_DIB0070)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_DIB0070)
 extern struct dvb_frontend *dib0070_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0070_config *cfg);
 extern u16 dib0070_wbd_offset(struct dvb_frontend *);
 extern void dib0070_ctrl_agc_filter(struct dvb_frontend *, u8 open);

+ 1 - 1
drivers/media/dvb-frontends/dib0090.h

@@ -75,7 +75,7 @@ struct dib0090_config {
 	u8 force_crystal_mode;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_DIB0090)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_DIB0090)
 extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);

+ 1 - 1
drivers/media/dvb-frontends/dib3000.h

@@ -41,7 +41,7 @@ struct dib_fe_xfer_ops
 	int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB3000MB)
+#if IS_REACHABLE(CONFIG_DVB_DIB3000MB)
 extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
 					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops);
 #else

+ 1 - 1
drivers/media/dvb-frontends/dib3000mc.h

@@ -41,7 +41,7 @@ struct dib3000mc_config {
 #define DEFAULT_DIB3000MC_I2C_ADDRESS 16
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
-#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
+#if IS_REACHABLE(CONFIG_DVB_DIB3000MC)
 extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
 					     u8 i2c_addr,
 					     struct dib3000mc_config *cfg);

+ 1 - 1
drivers/media/dvb-frontends/dib7000m.h

@@ -40,7 +40,7 @@ struct dib7000m_config {
 
 #define DEFAULT_DIB7000M_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB7000M)
+#if IS_REACHABLE(CONFIG_DVB_DIB7000M)
 extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
 					    u8 i2c_addr,
 					    struct dib7000m_config *cfg);

+ 1 - 1
drivers/media/dvb-frontends/dib7000p.h

@@ -66,7 +66,7 @@ struct dib7000p_ops {
 	struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB7000P)
+#if IS_REACHABLE(CONFIG_DVB_DIB7000P)
 void *dib7000p_attach(struct dib7000p_ops *ops);
 #else
 static inline void *dib7000p_attach(struct dib7000p_ops *ops)

+ 1 - 1
drivers/media/dvb-frontends/dib8000.h

@@ -63,7 +63,7 @@ struct dib8000_ops {
 	struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DIB8000)
+#if IS_REACHABLE(CONFIG_DVB_DIB8000)
 void *dib8000_attach(struct dib8000_ops *ops);
 #else
 static inline int dib8000_attach(struct dib8000_ops *ops)

+ 1 - 1
drivers/media/dvb-frontends/dib9000.h

@@ -27,7 +27,7 @@ struct dib9000_config {
 
 #define DEFAULT_DIB9000_I2C_ADDRESS 18
 
-#if IS_ENABLED(CONFIG_DVB_DIB9000)
+#if IS_REACHABLE(CONFIG_DVB_DIB9000)
 extern struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg);
 extern int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
 extern struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe);

+ 1 - 1
drivers/media/dvb-frontends/drx39xyj/drx39xxj.h

@@ -34,7 +34,7 @@ struct drx39xxj_state {
 	const struct firmware *fw;
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRX39XYJ)
+#if IS_REACHABLE(CONFIG_DVB_DRX39XYJ)
 struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c);
 #else
 static inline struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) {

+ 1 - 1
drivers/media/dvb-frontends/drxd.h

@@ -52,7 +52,7 @@ struct drxd_config {
 	 s16(*osc_deviation) (void *priv, s16 dev, int flag);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRXD)
+#if IS_REACHABLE(CONFIG_DVB_DRXD)
 extern
 struct dvb_frontend *drxd_attach(const struct drxd_config *config,
 				 void *priv, struct i2c_adapter *i2c,

+ 1 - 1
drivers/media/dvb-frontends/drxk.h

@@ -51,7 +51,7 @@ struct drxk_config {
 	int		 qam_demod_parameter_count;
 };
 
-#if IS_ENABLED(CONFIG_DVB_DRXK)
+#if IS_REACHABLE(CONFIG_DVB_DRXK)
 extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 					struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/ds3000.h

@@ -35,7 +35,7 @@ struct ds3000_config {
 	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
-#if IS_ENABLED(CONFIG_DVB_DS3000)
+#if IS_REACHABLE(CONFIG_DVB_DS3000)
 extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
 					struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/dvb-pll.h

@@ -38,7 +38,7 @@
  * @param pll_desc_id dvb_pll_desc to use.
  * @return Frontend pointer on success, NULL on failure
  */
-#if IS_ENABLED(CONFIG_DVB_PLL)
+#if IS_REACHABLE(CONFIG_DVB_PLL)
 extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe,
 					   int pll_addr,
 					   struct i2c_adapter *i2c,

+ 1 - 1
drivers/media/dvb-frontends/dvb_dummy_fe.h

@@ -26,7 +26,7 @@
 #include <linux/dvb/frontend.h>
 #include "dvb_frontend.h"
 
-#if IS_ENABLED(CONFIG_DVB_DUMMY_FE)
+#if IS_REACHABLE(CONFIG_DVB_DUMMY_FE)
 extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
 extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);

+ 1 - 1
drivers/media/dvb-frontends/ec100.h

@@ -31,7 +31,7 @@ struct ec100_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_EC100)
+#if IS_REACHABLE(CONFIG_DVB_EC100)
 extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/hd29l2.h

@@ -51,7 +51,7 @@ struct hd29l2_config {
 };
 
 
-#if IS_ENABLED(CONFIG_DVB_HD29L2)
+#if IS_REACHABLE(CONFIG_DVB_HD29L2)
 extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
 	struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/isl6405.h

@@ -55,7 +55,7 @@
 #define ISL6405_ENT2	0x20
 #define ISL6405_ISEL2	0x40
 
-#if IS_ENABLED(CONFIG_DVB_ISL6405)
+#if IS_REACHABLE(CONFIG_DVB_ISL6405)
 /* override_set and override_clear control which system register bits (above)
  * to always set & clear
  */

+ 1 - 1
drivers/media/dvb-frontends/isl6421.h

@@ -39,7 +39,7 @@
 #define ISL6421_ISEL1	0x20
 #define ISL6421_DCL	0x40
 
-#if IS_ENABLED(CONFIG_DVB_ISL6421)
+#if IS_REACHABLE(CONFIG_DVB_ISL6421)
 /* override_set and override_clear control which system register bits (above) to always set & clear */
 extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
 			  u8 override_set, u8 override_clear, bool override_tone);

+ 1 - 1
drivers/media/dvb-frontends/isl6423.h

@@ -42,7 +42,7 @@ struct isl6423_config {
 	u8 mod_extern;
 };
 
-#if IS_ENABLED(CONFIG_DVB_ISL6423)
+#if IS_REACHABLE(CONFIG_DVB_ISL6423)
 
 
 extern struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,

+ 1 - 1
drivers/media/dvb-frontends/itd1000.h

@@ -29,7 +29,7 @@ struct itd1000_config {
 	u8 i2c_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_TUNER_ITD1000)
+#if IS_REACHABLE(CONFIG_DVB_TUNER_ITD1000)
 extern struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg);
 #else
 static inline struct dvb_frontend *itd1000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct itd1000_config *cfg)

+ 1 - 1
drivers/media/dvb-frontends/ix2505v.h

@@ -49,7 +49,7 @@ struct ix2505v_config {
 
 };
 
-#if IS_ENABLED(CONFIG_DVB_IX2505V)
+#if IS_REACHABLE(CONFIG_DVB_IX2505V)
 extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
 	const struct ix2505v_config *config, struct i2c_adapter *i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/l64781.h

@@ -31,7 +31,7 @@ struct l64781_config
 	u8 demod_address;
 };
 
-#if IS_ENABLED(CONFIG_DVB_L64781)
+#if IS_REACHABLE(CONFIG_DVB_L64781)
 extern struct dvb_frontend* l64781_attach(const struct l64781_config* config,
 					  struct i2c_adapter* i2c);
 #else

+ 1 - 1
drivers/media/dvb-frontends/lg2160.h

@@ -67,7 +67,7 @@ struct lg2160_config {
 	enum lg_chip_type lg_chip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LG2160)
+#if IS_REACHABLE(CONFIG_DVB_LG2160)
 extern
 struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
 				     struct i2c_adapter *i2c_adap);

+ 1 - 1
drivers/media/dvb-frontends/lgdt3305.h

@@ -80,7 +80,7 @@ struct lgdt3305_config {
 	enum lgdt_demod_chip_type demod_chip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGDT3305)
+#if IS_REACHABLE(CONFIG_DVB_LGDT3305)
 extern
 struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
 				     struct i2c_adapter *i2c_adap);

+ 2144 - 0
drivers/media/dvb-frontends/lgdt3306a.c

@@ -0,0 +1,2144 @@
+/*
+ *    Support for LGDT3306A - 8VSB/QAM-B
+ *
+ *    Copyright (C) 2013 Fred Richter <frichter@hauppauge.com>
+ *    - driver structure based on lgdt3305.[ch] by Michael Krufky
+ *    - code based on LG3306_V0.35 API by LG Electronics Inc.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <asm/div64.h>
+#include <linux/dvb/frontend.h>
+#include "dvb_math.h"
+#include "lgdt3306a.h"
+
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (info=1, reg=2 (or-able))");
+
+#define DBG_INFO 1
+#define DBG_REG  2
+#define DBG_DUMP 4 /* FGR - comment out to remove dump code */
+
+#define lg_debug(fmt, arg...) \
+	printk(KERN_DEBUG pr_fmt(fmt), ## arg)
+
+#define dbg_info(fmt, arg...)					\
+	do {							\
+		if (debug & DBG_INFO)				\
+			lg_debug(fmt, ## arg);			\
+	} while (0)
+
+#define dbg_reg(fmt, arg...)					\
+	do {							\
+		if (debug & DBG_REG)				\
+			lg_debug(fmt, ## arg);			\
+	} while (0)
+
+#define lg_chkerr(ret)							\
+({									\
+	int __ret;							\
+	__ret = (ret < 0);						\
+	if (__ret)							\
+		pr_err("error %d on line %d\n",	ret, __LINE__);		\
+	__ret;								\
+})
+
+struct lgdt3306a_state {
+	struct i2c_adapter *i2c_adap;
+	const struct lgdt3306a_config *cfg;
+
+	struct dvb_frontend frontend;
+
+	fe_modulation_t current_modulation;
+	u32 current_frequency;
+	u32 snr;
+};
+
+/*
+ * LG3306A Register Usage
+ *  (LG does not really name the registers, so this code does not either)
+ *
+ * 0000 -> 00FF Common control and status
+ * 1000 -> 10FF Synchronizer control and status
+ * 1F00 -> 1FFF Smart Antenna control and status
+ * 2100 -> 21FF VSB Equalizer control and status
+ * 2800 -> 28FF QAM Equalizer control and status
+ * 3000 -> 30FF FEC control and status
+ */
+
+enum lgdt3306a_lock_status {
+	LG3306_UNLOCK       = 0x00,
+	LG3306_LOCK         = 0x01,
+	LG3306_UNKNOWN_LOCK = 0xff
+};
+
+enum lgdt3306a_neverlock_status {
+	LG3306_NL_INIT    = 0x00,
+	LG3306_NL_PROCESS = 0x01,
+	LG3306_NL_LOCK    = 0x02,
+	LG3306_NL_FAIL    = 0x03,
+	LG3306_NL_UNKNOWN = 0xff
+};
+
+enum lgdt3306a_modulation {
+	LG3306_VSB          = 0x00,
+	LG3306_QAM64        = 0x01,
+	LG3306_QAM256       = 0x02,
+	LG3306_UNKNOWN_MODE = 0xff
+};
+
+enum lgdt3306a_lock_check {
+	LG3306_SYNC_LOCK,
+	LG3306_FEC_LOCK,
+	LG3306_TR_LOCK,
+	LG3306_AGC_LOCK,
+};
+
+
+#ifdef DBG_DUMP
+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state);
+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state);
+#endif
+
+
+static int lgdt3306a_write_reg(struct lgdt3306a_state *state, u16 reg, u8 val)
+{
+	int ret;
+	u8 buf[] = { reg >> 8, reg & 0xff, val };
+	struct i2c_msg msg = {
+		.addr = state->cfg->i2c_addr, .flags = 0,
+		.buf = buf, .len = 3,
+	};
+
+	dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, val);
+
+	ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+	if (ret != 1) {
+		pr_err("error (addr %02x %02x <- %02x, err = %i)\n",
+		       msg.buf[0], msg.buf[1], msg.buf[2], ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int lgdt3306a_read_reg(struct lgdt3306a_state *state, u16 reg, u8 *val)
+{
+	int ret;
+	u8 reg_buf[] = { reg >> 8, reg & 0xff };
+	struct i2c_msg msg[] = {
+		{ .addr = state->cfg->i2c_addr,
+		  .flags = 0, .buf = reg_buf, .len = 2 },
+		{ .addr = state->cfg->i2c_addr,
+		  .flags = I2C_M_RD, .buf = val, .len = 1 },
+	};
+
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+
+	if (ret != 2) {
+		pr_err("error (addr %02x reg %04x error (ret == %i)\n",
+		       state->cfg->i2c_addr, reg, ret);
+		if (ret < 0)
+			return ret;
+		else
+			return -EREMOTEIO;
+	}
+	dbg_reg("reg: 0x%04x, val: 0x%02x\n", reg, *val);
+
+	return 0;
+}
+
+#define read_reg(state, reg)						\
+({									\
+	u8 __val;							\
+	int ret = lgdt3306a_read_reg(state, reg, &__val);		\
+	if (lg_chkerr(ret))						\
+		__val = 0;						\
+	__val;								\
+})
+
+static int lgdt3306a_set_reg_bit(struct lgdt3306a_state *state,
+				u16 reg, int bit, int onoff)
+{
+	u8 val;
+	int ret;
+
+	dbg_reg("reg: 0x%04x, bit: %d, level: %d\n", reg, bit, onoff);
+
+	ret = lgdt3306a_read_reg(state, reg, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	val &= ~(1 << bit);
+	val |= (onoff & 1) << bit;
+
+	ret = lgdt3306a_write_reg(state, reg, val);
+	lg_chkerr(ret);
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_soft_reset(struct lgdt3306a_state *state)
+{
+	int ret;
+
+	dbg_info("\n");
+
+	ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	msleep(20);
+	ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
+	lg_chkerr(ret);
+
+fail:
+	return ret;
+}
+
+static int lgdt3306a_mpeg_mode(struct lgdt3306a_state *state,
+				     enum lgdt3306a_mpeg_mode mode)
+{
+	u8 val;
+	int ret;
+
+	dbg_info("(%d)\n", mode);
+	/* transport packet format - TPSENB=0x80 */
+	ret = lgdt3306a_set_reg_bit(state, 0x0071, 7,
+				     mode == LGDT3306A_MPEG_PARALLEL ? 1 : 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/*
+	 * start of packet signal duration
+	 * TPSSOPBITEN=0x40; 0=byte duration, 1=bit duration
+	 */
+	ret = lgdt3306a_set_reg_bit(state, 0x0071, 6, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_read_reg(state, 0x0070, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	val |= 0x10; /* TPCLKSUPB=0x10 */
+
+	if (mode == LGDT3306A_MPEG_PARALLEL)
+		val &= ~0x10;
+
+	ret = lgdt3306a_write_reg(state, 0x0070, val);
+	lg_chkerr(ret);
+
+fail:
+	return ret;
+}
+
+static int lgdt3306a_mpeg_mode_polarity(struct lgdt3306a_state *state,
+				       enum lgdt3306a_tp_clock_edge edge,
+				       enum lgdt3306a_tp_valid_polarity valid)
+{
+	u8 val;
+	int ret;
+
+	dbg_info("edge=%d, valid=%d\n", edge, valid);
+
+	ret = lgdt3306a_read_reg(state, 0x0070, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	val &= ~0x06; /* TPCLKPOL=0x04, TPVALPOL=0x02 */
+
+	if (edge == LGDT3306A_TPCLK_RISING_EDGE)
+		val |= 0x04;
+	if (valid == LGDT3306A_TP_VALID_HIGH)
+		val |= 0x02;
+
+	ret = lgdt3306a_write_reg(state, 0x0070, val);
+	lg_chkerr(ret);
+
+fail:
+	return ret;
+}
+
+static int lgdt3306a_mpeg_tristate(struct lgdt3306a_state *state,
+				     int mode)
+{
+	u8 val;
+	int ret;
+
+	dbg_info("(%d)\n", mode);
+
+	if (mode) {
+		ret = lgdt3306a_read_reg(state, 0x0070, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+		/*
+		 * Tristate bus; TPOUTEN=0x80, TPCLKOUTEN=0x20,
+		 * TPDATAOUTEN=0x08
+		 */
+		val &= ~0xa8;
+		ret = lgdt3306a_write_reg(state, 0x0070, val);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		/* AGCIFOUTENB=0x40; 1=Disable IFAGC pin */
+		ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 1);
+		if (lg_chkerr(ret))
+			goto fail;
+
+	} else {
+		/* enable IFAGC pin */
+		ret = lgdt3306a_set_reg_bit(state, 0x0003, 6, 0);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		ret = lgdt3306a_read_reg(state, 0x0070, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		val |= 0xa8; /* enable bus */
+		ret = lgdt3306a_write_reg(state, 0x0070, val);
+		if (lg_chkerr(ret))
+			goto fail;
+	}
+
+fail:
+	return ret;
+}
+
+static int lgdt3306a_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	dbg_info("acquire=%d\n", acquire);
+
+	return lgdt3306a_mpeg_tristate(state, acquire ? 0 : 1);
+
+}
+
+static int lgdt3306a_power(struct lgdt3306a_state *state,
+				     int mode)
+{
+	int ret;
+
+	dbg_info("(%d)\n", mode);
+
+	if (mode == 0) {
+		/* into reset */
+		ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 0);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		/* power down */
+		ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 0);
+		if (lg_chkerr(ret))
+			goto fail;
+
+	} else {
+		/* out of reset */
+		ret = lgdt3306a_set_reg_bit(state, 0x0000, 7, 1);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		/* power up */
+		ret = lgdt3306a_set_reg_bit(state, 0x0000, 0, 1);
+		if (lg_chkerr(ret))
+			goto fail;
+	}
+
+#ifdef DBG_DUMP
+	lgdt3306a_DumpAllRegs(state);
+#endif
+fail:
+	return ret;
+}
+
+
+static int lgdt3306a_set_vsb(struct lgdt3306a_state *state)
+{
+	u8 val;
+	int ret;
+
+	dbg_info("\n");
+
+	/* 0. Spectrum inversion detection manual; spectrum inverted */
+	ret = lgdt3306a_read_reg(state, 0x0002, &val);
+	val &= 0xf7; /* SPECINVAUTO Off */
+	val |= 0x04; /* SPECINV On */
+	ret = lgdt3306a_write_reg(state, 0x0002, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
+	ret = lgdt3306a_write_reg(state, 0x0008, 0x80);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 2. Bandwidth mode for VSB(6MHz) */
+	ret = lgdt3306a_read_reg(state, 0x0009, &val);
+	val &= 0xe3;
+	val |= 0x0c; /* STDOPDETTMODE[2:0]=3 */
+	ret = lgdt3306a_write_reg(state, 0x0009, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 3. QAM mode detection mode(None) */
+	ret = lgdt3306a_read_reg(state, 0x0009, &val);
+	val &= 0xfc; /* STDOPDETCMODE[1:0]=0 */
+	ret = lgdt3306a_write_reg(state, 0x0009, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 4. ADC sampling frequency rate(2x sampling) */
+	ret = lgdt3306a_read_reg(state, 0x000d, &val);
+	val &= 0xbf; /* SAMPLING4XFEN=0 */
+	ret = lgdt3306a_write_reg(state, 0x000d, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+#if 0
+	/* FGR - disable any AICC filtering, testing only */
+
+	ret = lgdt3306a_write_reg(state, 0x0024, 0x00);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* AICCFIXFREQ0 NT N-1(Video rejection) */
+	ret = lgdt3306a_write_reg(state, 0x002e, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
+
+	/* AICCFIXFREQ1 NT N-1(Audio rejection) */
+	ret = lgdt3306a_write_reg(state, 0x002b, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
+
+	/* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
+	ret = lgdt3306a_write_reg(state, 0x0028, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
+
+	/* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
+	ret = lgdt3306a_write_reg(state, 0x0025, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
+
+#else
+	/* FGR - this works well for HVR-1955,1975 */
+
+	/* 5. AICCOPMODE  NT N-1 Adj. */
+	ret = lgdt3306a_write_reg(state, 0x0024, 0x5A);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* AICCFIXFREQ0 NT N-1(Video rejection) */
+	ret = lgdt3306a_write_reg(state, 0x002e, 0x5A);
+	ret = lgdt3306a_write_reg(state, 0x002f, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0030, 0x00);
+
+	/* AICCFIXFREQ1 NT N-1(Audio rejection) */
+	ret = lgdt3306a_write_reg(state, 0x002b, 0x36);
+	ret = lgdt3306a_write_reg(state, 0x002c, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002d, 0x00);
+
+	/* AICCFIXFREQ2 NT Co-Channel(Video rejection) */
+	ret = lgdt3306a_write_reg(state, 0x0028, 0x2A);
+	ret = lgdt3306a_write_reg(state, 0x0029, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x002a, 0x00);
+
+	/* AICCFIXFREQ3 NT Co-Channel(Audio rejection) */
+	ret = lgdt3306a_write_reg(state, 0x0025, 0x06);
+	ret = lgdt3306a_write_reg(state, 0x0026, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x0027, 0x00);
+#endif
+
+	ret = lgdt3306a_read_reg(state, 0x001e, &val);
+	val &= 0x0f;
+	val |= 0xa0;
+	ret = lgdt3306a_write_reg(state, 0x001e, val);
+
+	ret = lgdt3306a_write_reg(state, 0x0022, 0x08);
+
+	ret = lgdt3306a_write_reg(state, 0x0023, 0xFF);
+
+	ret = lgdt3306a_read_reg(state, 0x211f, &val);
+	val &= 0xef;
+	ret = lgdt3306a_write_reg(state, 0x211f, val);
+
+	ret = lgdt3306a_write_reg(state, 0x2173, 0x01);
+
+	ret = lgdt3306a_read_reg(state, 0x1061, &val);
+	val &= 0xf8;
+	val |= 0x04;
+	ret = lgdt3306a_write_reg(state, 0x1061, val);
+
+	ret = lgdt3306a_read_reg(state, 0x103d, &val);
+	val &= 0xcf;
+	ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+	ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
+
+	ret = lgdt3306a_read_reg(state, 0x2141, &val);
+	val &= 0x3f;
+	ret = lgdt3306a_write_reg(state, 0x2141, val);
+
+	ret = lgdt3306a_read_reg(state, 0x2135, &val);
+	val &= 0x0f;
+	val |= 0x70;
+	ret = lgdt3306a_write_reg(state, 0x2135, val);
+
+	ret = lgdt3306a_read_reg(state, 0x0003, &val);
+	val &= 0xf7;
+	ret = lgdt3306a_write_reg(state, 0x0003, val);
+
+	ret = lgdt3306a_read_reg(state, 0x001c, &val);
+	val &= 0x7f;
+	ret = lgdt3306a_write_reg(state, 0x001c, val);
+
+	/* 6. EQ step size */
+	ret = lgdt3306a_read_reg(state, 0x2179, &val);
+	val &= 0xf8;
+	ret = lgdt3306a_write_reg(state, 0x2179, val);
+
+	ret = lgdt3306a_read_reg(state, 0x217a, &val);
+	val &= 0xf8;
+	ret = lgdt3306a_write_reg(state, 0x217a, val);
+
+	/* 7. Reset */
+	ret = lgdt3306a_soft_reset(state);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	dbg_info("complete\n");
+fail:
+	return ret;
+}
+
+static int lgdt3306a_set_qam(struct lgdt3306a_state *state, int modulation)
+{
+	u8 val;
+	int ret;
+
+	dbg_info("modulation=%d\n", modulation);
+
+	/* 1. Selection of standard mode(0x08=QAM, 0x80=VSB) */
+	ret = lgdt3306a_write_reg(state, 0x0008, 0x08);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 1a. Spectrum inversion detection to Auto */
+	ret = lgdt3306a_read_reg(state, 0x0002, &val);
+	val &= 0xfb; /* SPECINV Off */
+	val |= 0x08; /* SPECINVAUTO On */
+	ret = lgdt3306a_write_reg(state, 0x0002, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 2. Bandwidth mode for QAM */
+	ret = lgdt3306a_read_reg(state, 0x0009, &val);
+	val &= 0xe3; /* STDOPDETTMODE[2:0]=0 VSB Off */
+	ret = lgdt3306a_write_reg(state, 0x0009, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 3. : 64QAM/256QAM detection(manual, auto) */
+	ret = lgdt3306a_read_reg(state, 0x0009, &val);
+	val &= 0xfc;
+	val |= 0x02; /* STDOPDETCMODE[1:0]=1=Manual 2=Auto */
+	ret = lgdt3306a_write_reg(state, 0x0009, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 3a. : 64QAM/256QAM selection for manual */
+	ret = lgdt3306a_read_reg(state, 0x101a, &val);
+	val &= 0xf8;
+	if (modulation == QAM_64)
+		val |= 0x02; /* QMDQMODE[2:0]=2=QAM64 */
+	else
+		val |= 0x04; /* QMDQMODE[2:0]=4=QAM256 */
+
+	ret = lgdt3306a_write_reg(state, 0x101a, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 4. ADC sampling frequency rate(4x sampling) */
+	ret = lgdt3306a_read_reg(state, 0x000d, &val);
+	val &= 0xbf;
+	val |= 0x40; /* SAMPLING4XFEN=1 */
+	ret = lgdt3306a_write_reg(state, 0x000d, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 5. No AICC operation in QAM mode */
+	ret = lgdt3306a_read_reg(state, 0x0024, &val);
+	val &= 0x00;
+	ret = lgdt3306a_write_reg(state, 0x0024, val);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 6. Reset */
+	ret = lgdt3306a_soft_reset(state);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	dbg_info("complete\n");
+fail:
+	return ret;
+}
+
+static int lgdt3306a_set_modulation(struct lgdt3306a_state *state,
+				   struct dtv_frontend_properties *p)
+{
+	int ret;
+
+	dbg_info("\n");
+
+	switch (p->modulation) {
+	case VSB_8:
+		ret = lgdt3306a_set_vsb(state);
+		break;
+	case QAM_64:
+		ret = lgdt3306a_set_qam(state, QAM_64);
+		break;
+	case QAM_256:
+		ret = lgdt3306a_set_qam(state, QAM_256);
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (lg_chkerr(ret))
+		goto fail;
+
+	state->current_modulation = p->modulation;
+
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_agc_setup(struct lgdt3306a_state *state,
+			      struct dtv_frontend_properties *p)
+{
+	/* TODO: anything we want to do here??? */
+	dbg_info("\n");
+
+	switch (p->modulation) {
+	case VSB_8:
+		break;
+	case QAM_64:
+	case QAM_256:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_set_inversion(struct lgdt3306a_state *state,
+				       int inversion)
+{
+	int ret;
+
+	dbg_info("(%d)\n", inversion);
+
+	ret = lgdt3306a_set_reg_bit(state, 0x0002, 2, inversion ? 1 : 0);
+	return ret;
+}
+
+static int lgdt3306a_set_inversion_auto(struct lgdt3306a_state *state,
+				       int enabled)
+{
+	int ret;
+
+	dbg_info("(%d)\n", enabled);
+
+	/* 0=Manual 1=Auto(QAM only) - SPECINVAUTO=0x04 */
+	ret = lgdt3306a_set_reg_bit(state, 0x0002, 3, enabled);
+	return ret;
+}
+
+static int lgdt3306a_spectral_inversion(struct lgdt3306a_state *state,
+				       struct dtv_frontend_properties *p,
+				       int inversion)
+{
+	int ret = 0;
+
+	dbg_info("(%d)\n", inversion);
+#if 0
+	/*
+	 * FGR - spectral_inversion defaults already set for VSB and QAM;
+	 * can enable later if desired
+	 */
+
+	ret = lgdt3306a_set_inversion(state, inversion);
+
+	switch (p->modulation) {
+	case VSB_8:
+		/* Manual only for VSB */
+		ret = lgdt3306a_set_inversion_auto(state, 0);
+		break;
+	case QAM_64:
+	case QAM_256:
+		/* Auto ok for QAM */
+		ret = lgdt3306a_set_inversion_auto(state, 1);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+#endif
+	return ret;
+}
+
+static int lgdt3306a_set_if(struct lgdt3306a_state *state,
+			   struct dtv_frontend_properties *p)
+{
+	int ret;
+	u16 if_freq_khz;
+	u8 nco1, nco2;
+
+	switch (p->modulation) {
+	case VSB_8:
+		if_freq_khz = state->cfg->vsb_if_khz;
+		break;
+	case QAM_64:
+	case QAM_256:
+		if_freq_khz = state->cfg->qam_if_khz;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (if_freq_khz) {
+	default:
+		pr_warn("IF=%d KHz is not supportted, 3250 assumed\n",
+			if_freq_khz);
+		/* fallthrough */
+	case 3250: /* 3.25Mhz */
+		nco1 = 0x34;
+		nco2 = 0x00;
+		break;
+	case 3500: /* 3.50Mhz */
+		nco1 = 0x38;
+		nco2 = 0x00;
+		break;
+	case 4000: /* 4.00Mhz */
+		nco1 = 0x40;
+		nco2 = 0x00;
+		break;
+	case 5000: /* 5.00Mhz */
+		nco1 = 0x50;
+		nco2 = 0x00;
+		break;
+	case 5380: /* 5.38Mhz */
+		nco1 = 0x56;
+		nco2 = 0x14;
+		break;
+	}
+	ret = lgdt3306a_write_reg(state, 0x0010, nco1);
+	if (ret)
+		return ret;
+	ret = lgdt3306a_write_reg(state, 0x0011, nco2);
+	if (ret)
+		return ret;
+
+	dbg_info("if_freq=%d KHz->[%04x]\n", if_freq_khz, nco1<<8 | nco2);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	if (state->cfg->deny_i2c_rptr) {
+		dbg_info("deny_i2c_rptr=%d\n", state->cfg->deny_i2c_rptr);
+		return 0;
+	}
+	dbg_info("(%d)\n", enable);
+
+	/* NI2CRPTEN=0x80 */
+	return lgdt3306a_set_reg_bit(state, 0x0002, 7, enable ? 0 : 1);
+}
+
+static int lgdt3306a_sleep(struct lgdt3306a_state *state)
+{
+	int ret;
+
+	dbg_info("\n");
+	state->current_frequency = -1; /* force re-tune, when we wake */
+
+	ret = lgdt3306a_mpeg_tristate(state, 1); /* disable data bus */
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_power(state, 0); /* power down */
+	lg_chkerr(ret);
+
+fail:
+	return 0;
+}
+
+static int lgdt3306a_fe_sleep(struct dvb_frontend *fe)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	return lgdt3306a_sleep(state);
+}
+
+static int lgdt3306a_init(struct dvb_frontend *fe)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	u8 val;
+	int ret;
+
+	dbg_info("\n");
+
+	/* 1. Normal operation mode */
+	ret = lgdt3306a_set_reg_bit(state, 0x0001, 0, 1); /* SIMFASTENB=0x01 */
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 2. Spectrum inversion auto detection (Not valid for VSB) */
+	ret = lgdt3306a_set_inversion_auto(state, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 3. Spectrum inversion(According to the tuner configuration) */
+	ret = lgdt3306a_set_inversion(state, 1);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 4. Peak-to-peak voltage of ADC input signal */
+
+	/* ADCSEL1V=0x80=1Vpp; 0x00=2Vpp */
+	ret = lgdt3306a_set_reg_bit(state, 0x0004, 7, 1);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 5. ADC output data capture clock phase */
+
+	/* 0=same phase as ADC clock */
+	ret = lgdt3306a_set_reg_bit(state, 0x0004, 2, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 5a. ADC sampling clock source */
+
+	/* ADCCLKPLLSEL=0x08; 0=use ext clock, not PLL */
+	ret = lgdt3306a_set_reg_bit(state, 0x0004, 3, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	/* 6. Automatic PLL set */
+
+	/* PLLSETAUTO=0x40; 0=off */
+	ret = lgdt3306a_set_reg_bit(state, 0x0005, 6, 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	if (state->cfg->xtalMHz == 24) {	/* 24MHz */
+		/* 7. Frequency for PLL output(0x2564 for 192MHz for 24MHz) */
+		ret = lgdt3306a_read_reg(state, 0x0005, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+		val &= 0xc0;
+		val |= 0x25;
+		ret = lgdt3306a_write_reg(state, 0x0005, val);
+		if (lg_chkerr(ret))
+			goto fail;
+		ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		/* 8. ADC sampling frequency(0x180000 for 24MHz sampling) */
+		ret = lgdt3306a_read_reg(state, 0x000d, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+		val &= 0xc0;
+		val |= 0x18;
+		ret = lgdt3306a_write_reg(state, 0x000d, val);
+		if (lg_chkerr(ret))
+			goto fail;
+
+	} else if (state->cfg->xtalMHz == 25) { /* 25MHz */
+		/* 7. Frequency for PLL output */
+		ret = lgdt3306a_read_reg(state, 0x0005, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+		val &= 0xc0;
+		val |= 0x25;
+		ret = lgdt3306a_write_reg(state, 0x0005, val);
+		if (lg_chkerr(ret))
+			goto fail;
+		ret = lgdt3306a_write_reg(state, 0x0006, 0x64);
+		if (lg_chkerr(ret))
+			goto fail;
+
+		/* 8. ADC sampling frequency(0x190000 for 25MHz sampling) */
+		ret = lgdt3306a_read_reg(state, 0x000d, &val);
+		if (lg_chkerr(ret))
+			goto fail;
+		val &= 0xc0;
+		val |= 0x19;
+		ret = lgdt3306a_write_reg(state, 0x000d, val);
+		if (lg_chkerr(ret))
+			goto fail;
+	} else {
+		pr_err("Bad xtalMHz=%d\n", state->cfg->xtalMHz);
+	}
+#if 0
+	ret = lgdt3306a_write_reg(state, 0x000e, 0x00);
+	ret = lgdt3306a_write_reg(state, 0x000f, 0x00);
+#endif
+
+	/* 9. Center frequency of input signal of ADC */
+	ret = lgdt3306a_write_reg(state, 0x0010, 0x34); /* 3.25MHz */
+	ret = lgdt3306a_write_reg(state, 0x0011, 0x00);
+
+	/* 10. Fixed gain error value */
+	ret = lgdt3306a_write_reg(state, 0x0014, 0); /* gain error=0 */
+
+	/* 10a. VSB TR BW gear shift initial step */
+	ret = lgdt3306a_read_reg(state, 0x103c, &val);
+	val &= 0x0f;
+	val |= 0x20; /* SAMGSAUTOSTL_V[3:0] = 2 */
+	ret = lgdt3306a_write_reg(state, 0x103c, val);
+
+	/* 10b. Timing offset calibration in low temperature for VSB */
+	ret = lgdt3306a_read_reg(state, 0x103d, &val);
+	val &= 0xfc;
+	val |= 0x03;
+	ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+	/* 10c. Timing offset calibration in low temperature for QAM */
+	ret = lgdt3306a_read_reg(state, 0x1036, &val);
+	val &= 0xf0;
+	val |= 0x0c;
+	ret = lgdt3306a_write_reg(state, 0x1036, val);
+
+	/* 11. Using the imaginary part of CIR in CIR loading */
+	ret = lgdt3306a_read_reg(state, 0x211f, &val);
+	val &= 0xef; /* do not use imaginary of CIR */
+	ret = lgdt3306a_write_reg(state, 0x211f, val);
+
+	/* 12. Control of no signal detector function */
+	ret = lgdt3306a_read_reg(state, 0x2849, &val);
+	val &= 0xef; /* NOUSENOSIGDET=0, enable no signal detector */
+	ret = lgdt3306a_write_reg(state, 0x2849, val);
+
+	/* FGR - put demod in some known mode */
+	ret = lgdt3306a_set_vsb(state);
+
+	/* 13. TP stream format */
+	ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
+
+	/* 14. disable output buses */
+	ret = lgdt3306a_mpeg_tristate(state, 1);
+
+	/* 15. Sleep (in reset) */
+	ret = lgdt3306a_sleep(state);
+	lg_chkerr(ret);
+
+fail:
+	return ret;
+}
+
+static int lgdt3306a_set_parameters(struct dvb_frontend *fe)
+{
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	int ret;
+
+	dbg_info("(%d, %d)\n", p->frequency, p->modulation);
+
+	if (state->current_frequency  == p->frequency &&
+	   state->current_modulation == p->modulation) {
+		dbg_info(" (already set, skipping ...)\n");
+		return 0;
+	}
+	state->current_frequency = -1;
+	state->current_modulation = -1;
+
+	ret = lgdt3306a_power(state, 1); /* power up */
+	if (lg_chkerr(ret))
+		goto fail;
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+#if 0
+		if (lg_chkerr(ret))
+			goto fail;
+		state->current_frequency = p->frequency;
+#endif
+	}
+
+	ret = lgdt3306a_set_modulation(state, p);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_agc_setup(state, p);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_set_if(state, p);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_spectral_inversion(state, p,
+					state->cfg->spectral_inversion ? 1 : 0);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_mpeg_mode(state, state->cfg->mpeg_mode);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_mpeg_mode_polarity(state,
+					  state->cfg->tpclk_edge,
+					  state->cfg->tpvalid_polarity);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_mpeg_tristate(state, 0); /* enable data bus */
+	if (lg_chkerr(ret))
+		goto fail;
+
+	ret = lgdt3306a_soft_reset(state);
+	if (lg_chkerr(ret))
+		goto fail;
+
+#ifdef DBG_DUMP
+	lgdt3306a_DumpAllRegs(state);
+#endif
+	state->current_frequency = p->frequency;
+fail:
+	return ret;
+}
+
+static int lgdt3306a_get_frontend(struct dvb_frontend *fe)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+
+	dbg_info("(%u, %d)\n",
+		 state->current_frequency, state->current_modulation);
+
+	p->modulation = state->current_modulation;
+	p->frequency = state->current_frequency;
+	return 0;
+}
+
+static enum dvbfe_algo lgdt3306a_get_frontend_algo(struct dvb_frontend *fe)
+{
+#if 1
+	return DVBFE_ALGO_CUSTOM;
+#else
+	return DVBFE_ALGO_HW;
+#endif
+}
+
+/* ------------------------------------------------------------------------ */
+static int lgdt3306a_monitor_vsb(struct lgdt3306a_state *state)
+{
+	u8 val;
+	int ret;
+	u8 snrRef, maxPowerMan, nCombDet;
+	u16 fbDlyCir;
+
+	ret = lgdt3306a_read_reg(state, 0x21a1, &val);
+	if (ret)
+		return ret;
+	snrRef = val & 0x3f;
+
+	ret = lgdt3306a_read_reg(state, 0x2185, &maxPowerMan);
+	if (ret)
+		return ret;
+
+	ret = lgdt3306a_read_reg(state, 0x2191, &val);
+	if (ret)
+		return ret;
+	nCombDet = (val & 0x80) >> 7;
+
+	ret = lgdt3306a_read_reg(state, 0x2180, &val);
+	if (ret)
+		return ret;
+	fbDlyCir = (val & 0x03) << 8;
+
+	ret = lgdt3306a_read_reg(state, 0x2181, &val);
+	if (ret)
+		return ret;
+	fbDlyCir |= val;
+
+	dbg_info("snrRef=%d maxPowerMan=0x%x nCombDet=%d fbDlyCir=0x%x\n",
+		snrRef, maxPowerMan, nCombDet, fbDlyCir);
+
+	/* Carrier offset sub loop bandwidth */
+	ret = lgdt3306a_read_reg(state, 0x1061, &val);
+	if (ret)
+		return ret;
+	val &= 0xf8;
+	if ((snrRef > 18) && (maxPowerMan > 0x68)
+	    && (nCombDet == 0x01)
+	    && ((fbDlyCir == 0x03FF) || (fbDlyCir < 0x6C))) {
+		/* SNR is over 18dB and no ghosting */
+		val |= 0x00; /* final bandwidth = 0 */
+	} else {
+		val |= 0x04; /* final bandwidth = 4 */
+	}
+	ret = lgdt3306a_write_reg(state, 0x1061, val);
+	if (ret)
+		return ret;
+
+	/* Adjust Notch Filter */
+	ret = lgdt3306a_read_reg(state, 0x0024, &val);
+	if (ret)
+		return ret;
+	val &= 0x0f;
+	if (nCombDet == 0) { /* Turn on the Notch Filter */
+		val |= 0x50;
+	}
+	ret = lgdt3306a_write_reg(state, 0x0024, val);
+	if (ret)
+		return ret;
+
+	/* VSB Timing Recovery output normalization */
+	ret = lgdt3306a_read_reg(state, 0x103d, &val);
+	if (ret)
+		return ret;
+	val &= 0xcf;
+	val |= 0x20;
+	ret = lgdt3306a_write_reg(state, 0x103d, val);
+
+	return ret;
+}
+
+static enum lgdt3306a_modulation
+lgdt3306a_check_oper_mode(struct lgdt3306a_state *state)
+{
+	u8 val = 0;
+	int ret;
+
+	ret = lgdt3306a_read_reg(state, 0x0081, &val);
+	if (ret)
+		goto err;
+
+	if (val & 0x80)	{
+		dbg_info("VSB\n");
+		return LG3306_VSB;
+	}
+	if (val & 0x08) {
+		ret = lgdt3306a_read_reg(state, 0x00a6, &val);
+		if (ret)
+			goto err;
+		val = val >> 2;
+		if (val & 0x01) {
+			dbg_info("QAM256\n");
+			return LG3306_QAM256;
+		}
+		dbg_info("QAM64\n");
+		return LG3306_QAM64;
+	}
+err:
+	pr_warn("UNKNOWN\n");
+	return LG3306_UNKNOWN_MODE;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_check_lock_status(struct lgdt3306a_state *state,
+			    enum lgdt3306a_lock_check whatLock)
+{
+	u8 val = 0;
+	int ret;
+	enum lgdt3306a_modulation	modeOper;
+	enum lgdt3306a_lock_status lockStatus;
+
+	modeOper = LG3306_UNKNOWN_MODE;
+
+	switch (whatLock) {
+	case LG3306_SYNC_LOCK:
+	{
+		ret = lgdt3306a_read_reg(state, 0x00a6, &val);
+		if (ret)
+			return ret;
+
+		if ((val & 0x80) == 0x80)
+			lockStatus = LG3306_LOCK;
+		else
+			lockStatus = LG3306_UNLOCK;
+
+		dbg_info("SYNC_LOCK=%x\n", lockStatus);
+		break;
+	}
+	case LG3306_AGC_LOCK:
+	{
+		ret = lgdt3306a_read_reg(state, 0x0080, &val);
+		if (ret)
+			return ret;
+
+		if ((val & 0x40) == 0x40)
+			lockStatus = LG3306_LOCK;
+		else
+			lockStatus = LG3306_UNLOCK;
+
+		dbg_info("AGC_LOCK=%x\n", lockStatus);
+		break;
+	}
+	case LG3306_TR_LOCK:
+	{
+		modeOper = lgdt3306a_check_oper_mode(state);
+		if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
+			ret = lgdt3306a_read_reg(state, 0x1094, &val);
+			if (ret)
+				return ret;
+
+			if ((val & 0x80) == 0x80)
+				lockStatus = LG3306_LOCK;
+			else
+				lockStatus = LG3306_UNLOCK;
+		} else
+			lockStatus = LG3306_UNKNOWN_LOCK;
+
+		dbg_info("TR_LOCK=%x\n", lockStatus);
+		break;
+	}
+	case LG3306_FEC_LOCK:
+	{
+		modeOper = lgdt3306a_check_oper_mode(state);
+		if ((modeOper == LG3306_QAM64) || (modeOper == LG3306_QAM256)) {
+			ret = lgdt3306a_read_reg(state, 0x0080, &val);
+			if (ret)
+				return ret;
+
+			if ((val & 0x10) == 0x10)
+				lockStatus = LG3306_LOCK;
+			else
+				lockStatus = LG3306_UNLOCK;
+		} else
+			lockStatus = LG3306_UNKNOWN_LOCK;
+
+		dbg_info("FEC_LOCK=%x\n", lockStatus);
+		break;
+	}
+
+	default:
+		lockStatus = LG3306_UNKNOWN_LOCK;
+		pr_warn("UNKNOWN whatLock=%d\n", whatLock);
+		break;
+	}
+
+	return lockStatus;
+}
+
+static enum lgdt3306a_neverlock_status
+lgdt3306a_check_neverlock_status(struct lgdt3306a_state *state)
+{
+	u8 val = 0;
+	int ret;
+	enum lgdt3306a_neverlock_status lockStatus;
+
+	ret = lgdt3306a_read_reg(state, 0x0080, &val);
+	if (ret)
+		return ret;
+	lockStatus = (enum lgdt3306a_neverlock_status)(val & 0x03);
+
+	dbg_info("NeverLock=%d", lockStatus);
+
+	return lockStatus;
+}
+
+static int lgdt3306a_pre_monitoring(struct lgdt3306a_state *state)
+{
+	u8 val = 0;
+	int ret;
+	u8 currChDiffACQ, snrRef, mainStrong, aiccrejStatus;
+
+	/* Channel variation */
+	ret = lgdt3306a_read_reg(state, 0x21bc, &currChDiffACQ);
+	if (ret)
+		return ret;
+
+	/* SNR of Frame sync */
+	ret = lgdt3306a_read_reg(state, 0x21a1, &val);
+	if (ret)
+		return ret;
+	snrRef = val & 0x3f;
+
+	/* Strong Main CIR */
+	ret = lgdt3306a_read_reg(state, 0x2199, &val);
+	if (ret)
+		return ret;
+	mainStrong = (val & 0x40) >> 6;
+
+	ret = lgdt3306a_read_reg(state, 0x0090, &val);
+	if (ret)
+		return ret;
+	aiccrejStatus = (val & 0xf0) >> 4;
+
+	dbg_info("snrRef=%d mainStrong=%d aiccrejStatus=%d currChDiffACQ=0x%x\n",
+		snrRef, mainStrong, aiccrejStatus, currChDiffACQ);
+
+#if 0
+	/* Dynamic ghost exists */
+	if ((mainStrong == 0) && (currChDiffACQ > 0x70))
+#endif
+	if (mainStrong == 0) {
+		ret = lgdt3306a_read_reg(state, 0x2135, &val);
+		if (ret)
+			return ret;
+		val &= 0x0f;
+		val |= 0xa0;
+		ret = lgdt3306a_write_reg(state, 0x2135, val);
+		if (ret)
+			return ret;
+
+		ret = lgdt3306a_read_reg(state, 0x2141, &val);
+		if (ret)
+			return ret;
+		val &= 0x3f;
+		val |= 0x80;
+		ret = lgdt3306a_write_reg(state, 0x2141, val);
+		if (ret)
+			return ret;
+
+		ret = lgdt3306a_write_reg(state, 0x2122, 0x70);
+		if (ret)
+			return ret;
+	} else { /* Weak ghost or static channel */
+		ret = lgdt3306a_read_reg(state, 0x2135, &val);
+		if (ret)
+			return ret;
+		val &= 0x0f;
+		val |= 0x70;
+		ret = lgdt3306a_write_reg(state, 0x2135, val);
+		if (ret)
+			return ret;
+
+		ret = lgdt3306a_read_reg(state, 0x2141, &val);
+		if (ret)
+			return ret;
+		val &= 0x3f;
+		val |= 0x40;
+		ret = lgdt3306a_write_reg(state, 0x2141, val);
+		if (ret)
+			return ret;
+
+		ret = lgdt3306a_write_reg(state, 0x2122, 0x40);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_sync_lock_poll(struct lgdt3306a_state *state)
+{
+	enum lgdt3306a_lock_status syncLockStatus = LG3306_UNLOCK;
+	int	i;
+
+	for (i = 0; i < 2; i++)	{
+		msleep(30);
+
+		syncLockStatus = lgdt3306a_check_lock_status(state,
+							     LG3306_SYNC_LOCK);
+
+		if (syncLockStatus == LG3306_LOCK) {
+			dbg_info("locked(%d)\n", i);
+			return LG3306_LOCK;
+		}
+	}
+	dbg_info("not locked\n");
+	return LG3306_UNLOCK;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_fec_lock_poll(struct lgdt3306a_state *state)
+{
+	enum lgdt3306a_lock_status FECLockStatus = LG3306_UNLOCK;
+	int	i;
+
+	for (i = 0; i < 2; i++)	{
+		msleep(30);
+
+		FECLockStatus = lgdt3306a_check_lock_status(state,
+							    LG3306_FEC_LOCK);
+
+		if (FECLockStatus == LG3306_LOCK) {
+			dbg_info("locked(%d)\n", i);
+			return FECLockStatus;
+		}
+	}
+	dbg_info("not locked\n");
+	return FECLockStatus;
+}
+
+static enum lgdt3306a_neverlock_status
+lgdt3306a_neverlock_poll(struct lgdt3306a_state *state)
+{
+	enum lgdt3306a_neverlock_status NLLockStatus = LG3306_NL_FAIL;
+	int	i;
+
+	for (i = 0; i < 5; i++) {
+		msleep(30);
+
+		NLLockStatus = lgdt3306a_check_neverlock_status(state);
+
+		if (NLLockStatus == LG3306_NL_LOCK) {
+			dbg_info("NL_LOCK(%d)\n", i);
+			return NLLockStatus;
+		}
+	}
+	dbg_info("NLLockStatus=%d\n", NLLockStatus);
+	return NLLockStatus;
+}
+
+static u8 lgdt3306a_get_packet_error(struct lgdt3306a_state *state)
+{
+	u8 val;
+	int ret;
+
+	ret = lgdt3306a_read_reg(state, 0x00fa, &val);
+	if (ret)
+		return ret;
+
+	return val;
+}
+
+static const u32 valx_x10[] = {
+	10,  11,  13,  15,  17,  20,  25,  33,  41,  50,  59,  73,  87,  100
+};
+static const u32 log10x_x1000[] = {
+	0,   41, 114, 176, 230, 301, 398, 518, 613, 699, 771, 863, 939, 1000
+};
+
+static u32 log10_x1000(u32 x)
+{
+	u32 diff_val, step_val, step_log10;
+	u32 log_val = 0;
+	u32 i;
+
+	if (x <= 0)
+		return -1000000; /* signal error */
+
+	if (x == 10)
+		return 0; /* log(1)=0 */
+
+	if (x < 10) {
+		while (x < 10) {
+			x = x * 10;
+			log_val--;
+		}
+	} else {	/* x > 10 */
+		while (x >= 100) {
+			x = x / 10;
+			log_val++;
+		}
+	}
+	log_val *= 1000;
+
+	if (x == 10) /* was our input an exact multiple of 10 */
+		return log_val;	/* don't need to interpolate */
+
+	/* find our place on the log curve */
+	for (i = 1; i < ARRAY_SIZE(valx_x10); i++) {
+		if (valx_x10[i] >= x)
+			break;
+	}
+	if (i == ARRAY_SIZE(valx_x10))
+		return log_val + log10x_x1000[i - 1];
+
+	diff_val   = x - valx_x10[i-1];
+	step_val   = valx_x10[i] - valx_x10[i - 1];
+	step_log10 = log10x_x1000[i] - log10x_x1000[i - 1];
+
+	/* do a linear interpolation to get in-between values */
+	return log_val + log10x_x1000[i - 1] +
+		((diff_val*step_log10) / step_val);
+}
+
+static u32 lgdt3306a_calculate_snr_x100(struct lgdt3306a_state *state)
+{
+	u32 mse; /* Mean-Square Error */
+	u32 pwr; /* Constelation power */
+	u32 snr_x100;
+
+	mse = (read_reg(state, 0x00ec) << 8) |
+	      (read_reg(state, 0x00ed));
+	pwr = (read_reg(state, 0x00e8) << 8) |
+	      (read_reg(state, 0x00e9));
+
+	if (mse == 0) /* no signal */
+		return 0;
+
+	snr_x100 = log10_x1000((pwr * 10000) / mse) - 3000;
+	dbg_info("mse=%u, pwr=%u, snr_x100=%d\n", mse, pwr, snr_x100);
+
+	return snr_x100;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_vsb_lock_poll(struct lgdt3306a_state *state)
+{
+	int ret;
+	u8 cnt = 0;
+	u8 packet_error;
+	u32 snr;
+
+	for (cnt = 0; cnt < 10; cnt++) {
+		if (lgdt3306a_sync_lock_poll(state) == LG3306_UNLOCK) {
+			dbg_info("no sync lock!\n");
+			return LG3306_UNLOCK;
+		}
+
+		msleep(20);
+		ret = lgdt3306a_pre_monitoring(state);
+		if (ret)
+			break;
+
+		packet_error = lgdt3306a_get_packet_error(state);
+		snr = lgdt3306a_calculate_snr_x100(state);
+		dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr);
+
+		if ((snr >= 1500) && (packet_error < 0xff))
+			return LG3306_LOCK;
+	}
+
+	dbg_info("not locked!\n");
+	return LG3306_UNLOCK;
+}
+
+static enum lgdt3306a_lock_status
+lgdt3306a_qam_lock_poll(struct lgdt3306a_state *state)
+{
+	u8 cnt;
+	u8 packet_error;
+	u32	snr;
+
+	for (cnt = 0; cnt < 10; cnt++) {
+		if (lgdt3306a_fec_lock_poll(state) == LG3306_UNLOCK) {
+			dbg_info("no fec lock!\n");
+			return LG3306_UNLOCK;
+		}
+
+		msleep(20);
+
+		packet_error = lgdt3306a_get_packet_error(state);
+		snr = lgdt3306a_calculate_snr_x100(state);
+		dbg_info("cnt=%d errors=%d snr=%d\n", cnt, packet_error, snr);
+
+		if ((snr >= 1500) && (packet_error < 0xff))
+			return LG3306_LOCK;
+	}
+
+	dbg_info("not locked!\n");
+	return LG3306_UNLOCK;
+}
+
+static int lgdt3306a_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	u16 strength = 0;
+	int ret = 0;
+
+	if (fe->ops.tuner_ops.get_rf_strength) {
+		ret = fe->ops.tuner_ops.get_rf_strength(fe, &strength);
+		if (ret == 0)
+			dbg_info("strength=%d\n", strength);
+		else
+			dbg_info("fe->ops.tuner_ops.get_rf_strength() failed\n");
+	}
+
+	*status = 0;
+	if (lgdt3306a_neverlock_poll(state) == LG3306_NL_LOCK) {
+		*status |= FE_HAS_SIGNAL;
+		*status |= FE_HAS_CARRIER;
+
+		switch (state->current_modulation) {
+		case QAM_256:
+		case QAM_64:
+			if (lgdt3306a_qam_lock_poll(state) == LG3306_LOCK) {
+				*status |= FE_HAS_VITERBI;
+				*status |= FE_HAS_SYNC;
+
+				*status |= FE_HAS_LOCK;
+			}
+			break;
+		case VSB_8:
+			if (lgdt3306a_vsb_lock_poll(state) == LG3306_LOCK) {
+				*status |= FE_HAS_VITERBI;
+				*status |= FE_HAS_SYNC;
+
+				*status |= FE_HAS_LOCK;
+
+				ret = lgdt3306a_monitor_vsb(state);
+			}
+			break;
+		default:
+			ret = -EINVAL;
+		}
+	}
+	return ret;
+}
+
+
+static int lgdt3306a_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	state->snr = lgdt3306a_calculate_snr_x100(state);
+	/* report SNR in dB * 10 */
+	*snr = state->snr/10;
+
+	return 0;
+}
+
+static int lgdt3306a_read_signal_strength(struct dvb_frontend *fe,
+					 u16 *strength)
+{
+	/*
+	 * Calculate some sort of "strength" from SNR
+	 */
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	u16 snr; /* snr_x10 */
+	int ret;
+	u32 ref_snr; /* snr*100 */
+	u32 str;
+
+	*strength = 0;
+
+	switch (state->current_modulation) {
+	case VSB_8:
+		 ref_snr = 1600; /* 16dB */
+		 break;
+	case QAM_64:
+		 ref_snr = 2200; /* 22dB */
+		 break;
+	case QAM_256:
+		 ref_snr = 2800; /* 28dB */
+		 break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = fe->ops.read_snr(fe, &snr);
+	if (lg_chkerr(ret))
+		goto fail;
+
+	if (state->snr <= (ref_snr - 100))
+		str = 0;
+	else if (state->snr <= ref_snr)
+		str = (0xffff * 65) / 100; /* 65% */
+	else {
+		str = state->snr - ref_snr;
+		str /= 50;
+		str += 78; /* 78%-100% */
+		if (str > 100)
+			str = 100;
+		str = (0xffff * str) / 100;
+	}
+	*strength = (u16)str;
+	dbg_info("strength=%u\n", *strength);
+
+fail:
+	return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int lgdt3306a_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+	u32 tmp;
+
+	*ber = 0;
+#if 1
+	/* FGR - FIXME - I don't know what value is expected by dvb_core
+	 * what is the scale of the value?? */
+	tmp =              read_reg(state, 0x00fc); /* NBERVALUE[24-31] */
+	tmp = (tmp << 8) | read_reg(state, 0x00fd); /* NBERVALUE[16-23] */
+	tmp = (tmp << 8) | read_reg(state, 0x00fe); /* NBERVALUE[8-15] */
+	tmp = (tmp << 8) | read_reg(state, 0x00ff); /* NBERVALUE[0-7] */
+	*ber = tmp;
+	dbg_info("ber=%u\n", tmp);
+#endif
+	return 0;
+}
+
+static int lgdt3306a_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	*ucblocks = 0;
+#if 1
+	/* FGR - FIXME - I don't know what value is expected by dvb_core
+	 * what happens when value wraps? */
+	*ucblocks = read_reg(state, 0x00f4); /* TPIFTPERRCNT[0-7] */
+	dbg_info("ucblocks=%u\n", *ucblocks);
+#endif
+
+	return 0;
+}
+
+static int lgdt3306a_tune(struct dvb_frontend *fe, bool re_tune,
+			  unsigned int mode_flags, unsigned int *delay,
+			  fe_status_t *status)
+{
+	int ret = 0;
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	dbg_info("re_tune=%u\n", re_tune);
+
+	if (re_tune) {
+		state->current_frequency = -1; /* force re-tune */
+		ret = lgdt3306a_set_parameters(fe);
+		if (ret != 0)
+			return ret;
+	}
+	*delay = 125;
+	ret = lgdt3306a_read_status(fe, status);
+
+	return ret;
+}
+
+static int lgdt3306a_get_tune_settings(struct dvb_frontend *fe,
+				       struct dvb_frontend_tune_settings
+				       *fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 100;
+	dbg_info("\n");
+	return 0;
+}
+
+static int lgdt3306a_search(struct dvb_frontend *fe)
+{
+	fe_status_t status = 0;
+	int i, ret;
+
+	/* set frontend */
+	ret = lgdt3306a_set_parameters(fe);
+	if (ret)
+		goto error;
+
+	/* wait frontend lock */
+	for (i = 20; i > 0; i--) {
+		dbg_info(": loop=%d\n", i);
+		msleep(50);
+		ret = lgdt3306a_read_status(fe, &status);
+		if (ret)
+			goto error;
+
+		if (status & FE_HAS_LOCK)
+			break;
+	}
+
+	/* check if we have a valid signal */
+	if (status & FE_HAS_LOCK)
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	else
+		return DVBFE_ALGO_SEARCH_AGAIN;
+
+error:
+	dbg_info("failed (%d)\n", ret);
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static void lgdt3306a_release(struct dvb_frontend *fe)
+{
+	struct lgdt3306a_state *state = fe->demodulator_priv;
+
+	dbg_info("\n");
+	kfree(state);
+}
+
+static struct dvb_frontend_ops lgdt3306a_ops;
+
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+				      struct i2c_adapter *i2c_adap)
+{
+	struct lgdt3306a_state *state = NULL;
+	int ret;
+	u8 val;
+
+	dbg_info("(%d-%04x)\n",
+	       i2c_adap ? i2c_adapter_id(i2c_adap) : 0,
+	       config ? config->i2c_addr : 0);
+
+	state = kzalloc(sizeof(struct lgdt3306a_state), GFP_KERNEL);
+	if (state == NULL)
+		goto fail;
+
+	state->cfg = config;
+	state->i2c_adap = i2c_adap;
+
+	memcpy(&state->frontend.ops, &lgdt3306a_ops,
+	       sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
+	/* verify that we're talking to a lg3306a */
+	/* FGR - NOTE - there is no obvious ChipId to check; we check
+	 * some "known" bits after reset, but it's still just a guess */
+	ret = lgdt3306a_read_reg(state, 0x0000, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+	if ((val & 0x74) != 0x74) {
+		pr_warn("expected 0x74, got 0x%x\n", (val & 0x74));
+#if 0
+		/* FIXME - re-enable when we know this is right */
+		goto fail;
+#endif
+	}
+	ret = lgdt3306a_read_reg(state, 0x0001, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+	if ((val & 0xf6) != 0xc6) {
+		pr_warn("expected 0xc6, got 0x%x\n", (val & 0xf6));
+#if 0
+		/* FIXME - re-enable when we know this is right */
+		goto fail;
+#endif
+	}
+	ret = lgdt3306a_read_reg(state, 0x0002, &val);
+	if (lg_chkerr(ret))
+		goto fail;
+	if ((val & 0x73) != 0x03) {
+		pr_warn("expected 0x03, got 0x%x\n", (val & 0x73));
+#if 0
+		/* FIXME - re-enable when we know this is right */
+		goto fail;
+#endif
+	}
+
+	state->current_frequency = -1;
+	state->current_modulation = -1;
+
+	lgdt3306a_sleep(state);
+
+	return &state->frontend;
+
+fail:
+	pr_warn("unable to detect LGDT3306A hardware\n");
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(lgdt3306a_attach);
+
+#ifdef DBG_DUMP
+
+static const short regtab[] = {
+	0x0000, /* SOFTRSTB 1'b1 1'b1 1'b1 ADCPDB 1'b1 PLLPDB GBBPDB 11111111 */
+	0x0001, /* 1'b1 1'b1 1'b0 1'b0 AUTORPTRS */
+	0x0002, /* NI2CRPTEN 1'b0 1'b0 1'b0 SPECINVAUT */
+	0x0003, /* AGCRFOUT */
+	0x0004, /* ADCSEL1V ADCCNT ADCCNF ADCCNS ADCCLKPLL */
+	0x0005, /* PLLINDIVSE */
+	0x0006, /* PLLCTRL[7:0] 11100001 */
+	0x0007, /* SYSINITWAITTIME[7:0] (msec) 00001000 */
+	0x0008, /* STDOPMODE[7:0] 10000000 */
+	0x0009, /* 1'b0 1'b0 1'b0 STDOPDETTMODE[2:0] STDOPDETCMODE[1:0] 00011110 */
+	0x000a, /* DAFTEN 1'b1 x x SCSYSLOCK */
+	0x000b, /* SCSYSLOCKCHKTIME[7:0] (10msec) 01100100 */
+	0x000d, /* x SAMPLING4 */
+	0x000e, /* SAMFREQ[15:8] 00000000 */
+	0x000f, /* SAMFREQ[7:0] 00000000 */
+	0x0010, /* IFFREQ[15:8] 01100000 */
+	0x0011, /* IFFREQ[7:0] 00000000 */
+	0x0012, /* AGCEN AGCREFMO */
+	0x0013, /* AGCRFFIXB AGCIFFIXB AGCLOCKDETRNGSEL[1:0] 1'b1 1'b0 1'b0 1'b0 11101000 */
+	0x0014, /* AGCFIXVALUE[7:0] 01111111 */
+	0x0015, /* AGCREF[15:8] 00001010 */
+	0x0016, /* AGCREF[7:0] 11100100 */
+	0x0017, /* AGCDELAY[7:0] 00100000 */
+	0x0018, /* AGCRFBW[3:0] AGCIFBW[3:0] 10001000 */
+	0x0019, /* AGCUDOUTMODE[1:0] AGCUDCTRLLEN[1:0] AGCUDCTRL */
+	0x001c, /* 1'b1 PFEN MFEN AICCVSYNC */
+	0x001d, /* 1'b0 1'b1 1'b0 1'b1 AICCVSYNC */
+	0x001e, /* AICCALPHA[3:0] 1'b1 1'b0 1'b1 1'b0 01111010 */
+	0x001f, /* AICCDETTH[19:16] AICCOFFTH[19:16] 00000000 */
+	0x0020, /* AICCDETTH[15:8] 01111100 */
+	0x0021, /* AICCDETTH[7:0] 00000000 */
+	0x0022, /* AICCOFFTH[15:8] 00000101 */
+	0x0023, /* AICCOFFTH[7:0] 11100000 */
+	0x0024, /* AICCOPMODE3[1:0] AICCOPMODE2[1:0] AICCOPMODE1[1:0] AICCOPMODE0[1:0] 00000000 */
+	0x0025, /* AICCFIXFREQ3[23:16] 00000000 */
+	0x0026, /* AICCFIXFREQ3[15:8] 00000000 */
+	0x0027, /* AICCFIXFREQ3[7:0] 00000000 */
+	0x0028, /* AICCFIXFREQ2[23:16] 00000000 */
+	0x0029, /* AICCFIXFREQ2[15:8] 00000000 */
+	0x002a, /* AICCFIXFREQ2[7:0] 00000000 */
+	0x002b, /* AICCFIXFREQ1[23:16] 00000000 */
+	0x002c, /* AICCFIXFREQ1[15:8] 00000000 */
+	0x002d, /* AICCFIXFREQ1[7:0] 00000000 */
+	0x002e, /* AICCFIXFREQ0[23:16] 00000000 */
+	0x002f, /* AICCFIXFREQ0[15:8] 00000000 */
+	0x0030, /* AICCFIXFREQ0[7:0] 00000000 */
+	0x0031, /* 1'b0 1'b1 1'b0 1'b0 x DAGC1STER */
+	0x0032, /* DAGC1STEN DAGC1STER */
+	0x0033, /* DAGC1STREF[15:8] 00001010 */
+	0x0034, /* DAGC1STREF[7:0] 11100100 */
+	0x0035, /* DAGC2NDE */
+	0x0036, /* DAGC2NDREF[15:8] 00001010 */
+	0x0037, /* DAGC2NDREF[7:0] 10000000 */
+	0x0038, /* DAGC2NDLOCKDETRNGSEL[1:0] */
+	0x003d, /* 1'b1 SAMGEARS */
+	0x0040, /* SAMLFGMA */
+	0x0041, /* SAMLFBWM */
+	0x0044, /* 1'b1 CRGEARSHE */
+	0x0045, /* CRLFGMAN */
+	0x0046, /* CFLFBWMA */
+	0x0047, /* CRLFGMAN */
+	0x0048, /* x x x x CRLFGSTEP_VS[3:0] xxxx1001 */
+	0x0049, /* CRLFBWMA */
+	0x004a, /* CRLFBWMA */
+	0x0050, /* 1'b0 1'b1 1'b1 1'b0 MSECALCDA */
+	0x0070, /* TPOUTEN TPIFEN TPCLKOUTE */
+	0x0071, /* TPSENB TPSSOPBITE */
+	0x0073, /* TP47HINS x x CHBERINT PERMODE[1:0] PERINT[1:0] 1xx11100 */
+	0x0075, /* x x x x x IQSWAPCTRL[2:0] xxxxx000 */
+	0x0076, /* NBERCON NBERST NBERPOL NBERWSYN */
+	0x0077, /* x NBERLOSTTH[2:0] NBERACQTH[3:0] x0000000 */
+	0x0078, /* NBERPOLY[31:24] 00000000 */
+	0x0079, /* NBERPOLY[23:16] 00000000 */
+	0x007a, /* NBERPOLY[15:8] 00000000 */
+	0x007b, /* NBERPOLY[7:0] 00000000 */
+	0x007c, /* NBERPED[31:24] 00000000 */
+	0x007d, /* NBERPED[23:16] 00000000 */
+	0x007e, /* NBERPED[15:8] 00000000 */
+	0x007f, /* NBERPED[7:0] 00000000 */
+	0x0080, /* x AGCLOCK DAGCLOCK SYSLOCK x x NEVERLOCK[1:0] */
+	0x0085, /* SPECINVST */
+	0x0088, /* SYSLOCKTIME[15:8] */
+	0x0089, /* SYSLOCKTIME[7:0] */
+	0x008c, /* FECLOCKTIME[15:8] */
+	0x008d, /* FECLOCKTIME[7:0] */
+	0x008e, /* AGCACCOUT[15:8] */
+	0x008f, /* AGCACCOUT[7:0] */
+	0x0090, /* AICCREJSTATUS[3:0] AICCREJBUSY[3:0] */
+	0x0091, /* AICCVSYNC */
+	0x009c, /* CARRFREQOFFSET[15:8] */
+	0x009d, /* CARRFREQOFFSET[7:0] */
+	0x00a1, /* SAMFREQOFFSET[23:16] */
+	0x00a2, /* SAMFREQOFFSET[15:8] */
+	0x00a3, /* SAMFREQOFFSET[7:0] */
+	0x00a6, /* SYNCLOCK SYNCLOCKH */
+#if 0 /* covered elsewhere */
+	0x00e8, /* CONSTPWR[15:8] */
+	0x00e9, /* CONSTPWR[7:0] */
+	0x00ea, /* BMSE[15:8] */
+	0x00eb, /* BMSE[7:0] */
+	0x00ec, /* MSE[15:8] */
+	0x00ed, /* MSE[7:0] */
+	0x00ee, /* CONSTI[7:0] */
+	0x00ef, /* CONSTQ[7:0] */
+#endif
+	0x00f4, /* TPIFTPERRCNT[7:0] */
+	0x00f5, /* TPCORREC */
+	0x00f6, /* VBBER[15:8] */
+	0x00f7, /* VBBER[7:0] */
+	0x00f8, /* VABER[15:8] */
+	0x00f9, /* VABER[7:0] */
+	0x00fa, /* TPERRCNT[7:0] */
+	0x00fb, /* NBERLOCK x x x x x x x */
+	0x00fc, /* NBERVALUE[31:24] */
+	0x00fd, /* NBERVALUE[23:16] */
+	0x00fe, /* NBERVALUE[15:8] */
+	0x00ff, /* NBERVALUE[7:0] */
+	0x1000, /* 1'b0 WODAGCOU */
+	0x1005, /* x x 1'b1 1'b1 x SRD_Q_QM */
+	0x1009, /* SRDWAITTIME[7:0] (10msec) 00100011 */
+	0x100a, /* SRDWAITTIME_CQS[7:0] (msec) 01100100 */
+	0x101a, /* x 1'b1 1'b0 1'b0 x QMDQAMMODE[2:0] x100x010 */
+	0x1036, /* 1'b0 1'b1 1'b0 1'b0 SAMGSEND_CQS[3:0] 01001110 */
+	0x103c, /* SAMGSAUTOSTL_V[3:0] SAMGSAUTOEDL_V[3:0] 01000110 */
+	0x103d, /* 1'b1 1'b1 SAMCNORMBP_V[1:0] 1'b0 1'b0 SAMMODESEL_V[1:0] 11100001 */
+	0x103f, /* SAMZTEDSE */
+	0x105d, /* EQSTATUSE */
+	0x105f, /* x PMAPG2_V[2:0] x DMAPG2_V[2:0] x001x011 */
+	0x1060, /* 1'b1 EQSTATUSE */
+	0x1061, /* CRMAPBWSTL_V[3:0] CRMAPBWEDL_V[3:0] 00000100 */
+	0x1065, /* 1'b0 x CRMODE_V[1:0] 1'b1 x 1'b1 x 0x111x1x */
+	0x1066, /* 1'b0 1'b0 1'b1 1'b0 1'b1 PNBOOSTSE */
+	0x1068, /* CREPHNGAIN2_V[3:0] CREPHNPBW_V[3:0] 10010001 */
+	0x106e, /* x x x x x CREPHNEN_ */
+	0x106f, /* CREPHNTH_V[7:0] 00010101 */
+	0x1072, /* CRSWEEPN */
+	0x1073, /* CRPGAIN_V[3:0] x x 1'b1 1'b1 1001xx11 */
+	0x1074, /* CRPBW_V[3:0] x x 1'b1 1'b1 0001xx11 */
+	0x1080, /* DAFTSTATUS[1:0] x x x x x x */
+	0x1081, /* SRDSTATUS[1:0] x x x x x SRDLOCK */
+	0x10a9, /* EQSTATUS_CQS[1:0] x x x x x x */
+	0x10b7, /* EQSTATUS_V[1:0] x x x x x x */
+#if 0 /* SMART_ANT */
+	0x1f00, /* MODEDETE */
+	0x1f01, /* x x x x x x x SFNRST xxxxxxx0 */
+	0x1f03, /* NUMOFANT[7:0] 10000000 */
+	0x1f04, /* x SELMASK[6:0] x0000000 */
+	0x1f05, /* x SETMASK[6:0] x0000000 */
+	0x1f06, /* x TXDATA[6:0] x0000000 */
+	0x1f07, /* x CHNUMBER[6:0] x0000000 */
+	0x1f09, /* AGCTIME[23:16] 10011000 */
+	0x1f0a, /* AGCTIME[15:8] 10010110 */
+	0x1f0b, /* AGCTIME[7:0] 10000000 */
+	0x1f0c, /* ANTTIME[31:24] 00000000 */
+	0x1f0d, /* ANTTIME[23:16] 00000011 */
+	0x1f0e, /* ANTTIME[15:8] 10010000 */
+	0x1f0f, /* ANTTIME[7:0] 10010000 */
+	0x1f11, /* SYNCTIME[23:16] 10011000 */
+	0x1f12, /* SYNCTIME[15:8] 10010110 */
+	0x1f13, /* SYNCTIME[7:0] 10000000 */
+	0x1f14, /* SNRTIME[31:24] 00000001 */
+	0x1f15, /* SNRTIME[23:16] 01111101 */
+	0x1f16, /* SNRTIME[15:8] 01111000 */
+	0x1f17, /* SNRTIME[7:0] 01000000 */
+	0x1f19, /* FECTIME[23:16] 00000000 */
+	0x1f1a, /* FECTIME[15:8] 01110010 */
+	0x1f1b, /* FECTIME[7:0] 01110000 */
+	0x1f1d, /* FECTHD[7:0] 00000011 */
+	0x1f1f, /* SNRTHD[23:16] 00001000 */
+	0x1f20, /* SNRTHD[15:8] 01111111 */
+	0x1f21, /* SNRTHD[7:0] 10000101 */
+	0x1f80, /* IRQFLG x x SFSDRFLG MODEBFLG SAVEFLG SCANFLG TRACKFLG */
+	0x1f81, /* x SYNCCON SNRCON FECCON x STDBUSY SYNCRST AGCFZCO */
+	0x1f82, /* x x x SCANOPCD[4:0] */
+	0x1f83, /* x x x x MAINOPCD[3:0] */
+	0x1f84, /* x x RXDATA[13:8] */
+	0x1f85, /* RXDATA[7:0] */
+	0x1f86, /* x x SDTDATA[13:8] */
+	0x1f87, /* SDTDATA[7:0] */
+	0x1f89, /* ANTSNR[23:16] */
+	0x1f8a, /* ANTSNR[15:8] */
+	0x1f8b, /* ANTSNR[7:0] */
+	0x1f8c, /* x x x x ANTFEC[13:8] */
+	0x1f8d, /* ANTFEC[7:0] */
+	0x1f8e, /* MAXCNT[7:0] */
+	0x1f8f, /* SCANCNT[7:0] */
+	0x1f91, /* MAXPW[23:16] */
+	0x1f92, /* MAXPW[15:8] */
+	0x1f93, /* MAXPW[7:0] */
+	0x1f95, /* CURPWMSE[23:16] */
+	0x1f96, /* CURPWMSE[15:8] */
+	0x1f97, /* CURPWMSE[7:0] */
+#endif /* SMART_ANT */
+	0x211f, /* 1'b1 1'b1 1'b1 CIRQEN x x 1'b0 1'b0 1111xx00 */
+	0x212a, /* EQAUTOST */
+	0x2122, /* CHFAST[7:0] 01100000 */
+	0x212b, /* FFFSTEP_V[3:0] x FBFSTEP_V[2:0] 0001x001 */
+	0x212c, /* PHDEROTBWSEL[3:0] 1'b1 1'b1 1'b1 1'b0 10001110 */
+	0x212d, /* 1'b1 1'b1 1'b1 1'b1 x x TPIFLOCKS */
+	0x2135, /* DYNTRACKFDEQ[3:0] x 1'b0 1'b0 1'b0 1010x000 */
+	0x2141, /* TRMODE[1:0] 1'b1 1'b1 1'b0 1'b1 1'b1 1'b1 01110111 */
+	0x2162, /* AICCCTRLE */
+	0x2173, /* PHNCNFCNT[7:0] 00000100 */
+	0x2179, /* 1'b0 1'b0 1'b0 1'b1 x BADSINGLEDYNTRACKFBF[2:0] 0001x001 */
+	0x217a, /* 1'b0 1'b0 1'b0 1'b1 x BADSLOWSINGLEDYNTRACKFBF[2:0] 0001x001 */
+	0x217e, /* CNFCNTTPIF[7:0] 00001000 */
+	0x217f, /* TPERRCNTTPIF[7:0] 00000001 */
+	0x2180, /* x x x x x x FBDLYCIR[9:8] */
+	0x2181, /* FBDLYCIR[7:0] */
+	0x2185, /* MAXPWRMAIN[7:0] */
+	0x2191, /* NCOMBDET x x x x x x x */
+	0x2199, /* x MAINSTRON */
+	0x219a, /* FFFEQSTEPOUT_V[3:0] FBFSTEPOUT_V[2:0] */
+	0x21a1, /* x x SNRREF[5:0] */
+	0x2845, /* 1'b0 1'b1 x x FFFSTEP_CQS[1:0] FFFCENTERTAP[1:0] 01xx1110 */
+	0x2846, /* 1'b0 x 1'b0 1'b1 FBFSTEP_CQS[1:0] 1'b1 1'b0 0x011110 */
+	0x2847, /* ENNOSIGDE */
+	0x2849, /* 1'b1 1'b1 NOUSENOSI */
+	0x284a, /* EQINITWAITTIME[7:0] 01100100 */
+	0x3000, /* 1'b1 1'b1 1'b1 x x x 1'b0 RPTRSTM */
+	0x3001, /* RPTRSTWAITTIME[7:0] (100msec) 00110010 */
+	0x3031, /* FRAMELOC */
+	0x3032, /* 1'b1 1'b0 1'b0 1'b0 x x FRAMELOCKMODE_CQS[1:0] 1000xx11 */
+	0x30a9, /* VDLOCK_Q FRAMELOCK */
+	0x30aa, /* MPEGLOCK */
+};
+
+#define numDumpRegs (sizeof(regtab)/sizeof(regtab[0]))
+static u8 regval1[numDumpRegs] = {0, };
+static u8 regval2[numDumpRegs] = {0, };
+
+static void lgdt3306a_DumpAllRegs(struct lgdt3306a_state *state)
+{
+		memset(regval2, 0xff, sizeof(regval2));
+		lgdt3306a_DumpRegs(state);
+}
+
+static void lgdt3306a_DumpRegs(struct lgdt3306a_state *state)
+{
+	int i;
+	int sav_debug = debug;
+
+	if ((debug & DBG_DUMP) == 0)
+		return;
+	debug &= ~DBG_REG; /* suppress DBG_REG during reg dump */
+
+	lg_debug("\n");
+
+	for (i = 0; i < numDumpRegs; i++) {
+		lgdt3306a_read_reg(state, regtab[i], &regval1[i]);
+		if (regval1[i] != regval2[i]) {
+			lg_debug(" %04X = %02X\n", regtab[i], regval1[i]);
+				 regval2[i] = regval1[i];
+		}
+	}
+	debug = sav_debug;
+}
+#endif /* DBG_DUMP */
+
+
+
+static struct dvb_frontend_ops lgdt3306a_ops = {
+	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
+	.info = {
+		.name = "LG Electronics LGDT3306A VSB/QAM Frontend",
+		.frequency_min      = 54000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.i2c_gate_ctrl        = lgdt3306a_i2c_gate_ctrl,
+	.init                 = lgdt3306a_init,
+	.sleep                = lgdt3306a_fe_sleep,
+	/* if this is set, it overrides the default swzigzag */
+	.tune                 = lgdt3306a_tune,
+	.set_frontend         = lgdt3306a_set_parameters,
+	.get_frontend         = lgdt3306a_get_frontend,
+	.get_frontend_algo    = lgdt3306a_get_frontend_algo,
+	.get_tune_settings    = lgdt3306a_get_tune_settings,
+	.read_status          = lgdt3306a_read_status,
+	.read_ber             = lgdt3306a_read_ber,
+	.read_signal_strength = lgdt3306a_read_signal_strength,
+	.read_snr             = lgdt3306a_read_snr,
+	.read_ucblocks        = lgdt3306a_read_ucblocks,
+	.release              = lgdt3306a_release,
+	.ts_bus_ctrl          = lgdt3306a_ts_bus_ctrl,
+	.search               = lgdt3306a_search,
+};
+
+MODULE_DESCRIPTION("LG Electronics LGDT3306A ATSC/QAM-B Demodulator Driver");
+MODULE_AUTHOR("Fred Richter <frichter@hauppauge.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2");

+ 74 - 0
drivers/media/dvb-frontends/lgdt3306a.h

@@ -0,0 +1,74 @@
+/*
+ *    Support for LGDT3306A - 8VSB/QAM-B
+ *
+ *    Copyright (C) 2013,2014 Fred Richter <frichter@hauppauge.com>
+ *      based on lgdt3305.[ch] by Michael Krufky
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ */
+
+#ifndef _LGDT3306A_H_
+#define _LGDT3306A_H_
+
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
+
+enum lgdt3306a_mpeg_mode {
+	LGDT3306A_MPEG_PARALLEL = 0,
+	LGDT3306A_MPEG_SERIAL = 1,
+};
+
+enum lgdt3306a_tp_clock_edge {
+	LGDT3306A_TPCLK_RISING_EDGE = 0,
+	LGDT3306A_TPCLK_FALLING_EDGE = 1,
+};
+
+enum lgdt3306a_tp_valid_polarity {
+	LGDT3306A_TP_VALID_LOW = 0,
+	LGDT3306A_TP_VALID_HIGH = 1,
+};
+
+struct lgdt3306a_config {
+	u8 i2c_addr;
+
+	/* user defined IF frequency in KHz */
+	u16 qam_if_khz;
+	u16 vsb_if_khz;
+
+	/* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
+	unsigned int deny_i2c_rptr:1;
+
+	/* spectral inversion - 0:disabled 1:enabled */
+	unsigned int spectral_inversion:1;
+
+	enum lgdt3306a_mpeg_mode mpeg_mode;
+	enum lgdt3306a_tp_clock_edge tpclk_edge;
+	enum lgdt3306a_tp_valid_polarity tpvalid_polarity;
+
+	/* demod clock freq in MHz; 24 or 25 supported */
+	int  xtalMHz;
+};
+
+#if IS_REACHABLE(CONFIG_DVB_LGDT3306A)
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+				      struct i2c_adapter *i2c_adap);
+#else
+static inline
+struct dvb_frontend *lgdt3306a_attach(const struct lgdt3306a_config *config,
+				      struct i2c_adapter *i2c_adap)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif /* CONFIG_DVB_LGDT3306A */
+
+#endif /* _LGDT3306A_H_ */

+ 1 - 1
drivers/media/dvb-frontends/lgdt330x.h

@@ -52,7 +52,7 @@ struct lgdt330x_config
 	int clock_polarity_flip;
 };
 
-#if IS_ENABLED(CONFIG_DVB_LGDT330X)
+#if IS_REACHABLE(CONFIG_DVB_LGDT330X)
 extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config,
 					    struct i2c_adapter* i2c);
 #else

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