Browse Source

Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits)
  [media] af9015: Fix max I2C message size when used with tda18271
  [media] IR: initialize ir_raw_event in few more drivers
  [media] Guard a divide in v4l1 compat layer
  [media] imon: fix nomouse modprobe option
  [media] imon: remove redundant change_protocol call
  [media] imon: fix my egregious brown paper bag w/rdev/idev split
  [media] cafe_ccic: Configure ov7670 correctly
  [media] ov7670: allow configuration of image size, clock speed, and I/O method
  [media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016]
  [media] af9015: map DigitalNow TinyTwin v2 remote
  [media] DigitalNow TinyTwin remote controller
  [media] af9015: RC fixes and improvements
  videodev2.h.xml: Update to reflect the latest changes at videodev2.h
  [media] v4l: document new Bayer and monochrome pixel formats
  [media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028
  [media] firedtv: add parameter to fake ca_system_ids in CA_INFO
  [media] tm6000: fix a macro coding style issue
  tm6000: Remove some ugly debug code
  [media] Nova-S-Plus audio line input
  [media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers
  ...
Linus Torvalds 14 years ago
parent
commit
0851668fdd
100 changed files with 6126 additions and 1520 deletions
  1. 6 0
      Documentation/DocBook/media-entities.tmpl
  2. 16 8
      Documentation/DocBook/v4l/compat.xml
  3. 8 4
      Documentation/DocBook/v4l/controls.xml
  4. 51 17
      Documentation/DocBook/v4l/dev-rds.xml
  5. 13 16
      Documentation/DocBook/v4l/dev-teletext.xml
  6. 1 1
      Documentation/DocBook/v4l/pixfmt-packed-rgb.xml
  7. 90 0
      Documentation/DocBook/v4l/pixfmt-srggb10.xml
  8. 67 0
      Documentation/DocBook/v4l/pixfmt-srggb8.xml
  9. 79 0
      Documentation/DocBook/v4l/pixfmt-y10.xml
  10. 27 5
      Documentation/DocBook/v4l/pixfmt.xml
  11. 9 1
      Documentation/DocBook/v4l/v4l2.xml
  12. 82 24
      Documentation/DocBook/v4l/videodev2.h.xml
  13. 1 2
      Documentation/DocBook/v4l/vidioc-g-dv-preset.xml
  14. 1 2
      Documentation/DocBook/v4l/vidioc-g-dv-timings.xml
  15. 1 1
      Documentation/DocBook/v4l/vidioc-query-dv-preset.xml
  16. 6 1
      Documentation/DocBook/v4l/vidioc-querycap.xml
  17. 12 6
      Documentation/DocBook/v4l/vidioc-queryctrl.xml
  18. 8 2
      Documentation/DocBook/v4l/vidioc-s-hw-freq-seek.xml
  19. 0 3
      Documentation/devices.txt
  20. 45 1
      Documentation/dvb/get_dvb_firmware
  21. 58 0
      Documentation/dvb/lmedm04.txt
  22. 16 24
      Documentation/feature-removal-schedule.txt
  23. 0 1
      Documentation/ioctl/ioctl-number.txt
  24. 1 0
      Documentation/video4linux/CARDLIST.cx88
  25. 2 1
      Documentation/video4linux/CARDLIST.em28xx
  26. 1 1
      Documentation/video4linux/CARDLIST.saa7134
  27. 0 1
      Documentation/video4linux/bttv/MAKEDEV
  28. 2 0
      Documentation/video4linux/gspca.txt
  29. 29 6
      Documentation/video4linux/v4l2-framework.txt
  30. 0 2
      arch/arm/mach-mx3/mach-pcm037.c
  31. 0 1
      arch/arm/mach-mx3/mx31moboard-marxbot.c
  32. 0 1
      arch/arm/mach-mx3/mx31moboard-smartbot.c
  33. 0 1
      arch/arm/mach-pxa/em-x270.c
  34. 0 2
      arch/arm/mach-pxa/ezx.c
  35. 0 1
      arch/arm/mach-pxa/mioa701.c
  36. 0 2
      arch/arm/mach-pxa/pcm990-baseboard.c
  37. 0 1
      arch/sh/boards/mach-ap325rxa/setup.c
  38. 0 4
      arch/sh/boards/mach-ecovec24/setup.c
  39. 0 1
      arch/sh/boards/mach-kfr2r09/setup.c
  40. 0 2
      arch/sh/boards/mach-migor/setup.c
  41. 0 1
      arch/sh/boards/mach-se/7724/setup.c
  42. 32 7
      drivers/media/IR/Kconfig
  43. 2 0
      drivers/media/IR/Makefile
  44. 507 300
      drivers/media/IR/ene_ir.c
  45. 151 124
      drivers/media/IR/ene_ir.h
  46. 368 148
      drivers/media/IR/imon.c
  47. 21 1
      drivers/media/IR/ir-core-priv.h
  48. 3 2
      drivers/media/IR/ir-jvc-decoder.c
  49. 6 1
      drivers/media/IR/ir-keytable.c
  50. 95 40
      drivers/media/IR/ir-lirc-codec.c
  51. 3 2
      drivers/media/IR/ir-nec-decoder.c
  52. 42 39
      drivers/media/IR/ir-raw-event.c
  53. 3 2
      drivers/media/IR/ir-rc5-decoder.c
  54. 154 0
      drivers/media/IR/ir-rc5-sz-decoder.c
  55. 3 2
      drivers/media/IR/ir-rc6-decoder.c
  56. 3 2
      drivers/media/IR/ir-sony-decoder.c
  57. 27 10
      drivers/media/IR/ir-sysfs.c
  58. 15 1
      drivers/media/IR/keymaps/Makefile
  59. 68 0
      drivers/media/IR/keymaps/rc-alink-dtu-m.c
  60. 93 0
      drivers/media/IR/keymaps/rc-anysee.c
  61. 40 40
      drivers/media/IR/keymaps/rc-asus-pc39.c
  62. 79 0
      drivers/media/IR/keymaps/rc-avermedia-rm-ks.c
  63. 102 0
      drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c
  64. 98 0
      drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c
  65. 82 0
      drivers/media/IR/keymaps/rc-digittrade.c
  66. 99 0
      drivers/media/IR/keymaps/rc-leadtek-y04g0051.c
  67. 68 0
      drivers/media/IR/keymaps/rc-lme2510.c
  68. 67 0
      drivers/media/IR/keymaps/rc-msi-digivox-ii.c
  69. 85 0
      drivers/media/IR/keymaps/rc-msi-digivox-iii.c
  70. 0 81
      drivers/media/IR/keymaps/rc-rc5-streamzap.c
  71. 45 43
      drivers/media/IR/keymaps/rc-rc6-mce.c
  72. 82 0
      drivers/media/IR/keymaps/rc-streamzap.c
  73. 79 0
      drivers/media/IR/keymaps/rc-terratec-slim.c
  74. 85 0
      drivers/media/IR/keymaps/rc-total-media-in-hand.c
  75. 80 0
      drivers/media/IR/keymaps/rc-trekstor.c
  76. 87 0
      drivers/media/IR/keymaps/rc-twinhan1027.c
  77. 89 44
      drivers/media/IR/lirc_dev.c
  78. 316 159
      drivers/media/IR/mceusb.c
  79. 1246 0
      drivers/media/IR/nuvoton-cir.c
  80. 408 0
      drivers/media/IR/nuvoton-cir.h
  81. 102 274
      drivers/media/IR/streamzap.c
  82. 1 1
      drivers/media/common/saa7146_fops.c
  83. 0 1
      drivers/media/common/saa7146_i2c.c
  84. 1 1
      drivers/media/common/saa7146_vbi.c
  85. 1 1
      drivers/media/common/saa7146_video.c
  86. 7 0
      drivers/media/common/tuners/Kconfig
  87. 1 0
      drivers/media/common/tuners/Makefile
  88. 334 0
      drivers/media/common/tuners/tda18218.c
  89. 45 0
      drivers/media/common/tuners/tda18218.h
  90. 106 0
      drivers/media/common/tuners/tda18218_priv.h
  91. 35 26
      drivers/media/common/tuners/tda18271-common.c
  92. 7 9
      drivers/media/common/tuners/tda18271-fe.c
  93. 3 2
      drivers/media/common/tuners/tda18271.h
  94. 1 1
      drivers/media/common/tuners/xc5000.c
  95. 2 2
      drivers/media/common/tuners/xc5000.h
  96. 0 3
      drivers/media/dvb/b2c2/flexcop-i2c.c
  97. 0 1
      drivers/media/dvb/dm1105/dm1105.c
  98. 2 2
      drivers/media/dvb/dvb-core/dvb_frontend.c
  99. 1 1
      drivers/media/dvb/dvb-core/dvb_frontend.h
  100. 12 0
      drivers/media/dvb/dvb-usb/Kconfig

+ 6 - 0
Documentation/DocBook/media-entities.tmpl

@@ -250,6 +250,9 @@
 <!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
 <!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
+<!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
+<!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
+<!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
@@ -347,6 +350,9 @@
 <!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
 <!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
+<!ENTITY srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
+<!ENTITY srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
+<!ENTITY y10 SYSTEM "v4l/pixfmt-y10.xml">
 <!ENTITY cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
 <!ENTITY dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
 <!ENTITY encoder-cmd SYSTEM "v4l/vidioc-encoder-cmd.xml">
 <!ENTITY encoder-cmd SYSTEM "v4l/vidioc-encoder-cmd.xml">

+ 16 - 8
Documentation/DocBook/v4l/compat.xml

@@ -21,11 +21,15 @@ API.</para>
       <title>Opening and Closing Devices</title>
       <title>Opening and Closing Devices</title>
 
 
       <para>For compatibility reasons the character device file names
       <para>For compatibility reasons the character device file names
-recommended for V4L2 video capture, overlay, radio, teletext and raw
+recommended for V4L2 video capture, overlay, radio and raw
 vbi capture devices did not change from those used by V4L. They are
 vbi capture devices did not change from those used by V4L. They are
 listed in <xref linkend="devices" /> and below in <xref
 listed in <xref linkend="devices" /> and below in <xref
 	  linkend="v4l-dev" />.</para>
 	  linkend="v4l-dev" />.</para>
 
 
+      <para>The teletext devices (minor range 192-223) have been removed in
+V4L2 and no longer exist. There is no hardware available anymore for handling
+pure teletext. Instead raw or sliced VBI is used.</para>
+
       <para>The V4L <filename>videodev</filename> module automatically
       <para>The V4L <filename>videodev</filename> module automatically
 assigns minor numbers to drivers in load order, depending on the
 assigns minor numbers to drivers in load order, depending on the
 registered device type. We recommend that V4L2 drivers by default
 registered device type. We recommend that V4L2 drivers by default
@@ -65,13 +69,6 @@ not compatible with V4L or V4L2.</para> </footnote>,
 <filename>/dev/radio63</filename></para></entry>
 <filename>/dev/radio63</filename></para></entry>
 	      <entry>64-127</entry>
 	      <entry>64-127</entry>
 	    </row>
 	    </row>
-	    <row>
-	      <entry>Teletext decoder</entry>
-	      <entry><para><filename>/dev/vtx</filename>,
-<filename>/dev/vtx0</filename> to
-<filename>/dev/vtx31</filename></para></entry>
-	      <entry>192-223</entry>
-	    </row>
 	    <row>
 	    <row>
 	      <entry>Raw VBI capture</entry>
 	      <entry>Raw VBI capture</entry>
 	      <entry><para><filename>/dev/vbi</filename>,
 	      <entry><para><filename>/dev/vbi</filename>,
@@ -2345,6 +2342,17 @@ more information.</para>
 	</listitem>
 	</listitem>
       </orderedlist>
       </orderedlist>
     </section>
     </section>
+    <section>
+      <title>V4L2 in Linux 2.6.37</title>
+      <orderedlist>
+	<listitem>
+	  <para>Remove the vtx (videotext/teletext) API. This API was no longer
+used and no hardware exists to verify the API. Nor were any userspace applications found
+that used it. It was originally scheduled for removal in 2.6.35.
+	  </para>
+	</listitem>
+      </orderedlist>
+    </section>
 
 
     <section id="other">
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
       <title>Relation of V4L2 to other Linux multimedia APIs</title>

+ 8 - 4
Documentation/DocBook/v4l/controls.xml

@@ -311,11 +311,18 @@ minimum value disables backlight compensation.</entry>
 	    bits 8-15 Green color information, bits 16-23 Blue color
 	    bits 8-15 Green color information, bits 16-23 Blue color
 	    information and bits 24-31 must be zero.</entry>
 	    information and bits 24-31 must be zero.</entry>
 	  </row>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CID_ILLUMINATORS_1</constant>
+		<constant>V4L2_CID_ILLUMINATORS_2</constant></entry>
+	    <entry>boolean</entry>
+	    <entry>Switch on or off the illuminator 1 or 2 of the device
+		(usually a microscope).</entry>
+	  </row>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CID_LASTP1</constant></entry>
 	    <entry><constant>V4L2_CID_LASTP1</constant></entry>
 	    <entry></entry>
 	    <entry></entry>
 	    <entry>End of the predefined control IDs (currently
 	    <entry>End of the predefined control IDs (currently
-<constant>V4L2_CID_BG_COLOR</constant> + 1).</entry>
+<constant>V4L2_CID_ILLUMINATORS_2</constant> + 1).</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
 	    <entry><constant>V4L2_CID_PRIVATE_BASE</constant></entry>
@@ -357,9 +364,6 @@ enumerate_menu (void)
 	      querymenu.index++) {
 	      querymenu.index++) {
 		if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
 		if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
 			printf ("  %s\n", querymenu.name);
 			printf ("  %s\n", querymenu.name);
-		} else {
-			perror ("VIDIOC_QUERYMENU");
-			exit (EXIT_FAILURE);
 		}
 		}
 	}
 	}
 }
 }

+ 51 - 17
Documentation/DocBook/v4l/dev-rds.xml

@@ -3,15 +3,16 @@
       <para>The Radio Data System transmits supplementary
       <para>The Radio Data System transmits supplementary
 information in binary format, for example the station name or travel
 information in binary format, for example the station name or travel
 information, on an inaudible audio subcarrier of a radio program. This
 information, on an inaudible audio subcarrier of a radio program. This
-interface is aimed at devices capable of receiving and decoding RDS
+interface is aimed at devices capable of receiving and/or transmitting RDS
 information.</para>
 information.</para>
 
 
       <para>For more information see the core RDS standard <xref linkend="en50067" />
       <para>For more information see the core RDS standard <xref linkend="en50067" />
 and the RBDS standard <xref linkend="nrsc4" />.</para>
 and the RBDS standard <xref linkend="nrsc4" />.</para>
 
 
       <para>Note that the RBDS standard as is used in the USA is almost identical
       <para>Note that the RBDS standard as is used in the USA is almost identical
-to the RDS standard. Any RDS decoder can also handle RBDS. Only some of the fields
-have slightly different meanings. See the RBDS standard for more information.</para>
+to the RDS standard. Any RDS decoder/encoder can also handle RBDS. Only some of the
+fields have slightly different meanings. See the RBDS standard for more
+information.</para>
 
 
       <para>The RBDS standard also specifies support for MMBS (Modified Mobile Search).
       <para>The RBDS standard also specifies support for MMBS (Modified Mobile Search).
 This is a proprietary format which seems to be discontinued. The RDS interface does not
 This is a proprietary format which seems to be discontinued. The RDS interface does not
@@ -21,16 +22,25 @@ be needed, then please contact the linux-media mailing list: &v4l-ml;.</para>
   <section>
   <section>
     <title>Querying Capabilities</title>
     <title>Querying Capabilities</title>
 
 
-    <para>Devices supporting the RDS capturing API
-set the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
+    <para>Devices supporting the RDS capturing API set
+the <constant>V4L2_CAP_RDS_CAPTURE</constant> flag in
 the <structfield>capabilities</structfield> field of &v4l2-capability;
 the <structfield>capabilities</structfield> field of &v4l2-capability;
-returned by the &VIDIOC-QUERYCAP; ioctl.
-Any tuner that supports RDS will set the
-<constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
-field of &v4l2-tuner;.
-Whether an RDS signal is present can be detected by looking at
-the <structfield>rxsubchans</structfield> field of &v4l2-tuner;: the
-<constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data was detected.</para>
+returned by the &VIDIOC-QUERYCAP; ioctl.  Any tuner that supports RDS
+will set the <constant>V4L2_TUNER_CAP_RDS</constant> flag in
+the <structfield>capability</structfield> field of &v4l2-tuner;.  If
+the driver only passes RDS blocks without interpreting the data
+the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be
+set, see <link linkend="reading-rds-data">Reading RDS data</link>.
+For future use the
+flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> has also been
+defined. However, a driver for a radio tuner with this capability does
+not yet exist, so if you are planning to write such a driver you
+should discuss this on the linux-media mailing list: &v4l-ml;.</para>
+
+    <para> Whether an RDS signal is present can be detected by looking
+at the <structfield>rxsubchans</structfield> field of &v4l2-tuner;:
+the <constant>V4L2_TUNER_SUB_RDS</constant> will be set if RDS data
+was detected.</para>
 
 
     <para>Devices supporting the RDS output API
     <para>Devices supporting the RDS output API
 set the <constant>V4L2_CAP_RDS_OUTPUT</constant> flag in
 set the <constant>V4L2_CAP_RDS_OUTPUT</constant> flag in
@@ -40,16 +50,31 @@ Any modulator that supports RDS will set the
 <constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
 <constant>V4L2_TUNER_CAP_RDS</constant> flag in the <structfield>capability</structfield>
 field of &v4l2-modulator;.
 field of &v4l2-modulator;.
 In order to enable the RDS transmission one must set the <constant>V4L2_TUNER_SUB_RDS</constant>
 In order to enable the RDS transmission one must set the <constant>V4L2_TUNER_SUB_RDS</constant>
-bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.</para>
-
+bit in the <structfield>txsubchans</structfield> field of &v4l2-modulator;.
+If the driver only passes RDS blocks without interpreting the data
+the <constant>V4L2_TUNER_SUB_RDS_BLOCK_IO</constant> flag has to be set. If the
+tuner is capable of handling RDS entities like program identification codes and radio
+text, the flag <constant>V4L2_TUNER_SUB_RDS_CONTROLS</constant> should be set,
+see <link linkend="writing-rds-data">Writing RDS data</link> and
+<link linkend="fm-tx-controls">FM Transmitter Control Reference</link>.</para>
   </section>
   </section>
 
 
-  <section>
+  <section  id="reading-rds-data">
     <title>Reading RDS data</title>
     <title>Reading RDS data</title>
 
 
       <para>RDS data can be read from the radio device
       <para>RDS data can be read from the radio device
-with the &func-read; function. The data is packed in groups of three bytes,
+with the &func-read; function. The data is packed in groups of three bytes.</para>
+  </section>
+
+  <section  id="writing-rds-data">
+    <title>Writing RDS data</title>
+
+      <para>RDS data can be written to the radio device
+with the &func-write; function. The data is packed in groups of three bytes,
 as follows:</para>
 as follows:</para>
+  </section>
+
+  <section>
     <table frame="none" pgwide="1" id="v4l2-rds-data">
     <table frame="none" pgwide="1" id="v4l2-rds-data">
       <title>struct
       <title>struct
 <structname>v4l2_rds_data</structname></title>
 <structname>v4l2_rds_data</structname></title>
@@ -111,48 +136,57 @@ as follows:</para>
 	<tbody valign="top">
 	<tbody valign="top">
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_MSK</entry>
 	    <entry>V4L2_RDS_BLOCK_MSK</entry>
+	    <entry> </entry>
 	    <entry>7</entry>
 	    <entry>7</entry>
 	    <entry>Mask for bits 0-2 to get the block ID.</entry>
 	    <entry>Mask for bits 0-2 to get the block ID.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_A</entry>
 	    <entry>V4L2_RDS_BLOCK_A</entry>
+	    <entry> </entry>
 	    <entry>0</entry>
 	    <entry>0</entry>
 	    <entry>Block A.</entry>
 	    <entry>Block A.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_B</entry>
 	    <entry>V4L2_RDS_BLOCK_B</entry>
+	    <entry> </entry>
 	    <entry>1</entry>
 	    <entry>1</entry>
 	    <entry>Block B.</entry>
 	    <entry>Block B.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_C</entry>
 	    <entry>V4L2_RDS_BLOCK_C</entry>
+	    <entry> </entry>
 	    <entry>2</entry>
 	    <entry>2</entry>
 	    <entry>Block C.</entry>
 	    <entry>Block C.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_D</entry>
 	    <entry>V4L2_RDS_BLOCK_D</entry>
+	    <entry> </entry>
 	    <entry>3</entry>
 	    <entry>3</entry>
 	    <entry>Block D.</entry>
 	    <entry>Block D.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_C_ALT</entry>
 	    <entry>V4L2_RDS_BLOCK_C_ALT</entry>
+	    <entry> </entry>
 	    <entry>4</entry>
 	    <entry>4</entry>
 	    <entry>Block C'.</entry>
 	    <entry>Block C'.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_INVALID</entry>
 	    <entry>V4L2_RDS_BLOCK_INVALID</entry>
+	    <entry>read-only</entry>
 	    <entry>7</entry>
 	    <entry>7</entry>
 	    <entry>An invalid block.</entry>
 	    <entry>An invalid block.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_CORRECTED</entry>
 	    <entry>V4L2_RDS_BLOCK_CORRECTED</entry>
+	    <entry>read-only</entry>
 	    <entry>0x40</entry>
 	    <entry>0x40</entry>
 	    <entry>A bit error was detected but corrected.</entry>
 	    <entry>A bit error was detected but corrected.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>V4L2_RDS_BLOCK_ERROR</entry>
 	    <entry>V4L2_RDS_BLOCK_ERROR</entry>
+	    <entry>read-only</entry>
 	    <entry>0x80</entry>
 	    <entry>0x80</entry>
-	    <entry>An incorrectable error occurred.</entry>
+	    <entry>An uncorrectable error occurred.</entry>
 	  </row>
 	  </row>
 	</tbody>
 	</tbody>
       </tgroup>
       </tgroup>

+ 13 - 16
Documentation/DocBook/v4l/dev-teletext.xml

@@ -1,35 +1,32 @@
   <title>Teletext Interface</title>
   <title>Teletext Interface</title>
 
 
-  <para>This interface aims at devices receiving and demodulating
+  <para>This interface was aimed at devices receiving and demodulating
 Teletext data [<xref linkend="ets300706" />, <xref linkend="itu653" />], evaluating the
 Teletext data [<xref linkend="ets300706" />, <xref linkend="itu653" />], evaluating the
 Teletext packages and storing formatted pages in cache memory. Such
 Teletext packages and storing formatted pages in cache memory. Such
 devices are usually implemented as microcontrollers with serial
 devices are usually implemented as microcontrollers with serial
-interface (I<superscript>2</superscript>C) and can be found on older
+interface (I<superscript>2</superscript>C) and could be found on old
 TV cards, dedicated Teletext decoding cards and home-brew devices
 TV cards, dedicated Teletext decoding cards and home-brew devices
 connected to the PC parallel port.</para>
 connected to the PC parallel port.</para>
 
 
-  <para>The Teletext API was designed by Martin Buck. It is defined in
+  <para>The Teletext API was designed by Martin Buck. It was defined in
 the kernel header file <filename>linux/videotext.h</filename>, the
 the kernel header file <filename>linux/videotext.h</filename>, the
 specification is available from <ulink url="ftp://ftp.gwdg.de/pub/linux/misc/videotext/">
 specification is available from <ulink url="ftp://ftp.gwdg.de/pub/linux/misc/videotext/">
 ftp://ftp.gwdg.de/pub/linux/misc/videotext/</ulink>. (Videotext is the name of
 ftp://ftp.gwdg.de/pub/linux/misc/videotext/</ulink>. (Videotext is the name of
-the German public television Teletext service.) Conventional character
-device file names are <filename>/dev/vtx</filename> and
-<filename>/dev/vttuner</filename>, with device number 83, 0 and 83, 16
-respectively. A similar interface exists for the Philips SAA5249
-Teletext decoder [specification?] with character device file names
-<filename>/dev/tlkN</filename>, device number 102, N.</para>
+the German public television Teletext service.)</para>
 
 
   <para>Eventually the Teletext API was integrated into the V4L API
   <para>Eventually the Teletext API was integrated into the V4L API
 with character device file names <filename>/dev/vtx0</filename> to
 with character device file names <filename>/dev/vtx0</filename> to
 <filename>/dev/vtx31</filename>, device major number 81, minor numbers
 <filename>/dev/vtx31</filename>, device major number 81, minor numbers
-192 to 223. For reference the V4L Teletext API specification is
-reproduced here in full: "Teletext interfaces talk the existing VTX
-API." Teletext devices with major number 83 and 102 will be removed in
-Linux 2.6.</para>
+192 to 223.</para>
 
 
-  <para>There are no plans to replace the Teletext API or to integrate
-it into V4L2. Please write to the linux-media mailing list: &v4l-ml;
-when the need arises.</para>
+  <para>However, teletext decoders were quickly replaced by more
+generic VBI demodulators and those dedicated teletext decoders no longer exist.
+For many years the vtx devices were still around, even though nobody used
+them. So the decision was made to finally remove support for the Teletext API in
+kernel 2.6.37.</para>
+
+  <para>Modern devices all use the <link linkend="raw-vbi">raw</link> or
+<link linkend="sliced">sliced</link> VBI API.</para>
 
 
   <!--
   <!--
 Local Variables:
 Local Variables:

+ 1 - 1
Documentation/DocBook/v4l/pixfmt-packed-rgb.xml

@@ -739,7 +739,7 @@ defined in error. Drivers may interpret them as in <xref
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>1</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	    <entry>b<subscript>0</subscript></entry>
 	  </row>
 	  </row>
-	  <row id="V4L2-PIX-FMT-BGR666">
+	  <row><!-- id="V4L2-PIX-FMT-BGR666" -->
 	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
 	    <entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
 	    <entry>'BGRH'</entry>
 	    <entry>'BGRH'</entry>
 	    <entry></entry>
 	    <entry></entry>

+ 90 - 0
Documentation/DocBook/v4l/pixfmt-srggb10.xml

@@ -0,0 +1,90 @@
+    <refentry>
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_SRGGB10 ('RG10'),
+	 V4L2_PIX_FMT_SGRBG10 ('BA10'),
+	 V4L2_PIX_FMT_SGBRG10 ('GB10'),
+	 V4L2_PIX_FMT_SBGGR10 ('BG10'),
+	 </refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname id="V4L2-PIX-FMT-SRGGB10"><constant>V4L2_PIX_FMT_SRGGB10</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGRBG10"><constant>V4L2_PIX_FMT_SGRBG10</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGBRG10"><constant>V4L2_PIX_FMT_SGBRG10</constant></refname>
+	<refname id="V4L2-PIX-FMT-SBGGR10"><constant>V4L2_PIX_FMT_SBGGR10</constant></refname>
+	<refpurpose>10-bit Bayer formats expanded to 16 bits</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>The following four pixel formats are raw sRGB / Bayer formats with
+10 bits per colour. Each colour component is stored in a 16-bit word, with 6
+unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
+and n/2 blue or red samples, with alternating red and blue rows. Bytes are
+stored in memory in little endian order. They are conventionally described
+as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
+formats</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_SBGGR10</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+	<title>Byte Order.</title>
+	<para>Each cell is one byte, high 6 bits in high bytes are 0.
+	  <informaltable frame="none">
+	    <tgroup cols="5" align="center">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>start&nbsp;+&nbsp;0:</entry>
+		  <entry>B<subscript>00low</subscript></entry>
+		  <entry>B<subscript>00high</subscript></entry>
+		  <entry>G<subscript>01low</subscript></entry>
+		  <entry>G<subscript>01high</subscript></entry>
+		  <entry>B<subscript>02low</subscript></entry>
+		  <entry>B<subscript>02high</subscript></entry>
+		  <entry>G<subscript>03low</subscript></entry>
+		  <entry>G<subscript>03high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;8:</entry>
+		  <entry>G<subscript>10low</subscript></entry>
+		  <entry>G<subscript>10high</subscript></entry>
+		  <entry>R<subscript>11low</subscript></entry>
+		  <entry>R<subscript>11high</subscript></entry>
+		  <entry>G<subscript>12low</subscript></entry>
+		  <entry>G<subscript>12high</subscript></entry>
+		  <entry>R<subscript>13low</subscript></entry>
+		  <entry>R<subscript>13high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;16:</entry>
+		  <entry>B<subscript>20low</subscript></entry>
+		  <entry>B<subscript>20high</subscript></entry>
+		  <entry>G<subscript>21low</subscript></entry>
+		  <entry>G<subscript>21high</subscript></entry>
+		  <entry>B<subscript>22low</subscript></entry>
+		  <entry>B<subscript>22high</subscript></entry>
+		  <entry>G<subscript>23low</subscript></entry>
+		  <entry>G<subscript>23high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;24:</entry>
+		  <entry>G<subscript>30low</subscript></entry>
+		  <entry>G<subscript>30high</subscript></entry>
+		  <entry>R<subscript>31low</subscript></entry>
+		  <entry>R<subscript>31high</subscript></entry>
+		  <entry>G<subscript>32low</subscript></entry>
+		  <entry>G<subscript>32high</subscript></entry>
+		  <entry>R<subscript>33low</subscript></entry>
+		  <entry>R<subscript>33high</subscript></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>

+ 67 - 0
Documentation/DocBook/v4l/pixfmt-srggb8.xml

@@ -0,0 +1,67 @@
+    <refentry id="V4L2-PIX-FMT-SRGGB8">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_SRGGB8 ('RGGB')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname><constant>V4L2_PIX_FMT_SRGGB8</constant></refname>
+	<refpurpose>Bayer RGB format</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>This is commonly the native format of digital cameras,
+reflecting the arrangement of sensors on the CCD device. Only one red,
+green or blue value is given for each pixel. Missing components must
+be interpolated from neighbouring pixels. From left to right the first
+row consists of a red and green value, the second row of a green and
+blue value. This scheme repeats to the right and down for every two
+columns and rows.</para>
+
+	<example>
+	  <title><constant>V4L2_PIX_FMT_SRGGB8</constant> 4 &times; 4
+pixel image</title>
+
+	  <formalpara>
+	    <title>Byte Order.</title>
+	    <para>Each cell is one byte.
+	      <informaltable frame="none">
+		<tgroup cols="5" align="center">
+		  <colspec align="left" colwidth="2*" />
+		  <tbody valign="top">
+		    <row>
+		      <entry>start&nbsp;+&nbsp;0:</entry>
+		      <entry>R<subscript>00</subscript></entry>
+		      <entry>G<subscript>01</subscript></entry>
+		      <entry>R<subscript>02</subscript></entry>
+		      <entry>G<subscript>03</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;4:</entry>
+		      <entry>G<subscript>10</subscript></entry>
+		      <entry>B<subscript>11</subscript></entry>
+		      <entry>G<subscript>12</subscript></entry>
+		      <entry>B<subscript>13</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;8:</entry>
+		      <entry>R<subscript>20</subscript></entry>
+		      <entry>G<subscript>21</subscript></entry>
+		      <entry>R<subscript>22</subscript></entry>
+		      <entry>G<subscript>23</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start&nbsp;+&nbsp;12:</entry>
+		      <entry>G<subscript>30</subscript></entry>
+		      <entry>B<subscript>31</subscript></entry>
+		      <entry>G<subscript>32</subscript></entry>
+		      <entry>B<subscript>33</subscript></entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+	      </informaltable>
+	    </para>
+	  </formalpara>
+	</example>
+      </refsect1>
+    </refentry>

+ 79 - 0
Documentation/DocBook/v4l/pixfmt-y10.xml

@@ -0,0 +1,79 @@
+<refentry id="V4L2-PIX-FMT-Y10">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y10 ('Y10 ')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y10</constant></refname>
+    <refpurpose>Grey-scale image</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a grey-scale image with a depth of 10 bits per pixel. Pixels
+are stored in 16-bit words with unused high bits padded with 0. The least
+significant byte is stored at lower memory addresses (little-endian).</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y10</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+	<title>Byte Order.</title>
+	<para>Each cell is one byte.
+	  <informaltable frame="none">
+	    <tgroup cols="9" align="center">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>start&nbsp;+&nbsp;0:</entry>
+		  <entry>Y'<subscript>00low</subscript></entry>
+		  <entry>Y'<subscript>00high</subscript></entry>
+		  <entry>Y'<subscript>01low</subscript></entry>
+		  <entry>Y'<subscript>01high</subscript></entry>
+		  <entry>Y'<subscript>02low</subscript></entry>
+		  <entry>Y'<subscript>02high</subscript></entry>
+		  <entry>Y'<subscript>03low</subscript></entry>
+		  <entry>Y'<subscript>03high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;8:</entry>
+		  <entry>Y'<subscript>10low</subscript></entry>
+		  <entry>Y'<subscript>10high</subscript></entry>
+		  <entry>Y'<subscript>11low</subscript></entry>
+		  <entry>Y'<subscript>11high</subscript></entry>
+		  <entry>Y'<subscript>12low</subscript></entry>
+		  <entry>Y'<subscript>12high</subscript></entry>
+		  <entry>Y'<subscript>13low</subscript></entry>
+		  <entry>Y'<subscript>13high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;16:</entry>
+		  <entry>Y'<subscript>20low</subscript></entry>
+		  <entry>Y'<subscript>20high</subscript></entry>
+		  <entry>Y'<subscript>21low</subscript></entry>
+		  <entry>Y'<subscript>21high</subscript></entry>
+		  <entry>Y'<subscript>22low</subscript></entry>
+		  <entry>Y'<subscript>22high</subscript></entry>
+		  <entry>Y'<subscript>23low</subscript></entry>
+		  <entry>Y'<subscript>23high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;24:</entry>
+		  <entry>Y'<subscript>30low</subscript></entry>
+		  <entry>Y'<subscript>30high</subscript></entry>
+		  <entry>Y'<subscript>31low</subscript></entry>
+		  <entry>Y'<subscript>31high</subscript></entry>
+		  <entry>Y'<subscript>32low</subscript></entry>
+		  <entry>Y'<subscript>32high</subscript></entry>
+		  <entry>Y'<subscript>33low</subscript></entry>
+		  <entry>Y'<subscript>33high</subscript></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>

+ 27 - 5
Documentation/DocBook/v4l/pixfmt.xml

@@ -566,7 +566,9 @@ access the palette, this must be done with ioctls of the Linux framebuffer API.<
     &sub-sbggr8;
     &sub-sbggr8;
     &sub-sgbrg8;
     &sub-sgbrg8;
     &sub-sgrbg8;
     &sub-sgrbg8;
+    &sub-srggb8;
     &sub-sbggr16;
     &sub-sbggr16;
+    &sub-srggb10;
   </section>
   </section>
 
 
   <section id="yuv-formats">
   <section id="yuv-formats">
@@ -589,6 +591,7 @@ information.</para>
 
 
     &sub-packed-yuv;
     &sub-packed-yuv;
     &sub-grey;
     &sub-grey;
+    &sub-y10;
     &sub-y16;
     &sub-y16;
     &sub-yuyv;
     &sub-yuyv;
     &sub-uyvy;
     &sub-uyvy;
@@ -685,6 +688,11 @@ http://www.ivtvdriver.org/</ulink></para><para>The format is documented in the
 kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm12</filename>
 kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm12</filename>
 </para></entry>
 </para></entry>
 	  </row>
 	  </row>
+	  <row id="V4L2-PIX-FMT-CPIA1">
+	    <entry><constant>V4L2_PIX_FMT_CPIA1</constant></entry>
+	    <entry>'CPIA'</entry>
+	    <entry>YUV format used by the gspca cpia1 driver.</entry>
+	  </row>
 	  <row id="V4L2-PIX-FMT-SPCA501">
 	  <row id="V4L2-PIX-FMT-SPCA501">
 	    <entry><constant>V4L2_PIX_FMT_SPCA501</constant></entry>
 	    <entry><constant>V4L2_PIX_FMT_SPCA501</constant></entry>
 	    <entry>'S501'</entry>
 	    <entry>'S501'</entry>
@@ -705,11 +713,6 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
 	    <entry>'S561'</entry>
 	    <entry>'S561'</entry>
 	    <entry>Compressed GBRG Bayer format used by the gspca driver.</entry>
 	    <entry>Compressed GBRG Bayer format used by the gspca driver.</entry>
 	  </row>
 	  </row>
-	  <row id="V4L2-PIX-FMT-SGRBG10">
-	    <entry><constant>V4L2_PIX_FMT_SGRBG10</constant></entry>
-	    <entry>'DA10'</entry>
-	    <entry>10 bit raw Bayer, expanded to 16 bits.</entry>
-	  </row>
 	  <row id="V4L2-PIX-FMT-SGRBG10DPCM8">
 	  <row id="V4L2-PIX-FMT-SGRBG10DPCM8">
 	    <entry><constant>V4L2_PIX_FMT_SGRBG10DPCM8</constant></entry>
 	    <entry><constant>V4L2_PIX_FMT_SGRBG10DPCM8</constant></entry>
 	    <entry>'DB10'</entry>
 	    <entry>'DB10'</entry>
@@ -770,6 +773,11 @@ kernel sources in the file <filename>Documentation/video4linux/cx2341x/README.hm
 	    <entry>'S920'</entry>
 	    <entry>'S920'</entry>
 	    <entry>YUV 4:2:0 format of the gspca sn9c20x driver.</entry>
 	    <entry>YUV 4:2:0 format of the gspca sn9c20x driver.</entry>
 	  </row>
 	  </row>
+	  <row id="V4L2-PIX-FMT-SN9C2028">
+	    <entry><constant>V4L2_PIX_FMT_SN9C2028</constant></entry>
+	    <entry>'SONX'</entry>
+	    <entry>Compressed GBRG bayer format of the gspca sn9c2028 driver.</entry>
+	  </row>
 	  <row id="V4L2-PIX-FMT-STV0680">
 	  <row id="V4L2-PIX-FMT-STV0680">
 	    <entry><constant>V4L2_PIX_FMT_STV0680</constant></entry>
 	    <entry><constant>V4L2_PIX_FMT_STV0680</constant></entry>
 	    <entry>'S680'</entry>
 	    <entry>'S680'</entry>
@@ -787,6 +795,20 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
 	    <entry>'TM60'</entry>
 	    <entry>'TM60'</entry>
 	    <entry><para>Used by Trident tm6000</para></entry>
 	    <entry><para>Used by Trident tm6000</para></entry>
 	  </row>
 	  </row>
+	  <row id="V4L2-PIX-FMT-CIT-YYVYUY">
+	    <entry><constant>V4L2_PIX_FMT_CIT_YYVYUY</constant></entry>
+	    <entry>'CITV'</entry>
+	    <entry><para>Used by xirlink CIT, found at IBM webcams.</para>
+	           <para>Uses one line of Y then 1 line of VYUY</para>
+	    </entry>
+	  </row>
+	  <row id="V4L2-PIX-FMT-KONICA420">
+	    <entry><constant>V4L2_PIX_FMT_KONICA420</constant></entry>
+	    <entry>'KONI'</entry>
+	    <entry><para>Used by Konica webcams.</para>
+	           <para>YUV420 planar in blocks of 256 pixels.</para>
+	    </entry>
+	  </row>
 	  <row id="V4L2-PIX-FMT-YYUV">
 	  <row id="V4L2-PIX-FMT-YYUV">
 	    <entry><constant>V4L2_PIX_FMT_YYUV</constant></entry>
 	    <entry><constant>V4L2_PIX_FMT_YYUV</constant></entry>
 	    <entry>'YYUV'</entry>
 	    <entry>'YYUV'</entry>

+ 9 - 1
Documentation/DocBook/v4l/v4l2.xml

@@ -99,6 +99,7 @@ Remote Controller chapter.</contrib>
       <year>2007</year>
       <year>2007</year>
       <year>2008</year>
       <year>2008</year>
       <year>2009</year>
       <year>2009</year>
+      <year>2010</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
 Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
     </copyright>
     </copyright>
@@ -110,9 +111,16 @@ Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
       <!-- Put document revisions here, newest first. -->
       <!-- Put document revisions here, newest first. -->
       <!-- API revisions (changes and additions of defines, enums,
       <!-- API revisions (changes and additions of defines, enums,
 structs, ioctls) must be noted in more detail in the history chapter
 structs, ioctls) must be noted in more detail in the history chapter
-(compat.sgml), along with the possible impact on existing drivers and
+(compat.xml), along with the possible impact on existing drivers and
 applications. -->
 applications. -->
 
 
+      <revision>
+	<revnumber>2.6.37</revnumber>
+	<date>2010-08-06</date>
+	<authorinitials>hv</authorinitials>
+	<revremark>Removed obsolete vtx (videotext) API.</revremark>
+      </revision>
+
       <revision>
       <revision>
 	<revnumber>2.6.33</revnumber>
 	<revnumber>2.6.33</revnumber>
 	<date>2009-12-03</date>
 	<date>2009-12-03</date>

+ 82 - 24
Documentation/DocBook/v4l/videodev2.h.xml

@@ -154,23 +154,13 @@ enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> {
         V4L2_BUF_TYPE_VBI_OUTPUT           = 5,
         V4L2_BUF_TYPE_VBI_OUTPUT           = 5,
         V4L2_BUF_TYPE_SLICED_VBI_CAPTURE   = 6,
         V4L2_BUF_TYPE_SLICED_VBI_CAPTURE   = 6,
         V4L2_BUF_TYPE_SLICED_VBI_OUTPUT    = 7,
         V4L2_BUF_TYPE_SLICED_VBI_OUTPUT    = 7,
-#if 1 /*KEEP*/
+#if 1
         /* Experimental */
         /* Experimental */
         V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
         V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
 #endif
 #endif
         V4L2_BUF_TYPE_PRIVATE              = 0x80,
         V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
 };
 
 
-enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
-        V4L2_CTRL_TYPE_INTEGER       = 1,
-        V4L2_CTRL_TYPE_BOOLEAN       = 2,
-        V4L2_CTRL_TYPE_MENU          = 3,
-        V4L2_CTRL_TYPE_BUTTON        = 4,
-        V4L2_CTRL_TYPE_INTEGER64     = 5,
-        V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
-        V4L2_CTRL_TYPE_STRING        = 7,
-};
-
 enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
 enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
         V4L2_TUNER_RADIO             = 1,
         V4L2_TUNER_RADIO             = 1,
         V4L2_TUNER_ANALOG_TV         = 2,
         V4L2_TUNER_ANALOG_TV         = 2,
@@ -288,6 +278,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-RGB565">V4L2_PIX_FMT_RGB565</link>  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
 #define <link linkend="V4L2-PIX-FMT-RGB565">V4L2_PIX_FMT_RGB565</link>  v4l2_fourcc('R', 'G', 'B', 'P') /* 16  RGB-5-6-5     */
 #define <link linkend="V4L2-PIX-FMT-RGB555X">V4L2_PIX_FMT_RGB555X</link> v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
 #define <link linkend="V4L2-PIX-FMT-RGB555X">V4L2_PIX_FMT_RGB555X</link> v4l2_fourcc('R', 'G', 'B', 'Q') /* 16  RGB-5-5-5 BE  */
 #define <link linkend="V4L2-PIX-FMT-RGB565X">V4L2_PIX_FMT_RGB565X</link> v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
 #define <link linkend="V4L2-PIX-FMT-RGB565X">V4L2_PIX_FMT_RGB565X</link> v4l2_fourcc('R', 'G', 'B', 'R') /* 16  RGB-5-6-5 BE  */
+#define <link linkend="V4L2-PIX-FMT-BGR666">V4L2_PIX_FMT_BGR666</link>  v4l2_fourcc('B', 'G', 'R', 'H') /* 18  BGR-6-6-6     */
 #define <link linkend="V4L2-PIX-FMT-BGR24">V4L2_PIX_FMT_BGR24</link>   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
 #define <link linkend="V4L2-PIX-FMT-BGR24">V4L2_PIX_FMT_BGR24</link>   v4l2_fourcc('B', 'G', 'R', '3') /* 24  BGR-8-8-8     */
 #define <link linkend="V4L2-PIX-FMT-RGB24">V4L2_PIX_FMT_RGB24</link>   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
 #define <link linkend="V4L2-PIX-FMT-RGB24">V4L2_PIX_FMT_RGB24</link>   v4l2_fourcc('R', 'G', 'B', '3') /* 24  RGB-8-8-8     */
 #define <link linkend="V4L2-PIX-FMT-BGR32">V4L2_PIX_FMT_BGR32</link>   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
 #define <link linkend="V4L2-PIX-FMT-BGR32">V4L2_PIX_FMT_BGR32</link>   v4l2_fourcc('B', 'G', 'R', '4') /* 32  BGR-8-8-8-8   */
@@ -295,6 +286,9 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 
 
 /* Grey formats */
 /* Grey formats */
 #define <link linkend="V4L2-PIX-FMT-GREY">V4L2_PIX_FMT_GREY</link>    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
 #define <link linkend="V4L2-PIX-FMT-GREY">V4L2_PIX_FMT_GREY</link>    v4l2_fourcc('G', 'R', 'E', 'Y') /*  8  Greyscale     */
+#define <link linkend="V4L2-PIX-FMT-Y4">V4L2_PIX_FMT_Y4</link>      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
+#define <link linkend="V4L2-PIX-FMT-Y6">V4L2_PIX_FMT_Y6</link>      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
+#define <link linkend="V4L2-PIX-FMT-Y10">V4L2_PIX_FMT_Y10</link>     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
 #define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 #define <link linkend="V4L2-PIX-FMT-Y16">V4L2_PIX_FMT_Y16</link>     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
 
 /* Palette formats */
 /* Palette formats */
@@ -330,7 +324,11 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link>  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
 #define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link>  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
 #define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link>  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
 #define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link>  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
 #define <link linkend="V4L2-PIX-FMT-SGRBG8">V4L2_PIX_FMT_SGRBG8</link>  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
 #define <link linkend="V4L2-PIX-FMT-SGRBG8">V4L2_PIX_FMT_SGRBG8</link>  v4l2_fourcc('G', 'R', 'B', 'G') /*  8  GRGR.. BGBG.. */
-#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10bit raw bayer */
+#define <link linkend="V4L2-PIX-FMT-SRGGB8">V4L2_PIX_FMT_SRGGB8</link>  v4l2_fourcc('R', 'G', 'G', 'B') /*  8  RGRG.. GBGB.. */
+#define <link linkend="V4L2-PIX-FMT-SBGGR10">V4L2_PIX_FMT_SBGGR10</link> v4l2_fourcc('B', 'G', '1', '0') /* 10  BGBG.. GRGR.. */
+#define <link linkend="V4L2-PIX-FMT-SGBRG10">V4L2_PIX_FMT_SGBRG10</link> v4l2_fourcc('G', 'B', '1', '0') /* 10  GBGB.. RGRG.. */
+#define <link linkend="V4L2-PIX-FMT-SGRBG10">V4L2_PIX_FMT_SGRBG10</link> v4l2_fourcc('B', 'A', '1', '0') /* 10  GRGR.. BGBG.. */
+#define <link linkend="V4L2-PIX-FMT-SRGGB10">V4L2_PIX_FMT_SRGGB10</link> v4l2_fourcc('R', 'G', '1', '0') /* 10  RGRG.. GBGB.. */
         /* 10bit raw bayer DPCM compressed to 8 bits */
         /* 10bit raw bayer DPCM compressed to 8 bits */
 #define <link linkend="V4L2-PIX-FMT-SGRBG10DPCM8">V4L2_PIX_FMT_SGRBG10DPCM8</link> v4l2_fourcc('B', 'D', '1', '0')
 #define <link linkend="V4L2-PIX-FMT-SGRBG10DPCM8">V4L2_PIX_FMT_SGRBG10DPCM8</link> v4l2_fourcc('B', 'D', '1', '0')
         /*
         /*
@@ -346,6 +344,7 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-MPEG">V4L2_PIX_FMT_MPEG</link>     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
 #define <link linkend="V4L2-PIX-FMT-MPEG">V4L2_PIX_FMT_MPEG</link>     v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4    */
 
 
 /*  Vendor-specific formats   */
 /*  Vendor-specific formats   */
+#define <link linkend="V4L2-PIX-FMT-CPIA1">V4L2_PIX_FMT_CPIA1</link>    v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
 #define <link linkend="V4L2-PIX-FMT-WNVA">V4L2_PIX_FMT_WNVA</link>     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
 #define <link linkend="V4L2-PIX-FMT-WNVA">V4L2_PIX_FMT_WNVA</link>     v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
 #define <link linkend="V4L2-PIX-FMT-SN9C10X">V4L2_PIX_FMT_SN9C10X</link>  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
 #define <link linkend="V4L2-PIX-FMT-SN9C10X">V4L2_PIX_FMT_SN9C10X</link>  v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
 #define <link linkend="V4L2-PIX-FMT-SN9C20X-I420">V4L2_PIX_FMT_SN9C20X_I420</link> v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
 #define <link linkend="V4L2-PIX-FMT-SN9C20X-I420">V4L2_PIX_FMT_SN9C20X_I420</link> v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
@@ -358,12 +357,15 @@ struct <link linkend="v4l2-pix-format">v4l2_pix_format</link> {
 #define <link linkend="V4L2-PIX-FMT-SPCA561">V4L2_PIX_FMT_SPCA561</link>  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
 #define <link linkend="V4L2-PIX-FMT-SPCA561">V4L2_PIX_FMT_SPCA561</link>  v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
 #define <link linkend="V4L2-PIX-FMT-PAC207">V4L2_PIX_FMT_PAC207</link>   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
 #define <link linkend="V4L2-PIX-FMT-PAC207">V4L2_PIX_FMT_PAC207</link>   v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
 #define <link linkend="V4L2-PIX-FMT-MR97310A">V4L2_PIX_FMT_MR97310A</link> v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
 #define <link linkend="V4L2-PIX-FMT-MR97310A">V4L2_PIX_FMT_MR97310A</link> v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
+#define <link linkend="V4L2-PIX-FMT-SN9C2028">V4L2_PIX_FMT_SN9C2028</link> v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
 #define <link linkend="V4L2-PIX-FMT-SQ905C">V4L2_PIX_FMT_SQ905C</link>   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
 #define <link linkend="V4L2-PIX-FMT-SQ905C">V4L2_PIX_FMT_SQ905C</link>   v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
 #define <link linkend="V4L2-PIX-FMT-PJPG">V4L2_PIX_FMT_PJPG</link>     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
 #define <link linkend="V4L2-PIX-FMT-PJPG">V4L2_PIX_FMT_PJPG</link>     v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
 #define <link linkend="V4L2-PIX-FMT-OV511">V4L2_PIX_FMT_OV511</link>    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
 #define <link linkend="V4L2-PIX-FMT-OV511">V4L2_PIX_FMT_OV511</link>    v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
 #define <link linkend="V4L2-PIX-FMT-OV518">V4L2_PIX_FMT_OV518</link>    v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
 #define <link linkend="V4L2-PIX-FMT-OV518">V4L2_PIX_FMT_OV518</link>    v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
-#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link>   v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
 #define <link linkend="V4L2-PIX-FMT-STV0680">V4L2_PIX_FMT_STV0680</link>  v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
 #define <link linkend="V4L2-PIX-FMT-STV0680">V4L2_PIX_FMT_STV0680</link>  v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
+#define <link linkend="V4L2-PIX-FMT-TM6000">V4L2_PIX_FMT_TM6000</link>   v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
+#define <link linkend="V4L2-PIX-FMT-CIT-YYVYUY">V4L2_PIX_FMT_CIT_YYVYUY</link> v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
+#define <link linkend="V4L2-PIX-FMT-KONICA420">V4L2_PIX_FMT_KONICA420</link>  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 
 
 /*
 /*
  *      F O R M A T   E N U M E R A T I O N
  *      F O R M A T   E N U M E R A T I O N
@@ -380,7 +382,7 @@ struct <link linkend="v4l2-fmtdesc">v4l2_fmtdesc</link> {
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 #define V4L2_FMT_FLAG_EMULATED   0x0002
 #define V4L2_FMT_FLAG_EMULATED   0x0002
 
 
-#if 1 /*KEEP*/
+#if 1
         /* Experimental Frame Size and frame rate enumeration */
         /* Experimental Frame Size and frame rate enumeration */
 /*
 /*
  *      F R A M E   S I Z E   E N U M E R A T I O N
  *      F R A M E   S I Z E   E N U M E R A T I O N
@@ -544,6 +546,8 @@ struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
 #define V4L2_BUF_FLAG_KEYFRAME  0x0008  /* Image is a keyframe (I-frame) */
 #define V4L2_BUF_FLAG_KEYFRAME  0x0008  /* Image is a keyframe (I-frame) */
 #define V4L2_BUF_FLAG_PFRAME    0x0010  /* Image is a P-frame */
 #define V4L2_BUF_FLAG_PFRAME    0x0010  /* Image is a P-frame */
 #define V4L2_BUF_FLAG_BFRAME    0x0020  /* Image is a B-frame */
 #define V4L2_BUF_FLAG_BFRAME    0x0020  /* Image is a B-frame */
+/* Buffer is ready, but the data contained within is corrupted. */
+#define V4L2_BUF_FLAG_ERROR     0x0040
 #define V4L2_BUF_FLAG_TIMECODE  0x0100  /* timecode field is valid */
 #define V4L2_BUF_FLAG_TIMECODE  0x0100  /* timecode field is valid */
 #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
 #define V4L2_BUF_FLAG_INPUT     0x0200  /* input field is valid */
 
 
@@ -934,6 +938,16 @@ struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link> {
 #define V4L2_CTRL_ID2CLASS(id)    ((id) &amp; 0x0fff0000UL)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) &amp; 0x0fff0000UL)
 #define V4L2_CTRL_DRIVER_PRIV(id) (((id) &amp; 0xffff) &gt;= 0x1000)
 #define V4L2_CTRL_DRIVER_PRIV(id) (((id) &amp; 0xffff) &gt;= 0x1000)
 
 
+enum <link linkend="v4l2-ctrl-type">v4l2_ctrl_type</link> {
+        V4L2_CTRL_TYPE_INTEGER       = 1,
+        V4L2_CTRL_TYPE_BOOLEAN       = 2,
+        V4L2_CTRL_TYPE_MENU          = 3,
+        V4L2_CTRL_TYPE_BUTTON        = 4,
+        V4L2_CTRL_TYPE_INTEGER64     = 5,
+        V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
+        V4L2_CTRL_TYPE_STRING        = 7,
+};
+
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
 struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link> {
 struct <link linkend="v4l2-queryctrl">v4l2_queryctrl</link> {
         __u32                id;
         __u32                id;
@@ -1018,21 +1032,27 @@ enum <link linkend="v4l2-colorfx">v4l2_colorfx</link> {
         V4L2_COLORFX_NONE       = 0,
         V4L2_COLORFX_NONE       = 0,
         V4L2_COLORFX_BW         = 1,
         V4L2_COLORFX_BW         = 1,
         V4L2_COLORFX_SEPIA      = 2,
         V4L2_COLORFX_SEPIA      = 2,
-        V4L2_COLORFX_NEGATIVE   = 3,
-        V4L2_COLORFX_EMBOSS     = 4,
-        V4L2_COLORFX_SKETCH     = 5,
-        V4L2_COLORFX_SKY_BLUE   = 6,
+        V4L2_COLORFX_NEGATIVE = 3,
+        V4L2_COLORFX_EMBOSS = 4,
+        V4L2_COLORFX_SKETCH = 5,
+        V4L2_COLORFX_SKY_BLUE = 6,
         V4L2_COLORFX_GRASS_GREEN = 7,
         V4L2_COLORFX_GRASS_GREEN = 7,
         V4L2_COLORFX_SKIN_WHITEN = 8,
         V4L2_COLORFX_SKIN_WHITEN = 8,
-        V4L2_COLORFX_VIVID      = 9.
+        V4L2_COLORFX_VIVID = 9,
 };
 };
 #define V4L2_CID_AUTOBRIGHTNESS                 (V4L2_CID_BASE+32)
 #define V4L2_CID_AUTOBRIGHTNESS                 (V4L2_CID_BASE+32)
 #define V4L2_CID_BAND_STOP_FILTER               (V4L2_CID_BASE+33)
 #define V4L2_CID_BAND_STOP_FILTER               (V4L2_CID_BASE+33)
 
 
 #define V4L2_CID_ROTATE                         (V4L2_CID_BASE+34)
 #define V4L2_CID_ROTATE                         (V4L2_CID_BASE+34)
 #define V4L2_CID_BG_COLOR                       (V4L2_CID_BASE+35)
 #define V4L2_CID_BG_COLOR                       (V4L2_CID_BASE+35)
+
+#define V4L2_CID_CHROMA_GAIN                    (V4L2_CID_BASE+36)
+
+#define V4L2_CID_ILLUMINATORS_1                 (V4L2_CID_BASE+37)
+#define V4L2_CID_ILLUMINATORS_2                 (V4L2_CID_BASE+38)
+
 /* last CID + 1 */
 /* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+36)
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+39)
 
 
 /*  MPEG-class control IDs defined by V4L2 */
 /*  MPEG-class control IDs defined by V4L2 */
 #define V4L2_CID_MPEG_BASE                      (V4L2_CTRL_CLASS_MPEG | 0x900)
 #define V4L2_CID_MPEG_BASE                      (V4L2_CTRL_CLASS_MPEG | 0x900)
@@ -1349,6 +1369,8 @@ struct <link linkend="v4l2-modulator">v4l2_modulator</link> {
 #define V4L2_TUNER_CAP_SAP              0x0020
 #define V4L2_TUNER_CAP_SAP              0x0020
 #define V4L2_TUNER_CAP_LANG1            0x0040
 #define V4L2_TUNER_CAP_LANG1            0x0040
 #define V4L2_TUNER_CAP_RDS              0x0080
 #define V4L2_TUNER_CAP_RDS              0x0080
+#define V4L2_TUNER_CAP_RDS_BLOCK_IO     0x0100
+#define V4L2_TUNER_CAP_RDS_CONTROLS     0x0200
 
 
 /*  Flags for the 'rxsubchans' field */
 /*  Flags for the 'rxsubchans' field */
 #define V4L2_TUNER_SUB_MONO             0x0001
 #define V4L2_TUNER_SUB_MONO             0x0001
@@ -1378,7 +1400,8 @@ struct <link linkend="v4l2-hw-freq-seek">v4l2_hw_freq_seek</link> {
         enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
         enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link>  type;
         __u32                 seek_upward;
         __u32                 seek_upward;
         __u32                 wrap_around;
         __u32                 wrap_around;
-        __u32                 reserved[8];
+        __u32                 spacing;
+        __u32                 reserved[7];
 };
 };
 
 
 /*
 /*
@@ -1433,7 +1456,7 @@ struct <link linkend="v4l2-audioout">v4l2_audioout</link> {
  *
  *
  *      NOTE: EXPERIMENTAL API
  *      NOTE: EXPERIMENTAL API
  */
  */
-#if 1 /*KEEP*/
+#if 1
 #define V4L2_ENC_IDX_FRAME_I    (0)
 #define V4L2_ENC_IDX_FRAME_I    (0)
 #define V4L2_ENC_IDX_FRAME_P    (1)
 #define V4L2_ENC_IDX_FRAME_P    (1)
 #define V4L2_ENC_IDX_FRAME_B    (2)
 #define V4L2_ENC_IDX_FRAME_B    (2)
@@ -1625,6 +1648,38 @@ struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
         } parm;
         } parm;
 };
 };
 
 
+/*
+ *      E V E N T S
+ */
+
+#define V4L2_EVENT_ALL                          0
+#define V4L2_EVENT_VSYNC                        1
+#define V4L2_EVENT_EOS                          2
+#define V4L2_EVENT_PRIVATE_START                0x08000000
+
+/* Payload for V4L2_EVENT_VSYNC */
+struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> {
+        /* Can be V4L2_FIELD_ANY, _NONE, _TOP or _BOTTOM */
+        __u8 field;
+} __attribute__ ((packed));
+
+struct <link linkend="v4l2-event">v4l2_event</link> {
+        __u32                           type;
+        union {
+                struct <link linkend="v4l2-event-vsync">v4l2_event_vsync</link> vsync;
+                __u8                    data[64];
+        } u;
+        __u32                           pending;
+        __u32                           sequence;
+        struct timespec                 timestamp;
+        __u32                           reserved[9];
+};
+
+struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link> {
+        __u32                           type;
+        __u32                           reserved[7];
+};
+
 /*
 /*
  *      A D V A N C E D   D E B U G G I N G
  *      A D V A N C E D   D E B U G G I N G
  *
  *
@@ -1720,7 +1775,7 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
 #define VIDIOC_G_EXT_CTRLS      _IOWR('V', 71, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
 #define VIDIOC_G_EXT_CTRLS      _IOWR('V', 71, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
 #define VIDIOC_S_EXT_CTRLS      _IOWR('V', 72, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
 #define VIDIOC_S_EXT_CTRLS      _IOWR('V', 72, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
 #define VIDIOC_TRY_EXT_CTRLS    _IOWR('V', 73, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
 #define VIDIOC_TRY_EXT_CTRLS    _IOWR('V', 73, struct <link linkend="v4l2-ext-controls">v4l2_ext_controls</link>)
-#if 1 /*KEEP*/
+#if 1
 #define VIDIOC_ENUM_FRAMESIZES  _IOWR('V', 74, struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link>)
 #define VIDIOC_ENUM_FRAMESIZES  _IOWR('V', 74, struct <link linkend="v4l2-frmsizeenum">v4l2_frmsizeenum</link>)
 #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link>)
 #define VIDIOC_ENUM_FRAMEINTERVALS _IOWR('V', 75, struct <link linkend="v4l2-frmivalenum">v4l2_frmivalenum</link>)
 #define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link>)
 #define VIDIOC_G_ENC_INDEX       _IOR('V', 76, struct <link linkend="v4l2-enc-idx">v4l2_enc_idx</link>)
@@ -1728,7 +1783,7 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
 #define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
 #define VIDIOC_TRY_ENCODER_CMD  _IOWR('V', 78, struct <link linkend="v4l2-encoder-cmd">v4l2_encoder_cmd</link>)
 #endif
 #endif
 
 
-#if 1 /*KEEP*/
+#if 1
 /* Experimental, meant for debugging, testing and internal use.
 /* Experimental, meant for debugging, testing and internal use.
    Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
    Only implemented if CONFIG_VIDEO_ADV_DEBUG is defined.
    You must be root to use these ioctls. Never use these in applications! */
    You must be root to use these ioctls. Never use these in applications! */
@@ -1747,6 +1802,9 @@ struct <link linkend="v4l2-dbg-chip-ident">v4l2_dbg_chip_ident</link> {
 #define VIDIOC_QUERY_DV_PRESET  _IOR('V',  86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
 #define VIDIOC_QUERY_DV_PRESET  _IOR('V',  86, struct <link linkend="v4l2-dv-preset">v4l2_dv_preset</link>)
 #define VIDIOC_S_DV_TIMINGS     _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
 #define VIDIOC_S_DV_TIMINGS     _IOWR('V', 87, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
 #define VIDIOC_G_DV_TIMINGS     _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
 #define VIDIOC_G_DV_TIMINGS     _IOWR('V', 88, struct <link linkend="v4l2-dv-timings">v4l2_dv_timings</link>)
+#define VIDIOC_DQEVENT           _IOR('V', 89, struct <link linkend="v4l2-event">v4l2_event</link>)
+#define VIDIOC_SUBSCRIBE_EVENT   _IOW('V', 90, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
+#define VIDIOC_UNSUBSCRIBE_EVENT _IOW('V', 91, struct <link linkend="v4l2-event-subscription">v4l2_event_subscription</link>)
 
 
 /* Reminder: when adding new ioctls please add support for them to
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
    drivers/media/video/v4l2-compat-ioctl32.c as well! */

+ 1 - 2
Documentation/DocBook/v4l/vidioc-g-dv-preset.xml

@@ -16,8 +16,7 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>&v4l2-dv-preset;
-*<parameter>argp</parameter></paramdef>
+	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
       </funcprototype>
       </funcprototype>
     </funcsynopsis>
     </funcsynopsis>
   </refsynopsisdiv>
   </refsynopsisdiv>

+ 1 - 2
Documentation/DocBook/v4l/vidioc-g-dv-timings.xml

@@ -16,8 +16,7 @@
 	<funcdef>int <function>ioctl</function></funcdef>
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>&v4l2-dv-timings;
-*<parameter>argp</parameter></paramdef>
+	<paramdef>struct v4l2_dv_timings *<parameter>argp</parameter></paramdef>
       </funcprototype>
       </funcprototype>
     </funcsynopsis>
     </funcsynopsis>
   </refsynopsisdiv>
   </refsynopsisdiv>

+ 1 - 1
Documentation/DocBook/v4l/vidioc-query-dv-preset.xml

@@ -16,7 +16,7 @@ input</refpurpose>
 	<funcdef>int <function>ioctl</function></funcdef>
 	<funcdef>int <function>ioctl</function></funcdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>fd</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
 	<paramdef>int <parameter>request</parameter></paramdef>
-	<paramdef>&v4l2-dv-preset; *<parameter>argp</parameter></paramdef>
+	<paramdef>struct v4l2_dv_preset *<parameter>argp</parameter></paramdef>
       </funcprototype>
       </funcprototype>
     </funcsynopsis>
     </funcsynopsis>
   </refsynopsisdiv>
   </refsynopsisdiv>

+ 6 - 1
Documentation/DocBook/v4l/vidioc-querycap.xml

@@ -184,7 +184,7 @@ data.</entry>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CAP_RDS_CAPTURE</constant></entry>
 	    <entry><constant>V4L2_CAP_RDS_CAPTURE</constant></entry>
 	    <entry>0x00000100</entry>
 	    <entry>0x00000100</entry>
-	    <entry>The device supports the <link linkend="rds">RDS</link> interface.</entry>
+	    <entry>The device supports the <link linkend="rds">RDS</link> capture interface.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant></entry>
 	    <entry><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant></entry>
@@ -205,6 +205,11 @@ driver capabilities.</para></footnote></entry>
 	    <entry>The device supports the &VIDIOC-S-HW-FREQ-SEEK; ioctl for
 	    <entry>The device supports the &VIDIOC-S-HW-FREQ-SEEK; ioctl for
 hardware frequency seeking.</entry>
 hardware frequency seeking.</entry>
 	  </row>
 	  </row>
+	  <row>
+	    <entry><constant>V4L2_CAP_RDS_OUTPUT</constant></entry>
+	    <entry>0x00000800</entry>
+	    <entry>The device supports the <link linkend="rds">RDS</link> output interface.</entry>
+	  </row>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CAP_TUNER</constant></entry>
 	    <entry><constant>V4L2_CAP_TUNER</constant></entry>
 	    <entry>0x00010000</entry>
 	    <entry>0x00010000</entry>

+ 12 - 6
Documentation/DocBook/v4l/vidioc-queryctrl.xml

@@ -103,8 +103,12 @@ structure. The driver fills the rest of the structure or returns an
 <structfield>index</structfield> is invalid. Menu items are enumerated
 <structfield>index</structfield> is invalid. Menu items are enumerated
 by calling <constant>VIDIOC_QUERYMENU</constant> with successive
 by calling <constant>VIDIOC_QUERYMENU</constant> with successive
 <structfield>index</structfield> values from &v4l2-queryctrl;
 <structfield>index</structfield> values from &v4l2-queryctrl;
-<structfield>minimum</structfield> (0) to
-<structfield>maximum</structfield>, inclusive.</para>
+<structfield>minimum</structfield> to
+<structfield>maximum</structfield>, inclusive. Note that it is possible
+for <constant>VIDIOC_QUERYMENU</constant> to return an &EINVAL; for some
+indices between <structfield>minimum</structfield> and <structfield>maximum</structfield>.
+In that case that particular menu item is not supported by this driver. Also note that
+the <structfield>minimum</structfield> value is not necessarily 0.</para>
 
 
     <para>See also the examples in <xref linkend="control" />.</para>
     <para>See also the examples in <xref linkend="control" />.</para>
 
 
@@ -139,7 +143,7 @@ string. This information is intended for the user.</entry>
 	    <entry><structfield>minimum</structfield></entry>
 	    <entry><structfield>minimum</structfield></entry>
 	    <entry>Minimum value, inclusive. This field gives a lower
 	    <entry>Minimum value, inclusive. This field gives a lower
 bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
 bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-lowest valid index (always 0) for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
+lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
 For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
 For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
 gives the minimum length of the string. This length <emphasis>does not include the terminating
 gives the minimum length of the string. This length <emphasis>does not include the terminating
 zero</emphasis>. It may not be valid for any other type of control, including
 zero</emphasis>. It may not be valid for any other type of control, including
@@ -279,7 +283,7 @@ values which are actually different on the hardware.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry><constant>V4L2_CTRL_TYPE_MENU</constant></entry>
 	    <entry><constant>V4L2_CTRL_TYPE_MENU</constant></entry>
-	    <entry>0</entry>
+	    <entry>&ge; 0</entry>
 	    <entry>1</entry>
 	    <entry>1</entry>
 	    <entry>N-1</entry>
 	    <entry>N-1</entry>
 	    <entry>The control has a menu of N choices. The names of
 	    <entry>The control has a menu of N choices. The names of
@@ -405,8 +409,10 @@ writing a value will cause the device to carry out a given action
 	<term><errorcode>EINVAL</errorcode></term>
 	<term><errorcode>EINVAL</errorcode></term>
 	<listitem>
 	<listitem>
 	  <para>The &v4l2-queryctrl; <structfield>id</structfield>
 	  <para>The &v4l2-queryctrl; <structfield>id</structfield>
-is invalid. The &v4l2-querymenu; <structfield>id</structfield> or
-<structfield>index</structfield> is invalid.</para>
+is invalid. The &v4l2-querymenu; <structfield>id</structfield> is
+invalid or <structfield>index</structfield> is out of range (less than
+<structfield>minimum</structfield> or greater than <structfield>maximum</structfield>)
+or this particular menu item is not supported by the driver.</para>
 	</listitem>
 	</listitem>
       </varlistentry>
       </varlistentry>
       <varlistentry>
       <varlistentry>

+ 8 - 2
Documentation/DocBook/v4l/vidioc-s-hw-freq-seek.xml

@@ -51,7 +51,8 @@
 
 
     <para>Start a hardware frequency seek from the current frequency.
     <para>Start a hardware frequency seek from the current frequency.
 To do this applications initialize the <structfield>tuner</structfield>,
 To do this applications initialize the <structfield>tuner</structfield>,
-<structfield>type</structfield>, <structfield>seek_upward</structfield> and
+<structfield>type</structfield>, <structfield>seek_upward</structfield>,
+<structfield>spacing</structfield> and
 <structfield>wrap_around</structfield> fields, and zero out the
 <structfield>wrap_around</structfield> fields, and zero out the
 <structfield>reserved</structfield> array of a &v4l2-hw-freq-seek; and
 <structfield>reserved</structfield> array of a &v4l2-hw-freq-seek; and
 call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
 call the <constant>VIDIOC_S_HW_FREQ_SEEK</constant> ioctl with a pointer
@@ -89,7 +90,12 @@ field and the &v4l2-tuner; <structfield>index</structfield> field.</entry>
 	  </row>
 	  </row>
 	  <row>
 	  <row>
 	    <entry>__u32</entry>
 	    <entry>__u32</entry>
-	    <entry><structfield>reserved</structfield>[8]</entry>
+	    <entry><structfield>spacing</structfield></entry>
+	    <entry>If non-zero, defines the hardware seek resolution in Hz. The driver selects the nearest value that is supported by the device. If spacing is zero a reasonable default value is used.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[7]</entry>
 	    <entry>Reserved for future extensions. Drivers and
 	    <entry>Reserved for future extensions. Drivers and
 	    applications must set the array to zero.</entry>
 	    applications must set the array to zero.</entry>
 	  </row>
 	  </row>

+ 0 - 3
Documentation/devices.txt

@@ -1496,9 +1496,6 @@ Your cooperation is appreciated.
 		 64 = /dev/radio0	Radio device
 		 64 = /dev/radio0	Radio device
 		    ...
 		    ...
 		127 = /dev/radio63	Radio device
 		127 = /dev/radio63	Radio device
-		192 = /dev/vtx0		Teletext device
-		    ...
-		223 = /dev/vtx31	Teletext device
 		224 = /dev/vbi0		Vertical blank interrupt
 		224 = /dev/vbi0		Vertical blank interrupt
 		    ...
 		    ...
 		255 = /dev/vbi31	Vertical blank interrupt
 		255 = /dev/vbi31	Vertical blank interrupt

+ 45 - 1
Documentation/dvb/get_dvb_firmware

@@ -26,7 +26,8 @@ use IO::Handle;
 		"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
 		"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
-		"af9015", "ngene", "az6027");
+		"af9015", "ngene", "az6027", "lme2510_lg", "lme2510c_s7395",
+		"lme2510c_s7395_old");
 
 
 # Check args
 # Check args
 syntax() if (scalar(@ARGV) != 1);
 syntax() if (scalar(@ARGV) != 1);
@@ -584,6 +585,49 @@ sub az6027{
 
 
     $firmware;
     $firmware;
 }
 }
+
+sub lme2510_lg {
+    my $sourcefile = "LMEBDA_DVBS.sys";
+    my $hash = "fc6017ad01e79890a97ec53bea157ed2";
+    my $outfile = "dvb-usb-lme2510-lg.fw";
+    my $hasho = "caa065d5fdbd2c09ad57b399bbf55cad";
+
+    checkstandard();
+
+    verify($sourcefile, $hash);
+    extract($sourcefile, 4168, 3841, $outfile);
+    verify($outfile, $hasho);
+    $outfile;
+}
+
+sub lme2510c_s7395 {
+    my $sourcefile = "US2A0D.sys";
+    my $hash = "b0155a8083fb822a3bd47bc360e74601";
+    my $outfile = "dvb-usb-lme2510c-s7395.fw";
+    my $hasho = "3a3cf1aeebd17b6ddc04cebe131e94cf";
+
+    checkstandard();
+
+    verify($sourcefile, $hash);
+    extract($sourcefile, 37248, 3720, $outfile);
+    verify($outfile, $hasho);
+    $outfile;
+}
+
+sub lme2510c_s7395_old {
+    my $sourcefile = "LMEBDA_DVBS7395C.sys";
+    my $hash = "7572ae0eb9cdf91baabd7c0ba9e09b31";
+    my $outfile = "dvb-usb-lme2510c-s7395.fw";
+    my $hasho = "90430c5b435eb5c6f88fd44a9d950674";
+
+    checkstandard();
+
+    verify($sourcefile, $hash);
+    extract($sourcefile, 4208, 3881, $outfile);
+    verify($outfile, $hasho);
+    $outfile;
+}
+
 # ---------------------------------------------------------------
 # ---------------------------------------------------------------
 # Utilities
 # Utilities
 
 

+ 58 - 0
Documentation/dvb/lmedm04.txt

@@ -0,0 +1,58 @@
+To extract firmware for the DM04/QQBOX you need to copy the
+following file(s) to this directory.
+
+for DM04+/QQBOX LME2510C (Sharp 7395 Tuner)
+-------------------------------------------
+
+The Sharp 7395 driver can be found in windows/system32/driver
+
+US2A0D.sys (dated 17 Mar 2009)
+
+
+and run
+./get_dvb_firmware lme2510c_s7395
+
+	will produce
+	dvb-usb-lme2510c-s7395.fw
+
+An alternative but older firmware can be found on the driver
+disk DVB-S_EN_3.5A in BDADriver/driver
+
+LMEBDA_DVBS7395C.sys (dated 18 Jan 2008)
+
+and run
+./get_dvb_firmware lme2510c_s7395_old
+
+	will produce
+	dvb-usb-lme2510c-s7395.fw
+
+--------------------------------------------------------------------
+
+The LG firmware can be found on the driver
+disk DM04+_5.1A[LG] in BDADriver/driver
+
+for DM04 LME2510 (LG Tuner)
+---------------------------
+
+LMEBDA_DVBS.sys (dated 13 Nov 2007)
+
+and run
+./get_dvb_firmware lme2510_lg
+
+	will produce
+	dvb-usb-lme2510-lg.fw
+
+
+Other LG firmware can be extracted manually from US280D.sys
+only found in windows/system32/driver.
+
+dd if=US280D.sys ibs=1 skip=42616 count=3668 of=dvb-usb-lme2510-lg.fw
+
+for DM04 LME2510C (LG Tuner)
+---------------------------
+
+dd if=US280D.sys ibs=1 skip=35200 count=3850 of=dvb-usb-lme2510c-lg.fw
+
+---------------------------------------------------------------------
+
+Copy the firmware file(s) to /lib/firmware

+ 16 - 24
Documentation/feature-removal-schedule.txt

@@ -98,7 +98,7 @@ Who:	Pavel Machek <pavel@ucw.cz>
 ---------------------------
 ---------------------------
 
 
 What:	Video4Linux API 1 ioctls and from Video devices.
 What:	Video4Linux API 1 ioctls and from Video devices.
-When:	July 2009
+When:	kernel 2.6.38
 Files:	include/linux/videodev.h
 Files:	include/linux/videodev.h
 Check:	include/linux/videodev.h
 Check:	include/linux/videodev.h
 Why:	V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
 Why:	V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
@@ -116,6 +116,21 @@ Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
 
 
 ---------------------------
 ---------------------------
 
 
+What:	Video4Linux obsolete drivers using V4L1 API
+When:	kernel 2.6.38
+Files:	drivers/staging/cpia/* drivers/staging/stradis/*
+Check:	drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
+Why:	There are some drivers still using V4L1 API, despite all efforts we've done
+	to migrate. Those drivers are for obsolete hardware that the old maintainer
+	didn't care (or not have the hardware anymore), and that no other developer
+	could find any hardware to buy. They probably have no practical usage today,
+	and people with such old hardware could probably keep using an older version
+	of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
+	care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
+Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
+
+---------------------------
+
 What:	sys_sysctl
 What:	sys_sysctl
 When:	September 2010
 When:	September 2010
 Option: CONFIG_SYSCTL_SYSCALL
 Option: CONFIG_SYSCTL_SYSCALL
@@ -470,29 +485,6 @@ When:	April 2011
 Why:	Superseded by xt_CT
 Why:	Superseded by xt_CT
 Who:	Netfilter developer team <netfilter-devel@vger.kernel.org>
 Who:	Netfilter developer team <netfilter-devel@vger.kernel.org>
 
 
----------------------------
-
-What:	video4linux /dev/vtx teletext API support
-When:	2.6.35
-Files:	drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
-	include/linux/videotext.h
-Why:	The vtx device nodes have been superseded by vbi device nodes
-	for many years. No applications exist that use the vtx support.
-	Of the two i2c drivers that actually support this API the saa5249
-	has been impossible to use for a year now and no known hardware
-	that supports this device exists. The saa5246a is theoretically
-	supported by the old mxb boards, but it never actually worked.
-
-	In summary: there is no hardware that can use this API and there
-	are no applications actually implementing this API.
-
-	The vtx support still reserves minors 192-223 and we would really
-	like to reuse those for upcoming new functionality. In the unlikely
-	event that new hardware appears that wants to use the functionality
-	provided by the vtx API, then that functionality should be build
-	around the sliced VBI API instead.
-Who:	Hans Verkuil <hverkuil@xs4all.nl>
-
 ----------------------------
 ----------------------------
 
 
 What:	IRQF_DISABLED
 What:	IRQF_DISABLED

+ 0 - 1
Documentation/ioctl/ioctl-number.txt

@@ -278,7 +278,6 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:oe@port.de>
 					<mailto:oe@port.de>
 'z'	10-4F	drivers/s390/crypto/zcrypt_api.h	conflict!
 'z'	10-4F	drivers/s390/crypto/zcrypt_api.h	conflict!
 0x80	00-1F	linux/fb.h
 0x80	00-1F	linux/fb.h
-0x81	00-1F	linux/videotext.h
 0x88	00-3F	media/ovcamchip.h
 0x88	00-3F	media/ovcamchip.h
 0x89	00-06	arch/x86/include/asm/sockios.h
 0x89	00-06	arch/x86/include/asm/sockios.h
 0x89	0B-DF	linux/sockios.h
 0x89	0B-DF	linux/sockios.h

+ 1 - 0
Documentation/video4linux/CARDLIST.cx88

@@ -83,3 +83,4 @@
  82 -> WinFast DTV2000 H rev. J                            [107d:6f2b]
  82 -> WinFast DTV2000 H rev. J                            [107d:6f2b]
  83 -> Prof 7301 DVB-S/S2                                  [b034:3034]
  83 -> Prof 7301 DVB-S/S2                                  [b034:3034]
  84 -> Samsung SMT 7020 DVB-S                              [18ac:dc00,18ac:dccd]
  84 -> Samsung SMT 7020 DVB-S                              [18ac:dc00,18ac:dccd]
+ 85 -> Twinhan VP-1027 DVB-S                               [1822:0023]

+ 2 - 1
Documentation/video4linux/CARDLIST.em28xx

@@ -31,6 +31,7 @@
  30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
  30 -> Videology 20K14XUSB USB2.0               (em2820/em2840)
  31 -> Usbgear VD204v9                          (em2821)
  31 -> Usbgear VD204v9                          (em2821)
  32 -> Supercomp USB 2.0 TV                     (em2821)
  32 -> Supercomp USB 2.0 TV                     (em2821)
+ 33 -> Elgato Video Capture                     (em2860)        [0fd9:0033]
  34 -> Terratec Cinergy A Hybrid XS             (em2860)        [0ccd:004f]
  34 -> Terratec Cinergy A Hybrid XS             (em2860)        [0ccd:004f]
  35 -> Typhoon DVD Maker                        (em2860)
  35 -> Typhoon DVD Maker                        (em2860)
  36 -> NetGMBH Cam                              (em2860)
  36 -> NetGMBH Cam                              (em2860)
@@ -45,7 +46,7 @@
  45 -> Pinnacle PCTV DVB-T                      (em2870)
  45 -> Pinnacle PCTV DVB-T                      (em2870)
  46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
  46 -> Compro, VideoMate U3                     (em2870)        [185b:2870]
  47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305]
  47 -> KWorld DVB-T 305U                        (em2880)        [eb1a:e305]
- 48 -> KWorld DVB-T 310U                        (em2880)        [eb1a:e310]
+ 48 -> KWorld DVB-T 310U                        (em2880)
  49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]
  49 -> MSI DigiVox A/D                          (em2880)        [eb1a:e310]
  50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
  50 -> MSI DigiVox A/D II                       (em2880)        [eb1a:e320]
  51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]
  51 -> Terratec Hybrid XS Secam                 (em2880)        [0ccd:004c]

+ 1 - 1
Documentation/video4linux/CARDLIST.saa7134

@@ -126,7 +126,7 @@
 125 -> Beholder BeholdTV 409                    [0000:4090]
 125 -> Beholder BeholdTV 409                    [0000:4090]
 126 -> Beholder BeholdTV 505 FM                 [5ace:5050]
 126 -> Beholder BeholdTV 505 FM                 [5ace:5050]
 127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
 127 -> Beholder BeholdTV 507 FM / BeholdTV 509 FM [5ace:5070,5ace:5090]
-128 -> Beholder BeholdTV Columbus TVFM          [0000:5201]
+128 -> Beholder BeholdTV Columbus TV/FM         [0000:5201]
 129 -> Beholder BeholdTV 607 FM                 [5ace:6070]
 129 -> Beholder BeholdTV 607 FM                 [5ace:6070]
 130 -> Beholder BeholdTV M6                     [5ace:6190]
 130 -> Beholder BeholdTV M6                     [5ace:6190]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]
 131 -> Twinhan Hybrid DTV-DVB 3056 PCI          [1822:0022]

+ 0 - 1
Documentation/video4linux/bttv/MAKEDEV

@@ -19,7 +19,6 @@ function makedev () {
 echo "*** new device names ***"
 echo "*** new device names ***"
 makedev video 0
 makedev video 0
 makedev radio 64
 makedev radio 64
-makedev vtx 192
 makedev vbi 224
 makedev vbi 224
 
 
 #echo "*** old device names (for compatibility only) ***"
 #echo "*** old device names (for compatibility only) ***"

+ 2 - 0
Documentation/video4linux/gspca.txt

@@ -302,12 +302,14 @@ sonixj		0c45:60fb	Surfer NoName
 sonixj		0c45:60fc	LG-LIC300
 sonixj		0c45:60fc	LG-LIC300
 sonixj		0c45:60fe	Microdia Audio
 sonixj		0c45:60fe	Microdia Audio
 sonixj		0c45:6100	PC Camera (SN9C128)
 sonixj		0c45:6100	PC Camera (SN9C128)
+sonixj		0c45:6102	PC Camera (SN9C128)
 sonixj		0c45:610a	PC Camera (SN9C128)
 sonixj		0c45:610a	PC Camera (SN9C128)
 sonixj		0c45:610b	PC Camera (SN9C128)
 sonixj		0c45:610b	PC Camera (SN9C128)
 sonixj		0c45:610c	PC Camera (SN9C128)
 sonixj		0c45:610c	PC Camera (SN9C128)
 sonixj		0c45:610e	PC Camera (SN9C128)
 sonixj		0c45:610e	PC Camera (SN9C128)
 sonixj		0c45:6128	Microdia/Sonix SNP325
 sonixj		0c45:6128	Microdia/Sonix SNP325
 sonixj		0c45:612a	Avant Camera
 sonixj		0c45:612a	Avant Camera
+sonixj		0c45:612b	Speed-Link REFLECT2
 sonixj		0c45:612c	Typhoon Rasy Cam 1.3MPix
 sonixj		0c45:612c	Typhoon Rasy Cam 1.3MPix
 sonixj		0c45:6130	Sonix Pccam
 sonixj		0c45:6130	Sonix Pccam
 sonixj		0c45:6138	Sn9c120 Mo4000
 sonixj		0c45:6138	Sn9c120 Mo4000

+ 29 - 6
Documentation/video4linux/v4l2-framework.txt

@@ -44,8 +44,8 @@ All drivers have the following structure:
 
 
 2) A way of initializing and commanding sub-devices (if any).
 2) A way of initializing and commanding sub-devices (if any).
 
 
-3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX, /dev/radioX and
-   /dev/vtxX) and keeping track of device-node specific data.
+3) Creating V4L2 device nodes (/dev/videoX, /dev/vbiX and /dev/radioX)
+   and keeping track of device-node specific data.
 
 
 4) Filehandle-specific structs containing per-filehandle data;
 4) Filehandle-specific structs containing per-filehandle data;
 
 
@@ -192,6 +192,11 @@ You also need a way to go from the low-level struct to v4l2_subdev. For the
 common i2c_client struct the i2c_set_clientdata() call is used to store a
 common i2c_client struct the i2c_set_clientdata() call is used to store a
 v4l2_subdev pointer, for other busses you may have to use other methods.
 v4l2_subdev pointer, for other busses you may have to use other methods.
 
 
+Bridges might also need to store per-subdev private data, such as a pointer to
+bridge-specific per-subdev private data. The v4l2_subdev structure provides
+host private data for that purpose that can be accessed with
+v4l2_get_subdev_hostdata() and v4l2_set_subdev_hostdata().
+
 From the bridge driver perspective you load the sub-device module and somehow
 From the bridge driver perspective you load the sub-device module and somehow
 obtain the v4l2_subdev pointer. For i2c devices this is easy: you call
 obtain the v4l2_subdev pointer. For i2c devices this is easy: you call
 i2c_get_clientdata(). For other busses something similar needs to be done.
 i2c_get_clientdata(). For other busses something similar needs to be done.
@@ -448,6 +453,10 @@ You should also set these fields:
 - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
 - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
   (highly recommended to use this and it might become compulsory in the
   (highly recommended to use this and it might become compulsory in the
   future!), then set this to your v4l2_ioctl_ops struct.
   future!), then set this to your v4l2_ioctl_ops struct.
+- lock: leave to NULL if you want to do all the locking in the driver.
+  Otherwise you give it a pointer to a struct mutex_lock and before any
+  of the v4l2_file_operations is called this lock will be taken by the
+  core and released afterwards.
 - parent: you only set this if v4l2_device was registered with NULL as
 - parent: you only set this if v4l2_device was registered with NULL as
   the parent device struct. This only happens in cases where one hardware
   the parent device struct. This only happens in cases where one hardware
   device has multiple PCI devices that all share the same v4l2_device core.
   device has multiple PCI devices that all share the same v4l2_device core.
@@ -464,6 +473,22 @@ If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
 The v4l2_file_operations struct is a subset of file_operations. The main
 The v4l2_file_operations struct is a subset of file_operations. The main
 difference is that the inode argument is omitted since it is never used.
 difference is that the inode argument is omitted since it is never used.
 
 
+v4l2_file_operations and locking
+--------------------------------
+
+You can set a pointer to a mutex_lock in struct video_device. Usually this
+will be either a top-level mutex or a mutex per device node. If you want
+finer-grained locking then you have to set it to NULL and do you own locking.
+
+If a lock is specified then all file operations will be serialized on that
+lock. If you use videobuf then you must pass the same lock to the videobuf
+queue initialize function: if videobuf has to wait for a frame to arrive, then
+it will temporarily unlock the lock and relock it afterwards. If your driver
+also waits in the code, then you should do the same to allow other processes
+to access the device node while the first process is waiting for something.
+
+The implementation of a hotplug disconnect should also take the lock before
+calling v4l2_device_disconnect.
 
 
 video_device registration
 video_device registration
 -------------------------
 -------------------------
@@ -483,7 +508,6 @@ types exist:
 VFL_TYPE_GRABBER: videoX for video input/output devices
 VFL_TYPE_GRABBER: videoX for video input/output devices
 VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext)
 VFL_TYPE_VBI: vbiX for vertical blank data (i.e. closed captions, teletext)
 VFL_TYPE_RADIO: radioX for radio tuners
 VFL_TYPE_RADIO: radioX for radio tuners
-VFL_TYPE_VTX: vtxX for teletext devices (deprecated, don't use)
 
 
 The last argument gives you a certain amount of control over the device
 The last argument gives you a certain amount of control over the device
 device node number used (i.e. the X in videoX). Normally you will pass -1
 device node number used (i.e. the X in videoX). Normally you will pass -1
@@ -547,9 +571,8 @@ from /dev).
 
 
 After video_unregister_device() returns no new opens can be done. However,
 After video_unregister_device() returns no new opens can be done. However,
 in the case of USB devices some application might still have one of these
 in the case of USB devices some application might still have one of these
-device nodes open. So after the unregister all file operations will return
-an error as well, except for the ioctl and unlocked_ioctl file operations:
-those will still be passed on since some buffer ioctls may still be needed.
+device nodes open. So after the unregister all file operations (except
+release, of course) will return an error as well.
 
 
 When the last user of the video device node exits, then the vdev->release()
 When the last user of the video device node exits, then the vdev->release()
 callback is called and you can do the final cleanup there.
 callback is called and you can do the final cleanup there.

+ 0 - 2
arch/arm/mach-mx3/mach-pcm037.c

@@ -311,7 +311,6 @@ static struct soc_camera_link iclink_mt9v022 = {
 	.bus_id		= 0,		/* Must match with the camera ID */
 	.bus_id		= 0,		/* Must match with the camera ID */
 	.board_info	= &pcm037_i2c_camera[1],
 	.board_info	= &pcm037_i2c_camera[1],
 	.i2c_adapter_id	= 2,
 	.i2c_adapter_id	= 2,
-	.module_name	= "mt9v022",
 };
 };
 
 
 static struct soc_camera_link iclink_mt9t031 = {
 static struct soc_camera_link iclink_mt9t031 = {
@@ -319,7 +318,6 @@ static struct soc_camera_link iclink_mt9t031 = {
 	.power		= pcm037_camera_power,
 	.power		= pcm037_camera_power,
 	.board_info	= &pcm037_i2c_camera[0],
 	.board_info	= &pcm037_i2c_camera[0],
 	.i2c_adapter_id	= 2,
 	.i2c_adapter_id	= 2,
-	.module_name	= "mt9t031",
 };
 };
 
 
 static struct i2c_board_info pcm037_i2c_devices[] = {
 static struct i2c_board_info pcm037_i2c_devices[] = {

+ 0 - 1
arch/arm/mach-mx3/mx31moboard-marxbot.c

@@ -179,7 +179,6 @@ static struct soc_camera_link base_iclink = {
 	.reset		= marxbot_basecam_reset,
 	.reset		= marxbot_basecam_reset,
 	.board_info	= &marxbot_i2c_devices[0],
 	.board_info	= &marxbot_i2c_devices[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "mt9t031",
 };
 };
 
 
 static struct platform_device marxbot_camera[] = {
 static struct platform_device marxbot_camera[] = {

+ 0 - 1
arch/arm/mach-mx3/mx31moboard-smartbot.c

@@ -88,7 +88,6 @@ static struct soc_camera_link base_iclink = {
 	.reset		= smartbot_cam_reset,
 	.reset		= smartbot_cam_reset,
 	.board_info	= &smartbot_i2c_devices[0],
 	.board_info	= &smartbot_i2c_devices[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "mt9t031",
 };
 };
 
 
 static struct platform_device smartbot_camera[] = {
 static struct platform_device smartbot_camera[] = {

+ 0 - 1
arch/arm/mach-pxa/em-x270.c

@@ -1015,7 +1015,6 @@ static struct soc_camera_link iclink = {
 	.power		= em_x270_sensor_power,
 	.power		= em_x270_sensor_power,
 	.board_info	= &em_x270_i2c_cam_info[0],
 	.board_info	= &em_x270_i2c_cam_info[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "mt9m111",
 };
 };
 
 
 static struct platform_device em_x270_camera = {
 static struct platform_device em_x270_camera = {

+ 0 - 2
arch/arm/mach-pxa/ezx.c

@@ -755,7 +755,6 @@ static struct soc_camera_link a780_iclink = {
 	.flags          = SOCAM_SENSOR_INVERT_PCLK,
 	.flags          = SOCAM_SENSOR_INVERT_PCLK,
 	.i2c_adapter_id = 0,
 	.i2c_adapter_id = 0,
 	.board_info     = &a780_camera_i2c_board_info,
 	.board_info     = &a780_camera_i2c_board_info,
-	.module_name    = "mt9m111",
 	.power          = a780_camera_power,
 	.power          = a780_camera_power,
 	.reset          = a780_camera_reset,
 	.reset          = a780_camera_reset,
 };
 };
@@ -1024,7 +1023,6 @@ static struct soc_camera_link a910_iclink = {
 	.bus_id         = 0,
 	.bus_id         = 0,
 	.i2c_adapter_id = 0,
 	.i2c_adapter_id = 0,
 	.board_info     = &a910_camera_i2c_board_info,
 	.board_info     = &a910_camera_i2c_board_info,
-	.module_name    = "mt9m111",
 	.power          = a910_camera_power,
 	.power          = a910_camera_power,
 	.reset          = a910_camera_reset,
 	.reset          = a910_camera_reset,
 };
 };

+ 0 - 1
arch/arm/mach-pxa/mioa701.c

@@ -711,7 +711,6 @@ static struct soc_camera_link iclink = {
 	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
 	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
 	.board_info	= &mioa701_i2c_devices[0],
 	.board_info	= &mioa701_i2c_devices[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "mt9m111",
 };
 };
 
 
 struct i2c_pxa_platform_data i2c_pdata = {
 struct i2c_pxa_platform_data i2c_pdata = {

+ 0 - 2
arch/arm/mach-pxa/pcm990-baseboard.c

@@ -453,7 +453,6 @@ static struct soc_camera_link iclink[] = {
 		.query_bus_param	= pcm990_camera_query_bus_param,
 		.query_bus_param	= pcm990_camera_query_bus_param,
 		.set_bus_param		= pcm990_camera_set_bus_param,
 		.set_bus_param		= pcm990_camera_set_bus_param,
 		.free_bus		= pcm990_camera_free_bus,
 		.free_bus		= pcm990_camera_free_bus,
-		.module_name		= "mt9v022",
 	}, {
 	}, {
 		.bus_id			= 0, /* Must match with the camera ID */
 		.bus_id			= 0, /* Must match with the camera ID */
 		.board_info		= &pcm990_camera_i2c[1],
 		.board_info		= &pcm990_camera_i2c[1],
@@ -461,7 +460,6 @@ static struct soc_camera_link iclink[] = {
 		.query_bus_param	= pcm990_camera_query_bus_param,
 		.query_bus_param	= pcm990_camera_query_bus_param,
 		.set_bus_param		= pcm990_camera_set_bus_param,
 		.set_bus_param		= pcm990_camera_set_bus_param,
 		.free_bus		= pcm990_camera_free_bus,
 		.free_bus		= pcm990_camera_free_bus,
-		.module_name		= "mt9m001",
 	},
 	},
 };
 };
 
 

+ 0 - 1
arch/sh/boards/mach-ap325rxa/setup.c

@@ -481,7 +481,6 @@ static struct soc_camera_link ov7725_link = {
 	.power		= ov7725_power,
 	.power		= ov7725_power,
 	.board_info	= &ap325rxa_i2c_camera[0],
 	.board_info	= &ap325rxa_i2c_camera[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "ov772x",
 	.priv		= &ov7725_info,
 	.priv		= &ov7725_info,
 };
 };
 
 

+ 0 - 4
arch/sh/boards/mach-ecovec24/setup.c

@@ -620,7 +620,6 @@ static struct soc_camera_link tw9910_link = {
 	.bus_id		= 1,
 	.bus_id		= 1,
 	.power		= tw9910_power,
 	.power		= tw9910_power,
 	.board_info	= &i2c_camera[0],
 	.board_info	= &i2c_camera[0],
-	.module_name	= "tw9910",
 	.priv		= &tw9910_info,
 	.priv		= &tw9910_info,
 };
 };
 
 
@@ -644,7 +643,6 @@ static struct soc_camera_link mt9t112_link1 = {
 	.power		= mt9t112_power1,
 	.power		= mt9t112_power1,
 	.bus_id		= 0,
 	.bus_id		= 0,
 	.board_info	= &i2c_camera[1],
 	.board_info	= &i2c_camera[1],
-	.module_name	= "mt9t112",
 	.priv		= &mt9t112_info1,
 	.priv		= &mt9t112_info1,
 };
 };
 
 
@@ -667,7 +665,6 @@ static struct soc_camera_link mt9t112_link2 = {
 	.power		= mt9t112_power2,
 	.power		= mt9t112_power2,
 	.bus_id		= 1,
 	.bus_id		= 1,
 	.board_info	= &i2c_camera[2],
 	.board_info	= &i2c_camera[2],
-	.module_name	= "mt9t112",
 	.priv		= &mt9t112_info2,
 	.priv		= &mt9t112_info2,
 };
 };
 
 
@@ -793,7 +790,6 @@ static struct sh_vou_pdata sh_vou_pdata = {
 	.flags		= SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
 	.flags		= SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
 	.board_info	= &ak8813,
 	.board_info	= &ak8813,
 	.i2c_adap	= 0,
 	.i2c_adap	= 0,
-	.module_name	= "ak881x",
 };
 };
 
 
 static struct resource sh_vou_resources[] = {
 static struct resource sh_vou_resources[] = {

+ 0 - 1
arch/sh/boards/mach-kfr2r09/setup.c

@@ -333,7 +333,6 @@ static struct soc_camera_link rj54n1_link = {
 	.power		= camera_power,
 	.power		= camera_power,
 	.board_info	= &kfr2r09_i2c_camera,
 	.board_info	= &kfr2r09_i2c_camera,
 	.i2c_adapter_id	= 1,
 	.i2c_adapter_id	= 1,
-	.module_name	= "rj54n1cb0c",
 	.priv		= &rj54n1_priv,
 	.priv		= &rj54n1_priv,
 };
 };
 
 

+ 0 - 2
arch/sh/boards/mach-migor/setup.c

@@ -450,7 +450,6 @@ static struct soc_camera_link ov7725_link = {
 	.power		= ov7725_power,
 	.power		= ov7725_power,
 	.board_info	= &migor_i2c_camera[0],
 	.board_info	= &migor_i2c_camera[0],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "ov772x",
 	.priv		= &ov7725_info,
 	.priv		= &ov7725_info,
 };
 };
 
 
@@ -463,7 +462,6 @@ static struct soc_camera_link tw9910_link = {
 	.power		= tw9910_power,
 	.power		= tw9910_power,
 	.board_info	= &migor_i2c_camera[1],
 	.board_info	= &migor_i2c_camera[1],
 	.i2c_adapter_id	= 0,
 	.i2c_adapter_id	= 0,
-	.module_name	= "tw9910",
 	.priv		= &tw9910_info,
 	.priv		= &tw9910_info,
 };
 };
 
 

+ 0 - 1
arch/sh/boards/mach-se/7724/setup.c

@@ -550,7 +550,6 @@ static struct sh_vou_pdata sh_vou_pdata = {
 	.flags		= SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
 	.flags		= SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
 	.board_info	= &ak8813,
 	.board_info	= &ak8813,
 	.i2c_adap	= 0,
 	.i2c_adap	= 0,
-	.module_name	= "ak881x",
 };
 };
 
 
 static struct resource sh_vou_resources[] = {
 static struct resource sh_vou_resources[] = {

+ 32 - 7
drivers/media/IR/Kconfig

@@ -79,6 +79,18 @@ config IR_SONY_DECODER
 	   Enable this option if you have an infrared remote control which
 	   Enable this option if you have an infrared remote control which
 	   uses the Sony protocol, and you need software decoding support.
 	   uses the Sony protocol, and you need software decoding support.
 
 
+config IR_RC5_SZ_DECODER
+	tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
+	depends on IR_CORE
+	select BITREVERSE
+	default y
+
+	---help---
+	   Enable this option if you have IR with RC-5 (streamzap) protocol,
+	   and if the IR is decoded in software. (The Streamzap PC Remote
+	   uses an IR protocol that is almost standard RC-5, but not quite,
+	   as it uses an additional bit).
+
 config IR_LIRC_CODEC
 config IR_LIRC_CODEC
 	tristate "Enable IR to LIRC bridge"
 	tristate "Enable IR to LIRC bridge"
 	depends on IR_CORE
 	depends on IR_CORE
@@ -89,6 +101,20 @@ config IR_LIRC_CODEC
 	   Enable this option to pass raw IR to and from userspace via
 	   Enable this option to pass raw IR to and from userspace via
 	   the LIRC interface.
 	   the LIRC interface.
 
 
+config IR_ENE
+	tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
+	depends on PNP
+	depends on IR_CORE
+	---help---
+	   Say Y here to enable support for integrated infrared receiver
+	   /transceiver made by ENE.
+
+	   You can see if you have it by looking at lspnp output.
+	   Output should include ENE0100 ENE0200 or something similar.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called ene_ir.
+
 config IR_IMON
 config IR_IMON
 	tristate "SoundGraph iMON Receiver and Display"
 	tristate "SoundGraph iMON Receiver and Display"
 	depends on USB_ARCH_HAS_HCD
 	depends on USB_ARCH_HAS_HCD
@@ -113,19 +139,18 @@ config IR_MCEUSB
 	   To compile this driver as a module, choose M here: the
 	   To compile this driver as a module, choose M here: the
 	   module will be called mceusb.
 	   module will be called mceusb.
 
 
-config IR_ENE
-	tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
+config IR_NUVOTON
+	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
 	depends on PNP
 	depends on PNP
 	depends on IR_CORE
 	depends on IR_CORE
 	---help---
 	---help---
 	   Say Y here to enable support for integrated infrared receiver
 	   Say Y here to enable support for integrated infrared receiver
-	   /transciever made by ENE.
-
-	   You can see if you have it by looking at lspnp output.
-	   Output should include ENE0100 ENE0200 or something similiar.
+	   /transciever made by Nuvoton (formerly Winbond). This chip is
+	   found in the ASRock ION 330HT, as well as assorted Intel
+	   DP55-series motherboards (and of course, possibly others).
 
 
 	   To compile this driver as a module, choose M here: the
 	   To compile this driver as a module, choose M here: the
-	   module will be called ene_ir.
+	   module will be called nuvoton-cir.
 
 
 config IR_STREAMZAP
 config IR_STREAMZAP
 	tristate "Streamzap PC Remote IR Receiver"
 	tristate "Streamzap PC Remote IR Receiver"

+ 2 - 0
drivers/media/IR/Makefile

@@ -11,10 +11,12 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
+obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 
 # stand-alone IR receivers/transmitters
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_IR_IMON) += imon.o
 obj-$(CONFIG_IR_IMON) += imon.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
+obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
 obj-$(CONFIG_IR_ENE) += ene_ir.o
 obj-$(CONFIG_IR_ENE) += ene_ir.o
 obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
 obj-$(CONFIG_IR_STREAMZAP) += streamzap.o

File diff suppressed because it is too large
+ 507 - 300
drivers/media/IR/ene_ir.c


+ 151 - 124
drivers/media/IR/ene_ir.h

@@ -1,5 +1,5 @@
 /*
 /*
- * driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX)
+ * driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
  *
  *
  * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
  * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
  *
  *
@@ -26,43 +26,50 @@
 #define ENE_ADDR_HI		1	/* hi byte of register address */
 #define ENE_ADDR_HI		1	/* hi byte of register address */
 #define ENE_ADDR_LO		2	/* low byte of register address */
 #define ENE_ADDR_LO		2	/* low byte of register address */
 #define ENE_IO			3	/* read/write window */
 #define ENE_IO			3	/* read/write window */
-#define ENE_MAX_IO		4
-
-/* 8 bytes of samples, divided in 2 halfs*/
-#define ENE_SAMPLE_BUFFER	0xF8F0	/* regular sample buffer */
-#define ENE_SAMPLE_SPC_MASK	0x80	/* sample is space */
-#define ENE_SAMPLE_VALUE_MASK	0x7F
-#define ENE_SAMPLE_OVERFLOW	0x7F
-#define ENE_SAMPLES_SIZE	4
-
-/* fan input sample buffer */
-#define ENE_SAMPLE_BUFFER_FAN	0xF8FB	/* this buffer holds high byte of */
-					/* each sample of normal buffer */
-#define ENE_FAN_SMPL_PULS_MSK	0x8000	/* this bit of combined sample */
-					/* if set, says that sample is pulse */
-#define ENE_FAN_VALUE_MASK	0x0FFF  /* mask for valid bits of the value */
-
-/* first firmware register */
-#define ENE_FW1			0xF8F8
+#define ENE_IO_SIZE		4
+
+/* 8 bytes of samples, divided in 2 packets*/
+#define ENE_FW_SAMPLE_BUFFER	0xF8F0	/* sample buffer */
+#define ENE_FW_SAMPLE_SPACE	0x80	/* sample is space */
+#define ENE_FW_PACKET_SIZE	4
+
+/* first firmware flag register */
+#define ENE_FW1			0xF8F8  /* flagr */
 #define	ENE_FW1_ENABLE		0x01	/* enable fw processing */
 #define	ENE_FW1_ENABLE		0x01	/* enable fw processing */
 #define ENE_FW1_TXIRQ		0x02	/* TX interrupt pending */
 #define ENE_FW1_TXIRQ		0x02	/* TX interrupt pending */
+#define ENE_FW1_HAS_EXTRA_BUF	0x04	/* fw uses extra buffer*/
+#define ENE_FW1_EXTRA_BUF_HND	0x08	/* extra buffer handshake bit*/
+#define ENE_FW1_LED_ON		0x10	/* turn on a led */
+
+#define ENE_FW1_WPATTERN	0x20	/* enable wake pattern */
 #define ENE_FW1_WAKE		0x40	/* enable wake from S3 */
 #define ENE_FW1_WAKE		0x40	/* enable wake from S3 */
 #define ENE_FW1_IRQ		0x80	/* enable interrupt */
 #define ENE_FW1_IRQ		0x80	/* enable interrupt */
 
 
-/* second firmware register */
-#define ENE_FW2			0xF8F9
-#define ENE_FW2_BUF_HIGH	0x01	/* which half of the buffer to read */
-#define ENE_FW2_IRQ_CLR		0x04	/* clear this on IRQ */
-#define ENE_FW2_GP40_AS_LEARN	0x08	/* normal input is used as */
-					/* learning input */
-#define ENE_FW2_FAN_AS_NRML_IN	0x40	/* fan is used as normal input */
+/* second firmware flag register */
+#define ENE_FW2			0xF8F9  /* flagw */
+#define ENE_FW2_BUF_WPTR	0x01	/* which half of the buffer to read */
+#define ENE_FW2_RXIRQ		0x04	/* RX IRQ pending*/
+#define ENE_FW2_GP0A		0x08	/* Use GPIO0A for demodulated input */
+#define ENE_FW2_EMMITER1_CONN	0x10	/* TX emmiter 1 connected */
+#define ENE_FW2_EMMITER2_CONN	0x20	/* TX emmiter 2 connected */
+
+#define ENE_FW2_FAN_INPUT	0x40	/* fan input used for demodulated data*/
 #define ENE_FW2_LEARNING	0x80	/* hardware supports learning and TX */
 #define ENE_FW2_LEARNING	0x80	/* hardware supports learning and TX */
 
 
+/* firmware RX pointer for new style buffer */
+#define ENE_FW_RX_POINTER	0xF8FA
+
+/* high parts of samples for fan input (8 samples)*/
+#define ENE_FW_SMPL_BUF_FAN	0xF8FB
+#define ENE_FW_SMPL_BUF_FAN_PLS	0x8000	/* combined sample is pulse */
+#define ENE_FW_SMPL_BUF_FAN_MSK	0x0FFF  /* combined sample maximum value */
+#define ENE_FW_SAMPLE_PERIOD_FAN 61	/* fan input has fixed sample period */
+
 /* transmitter ports */
 /* transmitter ports */
-#define ENE_TX_PORT2		0xFC01	/* this enables one or both */
-#define ENE_TX_PORT2_EN		0x20	/* TX ports */
-#define ENE_TX_PORT1		0xFC08
-#define ENE_TX_PORT1_EN		0x02
+#define ENE_GPIOFS1		0xFC01
+#define ENE_GPIOFS1_GPIO0D	0x20	/* enable tx output on GPIO0D */
+#define ENE_GPIOFS8		0xFC08
+#define ENE_GPIOFS8_GPIO41	0x02	/* enable tx output on GPIO40 */
 
 
 /* IRQ registers block (for revision B) */
 /* IRQ registers block (for revision B) */
 #define ENEB_IRQ		0xFD09	/* IRQ number */
 #define ENEB_IRQ		0xFD09	/* IRQ number */
@@ -70,97 +77,99 @@
 #define ENEB_IRQ_STATUS		0xFD80	/* irq status */
 #define ENEB_IRQ_STATUS		0xFD80	/* irq status */
 #define ENEB_IRQ_STATUS_IR	0x20	/* IR irq */
 #define ENEB_IRQ_STATUS_IR	0x20	/* IR irq */
 
 
-/* fan as input settings - only if learning capable */
+/* fan as input settings */
 #define ENE_FAN_AS_IN1		0xFE30  /* fan init reg 1 */
 #define ENE_FAN_AS_IN1		0xFE30  /* fan init reg 1 */
 #define ENE_FAN_AS_IN1_EN	0xCD
 #define ENE_FAN_AS_IN1_EN	0xCD
 #define ENE_FAN_AS_IN2		0xFE31  /* fan init reg 2 */
 #define ENE_FAN_AS_IN2		0xFE31  /* fan init reg 2 */
 #define ENE_FAN_AS_IN2_EN	0x03
 #define ENE_FAN_AS_IN2_EN	0x03
-#define ENE_SAMPLE_PERIOD_FAN   61	/* fan input has fixed sample period */
 
 
 /* IRQ registers block (for revision C,D) */
 /* IRQ registers block (for revision C,D) */
-#define ENEC_IRQ		0xFE9B	/* new irq settings register */
-#define ENEC_IRQ_MASK		0x0F	/* irq number mask */
-#define ENEC_IRQ_UNK_EN		0x10	/* always enabled */
-#define ENEC_IRQ_STATUS		0x20	/* irq status and ACK */
-
-/* CIR block settings */
-#define ENE_CIR_CONF1		0xFEC0
-#define ENE_CIR_CONF1_TX_CLEAR	0x01	/* clear that on revC */
-					/* while transmitting */
-#define ENE_CIR_CONF1_RX_ON	0x07	/* normal receiver enabled */
-#define ENE_CIR_CONF1_LEARN1	0x08	/* enabled on learning mode */
-#define ENE_CIR_CONF1_TX_ON	0x30	/* enabled on transmit */
-#define ENE_CIR_CONF1_TX_CARR	0x80	/* send TX carrier or not */
-
-#define ENE_CIR_CONF2		0xFEC1	/* unknown setting = 0 */
-#define ENE_CIR_CONF2_LEARN2	0x10	/* set on enable learning */
-#define ENE_CIR_CONF2_GPIO40DIS	0x20	/* disable input via gpio40 */
-
-#define ENE_CIR_SAMPLE_PERIOD	0xFEC8	/* sample period in us */
-#define ENE_CIR_SAMPLE_OVERFLOW	0x80	/* interrupt on overflows if set */
-
-
-/* Two byte tx buffer */
-#define ENE_TX_INPUT1		0xFEC9
-#define ENE_TX_INPUT2		0xFECA
-#define ENE_TX_PULSE_MASK	0x80	/* Transmitted sample is pulse */
-#define ENE_TX_SMLP_MASK	0x7F
-#define ENE_TX_SMPL_PERIOD	50	/* transmit sample period - fixed */
+#define ENE_IRQ			0xFE9B	/* new irq settings register */
+#define ENE_IRQ_MASK		0x0F	/* irq number mask */
+#define ENE_IRQ_UNK_EN		0x10	/* always enabled */
+#define ENE_IRQ_STATUS		0x20	/* irq status and ACK */
+
+/* CIR Config register #1 */
+#define ENE_CIRCFG		0xFEC0
+#define ENE_CIRCFG_RX_EN	0x01	/* RX enable */
+#define ENE_CIRCFG_RX_IRQ	0x02	/* Enable hardware interrupt */
+#define ENE_CIRCFG_REV_POL	0x04	/* Input polarity reversed */
+#define ENE_CIRCFG_CARR_DEMOD	0x08	/* Enable carrier demodulator */
+
+#define ENE_CIRCFG_TX_EN	0x10	/* TX enable */
+#define ENE_CIRCFG_TX_IRQ	0x20	/* Send interrupt on TX done */
+#define ENE_CIRCFG_TX_POL_REV	0x40	/* TX polarity reversed */
+#define ENE_CIRCFG_TX_CARR	0x80	/* send TX carrier or not */
+
+/* CIR config register #2 */
+#define ENE_CIRCFG2		0xFEC1
+#define ENE_CIRCFG2_RLC		0x00
+#define ENE_CIRCFG2_RC5		0x01
+#define ENE_CIRCFG2_RC6		0x02
+#define ENE_CIRCFG2_NEC		0x03
+#define ENE_CIRCFG2_CARR_DETECT	0x10	/* Enable carrier detection */
+#define ENE_CIRCFG2_GPIO0A	0x20	/* Use GPIO0A instead of GPIO40 for input */
+#define ENE_CIRCFG2_FAST_SAMPL1	0x40	/* Fast leading pulse detection for RC6 */
+#define ENE_CIRCFG2_FAST_SAMPL2	0x80	/* Fast data detection for RC6 */
+
+/* Knobs for protocol decoding - will document when/if will use them */
+#define ENE_CIRPF		0xFEC2
+#define ENE_CIRHIGH		0xFEC3
+#define ENE_CIRBIT		0xFEC4
+#define ENE_CIRSTART		0xFEC5
+#define ENE_CIRSTART2		0xFEC6
+
+/* Actual register which contains RLC RX data - read by firmware */
+#define ENE_CIRDAT_IN		0xFEC7
+
+
+/* RLC configuration - sample period (1us resulution) + idle mode */
+#define ENE_CIRRLC_CFG		0xFEC8
+#define ENE_CIRRLC_CFG_OVERFLOW	0x80	/* interrupt on overflows if set */
+#define ENE_DEFAULT_SAMPLE_PERIOD 50
+
+/* Two byte RLC TX buffer */
+#define ENE_CIRRLC_OUT0		0xFEC9
+#define ENE_CIRRLC_OUT1		0xFECA
+#define ENE_CIRRLC_OUT_PULSE	0x80	/* Transmitted sample is pulse */
+#define ENE_CIRRLC_OUT_MASK	0x7F
+
+
+/* Carrier detect setting
+ * Low nibble  - number of carrier pulses to average
+ * High nibble - number of initial carrier pulses to discard
+ */
+#define ENE_CIRCAR_PULS		0xFECB
 
 
+/* detected RX carrier period (resolution: 500 ns) */
+#define ENE_CIRCAR_PRD		0xFECC
+#define ENE_CIRCAR_PRD_VALID	0x80	/* data valid content valid */
 
 
-/* Unknown TX setting - TX sample period ??? */
-#define ENE_TX_UNK1		0xFECB	/* set to 0x63 */
+/* detected RX carrier pulse width (resolution: 500 ns) */
+#define ENE_CIRCAR_HPRD		0xFECD
 
 
-/* Current received carrier period */
-#define ENE_RX_CARRIER		0xFECC	/* RX period (500 ns) */
-#define ENE_RX_CARRIER_VALID	0x80	/* Register content valid */
+/* TX period (resolution: 500 ns, minimum 2)*/
+#define ENE_CIRMOD_PRD		0xFECE
+#define ENE_CIRMOD_PRD_POL	0x80	/* TX carrier polarity*/
 
 
+#define ENE_CIRMOD_PRD_MAX	0x7F	/* 15.87 kHz */
+#define ENE_CIRMOD_PRD_MIN	0x02	/* 1 Mhz */
 
 
-/* TX period (1/carrier) */
-#define ENE_TX_PERIOD		0xFECE	/* TX period (500 ns) */
-#define ENE_TX_PERIOD_UNKBIT	0x80	/* This bit set on transmit*/
-#define ENE_TX_PERIOD_PULSE	0xFECF	/* TX pulse period (500 ns)*/
+/* TX pulse width (resolution: 500 ns)*/
+#define ENE_CIRMOD_HPRD		0xFECF
 
 
 /* Hardware versions */
 /* Hardware versions */
-#define ENE_HW_VERSION		0xFF00	/* hardware revision */
+#define ENE_ECHV		0xFF00	/* hardware revision */
 #define ENE_PLLFRH		0xFF16
 #define ENE_PLLFRH		0xFF16
 #define ENE_PLLFRL		0xFF17
 #define ENE_PLLFRL		0xFF17
+#define ENE_DEFAULT_PLL_FREQ	1000
 
 
-#define ENE_HW_UNK		0xFF1D
-#define ENE_HW_UNK_CLR		0x04
-#define ENE_HW_VER_MAJOR	0xFF1E	/* chip version */
-#define ENE_HW_VER_MINOR	0xFF1F
-#define ENE_HW_VER_OLD		0xFD00
-
-/* Normal/Learning carrier ranges - only valid if we have learning input*/
-/* TODO: test */
-#define ENE_NORMAL_RX_LOW	34
-#define ENE_NORMAL_RX_HI	38
+#define ENE_ECSTS		0xFF1D
+#define ENE_ECSTS_RSRVD		0x04
 
 
-/* Tx carrier range */
-/* Hardware might be able to do more, but this range is enough for
-   all purposes */
-#define ENE_TX_PERIOD_MAX	32	/* corresponds to 29.4 kHz */
-#define ENE_TX_PERIOD_MIN	16	/* corrsponds to 62.5 kHz */
-
-
-
-/* Minimal and maximal gaps */
-
-/* Normal case:
-	Minimal gap is 0x7F * sample period
-	Maximum gap depends on hardware.
-	For KB3926B, it is unlimited, for newer models its around
-	250000, after which HW stops sending samples, and that is
-	not possible to change */
-
-/* Fan case:
-	Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
-	And there is nothing to change this setting
-*/
-
-#define ENE_MAXGAP		250000
-#define ENE_MINGAP		(127 * sample_period)
+#define ENE_ECVER_MAJOR		0xFF1E	/* chip version */
+#define ENE_ECVER_MINOR		0xFF1F
+#define ENE_HW_VER_OLD		0xFD00
 
 
 /******************************************************************************/
 /******************************************************************************/
 
 
@@ -171,46 +180,60 @@
 
 
 #define  ENE_HW_B		1	/* 3926B */
 #define  ENE_HW_B		1	/* 3926B */
 #define  ENE_HW_C		2	/* 3926C */
 #define  ENE_HW_C		2	/* 3926C */
-#define  ENE_HW_D		3	/* 3926D */
+#define  ENE_HW_D		3	/* 3926D or later */
 
 
 #define ene_printk(level, text, ...) \
 #define ene_printk(level, text, ...) \
-	printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
+	printk(level ENE_DRIVER_NAME ": " text "\n", ## __VA_ARGS__)
 
 
-#define ene_dbg(text, ...) \
-	if (debug) \
-		printk(KERN_DEBUG \
-			ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
+#define ene_notice(text, ...) ene_printk(KERN_NOTICE, text, ## __VA_ARGS__)
+#define ene_warn(text, ...) ene_printk(KERN_WARNING, text, ## __VA_ARGS__)
 
 
-#define ene_dbg_verbose(text, ...) \
-	if (debug > 1) \
-		printk(KERN_DEBUG \
-			ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
 
 
+#define __dbg(level, format, ...) \
+	do { \
+		if (debug >= level) \
+			printk(KERN_DEBUG ENE_DRIVER_NAME \
+				": " format "\n", ## __VA_ARGS__); \
+	} while (0)
+
+
+#define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
+#define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
+#define dbg_regs(format, ...)		__dbg(3, format, ## __VA_ARGS__)
+
+#define MS_TO_NS(msec) ((msec) * 1000)
 
 
 struct ene_device {
 struct ene_device {
 	struct pnp_dev *pnp_dev;
 	struct pnp_dev *pnp_dev;
 	struct input_dev *idev;
 	struct input_dev *idev;
 	struct ir_dev_props *props;
 	struct ir_dev_props *props;
-	int in_use;
 
 
 	/* hw IO settings */
 	/* hw IO settings */
-	unsigned long hw_io;
+	long hw_io;
 	int irq;
 	int irq;
 	spinlock_t hw_lock;
 	spinlock_t hw_lock;
 
 
 	/* HW features */
 	/* HW features */
 	int hw_revision;			/* hardware revision */
 	int hw_revision;			/* hardware revision */
-	bool hw_learning_and_tx_capable;	/* learning capable */
-	bool hw_gpio40_learning;		/* gpio40 is learning */
-	bool hw_fan_as_normal_input;		/* fan input is used as */
-						/* regular input */
+	bool hw_use_gpio_0a;			/* gpio0a is demodulated input*/
+	bool hw_extra_buffer;			/* hardware has 'extra buffer' */
+	bool hw_fan_input;			/* fan input is IR data source */
+	bool hw_learning_and_tx_capable;	/* learning & tx capable */
+	int  pll_freq;
+	int buffer_len;
+
+	/* Extra RX buffer location */
+	int extra_buf1_address;
+	int extra_buf1_len;
+	int extra_buf2_address;
+	int extra_buf2_len;
+
 	/* HW state*/
 	/* HW state*/
-	int rx_pointer;				/* hw pointer to rx buffer */
+	int r_pointer;				/* pointer to next sample to read */
+	int w_pointer;				/* pointer to next sample hw will write */
 	bool rx_fan_input_inuse;		/* is fan input in use for rx*/
 	bool rx_fan_input_inuse;		/* is fan input in use for rx*/
 	int tx_reg;				/* current reg used for TX */
 	int tx_reg;				/* current reg used for TX */
 	u8  saved_conf1;			/* saved FEC0 reg */
 	u8  saved_conf1;			/* saved FEC0 reg */
-
-	/* TX sample handling */
 	unsigned int tx_sample;			/* current sample for TX */
 	unsigned int tx_sample;			/* current sample for TX */
 	bool tx_sample_pulse;			/* current sample is pulse */
 	bool tx_sample_pulse;			/* current sample is pulse */
 
 
@@ -229,7 +252,11 @@ struct ene_device {
 	int transmitter_mask;
 	int transmitter_mask;
 
 
 	/* RX settings */
 	/* RX settings */
-	bool learning_enabled;			/* learning input enabled */
+	bool learning_mode_enabled;		/* learning input enabled */
 	bool carrier_detect_enabled;		/* carrier detect enabled */
 	bool carrier_detect_enabled;		/* carrier detect enabled */
 	int rx_period_adjust;
 	int rx_period_adjust;
+	bool rx_enabled;
 };
 };
+
+static int ene_irq_status(struct ene_device *dev);
+static void ene_rx_read_hw_pointer(struct ene_device *dev);

File diff suppressed because it is too large
+ 368 - 148
drivers/media/IR/imon.c


+ 21 - 1
drivers/media/IR/ir-core-priv.h

@@ -17,6 +17,7 @@
 #define _IR_RAW_EVENT
 #define _IR_RAW_EVENT
 
 
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #include <media/ir-core.h>
 #include <media/ir-core.h>
 
 
 struct ir_raw_handler {
 struct ir_raw_handler {
@@ -33,6 +34,7 @@ struct ir_raw_handler {
 struct ir_raw_event_ctrl {
 struct ir_raw_event_ctrl {
 	struct list_head		list;		/* to keep track of raw clients */
 	struct list_head		list;		/* to keep track of raw clients */
 	struct task_struct		*thread;
 	struct task_struct		*thread;
+	spinlock_t			lock;
 	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
 	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
 	ktime_t				last_event;	/* when last event occurred */
 	ktime_t				last_event;	/* when last event occurred */
 	enum raw_event_type		last_type;	/* last event type */
 	enum raw_event_type		last_type;	/* last event type */
@@ -76,10 +78,22 @@ struct ir_raw_event_ctrl {
 		bool first;
 		bool first;
 		bool toggle;
 		bool toggle;
 	} jvc;
 	} jvc;
+	struct rc5_sz_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc5_sz;
 	struct lirc_codec {
 	struct lirc_codec {
 		struct ir_input_dev *ir_dev;
 		struct ir_input_dev *ir_dev;
 		struct lirc_driver *drv;
 		struct lirc_driver *drv;
 		int carrier_low;
 		int carrier_low;
+
+		ktime_t gap_start;
+		u64 gap_duration;
+		bool gap;
+		bool send_timeout_reports;
+
 	} lirc;
 	} lirc;
 };
 };
 
 
@@ -107,13 +121,19 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
 		ev->duration -= duration;
 		ev->duration -= duration;
 }
 }
 
 
+/* Returns true if event is normal pulse/space event */
+static inline bool is_timing_event(struct ir_raw_event ev)
+{
+	return !ev.carrier_report && !ev.reset;
+}
+
 #define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
 #define TO_US(duration)			DIV_ROUND_CLOSEST((duration), 1000)
 #define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
 #define TO_STR(is_pulse)		((is_pulse) ? "pulse" : "space")
-#define IS_RESET(ev)			(ev.duration == 0)
 /*
 /*
  * Routines from ir-sysfs.c - Meant to be called only internally inside
  * Routines from ir-sysfs.c - Meant to be called only internally inside
  * ir-core
  * ir-core
  */
  */
+int ir_register_input(struct input_dev *input_dev);
 
 
 int ir_register_class(struct input_dev *input_dev);
 int ir_register_class(struct input_dev *input_dev);
 void ir_unregister_class(struct input_dev *input_dev);
 void ir_unregister_class(struct input_dev *input_dev);

+ 3 - 2
drivers/media/IR/ir-jvc-decoder.c

@@ -50,8 +50,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
 		return 0;
 		return 0;
 
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 6 - 1
drivers/media/IR/ir-keytable.c

@@ -435,7 +435,7 @@ EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
  * This routine is used to signal that a key has been released on the
  * This routine is used to signal that a key has been released on the
  * remote control. It reports a keyup input event via input_report_key().
  * remote control. It reports a keyup input event via input_report_key().
  */
  */
-static void ir_keyup(struct ir_input_dev *ir)
+void ir_keyup(struct ir_input_dev *ir)
 {
 {
 	if (!ir->keypressed)
 	if (!ir->keypressed)
 		return;
 		return;
@@ -445,6 +445,7 @@ static void ir_keyup(struct ir_input_dev *ir)
 	input_sync(ir->input_dev);
 	input_sync(ir->input_dev);
 	ir->keypressed = false;
 	ir->keypressed = false;
 }
 }
+EXPORT_SYMBOL_GPL(ir_keyup);
 
 
 /**
 /**
  * ir_timer_keyup() - generates a keyup event after a timeout
  * ir_timer_keyup() - generates a keyup event after a timeout
@@ -640,6 +641,10 @@ int __ir_input_register(struct input_dev *input_dev,
 				goto out_event;
 				goto out_event;
 		}
 		}
 
 
+	rc = ir_register_input(input_dev);
+	if (rc < 0)
+		goto out_event;
+
 	IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
 	IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
 		   driver_name, rc_tab->name,
 		   driver_name, rc_tab->name,
 		   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
 		   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?

+ 95 - 40
drivers/media/IR/ir-lirc-codec.c

@@ -32,6 +32,7 @@
 static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
 {
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct lirc_codec *lirc = &ir_dev->raw->lirc;
 	int sample;
 	int sample;
 
 
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
@@ -40,21 +41,57 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
 	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (IS_RESET(ev))
+	/* Packet start */
+	if (ev.reset)
 		return 0;
 		return 0;
 
 
-	IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
-		   TO_US(ev.duration), TO_STR(ev.pulse));
+	/* Carrier reports */
+	if (ev.carrier_report) {
+		sample = LIRC_FREQUENCY(ev.carrier);
+
+	/* Packet end */
+	} else if (ev.timeout) {
+
+		if (lirc->gap)
+			return 0;
+
+		lirc->gap_start = ktime_get();
+		lirc->gap = true;
+		lirc->gap_duration = ev.duration;
+
+		if (!lirc->send_timeout_reports)
+			return 0;
+
+		sample = LIRC_TIMEOUT(ev.duration / 1000);
 
 
-	sample = ev.duration / 1000;
-	if (ev.pulse)
-		sample |= PULSE_BIT;
+	/* Normal sample */
+	} else {
+
+		if (lirc->gap) {
+			int gap_sample;
+
+			lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+				lirc->gap_start));
+
+			/* Convert to ms and cap by LIRC_VALUE_MASK */
+			do_div(lirc->gap_duration, 1000);
+			lirc->gap_duration = min(lirc->gap_duration,
+							(u64)LIRC_VALUE_MASK);
+
+			gap_sample = LIRC_SPACE(lirc->gap_duration);
+			lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+						(unsigned char *) &gap_sample);
+			lirc->gap = false;
+		}
+
+		sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+					LIRC_SPACE(ev.duration / 1000);
+	}
 
 
 	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
 	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
 			  (unsigned char *) &sample);
 			  (unsigned char *) &sample);
 	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
 	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
 
 
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -102,7 +139,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	struct ir_input_dev *ir_dev;
 	struct ir_input_dev *ir_dev;
 	int ret = 0;
 	int ret = 0;
 	void *drv_data;
 	void *drv_data;
-	unsigned long val = 0;
+	__u32 val = 0, tmp;
 
 
 	lirc = lirc_get_pdata(filep);
 	lirc = lirc_get_pdata(filep);
 	if (!lirc)
 	if (!lirc)
@@ -115,7 +152,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	drv_data = ir_dev->props->priv;
 	drv_data = ir_dev->props->priv;
 
 
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
 	if (_IOC_DIR(cmd) & _IOC_WRITE) {
-		ret = get_user(val, (unsigned long *)arg);
+		ret = get_user(val, (__u32 *)arg);
 		if (ret)
 		if (ret)
 			return ret;
 			return ret;
 	}
 	}
@@ -130,22 +167,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	case LIRC_SET_SEND_MODE:
 	case LIRC_SET_SEND_MODE:
 		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
 		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
 			return -EINVAL;
 			return -EINVAL;
-		break;
+		return 0;
 
 
 	/* TX settings */
 	/* TX settings */
 	case LIRC_SET_TRANSMITTER_MASK:
 	case LIRC_SET_TRANSMITTER_MASK:
-		if (ir_dev->props->s_tx_mask)
-			ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
-		else
+		if (!ir_dev->props->s_tx_mask)
 			return -EINVAL;
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_mask(drv_data, val);
 
 
 	case LIRC_SET_SEND_CARRIER:
 	case LIRC_SET_SEND_CARRIER:
-		if (ir_dev->props->s_tx_carrier)
-			ir_dev->props->s_tx_carrier(drv_data, (u32)val);
-		else
+		if (!ir_dev->props->s_tx_carrier)
 			return -EINVAL;
 			return -EINVAL;
-		break;
+
+		return ir_dev->props->s_tx_carrier(drv_data, val);
 
 
 	case LIRC_SET_SEND_DUTY_CYCLE:
 	case LIRC_SET_SEND_DUTY_CYCLE:
 		if (!ir_dev->props->s_tx_duty_cycle)
 		if (!ir_dev->props->s_tx_duty_cycle)
@@ -154,39 +189,42 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		if (val <= 0 || val >= 100)
 		if (val <= 0 || val >= 100)
 			return -EINVAL;
 			return -EINVAL;
 
 
-		ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
-		break;
+		return ir_dev->props->s_tx_duty_cycle(drv_data, val);
 
 
 	/* RX settings */
 	/* RX settings */
 	case LIRC_SET_REC_CARRIER:
 	case LIRC_SET_REC_CARRIER:
-		if (ir_dev->props->s_rx_carrier_range)
-			ret = ir_dev->props->s_rx_carrier_range(
-				ir_dev->props->priv,
-				ir_dev->raw->lirc.carrier_low, val);
-		else
+		if (!ir_dev->props->s_rx_carrier_range)
 			return -ENOSYS;
 			return -ENOSYS;
 
 
-		if (!ret)
-			ir_dev->raw->lirc.carrier_low = 0;
-		break;
+		if (val <= 0)
+			return -EINVAL;
+
+		return ir_dev->props->s_rx_carrier_range(drv_data,
+			ir_dev->raw->lirc.carrier_low, val);
 
 
 	case LIRC_SET_REC_CARRIER_RANGE:
 	case LIRC_SET_REC_CARRIER_RANGE:
-		if (val >= 0)
-			ir_dev->raw->lirc.carrier_low = val;
-		break;
+		if (val <= 0)
+			return -EINVAL;
 
 
+		ir_dev->raw->lirc.carrier_low = val;
+		return 0;
 
 
 	case LIRC_GET_REC_RESOLUTION:
 	case LIRC_GET_REC_RESOLUTION:
 		val = ir_dev->props->rx_resolution;
 		val = ir_dev->props->rx_resolution;
 		break;
 		break;
 
 
 	case LIRC_SET_WIDEBAND_RECEIVER:
 	case LIRC_SET_WIDEBAND_RECEIVER:
-		if (ir_dev->props->s_learning_mode)
-			return ir_dev->props->s_learning_mode(
-				ir_dev->props->priv, !!val);
-		else
+		if (!ir_dev->props->s_learning_mode)
 			return -ENOSYS;
 			return -ENOSYS;
 
 
+		return ir_dev->props->s_learning_mode(drv_data, !!val);
+
+	case LIRC_SET_MEASURE_CARRIER_MODE:
+		if (!ir_dev->props->s_carrier_report)
+			return -ENOSYS;
+
+		return ir_dev->props->s_carrier_report(drv_data, !!val);
+
 	/* Generic timeout support */
 	/* Generic timeout support */
 	case LIRC_GET_MIN_TIMEOUT:
 	case LIRC_GET_MIN_TIMEOUT:
 		if (!ir_dev->props->max_timeout)
 		if (!ir_dev->props->max_timeout)
@@ -201,10 +239,20 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 		break;
 		break;
 
 
 	case LIRC_SET_REC_TIMEOUT:
 	case LIRC_SET_REC_TIMEOUT:
-		if (val < ir_dev->props->min_timeout ||
-		    val > ir_dev->props->max_timeout)
-			return -EINVAL;
-		ir_dev->props->timeout = val * 1000;
+		if (!ir_dev->props->max_timeout)
+			return -ENOSYS;
+
+		tmp = val * 1000;
+
+		if (tmp < ir_dev->props->min_timeout ||
+			tmp > ir_dev->props->max_timeout)
+				return -EINVAL;
+
+		ir_dev->props->timeout = tmp;
+		break;
+
+	case LIRC_SET_REC_TIMEOUT_REPORTS:
+		lirc->send_timeout_reports = !!val;
 		break;
 		break;
 
 
 	default:
 	default:
@@ -212,7 +260,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
 	}
 	}
 
 
 	if (_IOC_DIR(cmd) & _IOC_READ)
 	if (_IOC_DIR(cmd) & _IOC_READ)
-		ret = put_user(val, (unsigned long *)arg);
+		ret = put_user(val, (__u32 *)arg);
 
 
 	return ret;
 	return ret;
 }
 }
@@ -231,6 +279,9 @@ static struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.write		= ir_lirc_transmit_ir,
 	.write		= ir_lirc_transmit_ir,
 	.unlocked_ioctl	= ir_lirc_ioctl,
 	.unlocked_ioctl	= ir_lirc_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= ir_lirc_ioctl,
+#endif
 	.read		= lirc_dev_fop_read,
 	.read		= lirc_dev_fop_read,
 	.poll		= lirc_dev_fop_poll,
 	.poll		= lirc_dev_fop_poll,
 	.open		= lirc_dev_fop_open,
 	.open		= lirc_dev_fop_open,
@@ -278,6 +329,10 @@ static int ir_lirc_register(struct input_dev *input_dev)
 	if (ir_dev->props->s_learning_mode)
 	if (ir_dev->props->s_learning_mode)
 		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
 		features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
 
 
+	if (ir_dev->props->s_carrier_report)
+		features |= LIRC_CAN_MEASURE_CARRIER;
+
+
 	if (ir_dev->props->max_timeout)
 	if (ir_dev->props->max_timeout)
 		features |= LIRC_CAN_SET_REC_TIMEOUT;
 		features |= LIRC_CAN_SET_REC_TIMEOUT;
 
 

+ 3 - 2
drivers/media/IR/ir-nec-decoder.c

@@ -54,8 +54,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
 		return 0;
 		return 0;
 
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 42 - 39
drivers/media/IR/ir-raw-event.c

@@ -39,22 +39,34 @@ static int ir_raw_event_thread(void *data)
 	struct ir_raw_event ev;
 	struct ir_raw_event ev;
 	struct ir_raw_handler *handler;
 	struct ir_raw_handler *handler;
 	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
 	struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
+	int retval;
 
 
 	while (!kthread_should_stop()) {
 	while (!kthread_should_stop()) {
-		try_to_freeze();
 
 
-		mutex_lock(&ir_raw_handler_lock);
+		spin_lock_irq(&raw->lock);
+		retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
+
+		if (!retval) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
 
 
-		while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
-			list_for_each_entry(handler, &ir_raw_handler_list, list)
-				handler->decode(raw->input_dev, ev);
-			raw->prev_ev = ev;
+			spin_unlock_irq(&raw->lock);
+			schedule();
+			continue;
 		}
 		}
 
 
-		mutex_unlock(&ir_raw_handler_lock);
+		spin_unlock_irq(&raw->lock);
+
 
 
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule();
+		BUG_ON(retval != sizeof(ev));
+
+		mutex_lock(&ir_raw_handler_lock);
+		list_for_each_entry(handler, &ir_raw_handler_list, list)
+			handler->decode(raw->input_dev, ev);
+		raw->prev_ev = ev;
+		mutex_unlock(&ir_raw_handler_lock);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -77,7 +89,7 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
 	if (!ir->raw)
 	if (!ir->raw)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	IR_dprintk(2, "sample: (05%dus %s)\n",
+	IR_dprintk(2, "sample: (%05dus %s)\n",
 		TO_US(ev->duration), TO_STR(ev->pulse));
 		TO_US(ev->duration), TO_STR(ev->pulse));
 
 
 	if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
 	if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
@@ -162,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 	if (ir->idle && !ev->pulse)
 	if (ir->idle && !ev->pulse)
 		return 0;
 		return 0;
 	else if (ir->idle)
 	else if (ir->idle)
-		ir_raw_event_set_idle(input_dev, 0);
+		ir_raw_event_set_idle(input_dev, false);
 
 
 	if (!raw->this_ev.duration) {
 	if (!raw->this_ev.duration) {
 		raw->this_ev = *ev;
 		raw->this_ev = *ev;
@@ -175,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev,
 
 
 	/* Enter idle mode if nessesary */
 	/* Enter idle mode if nessesary */
 	if (!ev->pulse && ir->props->timeout &&
 	if (!ev->pulse && ir->props->timeout &&
-		raw->this_ev.duration >= ir->props->timeout)
-		ir_raw_event_set_idle(input_dev, 1);
+		raw->this_ev.duration >= ir->props->timeout) {
+		ir_raw_event_set_idle(input_dev, true);
+	}
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
 EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
 
 
-void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
+/**
+ * ir_raw_event_set_idle() - hint the ir core if device is receiving
+ * IR data or not
+ * @input_dev: the struct input_dev device descriptor
+ * @idle: the hint value
+ */
+void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle)
 {
 {
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
 	struct ir_raw_event_ctrl *raw = ir->raw;
 	struct ir_raw_event_ctrl *raw = ir->raw;
-	ktime_t now;
-	u64 delta;
 
 
-	if (!ir->props)
+	if (!ir->props || !ir->raw)
 		return;
 		return;
 
 
-	if (!ir->raw)
-		goto out;
+	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
 
 
 	if (idle) {
 	if (idle) {
-		IR_dprintk(2, "enter idle mode\n");
-		raw->last_event = ktime_get();
-	} else {
-		IR_dprintk(2, "exit idle mode\n");
-
-		now = ktime_get();
-		delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
-
-		WARN_ON(raw->this_ev.pulse);
-
-		raw->this_ev.duration =
-			min(raw->this_ev.duration + delta,
-						(u64)IR_MAX_DURATION);
-
+		raw->this_ev.timeout = true;
 		ir_raw_event_store(input_dev, &raw->this_ev);
 		ir_raw_event_store(input_dev, &raw->this_ev);
-
-		if (raw->this_ev.duration == IR_MAX_DURATION)
-			ir_raw_event_reset(input_dev);
-
-		raw->this_ev.duration = 0;
+		init_ir_raw_event(&raw->this_ev);
 	}
 	}
-out:
+
 	if (ir->props->s_idle)
 	if (ir->props->s_idle)
 		ir->props->s_idle(ir->props->priv, idle);
 		ir->props->s_idle(ir->props->priv, idle);
 	ir->idle = idle;
 	ir->idle = idle;
@@ -232,11 +231,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
 void ir_raw_event_handle(struct input_dev *input_dev)
 void ir_raw_event_handle(struct input_dev *input_dev)
 {
 {
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
 	struct ir_input_dev *ir = input_get_drvdata(input_dev);
+	unsigned long flags;
 
 
 	if (!ir->raw)
 	if (!ir->raw)
 		return;
 		return;
 
 
+	spin_lock_irqsave(&ir->raw->lock, flags);
 	wake_up_process(ir->raw->thread);
 	wake_up_process(ir->raw->thread);
+	spin_unlock_irqrestore(&ir->raw->lock, flags);
 }
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 
 
@@ -275,6 +277,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
 		return rc;
 		return rc;
 	}
 	}
 
 
+	spin_lock_init(&ir->raw->lock);
 	ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
 	ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
 			"rc%u",  (unsigned int)ir->devno);
 			"rc%u",  (unsigned int)ir->devno);
 
 

+ 3 - 2
drivers/media/IR/ir-rc5-decoder.c

@@ -55,8 +55,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
         if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
                 return 0;
                 return 0;
 
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 154 - 0
drivers/media/IR/ir-rc5-sz-decoder.c

@@ -0,0 +1,154 @@
+/* ir-rc5-sz-decoder.c - handle RC5 Streamzap IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2 of the License.
+ *
+ *  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.
+ */
+
+/*
+ * This code handles the 15 bit RC5-ish protocol used by the Streamzap
+ * PC Remote.
+ * It considers a carrier of 36 kHz, with a total of 15 bits, where
+ * the first two bits are start bits, and a third one is a filing bit
+ */
+
+#include "ir-core-priv.h"
+
+#define RC5_SZ_NBITS		15
+#define RC5_UNIT		888888 /* ns */
+#define RC5_BIT_START		(1 * RC5_UNIT)
+#define RC5_BIT_END		(1 * RC5_UNIT)
+
+enum rc5_sz_state {
+	STATE_INACTIVE,
+	STATE_BIT_START,
+	STATE_BIT_END,
+	STATE_FINISHED,
+};
+
+/**
+ * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
+ * @input_dev:	the struct input_dev descriptor of the device
+ * @ev:		the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
+{
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
+	u8 toggle, command, system;
+	u32 scancode;
+
+        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
+                return 0;
+
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		goto out;
+
+again:
+	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+
+	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
+		return 0;
+
+	switch (data->state) {
+
+	case STATE_INACTIVE:
+		if (!ev.pulse)
+			break;
+
+		data->state = STATE_BIT_START;
+		data->count = 1;
+		data->wanted_bits = RC5_SZ_NBITS;
+		decrease_duration(&ev, RC5_BIT_START);
+		goto again;
+
+	case STATE_BIT_START:
+		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
+			break;
+
+		data->bits <<= 1;
+		if (!ev.pulse)
+			data->bits |= 1;
+		data->count++;
+		data->state = STATE_BIT_END;
+		return 0;
+
+	case STATE_BIT_END:
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
+			break;
+
+		if (data->count == data->wanted_bits)
+			data->state = STATE_FINISHED;
+		else
+			data->state = STATE_BIT_START;
+
+		decrease_duration(&ev, RC5_BIT_END);
+		goto again;
+
+	case STATE_FINISHED:
+		if (ev.pulse)
+			break;
+
+		/* RC5-sz */
+		command  = (data->bits & 0x0003F) >> 0;
+		system   = (data->bits & 0x02FC0) >> 6;
+		toggle   = (data->bits & 0x01000) ? 1 : 0;
+		scancode = system << 6 | command;
+
+		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
+			   scancode, toggle);
+
+		ir_keydown(input_dev, scancode, toggle);
+		data->state = STATE_INACTIVE;
+		return 0;
+	}
+
+out:
+	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
+		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+	data->state = STATE_INACTIVE;
+	return -EINVAL;
+}
+
+static struct ir_raw_handler rc5_sz_handler = {
+	.protocols	= IR_TYPE_RC5_SZ,
+	.decode		= ir_rc5_sz_decode,
+};
+
+static int __init ir_rc5_sz_decode_init(void)
+{
+	ir_raw_handler_register(&rc5_sz_handler);
+
+	printk(KERN_INFO "IR RC5 (streamzap) protocol handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_rc5_sz_decode_exit(void)
+{
+	ir_raw_handler_unregister(&rc5_sz_handler);
+}
+
+module_init(ir_rc5_sz_decode_init);
+module_exit(ir_rc5_sz_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("RC5 (streamzap) IR protocol decoder");

+ 3 - 2
drivers/media/IR/ir-rc6-decoder.c

@@ -85,8 +85,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
 		return 0;
 		return 0;
 
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 3 - 2
drivers/media/IR/ir-sony-decoder.c

@@ -48,8 +48,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
 	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
 		return 0;
 		return 0;
 
 
-	if (IS_RESET(ev)) {
-		data->state = STATE_INACTIVE;
+	if (!is_timing_event(ev)) {
+		if (ev.reset)
+			data->state = STATE_INACTIVE;
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 27 - 10
drivers/media/IR/ir-sysfs.c

@@ -43,6 +43,7 @@ static struct {
 	{ IR_TYPE_RC6,		"rc-6"		},
 	{ IR_TYPE_RC6,		"rc-6"		},
 	{ IR_TYPE_JVC,		"jvc"		},
 	{ IR_TYPE_JVC,		"jvc"		},
 	{ IR_TYPE_SONY,		"sony"		},
 	{ IR_TYPE_SONY,		"sony"		},
+	{ IR_TYPE_RC5_SZ,	"rc-5-sz"	},
 	{ IR_TYPE_LIRC,		"lirc"		},
 	{ IR_TYPE_LIRC,		"lirc"		},
 };
 };
 
 
@@ -67,6 +68,10 @@ static ssize_t show_protocols(struct device *d,
 	char *tmp = buf;
 	char *tmp = buf;
 	int i;
 	int i;
 
 
+	/* Device is being removed */
+	if (!ir_dev)
+		return -EINVAL;
+
 	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
 	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
 		enabled = ir_dev->rc_tab.ir_type;
 		enabled = ir_dev->rc_tab.ir_type;
 		allowed = ir_dev->props->allowed_protos;
 		allowed = ir_dev->props->allowed_protos;
@@ -122,6 +127,10 @@ static ssize_t store_protocols(struct device *d,
 	int rc, i, count = 0;
 	int rc, i, count = 0;
 	unsigned long flags;
 	unsigned long flags;
 
 
+	/* Device is being removed */
+	if (!ir_dev)
+		return -EINVAL;
+
 	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
 	if (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
 		type = ir_dev->rc_tab.ir_type;
 		type = ir_dev->rc_tab.ir_type;
 	else if (ir_dev->raw)
 	else if (ir_dev->raw)
@@ -256,8 +265,6 @@ static struct device_type rc_dev_type = {
  */
  */
 int ir_register_class(struct input_dev *input_dev)
 int ir_register_class(struct input_dev *input_dev)
 {
 {
-	int rc;
-	const char *path;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 	int devno = find_first_zero_bit(&ir_core_dev_number,
 	int devno = find_first_zero_bit(&ir_core_dev_number,
 					IRRCV_NUM_DEVICES);
 					IRRCV_NUM_DEVICES);
@@ -266,17 +273,28 @@ int ir_register_class(struct input_dev *input_dev)
 		return devno;
 		return devno;
 
 
 	ir_dev->dev.type = &rc_dev_type;
 	ir_dev->dev.type = &rc_dev_type;
+	ir_dev->devno = devno;
 
 
 	ir_dev->dev.class = &ir_input_class;
 	ir_dev->dev.class = &ir_input_class;
 	ir_dev->dev.parent = input_dev->dev.parent;
 	ir_dev->dev.parent = input_dev->dev.parent;
+	input_dev->dev.parent = &ir_dev->dev;
 	dev_set_name(&ir_dev->dev, "rc%d", devno);
 	dev_set_name(&ir_dev->dev, "rc%d", devno);
 	dev_set_drvdata(&ir_dev->dev, ir_dev);
 	dev_set_drvdata(&ir_dev->dev, ir_dev);
-	rc = device_register(&ir_dev->dev);
-	if (rc)
-		return rc;
+	return  device_register(&ir_dev->dev);
+};
+
+/**
+ * ir_register_input - registers ir input device with input subsystem
+ * @input_dev:	the struct input_dev descriptor of the device
+ */
+
+int ir_register_input(struct input_dev *input_dev)
+{
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	int rc;
+	const char *path;
 
 
 
 
-	input_dev->dev.parent = &ir_dev->dev;
 	rc = input_register_device(input_dev);
 	rc = input_register_device(input_dev);
 	if (rc < 0) {
 	if (rc < 0) {
 		device_del(&ir_dev->dev);
 		device_del(&ir_dev->dev);
@@ -292,11 +310,9 @@ int ir_register_class(struct input_dev *input_dev)
 		path ? path : "N/A");
 		path ? path : "N/A");
 	kfree(path);
 	kfree(path);
 
 
-	ir_dev->devno = devno;
-	set_bit(devno, &ir_core_dev_number);
-
+	set_bit(ir_dev->devno, &ir_core_dev_number);
 	return 0;
 	return 0;
-};
+}
 
 
 /**
 /**
  * ir_unregister_class() - removes the sysfs for sysfs for
  * ir_unregister_class() - removes the sysfs for sysfs for
@@ -309,6 +325,7 @@ void ir_unregister_class(struct input_dev *input_dev)
 {
 {
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 
 
+	input_set_drvdata(input_dev, NULL);
 	clear_bit(ir_dev->devno, &ir_core_dev_number);
 	clear_bit(ir_dev->devno, &ir_core_dev_number);
 	input_unregister_device(input_dev);
 	input_unregister_device(input_dev);
 	device_del(&ir_dev->dev);
 	device_del(&ir_dev->dev);

+ 15 - 1
drivers/media/IR/keymaps/Makefile

@@ -1,4 +1,6 @@
 obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
+			rc-alink-dtu-m.o \
+			rc-anysee.o \
 			rc-apac-viewcomp.o \
 			rc-apac-viewcomp.o \
 			rc-asus-pc39.o \
 			rc-asus-pc39.o \
 			rc-ati-tv-wonder-hd-600.o \
 			rc-ati-tv-wonder-hd-600.o \
@@ -8,7 +10,9 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-avermedia-dvbt.o \
 			rc-avermedia-dvbt.o \
 			rc-avermedia-m135a.o \
 			rc-avermedia-m135a.o \
 			rc-avermedia-m733a-rm-k6.o \
 			rc-avermedia-m733a-rm-k6.o \
+			rc-avermedia-rm-ks.o \
 			rc-avertv-303.o \
 			rc-avertv-303.o \
+			rc-azurewave-ad-tu700.o \
 			rc-behold.o \
 			rc-behold.o \
 			rc-behold-columbus.o \
 			rc-behold-columbus.o \
 			rc-budget-ci-old.o \
 			rc-budget-ci-old.o \
@@ -16,6 +20,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-cinergy.o \
 			rc-cinergy.o \
 			rc-dib0700-nec.o \
 			rc-dib0700-nec.o \
 			rc-dib0700-rc5.o \
 			rc-dib0700-rc5.o \
+			rc-digitalnow-tinytwin.o \
+			rc-digittrade.o \
 			rc-dm1105-nec.o \
 			rc-dm1105-nec.o \
 			rc-dntv-live-dvb-t.o \
 			rc-dntv-live-dvb-t.o \
 			rc-dntv-live-dvbt-pro.o \
 			rc-dntv-live-dvbt-pro.o \
@@ -38,8 +44,12 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-kaiomy.o \
 			rc-kaiomy.o \
 			rc-kworld-315u.o \
 			rc-kworld-315u.o \
 			rc-kworld-plus-tv-analog.o \
 			rc-kworld-plus-tv-analog.o \
+			rc-leadtek-y04g0051.o \
 			rc-lirc.o \
 			rc-lirc.o \
+			rc-lme2510.o \
 			rc-manli.o \
 			rc-manli.o \
+			rc-msi-digivox-ii.o \
+			rc-msi-digivox-iii.o \
 			rc-msi-tvanywhere.o \
 			rc-msi-tvanywhere.o \
 			rc-msi-tvanywhere-plus.o \
 			rc-msi-tvanywhere-plus.o \
 			rc-nebula.o \
 			rc-nebula.o \
@@ -58,14 +68,18 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-purpletv.o \
 			rc-purpletv.o \
 			rc-pv951.o \
 			rc-pv951.o \
 			rc-rc5-hauppauge-new.o \
 			rc-rc5-hauppauge-new.o \
-			rc-rc5-streamzap.o \
 			rc-rc5-tv.o \
 			rc-rc5-tv.o \
 			rc-rc6-mce.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
 			rc-real-audio-220-32-keys.o \
+			rc-streamzap.o \
 			rc-tbs-nec.o \
 			rc-tbs-nec.o \
 			rc-terratec-cinergy-xs.o \
 			rc-terratec-cinergy-xs.o \
+			rc-terratec-slim.o \
 			rc-tevii-nec.o \
 			rc-tevii-nec.o \
+			rc-total-media-in-hand.o \
+			rc-trekstor.o \
 			rc-tt-1500.o \
 			rc-tt-1500.o \
+			rc-twinhan1027.o \
 			rc-videomate-s350.o \
 			rc-videomate-s350.o \
 			rc-videomate-tv-pvr.o \
 			rc-videomate-tv-pvr.o \
 			rc-winfast.o \
 			rc-winfast.o \

+ 68 - 0
drivers/media/IR/keymaps/rc-alink-dtu-m.c

@@ -0,0 +1,68 @@
+/*
+ * A-Link DTU(m) remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
+static struct ir_scancode alink_dtu_m[] = {
+	{ 0x0800, KEY_VOLUMEUP },
+	{ 0x0801, KEY_1 },
+	{ 0x0802, KEY_3 },
+	{ 0x0803, KEY_7 },
+	{ 0x0804, KEY_9 },
+	{ 0x0805, KEY_NEW },             /* symbol: PIP */
+	{ 0x0806, KEY_0 },
+	{ 0x0807, KEY_CHANNEL },         /* JUMP */
+	{ 0x080d, KEY_5 },
+	{ 0x080f, KEY_2 },
+	{ 0x0812, KEY_POWER2 },
+	{ 0x0814, KEY_CHANNELUP },
+	{ 0x0816, KEY_VOLUMEDOWN },
+	{ 0x0818, KEY_6 },
+	{ 0x081a, KEY_MUTE },
+	{ 0x081b, KEY_8 },
+	{ 0x081c, KEY_4 },
+	{ 0x081d, KEY_CHANNELDOWN },
+};
+
+static struct rc_keymap alink_dtu_m_map = {
+	.map = {
+		.scan    = alink_dtu_m,
+		.size    = ARRAY_SIZE(alink_dtu_m),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_ALINK_DTU_M,
+	}
+};
+
+static int __init init_rc_map_alink_dtu_m(void)
+{
+	return ir_register_map(&alink_dtu_m_map);
+}
+
+static void __exit exit_rc_map_alink_dtu_m(void)
+{
+	ir_unregister_map(&alink_dtu_m_map);
+}
+
+module_init(init_rc_map_alink_dtu_m)
+module_exit(exit_rc_map_alink_dtu_m)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 93 - 0
drivers/media/IR/keymaps/rc-anysee.c

@@ -0,0 +1,93 @@
+/*
+ * Anysee remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode anysee[] = {
+	{ 0x0800, KEY_0 },
+	{ 0x0801, KEY_1 },
+	{ 0x0802, KEY_2 },
+	{ 0x0803, KEY_3 },
+	{ 0x0804, KEY_4 },
+	{ 0x0805, KEY_5 },
+	{ 0x0806, KEY_6 },
+	{ 0x0807, KEY_7 },
+	{ 0x0808, KEY_8 },
+	{ 0x0809, KEY_9 },
+	{ 0x080a, KEY_POWER2 },          /* [red power button] */
+	{ 0x080b, KEY_VIDEO },           /* [*] MODE */
+	{ 0x080c, KEY_CHANNEL },         /* [symbol counterclockwise arrow] */
+	{ 0x080d, KEY_NEXT },            /* [>>|] */
+	{ 0x080e, KEY_MENU },            /* MENU */
+	{ 0x080f, KEY_EPG },             /* [EPG] */
+	{ 0x0810, KEY_CLEAR },           /* EXIT */
+	{ 0x0811, KEY_CHANNELUP },
+	{ 0x0812, KEY_VOLUMEDOWN },
+	{ 0x0813, KEY_VOLUMEUP },
+	{ 0x0814, KEY_CHANNELDOWN },
+	{ 0x0815, KEY_OK },
+	{ 0x0816, KEY_RADIO },           /* [symbol TV/radio] */
+	{ 0x0817, KEY_INFO },            /* [i] */
+	{ 0x0818, KEY_PREVIOUS },        /* [|<<] */
+	{ 0x0819, KEY_FAVORITES },       /* FAV. */
+	{ 0x081a, KEY_SUBTITLE },        /* Subtitle */
+	{ 0x081b, KEY_CAMERA },          /* [symbol camera] */
+	{ 0x081c, KEY_YELLOW },
+	{ 0x081d, KEY_RED },
+	{ 0x081e, KEY_LANGUAGE },        /* [symbol Second Audio Program] */
+	{ 0x081f, KEY_GREEN },
+	{ 0x0820, KEY_SLEEP },           /* Sleep */
+	{ 0x0821, KEY_SCREEN },          /* 16:9 / 4:3 */
+	{ 0x0822, KEY_ZOOM },            /* SIZE */
+	{ 0x0824, KEY_FN },              /* [F1] */
+	{ 0x0825, KEY_FN },              /* [F2] */
+	{ 0x0842, KEY_MUTE },            /* symbol mute */
+	{ 0x0844, KEY_BLUE },
+	{ 0x0847, KEY_TEXT },            /* TEXT */
+	{ 0x0848, KEY_STOP },
+	{ 0x0849, KEY_RECORD },
+	{ 0x0850, KEY_PLAY },
+	{ 0x0851, KEY_PAUSE },
+};
+
+static struct rc_keymap anysee_map = {
+	.map = {
+		.scan    = anysee,
+		.size    = ARRAY_SIZE(anysee),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_ANYSEE,
+	}
+};
+
+static int __init init_rc_map_anysee(void)
+{
+	return ir_register_map(&anysee_map);
+}
+
+static void __exit exit_rc_map_anysee(void)
+{
+	ir_unregister_map(&anysee_map);
+}
+
+module_init(init_rc_map_anysee)
+module_exit(exit_rc_map_anysee)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 40 - 40
drivers/media/IR/keymaps/rc-asus-pc39.c

@@ -20,56 +20,56 @@
 
 
 static struct ir_scancode asus_pc39[] = {
 static struct ir_scancode asus_pc39[] = {
 	/* Keys 0 to 9 */
 	/* Keys 0 to 9 */
-	{ 0x15, KEY_0 },
-	{ 0x29, KEY_1 },
-	{ 0x2d, KEY_2 },
-	{ 0x2b, KEY_3 },
-	{ 0x09, KEY_4 },
-	{ 0x0d, KEY_5 },
-	{ 0x0b, KEY_6 },
-	{ 0x31, KEY_7 },
-	{ 0x35, KEY_8 },
-	{ 0x33, KEY_9 },
+	{ 0x082a, KEY_0 },
+	{ 0x0816, KEY_1 },
+	{ 0x0812, KEY_2 },
+	{ 0x0814, KEY_3 },
+	{ 0x0836, KEY_4 },
+	{ 0x0832, KEY_5 },
+	{ 0x0834, KEY_6 },
+	{ 0x080e, KEY_7 },
+	{ 0x080a, KEY_8 },
+	{ 0x080c, KEY_9 },
 
 
-	{ 0x3e, KEY_RADIO },		/* radio */
-	{ 0x03, KEY_MENU },		/* dvd/menu */
-	{ 0x2a, KEY_VOLUMEUP },
-	{ 0x19, KEY_VOLUMEDOWN },
-	{ 0x37, KEY_UP },
-	{ 0x3b, KEY_DOWN },
-	{ 0x27, KEY_LEFT },
-	{ 0x2f, KEY_RIGHT },
-	{ 0x25, KEY_VIDEO },		/* video */
-	{ 0x39, KEY_AUDIO },		/* music */
+	{ 0x0801, KEY_RADIO },		/* radio */
+	{ 0x083c, KEY_MENU },		/* dvd/menu */
+	{ 0x0815, KEY_VOLUMEUP },
+	{ 0x0826, KEY_VOLUMEDOWN },
+	{ 0x0808, KEY_UP },
+	{ 0x0804, KEY_DOWN },
+	{ 0x0818, KEY_LEFT },
+	{ 0x0810, KEY_RIGHT },
+	{ 0x081a, KEY_VIDEO },		/* video */
+	{ 0x0806, KEY_AUDIO },		/* music */
 
 
-	{ 0x21, KEY_TV },		/* tv */
-	{ 0x1d, KEY_EXIT },		/* back */
-	{ 0x0a, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x1b, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x1a, KEY_ENTER },		/* enter */
+	{ 0x081e, KEY_TV },		/* tv */
+	{ 0x0822, KEY_EXIT },		/* back */
+	{ 0x0835, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x0824, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x0825, KEY_ENTER },		/* enter */
 
 
-	{ 0x06, KEY_PAUSE },		/* play/pause */
-	{ 0x1e, KEY_PREVIOUS },		/* rew */
-	{ 0x26, KEY_NEXT },		/* forward */
-	{ 0x0e, KEY_REWIND },		/* backward << */
-	{ 0x3a, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x36, KEY_STOP },
-	{ 0x2e, KEY_RECORD },		/* recording */
-	{ 0x16, KEY_POWER },		/* the button that reads "close" */
+	{ 0x0839, KEY_PAUSE },		/* play/pause */
+	{ 0x0821, KEY_PREVIOUS },		/* rew */
+	{ 0x0819, KEY_NEXT },		/* forward */
+	{ 0x0831, KEY_REWIND },		/* backward << */
+	{ 0x0805, KEY_FASTFORWARD },	/* forward >> */
+	{ 0x0809, KEY_STOP },
+	{ 0x0811, KEY_RECORD },		/* recording */
+	{ 0x0829, KEY_POWER },		/* the button that reads "close" */
 
 
-	{ 0x11, KEY_ZOOM },		/* full screen */
-	{ 0x13, KEY_MACRO },		/* recall */
-	{ 0x23, KEY_HOME },		/* home */
-	{ 0x05, KEY_PVR },		/* picture */
-	{ 0x3d, KEY_MUTE },		/* mute */
-	{ 0x01, KEY_DVD },		/* dvd */
+	{ 0x082e, KEY_ZOOM },		/* full screen */
+	{ 0x082c, KEY_MACRO },		/* recall */
+	{ 0x081c, KEY_HOME },		/* home */
+	{ 0x083a, KEY_PVR },		/* picture */
+	{ 0x0802, KEY_MUTE },		/* mute */
+	{ 0x083e, KEY_DVD },		/* dvd */
 };
 };
 
 
 static struct rc_keymap asus_pc39_map = {
 static struct rc_keymap asus_pc39_map = {
 	.map = {
 	.map = {
 		.scan    = asus_pc39,
 		.scan    = asus_pc39,
 		.size    = ARRAY_SIZE(asus_pc39),
 		.size    = ARRAY_SIZE(asus_pc39),
-		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
+		.ir_type = IR_TYPE_RC5,
 		.name    = RC_MAP_ASUS_PC39,
 		.name    = RC_MAP_ASUS_PC39,
 	}
 	}
 };
 };

+ 79 - 0
drivers/media/IR/keymaps/rc-avermedia-rm-ks.c

@@ -0,0 +1,79 @@
+/*
+ * AverMedia RM-KS remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
+   and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
+/* FIXME: mappings are not 100% correct? */
+static struct ir_scancode avermedia_rm_ks[] = {
+	{ 0x0501, KEY_POWER2 },
+	{ 0x0502, KEY_CHANNELUP },
+	{ 0x0503, KEY_CHANNELDOWN },
+	{ 0x0504, KEY_VOLUMEUP },
+	{ 0x0505, KEY_VOLUMEDOWN },
+	{ 0x0506, KEY_MUTE },
+	{ 0x0507, KEY_RIGHT },
+	{ 0x0508, KEY_PROG1 },
+	{ 0x0509, KEY_1 },
+	{ 0x050a, KEY_2 },
+	{ 0x050b, KEY_3 },
+	{ 0x050c, KEY_4 },
+	{ 0x050d, KEY_5 },
+	{ 0x050e, KEY_6 },
+	{ 0x050f, KEY_7 },
+	{ 0x0510, KEY_8 },
+	{ 0x0511, KEY_9 },
+	{ 0x0512, KEY_0 },
+	{ 0x0513, KEY_AUDIO },
+	{ 0x0515, KEY_EPG },
+	{ 0x0516, KEY_PLAY },
+	{ 0x0517, KEY_RECORD },
+	{ 0x0518, KEY_STOP },
+	{ 0x051c, KEY_BACK },
+	{ 0x051d, KEY_FORWARD },
+	{ 0x054d, KEY_LEFT },
+	{ 0x0556, KEY_ZOOM },
+};
+
+static struct rc_keymap avermedia_rm_ks_map = {
+	.map = {
+		.scan    = avermedia_rm_ks,
+		.size    = ARRAY_SIZE(avermedia_rm_ks),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_AVERMEDIA_RM_KS,
+	}
+};
+
+static int __init init_rc_map_avermedia_rm_ks(void)
+{
+	return ir_register_map(&avermedia_rm_ks_map);
+}
+
+static void __exit exit_rc_map_avermedia_rm_ks(void)
+{
+	ir_unregister_map(&avermedia_rm_ks_map);
+}
+
+module_init(init_rc_map_avermedia_rm_ks)
+module_exit(exit_rc_map_avermedia_rm_ks)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 102 - 0
drivers/media/IR/keymaps/rc-azurewave-ad-tu700.c

@@ -0,0 +1,102 @@
+/*
+ * TwinHan AzureWave AD-TU700(704J) remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode azurewave_ad_tu700[] = {
+	{ 0x0000, KEY_TAB },             /* Tab */
+	{ 0x0001, KEY_2 },
+	{ 0x0002, KEY_CHANNELDOWN },
+	{ 0x0003, KEY_1 },
+	{ 0x0004, KEY_MENU },            /* Record List */
+	{ 0x0005, KEY_CHANNELUP },
+	{ 0x0006, KEY_3 },
+	{ 0x0007, KEY_SLEEP },           /* Hibernate */
+	{ 0x0008, KEY_VIDEO },           /* A/V */
+	{ 0x0009, KEY_4 },
+	{ 0x000a, KEY_VOLUMEDOWN },
+	{ 0x000c, KEY_CANCEL },          /* Cancel */
+	{ 0x000d, KEY_7 },
+	{ 0x000e, KEY_AGAIN },           /* Recall */
+	{ 0x000f, KEY_TEXT },            /* Teletext */
+	{ 0x0010, KEY_MUTE },
+	{ 0x0011, KEY_RECORD },
+	{ 0x0012, KEY_FASTFORWARD },     /* FF >> */
+	{ 0x0013, KEY_BACK },            /* Back */
+	{ 0x0014, KEY_PLAY },
+	{ 0x0015, KEY_0 },
+	{ 0x0016, KEY_POWER2 },          /* [red power button] */
+	{ 0x0017, KEY_FAVORITES },       /* Favorite List */
+	{ 0x0018, KEY_RED },
+	{ 0x0019, KEY_8 },
+	{ 0x001a, KEY_STOP },
+	{ 0x001b, KEY_9 },
+	{ 0x001c, KEY_EPG },             /* Info/EPG */
+	{ 0x001d, KEY_5 },
+	{ 0x001e, KEY_VOLUMEUP },
+	{ 0x001f, KEY_6 },
+	{ 0x0040, KEY_REWIND },          /* FR << */
+	{ 0x0041, KEY_PREVIOUS },        /* Replay */
+	{ 0x0042, KEY_NEXT },            /* Skip */
+	{ 0x0043, KEY_SUBTITLE },        /* Subtitle / CC */
+	{ 0x0045, KEY_KPPLUS },          /* Zoom+ */
+	{ 0x0046, KEY_KPMINUS },         /* Zoom- */
+	{ 0x0047, KEY_NEW },             /* PIP */
+	{ 0x0048, KEY_INFO },            /* Preview */
+	{ 0x0049, KEY_MODE },            /* L/R */
+	{ 0x004a, KEY_CLEAR },           /* Clear */
+	{ 0x004b, KEY_UP },              /* up arrow */
+	{ 0x004c, KEY_PAUSE },
+	{ 0x004d, KEY_ZOOM },            /* Full Screen */
+	{ 0x004e, KEY_LEFT },            /* left arrow */
+	{ 0x004f, KEY_OK },              /* Enter / ok */
+	{ 0x0050, KEY_LANGUAGE },        /* SAP */
+	{ 0x0051, KEY_DOWN },            /* down arrow */
+	{ 0x0052, KEY_RIGHT },           /* right arrow */
+	{ 0x0053, KEY_GREEN },
+	{ 0x0054, KEY_CAMERA },          /* Capture */
+	{ 0x005e, KEY_YELLOW },
+	{ 0x005f, KEY_BLUE },
+};
+
+static struct rc_keymap azurewave_ad_tu700_map = {
+	.map = {
+		.scan    = azurewave_ad_tu700,
+		.size    = ARRAY_SIZE(azurewave_ad_tu700),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_AZUREWAVE_AD_TU700,
+	}
+};
+
+static int __init init_rc_map_azurewave_ad_tu700(void)
+{
+	return ir_register_map(&azurewave_ad_tu700_map);
+}
+
+static void __exit exit_rc_map_azurewave_ad_tu700(void)
+{
+	ir_unregister_map(&azurewave_ad_tu700_map);
+}
+
+module_init(init_rc_map_azurewave_ad_tu700)
+module_exit(exit_rc_map_azurewave_ad_tu700)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 98 - 0
drivers/media/IR/keymaps/rc-digitalnow-tinytwin.c

@@ -0,0 +1,98 @@
+/*
+ * DigitalNow TinyTwin remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode digitalnow_tinytwin[] = {
+	{ 0x0000, KEY_MUTE },            /* [symbol speaker] */
+	{ 0x0001, KEY_VOLUMEUP },
+	{ 0x0002, KEY_POWER2 },          /* TV [power button] */
+	{ 0x0003, KEY_2 },
+	{ 0x0004, KEY_3 },
+	{ 0x0005, KEY_4 },
+	{ 0x0006, KEY_6 },
+	{ 0x0007, KEY_7 },
+	{ 0x0008, KEY_8 },
+	{ 0x0009, KEY_NUMERIC_STAR },    /* [*] */
+	{ 0x000a, KEY_0 },
+	{ 0x000b, KEY_NUMERIC_POUND },   /* [#] */
+	{ 0x000c, KEY_RIGHT },           /* [right arrow] */
+	{ 0x000d, KEY_HOMEPAGE },        /* [symbol home] Start */
+	{ 0x000e, KEY_RED },             /* [red] Videos */
+	{ 0x0010, KEY_POWER },           /* PC [power button] */
+	{ 0x0011, KEY_YELLOW },          /* [yellow] Pictures */
+	{ 0x0012, KEY_DOWN },            /* [down arrow] */
+	{ 0x0013, KEY_GREEN },           /* [green] Music */
+	{ 0x0014, KEY_CYCLEWINDOWS },    /* BACK */
+	{ 0x0015, KEY_FAVORITES },       /* MORE */
+	{ 0x0016, KEY_UP },              /* [up arrow] */
+	{ 0x0017, KEY_LEFT },            /* [left arrow] */
+	{ 0x0018, KEY_OK },              /* OK */
+	{ 0x0019, KEY_BLUE },            /* [blue] MyTV */
+	{ 0x001a, KEY_REWIND },          /* REW [<<] */
+	{ 0x001b, KEY_PLAY },            /* PLAY */
+	{ 0x001c, KEY_5 },
+	{ 0x001d, KEY_9 },
+	{ 0x001e, KEY_VOLUMEDOWN },
+	{ 0x001f, KEY_1 },
+	{ 0x0040, KEY_STOP },            /* STOP */
+	{ 0x0042, KEY_PAUSE },           /* PAUSE */
+	{ 0x0043, KEY_SCREEN },          /* Aspect */
+	{ 0x0044, KEY_FORWARD },         /* FWD [>>] */
+	{ 0x0045, KEY_NEXT },            /* SKIP */
+	{ 0x0048, KEY_RECORD },          /* RECORD */
+	{ 0x0049, KEY_VIDEO },           /* RTV */
+	{ 0x004a, KEY_EPG },             /* Guide */
+	{ 0x004b, KEY_CHANNELUP },
+	{ 0x004c, KEY_HELP },            /* Help */
+	{ 0x004d, KEY_RADIO },           /* Radio */
+	{ 0x004f, KEY_CHANNELDOWN },
+	{ 0x0050, KEY_DVD },             /* DVD */
+	{ 0x0051, KEY_AUDIO },           /* Audio */
+	{ 0x0052, KEY_TITLE },           /* Title */
+	{ 0x0053, KEY_NEW },             /* [symbol PIP?] */
+	{ 0x0057, KEY_MENU },            /* Mouse */
+	{ 0x005a, KEY_PREVIOUS },        /* REPLAY */
+};
+
+static struct rc_keymap digitalnow_tinytwin_map = {
+	.map = {
+		.scan    = digitalnow_tinytwin,
+		.size    = ARRAY_SIZE(digitalnow_tinytwin),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_DIGITALNOW_TINYTWIN,
+	}
+};
+
+static int __init init_rc_map_digitalnow_tinytwin(void)
+{
+	return ir_register_map(&digitalnow_tinytwin_map);
+}
+
+static void __exit exit_rc_map_digitalnow_tinytwin(void)
+{
+	ir_unregister_map(&digitalnow_tinytwin_map);
+}
+
+module_init(init_rc_map_digitalnow_tinytwin)
+module_exit(exit_rc_map_digitalnow_tinytwin)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 82 - 0
drivers/media/IR/keymaps/rc-digittrade.c

@@ -0,0 +1,82 @@
+/*
+ * Digittrade DVB-T USB Stick remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* Digittrade DVB-T USB Stick remote controller. */
+/* Imported from af9015.h.
+   Initial keytable was from Alain Kalker <miki@dds.nl> */
+
+/* Digittrade DVB-T USB Stick */
+static struct ir_scancode digittrade[] = {
+	{ 0x0000, KEY_9 },
+	{ 0x0001, KEY_EPG },             /* EPG */
+	{ 0x0002, KEY_VOLUMEDOWN },      /* Vol Dn */
+	{ 0x0003, KEY_TEXT },            /* TELETEXT */
+	{ 0x0004, KEY_8 },
+	{ 0x0005, KEY_MUTE },            /* MUTE */
+	{ 0x0006, KEY_POWER2 },          /* POWER */
+	{ 0x0009, KEY_ZOOM },            /* FULLSCREEN */
+	{ 0x000a, KEY_RECORD },          /* RECORD */
+	{ 0x000d, KEY_SUBTITLE },        /* SUBTITLE */
+	{ 0x000e, KEY_STOP },            /* STOP */
+	{ 0x0010, KEY_OK },              /* RETURN */
+	{ 0x0011, KEY_2 },
+	{ 0x0012, KEY_4 },
+	{ 0x0015, KEY_3 },
+	{ 0x0016, KEY_5 },
+	{ 0x0017, KEY_CHANNELDOWN },     /* Ch Dn */
+	{ 0x0019, KEY_CHANNELUP },       /* CH Up */
+	{ 0x001a, KEY_PAUSE },           /* PAUSE */
+	{ 0x001b, KEY_1 },
+	{ 0x001d, KEY_AUDIO },           /* DUAL SOUND */
+	{ 0x001e, KEY_PLAY },            /* PLAY */
+	{ 0x001f, KEY_CAMERA },          /* SNAPSHOT */
+	{ 0x0040, KEY_VOLUMEUP },        /* Vol Up */
+	{ 0x0048, KEY_7 },
+	{ 0x004c, KEY_6 },
+	{ 0x004d, KEY_PLAYPAUSE },       /* TIMESHIFT */
+	{ 0x0054, KEY_0 },
+};
+
+static struct rc_keymap digittrade_map = {
+	.map = {
+		.scan    = digittrade,
+		.size    = ARRAY_SIZE(digittrade),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_DIGITTRADE,
+	}
+};
+
+static int __init init_rc_map_digittrade(void)
+{
+	return ir_register_map(&digittrade_map);
+}
+
+static void __exit exit_rc_map_digittrade(void)
+{
+	ir_unregister_map(&digittrade_map);
+}
+
+module_init(init_rc_map_digittrade)
+module_exit(exit_rc_map_digittrade)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 99 - 0
drivers/media/IR/keymaps/rc-leadtek-y04g0051.c

@@ -0,0 +1,99 @@
+/*
+ * LeadTek Y04G0051 remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode leadtek_y04g0051[] = {
+	{ 0x0300, KEY_POWER2 },
+	{ 0x0303, KEY_SCREEN },
+	{ 0x0304, KEY_RIGHT },
+	{ 0x0305, KEY_1 },
+	{ 0x0306, KEY_2 },
+	{ 0x0307, KEY_3 },
+	{ 0x0308, KEY_LEFT },
+	{ 0x0309, KEY_4 },
+	{ 0x030a, KEY_5 },
+	{ 0x030b, KEY_6 },
+	{ 0x030c, KEY_UP },
+	{ 0x030d, KEY_7 },
+	{ 0x030e, KEY_8 },
+	{ 0x030f, KEY_9 },
+	{ 0x0310, KEY_DOWN },
+	{ 0x0311, KEY_AGAIN },
+	{ 0x0312, KEY_0 },
+	{ 0x0313, KEY_OK },              /* 1st ok */
+	{ 0x0314, KEY_MUTE },
+	{ 0x0316, KEY_OK },              /* 2nd ok */
+	{ 0x031e, KEY_VIDEO },           /* 2nd video */
+	{ 0x031b, KEY_AUDIO },
+	{ 0x031f, KEY_TEXT },
+	{ 0x0340, KEY_SLEEP },
+	{ 0x0341, KEY_DOT },
+	{ 0x0342, KEY_REWIND },
+	{ 0x0343, KEY_PLAY },
+	{ 0x0344, KEY_FASTFORWARD },
+	{ 0x0345, KEY_TIME },
+	{ 0x0346, KEY_STOP },            /* 2nd stop */
+	{ 0x0347, KEY_RECORD },
+	{ 0x0348, KEY_CAMERA },
+	{ 0x0349, KEY_ESC },
+	{ 0x034a, KEY_NEW },
+	{ 0x034b, KEY_RED },
+	{ 0x034c, KEY_GREEN },
+	{ 0x034d, KEY_YELLOW },
+	{ 0x034e, KEY_BLUE },
+	{ 0x034f, KEY_MENU },
+	{ 0x0350, KEY_STOP },            /* 1st stop */
+	{ 0x0351, KEY_CHANNEL },
+	{ 0x0352, KEY_VIDEO },           /* 1st video */
+	{ 0x0353, KEY_EPG },
+	{ 0x0354, KEY_PREVIOUS },
+	{ 0x0355, KEY_NEXT },
+	{ 0x0356, KEY_TV },
+	{ 0x035a, KEY_VOLUMEDOWN },
+	{ 0x035b, KEY_CHANNELUP },
+	{ 0x035e, KEY_VOLUMEUP },
+	{ 0x035f, KEY_CHANNELDOWN },
+};
+
+static struct rc_keymap leadtek_y04g0051_map = {
+	.map = {
+		.scan    = leadtek_y04g0051,
+		.size    = ARRAY_SIZE(leadtek_y04g0051),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_LEADTEK_Y04G0051,
+	}
+};
+
+static int __init init_rc_map_leadtek_y04g0051(void)
+{
+	return ir_register_map(&leadtek_y04g0051_map);
+}
+
+static void __exit exit_rc_map_leadtek_y04g0051(void)
+{
+	ir_unregister_map(&leadtek_y04g0051_map);
+}
+
+module_init(init_rc_map_leadtek_y04g0051)
+module_exit(exit_rc_map_leadtek_y04g0051)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 68 - 0
drivers/media/IR/keymaps/rc-lme2510.c

@@ -0,0 +1,68 @@
+/* LME2510 remote control
+ *
+ *
+ * Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+
+
+static struct ir_scancode lme2510_rc[] = {
+	{ 0xba45, KEY_0 },
+	{ 0xa05f, KEY_1 },
+	{ 0xaf50, KEY_2 },
+	{ 0xa25d, KEY_3 },
+	{ 0xbe41, KEY_4 },
+	{ 0xf50a, KEY_5 },
+	{ 0xbd42, KEY_6 },
+	{ 0xb847, KEY_7 },
+	{ 0xb649, KEY_8 },
+	{ 0xfa05, KEY_9 },
+	{ 0xbc43, KEY_POWER },
+	{ 0xb946, KEY_SUBTITLE },
+	{ 0xf906, KEY_PAUSE },
+	{ 0xfc03, KEY_MEDIA_REPEAT},
+	{ 0xfd02, KEY_PAUSE },
+	{ 0xa15e, KEY_VOLUMEUP },
+	{ 0xa35c, KEY_VOLUMEDOWN },
+	{ 0xf609, KEY_CHANNELUP },
+	{ 0xe51a, KEY_CHANNELDOWN },
+	{ 0xe11e, KEY_PLAY },
+	{ 0xe41b, KEY_ZOOM },
+	{ 0xa659, KEY_MUTE },
+	{ 0xa55a, KEY_TV },
+	{ 0xe718, KEY_RECORD },
+	{ 0xf807, KEY_EPG },
+	{ 0xfe01, KEY_STOP },
+
+};
+
+static struct rc_keymap lme2510_map = {
+	.map = {
+		.scan    = lme2510_rc,
+		.size    = ARRAY_SIZE(lme2510_rc),
+		.ir_type = IR_TYPE_UNKNOWN,
+		.name    = RC_MAP_LME2510,
+	}
+};
+
+static int __init init_rc_lme2510_map(void)
+{
+	return ir_register_map(&lme2510_map);
+}
+
+static void __exit exit_rc_lme2510_map(void)
+{
+	ir_unregister_map(&lme2510_map);
+}
+
+module_init(init_rc_lme2510_map)
+module_exit(exit_rc_lme2510_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");

+ 67 - 0
drivers/media/IR/keymaps/rc-msi-digivox-ii.c

@@ -0,0 +1,67 @@
+/*
+ * MSI DIGIVOX mini II remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode msi_digivox_ii[] = {
+	{ 0x0002, KEY_2 },
+	{ 0x0003, KEY_UP },              /* up */
+	{ 0x0004, KEY_3 },
+	{ 0x0005, KEY_CHANNELDOWN },
+	{ 0x0008, KEY_5 },
+	{ 0x0009, KEY_0 },
+	{ 0x000b, KEY_8 },
+	{ 0x000d, KEY_DOWN },            /* down */
+	{ 0x0010, KEY_9 },
+	{ 0x0011, KEY_7 },
+	{ 0x0014, KEY_VOLUMEUP },
+	{ 0x0015, KEY_CHANNELUP },
+	{ 0x0016, KEY_OK },
+	{ 0x0017, KEY_POWER2 },
+	{ 0x001a, KEY_1 },
+	{ 0x001c, KEY_4 },
+	{ 0x001d, KEY_6 },
+	{ 0x001f, KEY_VOLUMEDOWN },
+};
+
+static struct rc_keymap msi_digivox_ii_map = {
+	.map = {
+		.scan    = msi_digivox_ii,
+		.size    = ARRAY_SIZE(msi_digivox_ii),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_MSI_DIGIVOX_II,
+	}
+};
+
+static int __init init_rc_map_msi_digivox_ii(void)
+{
+	return ir_register_map(&msi_digivox_ii_map);
+}
+
+static void __exit exit_rc_map_msi_digivox_ii(void)
+{
+	ir_unregister_map(&msi_digivox_ii_map);
+}
+
+module_init(init_rc_map_msi_digivox_ii)
+module_exit(exit_rc_map_msi_digivox_ii)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 85 - 0
drivers/media/IR/keymaps/rc-msi-digivox-iii.c

@@ -0,0 +1,85 @@
+/*
+ * MSI DIGIVOX mini III remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* MSI DIGIVOX mini III */
+/* Uses NEC extended 0x61d6. */
+/* This remote seems to be same as rc-kworld-315u.c. Anyhow, add new remote
+   since rc-kworld-315u.c lacks NEC extended address byte. */
+static struct ir_scancode msi_digivox_iii[] = {
+	{ 0x61d601, KEY_VIDEO },           /* Source */
+	{ 0x61d602, KEY_3 },
+	{ 0x61d603, KEY_POWER },           /* ShutDown */
+	{ 0x61d604, KEY_1 },
+	{ 0x61d605, KEY_5 },
+	{ 0x61d606, KEY_6 },
+	{ 0x61d607, KEY_CHANNELDOWN },     /* CH- */
+	{ 0x61d608, KEY_2 },
+	{ 0x61d609, KEY_CHANNELUP },       /* CH+ */
+	{ 0x61d60a, KEY_9 },
+	{ 0x61d60b, KEY_ZOOM },            /* Zoom */
+	{ 0x61d60c, KEY_7 },
+	{ 0x61d60d, KEY_8 },
+	{ 0x61d60e, KEY_VOLUMEUP },        /* Vol+ */
+	{ 0x61d60f, KEY_4 },
+	{ 0x61d610, KEY_ESC },             /* [back up arrow] */
+	{ 0x61d611, KEY_0 },
+	{ 0x61d612, KEY_OK },              /* [enter arrow] */
+	{ 0x61d613, KEY_VOLUMEDOWN },      /* Vol- */
+	{ 0x61d614, KEY_RECORD },          /* Rec */
+	{ 0x61d615, KEY_STOP },            /* Stop */
+	{ 0x61d616, KEY_PLAY },            /* Play */
+	{ 0x61d617, KEY_MUTE },            /* Mute */
+	{ 0x61d618, KEY_UP },
+	{ 0x61d619, KEY_DOWN },
+	{ 0x61d61a, KEY_LEFT },
+	{ 0x61d61b, KEY_RIGHT },
+	{ 0x61d61c, KEY_RED },
+	{ 0x61d61d, KEY_GREEN },
+	{ 0x61d61e, KEY_YELLOW },
+	{ 0x61d61f, KEY_BLUE },
+	{ 0x61d643, KEY_POWER2 },          /* [red power button] */
+};
+
+static struct rc_keymap msi_digivox_iii_map = {
+	.map = {
+		.scan    = msi_digivox_iii,
+		.size    = ARRAY_SIZE(msi_digivox_iii),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_MSI_DIGIVOX_III,
+	}
+};
+
+static int __init init_rc_map_msi_digivox_iii(void)
+{
+	return ir_register_map(&msi_digivox_iii_map);
+}
+
+static void __exit exit_rc_map_msi_digivox_iii(void)
+{
+	ir_unregister_map(&msi_digivox_iii_map);
+}
+
+module_init(init_rc_map_msi_digivox_iii)
+module_exit(exit_rc_map_msi_digivox_iii)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 0 - 81
drivers/media/IR/keymaps/rc-rc5-streamzap.c

@@ -1,81 +0,0 @@
-/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
- * with the Streamzap PC Remote IR Receiver.
- *
- * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <media/rc-map.h>
-
-static struct ir_scancode rc5_streamzap[] = {
-/*
- * FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
- * bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
- * We either have to enhance the decoder to support it, add a new decoder,
- * or just rely on lirc userspace decoding.
- */
-	{ 0x00, KEY_NUMERIC_0 },
-	{ 0x01, KEY_NUMERIC_1 },
-	{ 0x02, KEY_NUMERIC_2 },
-	{ 0x03, KEY_NUMERIC_3 },
-	{ 0x04, KEY_NUMERIC_4 },
-	{ 0x05, KEY_NUMERIC_5 },
-	{ 0x06, KEY_NUMERIC_6 },
-	{ 0x07, KEY_NUMERIC_7 },
-	{ 0x08, KEY_NUMERIC_8 },
-	{ 0x0a, KEY_POWER },
-	{ 0x0b, KEY_MUTE },
-	{ 0x0c, KEY_CHANNELUP },
-	{ 0x0d, KEY_VOLUMEUP },
-	{ 0x0e, KEY_CHANNELDOWN },
-	{ 0x0f, KEY_VOLUMEDOWN },
-	{ 0x10, KEY_UP },
-	{ 0x11, KEY_LEFT },
-	{ 0x12, KEY_OK },
-	{ 0x13, KEY_RIGHT },
-	{ 0x14, KEY_DOWN },
-	{ 0x15, KEY_MENU },
-	{ 0x16, KEY_EXIT },
-	{ 0x17, KEY_PLAY },
-	{ 0x18, KEY_PAUSE },
-	{ 0x19, KEY_STOP },
-	{ 0x1a, KEY_BACK },
-	{ 0x1b, KEY_FORWARD },
-	{ 0x1c, KEY_RECORD },
-	{ 0x1d, KEY_REWIND },
-	{ 0x1e, KEY_FASTFORWARD },
-	{ 0x20, KEY_RED },
-	{ 0x21, KEY_GREEN },
-	{ 0x22, KEY_YELLOW },
-	{ 0x23, KEY_BLUE },
-
-};
-
-static struct rc_keymap rc5_streamzap_map = {
-	.map = {
-		.scan    = rc5_streamzap,
-		.size    = ARRAY_SIZE(rc5_streamzap),
-		.ir_type = IR_TYPE_RC5,
-		.name    = RC_MAP_RC5_STREAMZAP,
-	}
-};
-
-static int __init init_rc_map_rc5_streamzap(void)
-{
-	return ir_register_map(&rc5_streamzap_map);
-}
-
-static void __exit exit_rc_map_rc5_streamzap(void)
-{
-	ir_unregister_map(&rc5_streamzap_map);
-}
-
-module_init(init_rc_map_rc5_streamzap)
-module_exit(exit_rc_map_rc5_streamzap)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

+ 45 - 43
drivers/media/IR/keymaps/rc-rc6-mce.c

@@ -12,76 +12,78 @@
 #include <media/rc-map.h>
 #include <media/rc-map.h>
 
 
 static struct ir_scancode rc6_mce[] = {
 static struct ir_scancode rc6_mce[] = {
-	{ 0x800f0415, KEY_REWIND },
-	{ 0x800f0414, KEY_FASTFORWARD },
-	{ 0x800f041b, KEY_PREVIOUS },
-	{ 0x800f041a, KEY_NEXT },
 
 
+	{ 0x800f0400, KEY_NUMERIC_0 },
+	{ 0x800f0401, KEY_NUMERIC_1 },
+	{ 0x800f0402, KEY_NUMERIC_2 },
+	{ 0x800f0403, KEY_NUMERIC_3 },
+	{ 0x800f0404, KEY_NUMERIC_4 },
+	{ 0x800f0405, KEY_NUMERIC_5 },
+	{ 0x800f0406, KEY_NUMERIC_6 },
+	{ 0x800f0407, KEY_NUMERIC_7 },
+	{ 0x800f0408, KEY_NUMERIC_8 },
+	{ 0x800f0409, KEY_NUMERIC_9 },
+
+	{ 0x800f040a, KEY_DELETE },
+	{ 0x800f040b, KEY_ENTER },
+	{ 0x800f040c, KEY_POWER },
+	{ 0x800f040d, KEY_PROG1 }, 		/* Windows MCE button */
+	{ 0x800f040e, KEY_MUTE },
+	{ 0x800f040f, KEY_INFO },
+
+	{ 0x800f0410, KEY_VOLUMEUP },
+	{ 0x800f0411, KEY_VOLUMEDOWN },
+	{ 0x800f0412, KEY_CHANNELUP },
+	{ 0x800f0413, KEY_CHANNELDOWN },
+
+	{ 0x800f0414, KEY_FASTFORWARD },
+	{ 0x800f0415, KEY_REWIND },
 	{ 0x800f0416, KEY_PLAY },
 	{ 0x800f0416, KEY_PLAY },
+	{ 0x800f0417, KEY_RECORD },
 	{ 0x800f0418, KEY_PAUSE },
 	{ 0x800f0418, KEY_PAUSE },
 	{ 0x800f046e, KEY_PLAYPAUSE },
 	{ 0x800f046e, KEY_PLAYPAUSE },
 	{ 0x800f0419, KEY_STOP },
 	{ 0x800f0419, KEY_STOP },
-	{ 0x800f0417, KEY_RECORD },
+	{ 0x800f041a, KEY_NEXT },
+	{ 0x800f041b, KEY_PREVIOUS },
+	{ 0x800f041c, KEY_NUMERIC_POUND },
+	{ 0x800f041d, KEY_NUMERIC_STAR },
 
 
 	{ 0x800f041e, KEY_UP },
 	{ 0x800f041e, KEY_UP },
 	{ 0x800f041f, KEY_DOWN },
 	{ 0x800f041f, KEY_DOWN },
 	{ 0x800f0420, KEY_LEFT },
 	{ 0x800f0420, KEY_LEFT },
 	{ 0x800f0421, KEY_RIGHT },
 	{ 0x800f0421, KEY_RIGHT },
 
 
-	{ 0x800f040b, KEY_ENTER },
 	{ 0x800f0422, KEY_OK },
 	{ 0x800f0422, KEY_OK },
 	{ 0x800f0423, KEY_EXIT },
 	{ 0x800f0423, KEY_EXIT },
-	{ 0x800f040a, KEY_DELETE },
+	{ 0x800f0424, KEY_DVD },
+	{ 0x800f0425, KEY_TUNER }, 		/* LiveTV */
+	{ 0x800f0426, KEY_EPG }, 		/* Guide */
+	{ 0x800f0427, KEY_ZOOM }, 		/* Aspect */
 
 
-	{ 0x800f040e, KEY_MUTE },
-	{ 0x800f0410, KEY_VOLUMEUP },
-	{ 0x800f0411, KEY_VOLUMEDOWN },
-	{ 0x800f0412, KEY_CHANNELUP },
-	{ 0x800f0413, KEY_CHANNELDOWN },
 	{ 0x800f043a, KEY_BRIGHTNESSUP },
 	{ 0x800f043a, KEY_BRIGHTNESSUP },
-	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
-
-	{ 0x800f0401, KEY_NUMERIC_1 },
-	{ 0x800f0402, KEY_NUMERIC_2 },
-	{ 0x800f0403, KEY_NUMERIC_3 },
-	{ 0x800f0404, KEY_NUMERIC_4 },
-	{ 0x800f0405, KEY_NUMERIC_5 },
-	{ 0x800f0406, KEY_NUMERIC_6 },
-	{ 0x800f0407, KEY_NUMERIC_7 },
-	{ 0x800f0408, KEY_NUMERIC_8 },
-	{ 0x800f0409, KEY_NUMERIC_9 },
-	{ 0x800f0400, KEY_NUMERIC_0 },
-
-	{ 0x800f041d, KEY_NUMERIC_STAR },
-	{ 0x800f041c, KEY_NUMERIC_POUND },
 
 
 	{ 0x800f0446, KEY_TV },
 	{ 0x800f0446, KEY_TV },
-	{ 0x800f0447, KEY_AUDIO }, /* My Music */
-	{ 0x800f0448, KEY_PVR }, /* RecordedTV */
+	{ 0x800f0447, KEY_AUDIO }, 		/* My Music */
+	{ 0x800f0448, KEY_PVR }, 		/* RecordedTV */
 	{ 0x800f0449, KEY_CAMERA },
 	{ 0x800f0449, KEY_CAMERA },
 	{ 0x800f044a, KEY_VIDEO },
 	{ 0x800f044a, KEY_VIDEO },
-	{ 0x800f0424, KEY_DVD },
-	{ 0x800f0425, KEY_TUNER }, /* LiveTV */
-	{ 0x800f0450, KEY_RADIO },
-
 	{ 0x800f044c, KEY_LANGUAGE },
 	{ 0x800f044c, KEY_LANGUAGE },
-	{ 0x800f0427, KEY_ZOOM }, /* Aspect */
+	{ 0x800f044d, KEY_TITLE },
+	{ 0x800f044e, KEY_PRINT }, 	/* Print - HP OEM version of remote */
 
 
+	{ 0x800f0450, KEY_RADIO },
+
+	{ 0x800f045a, KEY_SUBTITLE }, 		/* Caption/Teletext */
 	{ 0x800f045b, KEY_RED },
 	{ 0x800f045b, KEY_RED },
 	{ 0x800f045c, KEY_GREEN },
 	{ 0x800f045c, KEY_GREEN },
 	{ 0x800f045d, KEY_YELLOW },
 	{ 0x800f045d, KEY_YELLOW },
 	{ 0x800f045e, KEY_BLUE },
 	{ 0x800f045e, KEY_BLUE },
 
 
-	{ 0x800f040f, KEY_INFO },
-	{ 0x800f0426, KEY_EPG }, /* Guide */
-	{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
-	{ 0x800f044d, KEY_TITLE },
-
-       { 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
-
-	{ 0x800f040c, KEY_POWER },
-	{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
+	{ 0x800f046e, KEY_PLAYPAUSE },
+	{ 0x800f046f, KEY_MEDIA }, 	/* Start media application (NEW) */
 
 
+	{ 0x800f0480, KEY_BRIGHTNESSDOWN },
+	{ 0x800f0481, KEY_PLAYPAUSE },
 };
 };
 
 
 static struct rc_keymap rc6_mce_map = {
 static struct rc_keymap rc6_mce_map = {

+ 82 - 0
drivers/media/IR/keymaps/rc-streamzap.c

@@ -0,0 +1,82 @@
+/* rc-streamzap.c - Keytable for Streamzap PC Remote, for use
+ * with the Streamzap PC Remote IR Receiver.
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <media/rc-map.h>
+
+static struct ir_scancode streamzap[] = {
+/*
+ * The Streamzap remote is almost, but not quite, RC-5, as it has an extra
+ * bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
+ * an additional RC-5-sz decoder is being deployed to support it, but it
+ * may be possible to merge it back with the standard RC-5 decoder.
+ */
+	{ 0x28c0, KEY_NUMERIC_0 },
+	{ 0x28c1, KEY_NUMERIC_1 },
+	{ 0x28c2, KEY_NUMERIC_2 },
+	{ 0x28c3, KEY_NUMERIC_3 },
+	{ 0x28c4, KEY_NUMERIC_4 },
+	{ 0x28c5, KEY_NUMERIC_5 },
+	{ 0x28c6, KEY_NUMERIC_6 },
+	{ 0x28c7, KEY_NUMERIC_7 },
+	{ 0x28c8, KEY_NUMERIC_8 },
+	{ 0x28c9, KEY_NUMERIC_9 },
+	{ 0x28ca, KEY_POWER },
+	{ 0x28cb, KEY_MUTE },
+	{ 0x28cc, KEY_CHANNELUP },
+	{ 0x28cd, KEY_VOLUMEUP },
+	{ 0x28ce, KEY_CHANNELDOWN },
+	{ 0x28cf, KEY_VOLUMEDOWN },
+	{ 0x28d0, KEY_UP },
+	{ 0x28d1, KEY_LEFT },
+	{ 0x28d2, KEY_OK },
+	{ 0x28d3, KEY_RIGHT },
+	{ 0x28d4, KEY_DOWN },
+	{ 0x28d5, KEY_MENU },
+	{ 0x28d6, KEY_EXIT },
+	{ 0x28d7, KEY_PLAY },
+	{ 0x28d8, KEY_PAUSE },
+	{ 0x28d9, KEY_STOP },
+	{ 0x28da, KEY_BACK },
+	{ 0x28db, KEY_FORWARD },
+	{ 0x28dc, KEY_RECORD },
+	{ 0x28dd, KEY_REWIND },
+	{ 0x28de, KEY_FASTFORWARD },
+	{ 0x28e0, KEY_RED },
+	{ 0x28e1, KEY_GREEN },
+	{ 0x28e2, KEY_YELLOW },
+	{ 0x28e3, KEY_BLUE },
+
+};
+
+static struct rc_keymap streamzap_map = {
+	.map = {
+		.scan    = streamzap,
+		.size    = ARRAY_SIZE(streamzap),
+		.ir_type = IR_TYPE_RC5_SZ,
+		.name    = RC_MAP_STREAMZAP,
+	}
+};
+
+static int __init init_rc_map_streamzap(void)
+{
+	return ir_register_map(&streamzap_map);
+}
+
+static void __exit exit_rc_map_streamzap(void)
+{
+	ir_unregister_map(&streamzap_map);
+}
+
+module_init(init_rc_map_streamzap)
+module_exit(exit_rc_map_streamzap)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

+ 79 - 0
drivers/media/IR/keymaps/rc-terratec-slim.c

@@ -0,0 +1,79 @@
+/*
+ * TerraTec remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* TerraTec slim remote, 7 rows, 4 columns. */
+/* Uses NEC extended 0x02bd. */
+static struct ir_scancode terratec_slim[] = {
+	{ 0x02bd00, KEY_1 },
+	{ 0x02bd01, KEY_2 },
+	{ 0x02bd02, KEY_3 },
+	{ 0x02bd03, KEY_4 },
+	{ 0x02bd04, KEY_5 },
+	{ 0x02bd05, KEY_6 },
+	{ 0x02bd06, KEY_7 },
+	{ 0x02bd07, KEY_8 },
+	{ 0x02bd08, KEY_9 },
+	{ 0x02bd09, KEY_0 },
+	{ 0x02bd0a, KEY_MUTE },
+	{ 0x02bd0b, KEY_NEW },             /* symbol: PIP */
+	{ 0x02bd0e, KEY_VOLUMEDOWN },
+	{ 0x02bd0f, KEY_PLAYPAUSE },
+	{ 0x02bd10, KEY_RIGHT },
+	{ 0x02bd11, KEY_LEFT },
+	{ 0x02bd12, KEY_UP },
+	{ 0x02bd13, KEY_DOWN },
+	{ 0x02bd15, KEY_OK },
+	{ 0x02bd16, KEY_STOP },
+	{ 0x02bd17, KEY_CAMERA },          /* snapshot */
+	{ 0x02bd18, KEY_CHANNELUP },
+	{ 0x02bd19, KEY_RECORD },
+	{ 0x02bd1a, KEY_CHANNELDOWN },
+	{ 0x02bd1c, KEY_ESC },
+	{ 0x02bd1f, KEY_VOLUMEUP },
+	{ 0x02bd44, KEY_EPG },
+	{ 0x02bd45, KEY_POWER2 },          /* [red power button] */
+};
+
+static struct rc_keymap terratec_slim_map = {
+	.map = {
+		.scan    = terratec_slim,
+		.size    = ARRAY_SIZE(terratec_slim),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_TERRATEC_SLIM,
+	}
+};
+
+static int __init init_rc_map_terratec_slim(void)
+{
+	return ir_register_map(&terratec_slim_map);
+}
+
+static void __exit exit_rc_map_terratec_slim(void)
+{
+	ir_unregister_map(&terratec_slim_map);
+}
+
+module_init(init_rc_map_terratec_slim)
+module_exit(exit_rc_map_terratec_slim)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 85 - 0
drivers/media/IR/keymaps/rc-total-media-in-hand.c

@@ -0,0 +1,85 @@
+/*
+ * Total Media In Hand remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* Uses NEC extended 0x02bd */
+static struct ir_scancode total_media_in_hand[] = {
+	{ 0x02bd00, KEY_1 },
+	{ 0x02bd01, KEY_2 },
+	{ 0x02bd02, KEY_3 },
+	{ 0x02bd03, KEY_4 },
+	{ 0x02bd04, KEY_5 },
+	{ 0x02bd05, KEY_6 },
+	{ 0x02bd06, KEY_7 },
+	{ 0x02bd07, KEY_8 },
+	{ 0x02bd08, KEY_9 },
+	{ 0x02bd09, KEY_0 },
+	{ 0x02bd0a, KEY_MUTE },
+	{ 0x02bd0b, KEY_CYCLEWINDOWS },    /* yellow, [min / max] */
+	{ 0x02bd0c, KEY_VIDEO },           /* TV / AV */
+	{ 0x02bd0e, KEY_VOLUMEDOWN },
+	{ 0x02bd0f, KEY_TIME },            /* TimeShift */
+	{ 0x02bd10, KEY_RIGHT },           /* right arrow */
+	{ 0x02bd11, KEY_LEFT },            /* left arrow */
+	{ 0x02bd12, KEY_UP },              /* up arrow */
+	{ 0x02bd13, KEY_DOWN },            /* down arrow */
+	{ 0x02bd14, KEY_POWER2 },          /* [red] */
+	{ 0x02bd15, KEY_OK },              /* OK */
+	{ 0x02bd16, KEY_STOP },
+	{ 0x02bd17, KEY_CAMERA },          /* Snapshot */
+	{ 0x02bd18, KEY_CHANNELUP },
+	{ 0x02bd19, KEY_RECORD },
+	{ 0x02bd1a, KEY_CHANNELDOWN },
+	{ 0x02bd1c, KEY_ESC },             /* Esc */
+	{ 0x02bd1e, KEY_PLAY },
+	{ 0x02bd1f, KEY_VOLUMEUP },
+	{ 0x02bd40, KEY_PAUSE },
+	{ 0x02bd41, KEY_FASTFORWARD },     /* FF >> */
+	{ 0x02bd42, KEY_REWIND },          /* FR << */
+	{ 0x02bd43, KEY_ZOOM },            /* [window + mouse pointer] */
+	{ 0x02bd44, KEY_SHUFFLE },         /* Shuffle */
+	{ 0x02bd45, KEY_INFO },            /* [red (I)] */
+};
+
+static struct rc_keymap total_media_in_hand_map = {
+	.map = {
+		.scan    = total_media_in_hand,
+		.size    = ARRAY_SIZE(total_media_in_hand),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_TOTAL_MEDIA_IN_HAND,
+	}
+};
+
+static int __init init_rc_map_total_media_in_hand(void)
+{
+	return ir_register_map(&total_media_in_hand_map);
+}
+
+static void __exit exit_rc_map_total_media_in_hand(void)
+{
+	ir_unregister_map(&total_media_in_hand_map);
+}
+
+module_init(init_rc_map_total_media_in_hand)
+module_exit(exit_rc_map_total_media_in_hand)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 80 - 0
drivers/media/IR/keymaps/rc-trekstor.c

@@ -0,0 +1,80 @@
+/*
+ * TrekStor remote controller keytable
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License along
+ *    with this program; if not, write to the Free Software Foundation, Inc.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <media/rc-map.h>
+
+/* TrekStor DVB-T USB Stick remote controller. */
+/* Imported from af9015.h.
+   Initial keytable was from Marc Schneider <macke@macke.org> */
+static struct ir_scancode trekstor[] = {
+	{ 0x0084, KEY_0 },
+	{ 0x0085, KEY_MUTE },            /* Mute */
+	{ 0x0086, KEY_HOMEPAGE },        /* Home */
+	{ 0x0087, KEY_UP },              /* Up */
+	{ 0x0088, KEY_OK },              /* OK */
+	{ 0x0089, KEY_RIGHT },           /* Right */
+	{ 0x008a, KEY_FASTFORWARD },     /* Fast forward */
+	{ 0x008b, KEY_VOLUMEUP },        /* Volume + */
+	{ 0x008c, KEY_DOWN },            /* Down */
+	{ 0x008d, KEY_PLAY },            /* Play/Pause */
+	{ 0x008e, KEY_STOP },            /* Stop */
+	{ 0x008f, KEY_EPG },             /* Info/EPG */
+	{ 0x0090, KEY_7 },
+	{ 0x0091, KEY_4 },
+	{ 0x0092, KEY_1 },
+	{ 0x0093, KEY_CHANNELDOWN },     /* Channel - */
+	{ 0x0094, KEY_8 },
+	{ 0x0095, KEY_5 },
+	{ 0x0096, KEY_2 },
+	{ 0x0097, KEY_CHANNELUP },       /* Channel + */
+	{ 0x0098, KEY_9 },
+	{ 0x0099, KEY_6 },
+	{ 0x009a, KEY_3 },
+	{ 0x009b, KEY_VOLUMEDOWN },      /* Volume - */
+	{ 0x009c, KEY_TV },              /* TV */
+	{ 0x009d, KEY_RECORD },          /* Record */
+	{ 0x009e, KEY_REWIND },          /* Rewind */
+	{ 0x009f, KEY_LEFT },            /* Left */
+};
+
+static struct rc_keymap trekstor_map = {
+	.map = {
+		.scan    = trekstor,
+		.size    = ARRAY_SIZE(trekstor),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_TREKSTOR,
+	}
+};
+
+static int __init init_rc_map_trekstor(void)
+{
+	return ir_register_map(&trekstor_map);
+}
+
+static void __exit exit_rc_map_trekstor(void)
+{
+	ir_unregister_map(&trekstor_map);
+}
+
+module_init(init_rc_map_trekstor)
+module_exit(exit_rc_map_trekstor)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

+ 87 - 0
drivers/media/IR/keymaps/rc-twinhan1027.c

@@ -0,0 +1,87 @@
+#include <media/rc-map.h>
+
+static struct ir_scancode twinhan_vp1027[] = {
+	{ 0x16, KEY_POWER2 },
+	{ 0x17, KEY_FAVORITES },
+	{ 0x0f, KEY_TEXT },
+	{ 0x48, KEY_INFO},
+	{ 0x1c, KEY_EPG },
+	{ 0x04, KEY_LIST },
+
+	{ 0x03, KEY_1 },
+	{ 0x01, KEY_2 },
+	{ 0x06, KEY_3 },
+	{ 0x09, KEY_4 },
+	{ 0x1d, KEY_5 },
+	{ 0x1f, KEY_6 },
+	{ 0x0d, KEY_7 },
+	{ 0x19, KEY_8 },
+	{ 0x1b, KEY_9 },
+	{ 0x15, KEY_0 },
+
+	{ 0x0c, KEY_CANCEL },
+	{ 0x4a, KEY_CLEAR },
+	{ 0x13, KEY_BACKSPACE },
+	{ 0x00, KEY_TAB },
+
+	{ 0x4b, KEY_UP },
+	{ 0x51, KEY_DOWN },
+	{ 0x4e, KEY_LEFT },
+	{ 0x52, KEY_RIGHT },
+	{ 0x4f, KEY_ENTER },
+
+	{ 0x1e, KEY_VOLUMEUP },
+	{ 0x0a, KEY_VOLUMEDOWN },
+	{ 0x02, KEY_CHANNELDOWN },
+	{ 0x05, KEY_CHANNELUP },
+	{ 0x11, KEY_RECORD },
+
+	{ 0x14, KEY_PLAY },
+	{ 0x4c, KEY_PAUSE },
+	{ 0x1a, KEY_STOP },
+	{ 0x40, KEY_REWIND },
+	{ 0x12, KEY_FASTFORWARD },
+	{ 0x41, KEY_PREVIOUSSONG },
+	{ 0x42, KEY_NEXTSONG },
+	{ 0x54, KEY_SAVE },
+	{ 0x50, KEY_LANGUAGE },
+	{ 0x47, KEY_MEDIA },
+	{ 0x4d, KEY_SCREEN },
+	{ 0x43, KEY_SUBTITLE },
+	{ 0x10, KEY_MUTE },
+	{ 0x49, KEY_AUDIO },
+	{ 0x07, KEY_SLEEP },
+	{ 0x08, KEY_VIDEO },
+	{ 0x0e, KEY_AGAIN },
+	{ 0x45, KEY_EQUAL },
+	{ 0x46, KEY_MINUS },
+	{ 0x18, KEY_RED },
+	{ 0x53, KEY_GREEN },
+	{ 0x5e, KEY_YELLOW },
+	{ 0x5f, KEY_BLUE },
+};
+
+static struct rc_keymap twinhan_vp1027_map = {
+	.map = {
+		.scan    = twinhan_vp1027,
+		.size    = ARRAY_SIZE(twinhan_vp1027),
+		.ir_type = IR_TYPE_UNKNOWN,	/* Legacy IR type */
+		.name    = RC_MAP_TWINHAN_VP1027_DVBS,
+	}
+};
+
+static int __init init_rc_map_twinhan_vp1027(void)
+{
+	return ir_register_map(&twinhan_vp1027_map);
+}
+
+static void __exit exit_rc_map_twinhan_vp1027(void)
+{
+	ir_unregister_map(&twinhan_vp1027_map);
+}
+
+module_init(init_rc_map_twinhan_vp1027)
+module_exit(exit_rc_map_twinhan_vp1027)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sergey Ivanov <123kash@gmail.com>");

+ 89 - 44
drivers/media/IR/lirc_dev.c

@@ -57,13 +57,12 @@ struct irctl {
 
 
 	struct task_struct *task;
 	struct task_struct *task;
 	long jiffies_to_wait;
 	long jiffies_to_wait;
-
-	struct cdev cdev;
 };
 };
 
 
 static DEFINE_MUTEX(lirc_dev_lock);
 static DEFINE_MUTEX(lirc_dev_lock);
 
 
 static struct irctl *irctls[MAX_IRCTL_DEVICES];
 static struct irctl *irctls[MAX_IRCTL_DEVICES];
+static struct cdev cdevs[MAX_IRCTL_DEVICES];
 
 
 /* Only used for sysfs but defined to void otherwise */
 /* Only used for sysfs but defined to void otherwise */
 static struct class *lirc_class;
 static struct class *lirc_class;
@@ -71,15 +70,13 @@ static struct class *lirc_class;
 /*  helper function
 /*  helper function
  *  initializes the irctl structure
  *  initializes the irctl structure
  */
  */
-static void init_irctl(struct irctl *ir)
+static void lirc_irctl_init(struct irctl *ir)
 {
 {
-	dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
-		ir->d.name, ir->d.minor);
 	mutex_init(&ir->irctl_lock);
 	mutex_init(&ir->irctl_lock);
 	ir->d.minor = NOPLUG;
 	ir->d.minor = NOPLUG;
 }
 }
 
 
-static void cleanup(struct irctl *ir)
+static void lirc_irctl_cleanup(struct irctl *ir)
 {
 {
 	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
 
 
@@ -96,7 +93,7 @@ static void cleanup(struct irctl *ir)
  *  reads key codes from driver and puts them into buffer
  *  reads key codes from driver and puts them into buffer
  *  returns 0 on success
  *  returns 0 on success
  */
  */
-static int add_to_buf(struct irctl *ir)
+static int lirc_add_to_buf(struct irctl *ir)
 {
 {
 	if (ir->d.add_to_buf) {
 	if (ir->d.add_to_buf) {
 		int res = -ENODATA;
 		int res = -ENODATA;
@@ -139,7 +136,7 @@ static int lirc_thread(void *irctl)
 			}
 			}
 			if (kthread_should_stop())
 			if (kthread_should_stop())
 				break;
 				break;
-			if (!add_to_buf(ir))
+			if (!lirc_add_to_buf(ir))
 				wake_up_interruptible(&ir->buf->wait_poll);
 				wake_up_interruptible(&ir->buf->wait_poll);
 		} else {
 		} else {
 			set_current_state(TASK_INTERRUPTIBLE);
 			set_current_state(TASK_INTERRUPTIBLE);
@@ -154,12 +151,15 @@ static int lirc_thread(void *irctl)
 }
 }
 
 
 
 
-static struct file_operations fops = {
+static struct file_operations lirc_dev_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.read		= lirc_dev_fop_read,
 	.read		= lirc_dev_fop_read,
 	.write		= lirc_dev_fop_write,
 	.write		= lirc_dev_fop_write,
 	.poll		= lirc_dev_fop_poll,
 	.poll		= lirc_dev_fop_poll,
 	.unlocked_ioctl	= lirc_dev_fop_ioctl,
 	.unlocked_ioctl	= lirc_dev_fop_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= lirc_dev_fop_ioctl,
+#endif
 	.open		= lirc_dev_fop_open,
 	.open		= lirc_dev_fop_open,
 	.release	= lirc_dev_fop_close,
 	.release	= lirc_dev_fop_close,
 	.llseek		= noop_llseek,
 	.llseek		= noop_llseek,
@@ -169,19 +169,20 @@ static int lirc_cdev_add(struct irctl *ir)
 {
 {
 	int retval;
 	int retval;
 	struct lirc_driver *d = &ir->d;
 	struct lirc_driver *d = &ir->d;
+	struct cdev *cdev = &cdevs[d->minor];
 
 
 	if (d->fops) {
 	if (d->fops) {
-		cdev_init(&ir->cdev, d->fops);
-		ir->cdev.owner = d->owner;
+		cdev_init(cdev, d->fops);
+		cdev->owner = d->owner;
 	} else {
 	} else {
-		cdev_init(&ir->cdev, &fops);
-		ir->cdev.owner = THIS_MODULE;
+		cdev_init(cdev, &lirc_dev_fops);
+		cdev->owner = THIS_MODULE;
 	}
 	}
-	kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
+	kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
 
 
-	retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+	retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
 	if (retval)
 	if (retval)
-		kobject_put(&ir->cdev.kobj);
+		kobject_put(&cdev->kobj);
 
 
 	return retval;
 	return retval;
 }
 }
@@ -202,6 +203,12 @@ int lirc_register_driver(struct lirc_driver *d)
 		goto out;
 		goto out;
 	}
 	}
 
 
+	if (!d->dev) {
+		printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
+		err = -EINVAL;
+		goto out;
+	}
+
 	if (MAX_IRCTL_DEVICES <= d->minor) {
 	if (MAX_IRCTL_DEVICES <= d->minor) {
 		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
 		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
 			"\"minor\" must be between 0 and %d (%d)!\n",
 			"\"minor\" must be between 0 and %d (%d)!\n",
@@ -277,7 +284,7 @@ int lirc_register_driver(struct lirc_driver *d)
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto out_lock;
 		goto out_lock;
 	}
 	}
-	init_irctl(ir);
+	lirc_irctl_init(ir);
 	irctls[minor] = ir;
 	irctls[minor] = ir;
 	d->minor = minor;
 	d->minor = minor;
 
 
@@ -316,7 +323,6 @@ int lirc_register_driver(struct lirc_driver *d)
 		d->features = LIRC_CAN_REC_LIRCCODE;
 		d->features = LIRC_CAN_REC_LIRCCODE;
 
 
 	ir->d = *d;
 	ir->d = *d;
-	ir->d.minor = minor;
 
 
 	device_create(lirc_class, ir->d.dev,
 	device_create(lirc_class, ir->d.dev,
 		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
 		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
@@ -357,21 +363,28 @@ EXPORT_SYMBOL(lirc_register_driver);
 int lirc_unregister_driver(int minor)
 int lirc_unregister_driver(int minor)
 {
 {
 	struct irctl *ir;
 	struct irctl *ir;
+	struct cdev *cdev;
 
 
 	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
 	if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
-		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
-		       "\"minor (%d)\" must be between 0 and %d!\n",
-		       minor, MAX_IRCTL_DEVICES-1);
+		printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
+		       "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
 		return -EBADRQC;
 		return -EBADRQC;
 	}
 	}
 
 
 	ir = irctls[minor];
 	ir = irctls[minor];
+	if (!ir) {
+		printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
+		       "for minor %d!\n", __func__, minor);
+		return -ENOENT;
+	}
+
+	cdev = &cdevs[minor];
 
 
 	mutex_lock(&lirc_dev_lock);
 	mutex_lock(&lirc_dev_lock);
 
 
 	if (ir->d.minor != minor) {
 	if (ir->d.minor != minor) {
-		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
-		       "minor (%d) device not registered!", minor);
+		printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
+		       "registered!\n", __func__, minor);
 		mutex_unlock(&lirc_dev_lock);
 		mutex_unlock(&lirc_dev_lock);
 		return -ENOENT;
 		return -ENOENT;
 	}
 	}
@@ -390,12 +403,11 @@ int lirc_unregister_driver(int minor)
 		wake_up_interruptible(&ir->buf->wait_poll);
 		wake_up_interruptible(&ir->buf->wait_poll);
 		mutex_lock(&ir->irctl_lock);
 		mutex_lock(&ir->irctl_lock);
 		ir->d.set_use_dec(ir->d.data);
 		ir->d.set_use_dec(ir->d.data);
-		module_put(ir->d.owner);
+		module_put(cdev->owner);
 		mutex_unlock(&ir->irctl_lock);
 		mutex_unlock(&ir->irctl_lock);
-		cdev_del(&ir->cdev);
 	} else {
 	} else {
-		cleanup(ir);
-		cdev_del(&ir->cdev);
+		lirc_irctl_cleanup(ir);
+		cdev_del(cdev);
 		kfree(ir);
 		kfree(ir);
 		irctls[minor] = NULL;
 		irctls[minor] = NULL;
 	}
 	}
@@ -409,6 +421,7 @@ EXPORT_SYMBOL(lirc_unregister_driver);
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 int lirc_dev_fop_open(struct inode *inode, struct file *file)
 {
 {
 	struct irctl *ir;
 	struct irctl *ir;
+	struct cdev *cdev;
 	int retval = 0;
 	int retval = 0;
 
 
 	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
 	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
@@ -425,7 +438,6 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 		retval = -ENODEV;
 		retval = -ENODEV;
 		goto error;
 		goto error;
 	}
 	}
-	file->private_data = ir;
 
 
 	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
 
 
@@ -439,13 +451,14 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	if (try_module_get(ir->d.owner)) {
-		++ir->open;
+	cdev = &cdevs[iminor(inode)];
+	if (try_module_get(cdev->owner)) {
+		ir->open++;
 		retval = ir->d.set_use_inc(ir->d.data);
 		retval = ir->d.set_use_inc(ir->d.data);
 
 
 		if (retval) {
 		if (retval) {
-			module_put(ir->d.owner);
-			--ir->open;
+			module_put(cdev->owner);
+			ir->open--;
 		} else {
 		} else {
 			lirc_buffer_clear(ir->buf);
 			lirc_buffer_clear(ir->buf);
 		}
 		}
@@ -469,17 +482,24 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 int lirc_dev_fop_close(struct inode *inode, struct file *file)
 {
 {
 	struct irctl *ir = irctls[iminor(inode)];
 	struct irctl *ir = irctls[iminor(inode)];
+	struct cdev *cdev = &cdevs[iminor(inode)];
+
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -EINVAL;
+	}
 
 
 	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
 
 
 	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
 	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
 
 
-	--ir->open;
+	ir->open--;
 	if (ir->attached) {
 	if (ir->attached) {
 		ir->d.set_use_dec(ir->d.data);
 		ir->d.set_use_dec(ir->d.data);
-		module_put(ir->d.owner);
+		module_put(cdev->owner);
 	} else {
 	} else {
-		cleanup(ir);
+		lirc_irctl_cleanup(ir);
+		cdev_del(cdev);
 		irctls[ir->d.minor] = NULL;
 		irctls[ir->d.minor] = NULL;
 		kfree(ir);
 		kfree(ir);
 	}
 	}
@@ -495,6 +515,11 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
 	unsigned int ret;
 	unsigned int ret;
 
 
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return POLLERR;
+	}
+
 	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 
 
 	if (!ir->attached) {
 	if (!ir->attached) {
@@ -521,9 +546,14 @@ EXPORT_SYMBOL(lirc_dev_fop_poll);
 
 
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 {
-	unsigned long mode;
+	__u32 mode;
 	int result = 0;
 	int result = 0;
-	struct irctl *ir = file->private_data;
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+	if (!ir) {
+		printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
+		return -ENODEV;
+	}
 
 
 	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
 	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
 		ir->d.name, ir->d.minor, cmd);
 		ir->d.name, ir->d.minor, cmd);
@@ -538,7 +568,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 
 	switch (cmd) {
 	switch (cmd) {
 	case LIRC_GET_FEATURES:
 	case LIRC_GET_FEATURES:
-		result = put_user(ir->d.features, (unsigned long *)arg);
+		result = put_user(ir->d.features, (__u32 *)arg);
 		break;
 		break;
 	case LIRC_GET_REC_MODE:
 	case LIRC_GET_REC_MODE:
 		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
 		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
@@ -548,7 +578,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 
 		result = put_user(LIRC_REC2MODE
 		result = put_user(LIRC_REC2MODE
 				  (ir->d.features & LIRC_CAN_REC_MASK),
 				  (ir->d.features & LIRC_CAN_REC_MASK),
-				  (unsigned long *)arg);
+				  (__u32 *)arg);
 		break;
 		break;
 	case LIRC_SET_REC_MODE:
 	case LIRC_SET_REC_MODE:
 		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
 		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
@@ -556,7 +586,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			break;
 			break;
 		}
 		}
 
 
-		result = get_user(mode, (unsigned long *)arg);
+		result = get_user(mode, (__u32 *)arg);
 		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
 		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
 			result = -EINVAL;
 			result = -EINVAL;
 		/*
 		/*
@@ -565,7 +595,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		 */
 		 */
 		break;
 		break;
 	case LIRC_GET_LENGTH:
 	case LIRC_GET_LENGTH:
-		result = put_user(ir->d.code_length, (unsigned long *)arg);
+		result = put_user(ir->d.code_length, (__u32 *)arg);
 		break;
 		break;
 	case LIRC_GET_MIN_TIMEOUT:
 	case LIRC_GET_MIN_TIMEOUT:
 		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
 		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
@@ -574,7 +604,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			break;
 			break;
 		}
 		}
 
 
-		result = put_user(ir->d.min_timeout, (unsigned long *)arg);
+		result = put_user(ir->d.min_timeout, (__u32 *)arg);
 		break;
 		break;
 	case LIRC_GET_MAX_TIMEOUT:
 	case LIRC_GET_MAX_TIMEOUT:
 		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
 		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
@@ -583,7 +613,7 @@ long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			break;
 			break;
 		}
 		}
 
 
-		result = put_user(ir->d.max_timeout, (unsigned long *)arg);
+		result = put_user(ir->d.max_timeout, (__u32 *)arg);
 		break;
 		break;
 	default:
 	default:
 		result = -EINVAL;
 		result = -EINVAL;
@@ -604,12 +634,21 @@ ssize_t lirc_dev_fop_read(struct file *file,
 			  loff_t *ppos)
 			  loff_t *ppos)
 {
 {
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-	unsigned char buf[ir->chunk_size];
+	unsigned char *buf;
 	int ret = 0, written = 0;
 	int ret = 0, written = 0;
 	DECLARE_WAITQUEUE(wait, current);
 	DECLARE_WAITQUEUE(wait, current);
 
 
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -ENODEV;
+	}
+
 	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
 
 
+	buf = kzalloc(ir->chunk_size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	if (mutex_lock_interruptible(&ir->irctl_lock))
 	if (mutex_lock_interruptible(&ir->irctl_lock))
 		return -ERESTARTSYS;
 		return -ERESTARTSYS;
 	if (!ir->attached) {
 	if (!ir->attached) {
@@ -681,6 +720,7 @@ ssize_t lirc_dev_fop_read(struct file *file,
 	mutex_unlock(&ir->irctl_lock);
 	mutex_unlock(&ir->irctl_lock);
 
 
 out_unlocked:
 out_unlocked:
+	kfree(buf);
 	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
 	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
 		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
 		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
 
 
@@ -709,6 +749,11 @@ ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
 {
 {
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
 	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
 
 
+	if (!ir) {
+		printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+		return -ENODEV;
+	}
+
 	dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
 	dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
 
 
 	if (!ir->attached)
 	if (!ir->attached)

+ 316 - 159
drivers/media/IR/mceusb.c

@@ -46,24 +46,58 @@
 			"device driver"
 			"device driver"
 #define DRIVER_NAME	"mceusb"
 #define DRIVER_NAME	"mceusb"
 
 
-#define USB_BUFLEN	32	/* USB reception buffer length */
-#define USB_CTRL_MSG_SZ	2	/* Size of usb ctrl msg on gen1 hw */
-#define MCE_G1_INIT_MSGS 40	/* Init messages on gen1 hw to throw out */
+#define USB_BUFLEN		32 /* USB reception buffer length */
+#define USB_CTRL_MSG_SZ		2  /* Size of usb ctrl msg on gen1 hw */
+#define MCE_G1_INIT_MSGS	40 /* Init messages on gen1 hw to throw out */
 
 
 /* MCE constants */
 /* MCE constants */
-#define MCE_CMDBUF_SIZE	384 /* MCE Command buffer length */
-#define MCE_TIME_UNIT	50 /* Approx 50us resolution */
-#define MCE_CODE_LENGTH	5 /* Normal length of packet (with header) */
-#define MCE_PACKET_SIZE	4 /* Normal length of packet (without header) */
-#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */
-#define MCE_CONTROL_HEADER 0x9F /* MCE status header */
-#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */
-#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */
-#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */
-#define MCE_PULSE_BIT	0x80 /* Pulse bit, MSB set == PULSE else SPACE */
-#define MCE_PULSE_MASK	0x7F /* Pulse mask */
-#define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */
-#define MCE_PACKET_LENGTH_MASK  0x1F /* Packet length mask */
+#define MCE_CMDBUF_SIZE		384  /* MCE Command buffer length */
+#define MCE_TIME_UNIT		50   /* Approx 50us resolution */
+#define MCE_CODE_LENGTH		5    /* Normal length of packet (with header) */
+#define MCE_PACKET_SIZE		4    /* Normal length of packet (without header) */
+#define MCE_IRDATA_HEADER	0x84 /* Actual header format is 0x80 + num_bytes */
+#define MCE_IRDATA_TRAILER	0x80 /* End of IR data */
+#define MCE_TX_HEADER_LENGTH	3    /* # of bytes in the initializing tx header */
+#define MCE_MAX_CHANNELS	2    /* Two transmitters, hardware dependent? */
+#define MCE_DEFAULT_TX_MASK	0x03 /* Vals: TX1=0x01, TX2=0x02, ALL=0x03 */
+#define MCE_PULSE_BIT		0x80 /* Pulse bit, MSB set == PULSE else SPACE */
+#define MCE_PULSE_MASK		0x7f /* Pulse mask */
+#define MCE_MAX_PULSE_LENGTH	0x7f /* Longest transmittable pulse symbol */
+
+#define MCE_HW_CMD_HEADER	0xff	/* MCE hardware command header */
+#define MCE_COMMAND_HEADER	0x9f	/* MCE command header */
+#define MCE_COMMAND_MASK	0xe0	/* Mask out command bits */
+#define MCE_COMMAND_NULL	0x00	/* These show up various places... */
+/* if buf[i] & MCE_COMMAND_MASK == 0x80 and buf[i] != MCE_COMMAND_HEADER,
+ * then we're looking at a raw IR data sample */
+#define MCE_COMMAND_IRDATA	0x80
+#define MCE_PACKET_LENGTH_MASK	0x1f /* Packet length mask */
+
+/* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+#define MCE_CMD_PING		0x03	/* Ping device */
+#define MCE_CMD_UNKNOWN		0x04	/* Unknown */
+#define MCE_CMD_UNKNOWN2	0x05	/* Unknown */
+#define MCE_CMD_S_CARRIER	0x06	/* Set TX carrier frequency */
+#define MCE_CMD_G_CARRIER	0x07	/* Get TX carrier frequency */
+#define MCE_CMD_S_TXMASK	0x08	/* Set TX port bitmask */
+#define MCE_CMD_UNKNOWN3	0x09	/* Unknown */
+#define MCE_CMD_UNKNOWN4	0x0a	/* Unknown */
+#define MCE_CMD_G_REVISION	0x0b	/* Get hw/sw revision */
+#define MCE_CMD_S_TIMEOUT	0x0c	/* Set RX timeout value */
+#define MCE_CMD_G_TIMEOUT	0x0d	/* Get RX timeout value */
+#define MCE_CMD_UNKNOWN5	0x0e	/* Unknown */
+#define MCE_CMD_UNKNOWN6	0x0f	/* Unknown */
+#define MCE_CMD_G_RXPORTSTS	0x11	/* Get RX port status */
+#define MCE_CMD_G_TXMASK	0x13	/* Set TX port bitmask */
+#define MCE_CMD_S_RXSENSOR	0x14	/* Set RX sensor (std/learning) */
+#define MCE_CMD_G_RXSENSOR	0x15	/* Get RX sensor (std/learning) */
+#define MCE_CMD_TX_PORTS	0x16	/* Get number of TX ports */
+#define MCE_CMD_G_WAKESRC	0x17	/* Get wake source */
+#define MCE_CMD_UNKNOWN7	0x18	/* Unknown */
+#define MCE_CMD_UNKNOWN8	0x19	/* Unknown */
+#define MCE_CMD_UNKNOWN9	0x1b	/* Unknown */
+#define MCE_CMD_DEVICE_RESET	0xaa	/* Reset the hardware */
+#define MCE_RSP_CMD_INVALID	0xfe	/* Invalid command issued */
 
 
 
 
 /* module parameters */
 /* module parameters */
@@ -104,14 +138,64 @@ static int debug;
 #define VENDOR_NORTHSTAR	0x04eb
 #define VENDOR_NORTHSTAR	0x04eb
 #define VENDOR_REALTEK		0x0bda
 #define VENDOR_REALTEK		0x0bda
 #define VENDOR_TIVO		0x105a
 #define VENDOR_TIVO		0x105a
+#define VENDOR_CONEXANT		0x0572
+
+enum mceusb_model_type {
+	MCE_GEN2 = 0,		/* Most boards */
+	MCE_GEN1,
+	MCE_GEN3,
+	MCE_GEN2_TX_INV,
+	POLARIS_EVK,
+};
+
+struct mceusb_model {
+	u32 mce_gen1:1;
+	u32 mce_gen2:1;
+	u32 mce_gen3:1;
+	u32 tx_mask_inverted:1;
+	u32 is_polaris:1;
+
+	const char *rc_map;	/* Allow specify a per-board map */
+	const char *name;	/* per-board name */
+};
+
+static const struct mceusb_model mceusb_model[] = {
+	[MCE_GEN1] = {
+		.mce_gen1 = 1,
+		.tx_mask_inverted = 1,
+	},
+	[MCE_GEN2] = {
+		.mce_gen2 = 1,
+	},
+	[MCE_GEN2_TX_INV] = {
+		.mce_gen2 = 1,
+		.tx_mask_inverted = 1,
+	},
+	[MCE_GEN3] = {
+		.mce_gen3 = 1,
+		.tx_mask_inverted = 1,
+	},
+	[POLARIS_EVK] = {
+		.is_polaris = 1,
+		/*
+		 * In fact, the EVK is shipped without
+		 * remotes, but we should have something handy,
+		 * to allow testing it
+		 */
+		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.name = "cx231xx MCE IR",
+	},
+};
 
 
 static struct usb_device_id mceusb_dev_table[] = {
 static struct usb_device_id mceusb_dev_table[] = {
 	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
 	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
-	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d),
+	  .driver_info = MCE_GEN1 },
 	/* Philips Infrared Transceiver - Sahara branded */
 	/* Philips Infrared Transceiver - Sahara branded */
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
 	/* Philips Infrared Transceiver - HP branded */
 	/* Philips Infrared Transceiver - HP branded */
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Philips SRM5100 */
 	/* Philips SRM5100 */
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
 	/* Philips Infrared Transceiver - Omaura */
 	/* Philips Infrared Transceiver - Omaura */
@@ -127,11 +211,14 @@ static struct usb_device_id mceusb_dev_table[] = {
 	/* Realtek MCE IR Receiver */
 	/* Realtek MCE IR Receiver */
 	{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
 	{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
 	/* SMK/Toshiba G83C0004D410 */
 	/* SMK/Toshiba G83C0004D410 */
-	{ USB_DEVICE(VENDOR_SMK, 0x031d) },
+	{ USB_DEVICE(VENDOR_SMK, 0x031d),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* SMK eHome Infrared Transceiver (Sony VAIO) */
 	/* SMK eHome Infrared Transceiver (Sony VAIO) */
-	{ USB_DEVICE(VENDOR_SMK, 0x0322) },
+	{ USB_DEVICE(VENDOR_SMK, 0x0322),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* bundled with Hauppauge PVR-150 */
 	/* bundled with Hauppauge PVR-150 */
-	{ USB_DEVICE(VENDOR_SMK, 0x0334) },
+	{ USB_DEVICE(VENDOR_SMK, 0x0334),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* SMK eHome Infrared Transceiver */
 	/* SMK eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_SMK, 0x0338) },
 	{ USB_DEVICE(VENDOR_SMK, 0x0338) },
 	/* Tatung eHome Infrared Transceiver */
 	/* Tatung eHome Infrared Transceiver */
@@ -145,17 +232,23 @@ static struct usb_device_id mceusb_dev_table[] = {
 	/* Mitsumi */
 	/* Mitsumi */
 	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
 	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
 	/* Topseed eHome Infrared Transceiver */
 	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed HP eHome Infrared Transceiver */
 	/* Topseed HP eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed eHome Infrared Transceiver */
 	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed eHome Infrared Transceiver */
 	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008),
+	  .driver_info = MCE_GEN3 },
 	/* Topseed eHome Infrared Transceiver */
 	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed eHome Infrared Transceiver */
 	/* Topseed eHome Infrared Transceiver */
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
+	  .driver_info = MCE_GEN2_TX_INV },
 	/* Ricavision internal Infrared Transceiver */
 	/* Ricavision internal Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 	/* Itron ione Libra Q-11 */
 	/* Itron ione Libra Q-11 */
@@ -185,7 +278,8 @@ static struct usb_device_id mceusb_dev_table[] = {
 	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
 	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
 	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
 	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
 	/* Pinnacle Remote Kit */
 	/* Pinnacle Remote Kit */
-	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225),
+	  .driver_info = MCE_GEN3 },
 	/* Elitegroup Computer Systems IR */
 	/* Elitegroup Computer Systems IR */
 	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
 	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
 	/* Wistron Corp. eHome Infrared Receiver */
 	/* Wistron Corp. eHome Infrared Receiver */
@@ -198,37 +292,13 @@ static struct usb_device_id mceusb_dev_table[] = {
 	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
 	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
 	/* TiVo PC IR Receiver */
 	/* TiVo PC IR Receiver */
 	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
 	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
+	/* Conexant SDK */
+	{ USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
+	  .driver_info = POLARIS_EVK },
 	/* Terminating entry */
 	/* Terminating entry */
 	{ }
 	{ }
 };
 };
 
 
-static struct usb_device_id gen3_list[] = {
-	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
-	{}
-};
-
-static struct usb_device_id microsoft_gen1_list[] = {
-	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
-	{}
-};
-
-static struct usb_device_id std_tx_mask_list[] = {
-	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
-	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
-	{ USB_DEVICE(VENDOR_SMK, 0x031d) },
-	{ USB_DEVICE(VENDOR_SMK, 0x0322) },
-	{ USB_DEVICE(VENDOR_SMK, 0x0334) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
-	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
-	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
-	{}
-};
-
 /* data structure for each usb transceiver */
 /* data structure for each usb transceiver */
 struct mceusb_dev {
 struct mceusb_dev {
 	/* ir-core bits */
 	/* ir-core bits */
@@ -248,8 +318,15 @@ struct mceusb_dev {
 	/* buffers and dma */
 	/* buffers and dma */
 	unsigned char *buf_in;
 	unsigned char *buf_in;
 	unsigned int len_in;
 	unsigned int len_in;
-	u8 cmd;		/* MCE command type */
-	u8 rem;		/* Remaining IR data bytes in packet */
+
+	enum {
+		CMD_HEADER = 0,
+		SUBCMD,
+		CMD_DATA,
+		PARSE_IRDATA,
+	} parser_state;
+	u8 cmd, rem;		/* Remaining IR data bytes in packet */
+
 	dma_addr_t dma_in;
 	dma_addr_t dma_in;
 	dma_addr_t dma_out;
 	dma_addr_t dma_out;
 
 
@@ -257,7 +334,6 @@ struct mceusb_dev {
 		u32 connected:1;
 		u32 connected:1;
 		u32 tx_mask_inverted:1;
 		u32 tx_mask_inverted:1;
 		u32 microsoft_gen1:1;
 		u32 microsoft_gen1:1;
-		u32 reserved:29;
 	} flags;
 	} flags;
 
 
 	/* transmit support */
 	/* transmit support */
@@ -267,6 +343,7 @@ struct mceusb_dev {
 
 
 	char name[128];
 	char name[128];
 	char phys[64];
 	char phys[64];
+	enum mceusb_model_type model;
 };
 };
 
 
 /*
 /*
@@ -291,43 +368,81 @@ struct mceusb_dev {
  * - SET_RX_TIMEOUT sets the receiver timeout
  * - SET_RX_TIMEOUT sets the receiver timeout
  * - SET_RX_SENSOR sets which receiver sensor to use
  * - SET_RX_SENSOR sets which receiver sensor to use
  */
  */
-static char DEVICE_RESET[]	= {0x00, 0xff, 0xaa};
-static char GET_REVISION[]	= {0xff, 0x0b};
-static char GET_UNKNOWN[]	= {0xff, 0x18};
-static char GET_UNKNOWN2[]	= {0x9f, 0x05};
-static char GET_CARRIER_FREQ[]	= {0x9f, 0x07};
-static char GET_RX_TIMEOUT[]	= {0x9f, 0x0d};
-static char GET_TX_BITMASK[]	= {0x9f, 0x13};
-static char GET_RX_SENSOR[]	= {0x9f, 0x15};
+static char DEVICE_RESET[]	= {MCE_COMMAND_NULL, MCE_HW_CMD_HEADER,
+				   MCE_CMD_DEVICE_RESET};
+static char GET_REVISION[]	= {MCE_HW_CMD_HEADER, MCE_CMD_G_REVISION};
+static char GET_UNKNOWN[]	= {MCE_HW_CMD_HEADER, MCE_CMD_UNKNOWN7};
+static char GET_UNKNOWN2[]	= {MCE_COMMAND_HEADER, MCE_CMD_UNKNOWN2};
+static char GET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_CARRIER};
+static char GET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TIMEOUT};
+static char GET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_TXMASK};
+static char GET_RX_SENSOR[]	= {MCE_COMMAND_HEADER, MCE_CMD_G_RXSENSOR};
 /* sub in desired values in lower byte or bytes for full command */
 /* sub in desired values in lower byte or bytes for full command */
 /* FIXME: make use of these for transmit.
 /* FIXME: make use of these for transmit.
-static char SET_CARRIER_FREQ[]	= {0x9f, 0x06, 0x00, 0x00};
-static char SET_TX_BITMASK[]	= {0x9f, 0x08, 0x00};
-static char SET_RX_TIMEOUT[]	= {0x9f, 0x0c, 0x00, 0x00};
-static char SET_RX_SENSOR[]	= {0x9f, 0x14, 0x00};
+static char SET_CARRIER_FREQ[]	= {MCE_COMMAND_HEADER,
+				   MCE_CMD_S_CARRIER, 0x00, 0x00};
+static char SET_TX_BITMASK[]	= {MCE_COMMAND_HEADER, MCE_CMD_S_TXMASK, 0x00};
+static char SET_RX_TIMEOUT[]	= {MCE_COMMAND_HEADER,
+				   MCE_CMD_S_TIMEOUT, 0x00, 0x00};
+static char SET_RX_SENSOR[]	= {MCE_COMMAND_HEADER,
+				   MCE_CMD_S_RXSENSOR, 0x00};
 */
 */
 
 
+static int mceusb_cmdsize(u8 cmd, u8 subcmd)
+{
+	int datasize = 0;
+
+	switch (cmd) {
+	case MCE_COMMAND_NULL:
+		if (subcmd == MCE_HW_CMD_HEADER)
+			datasize = 1;
+		break;
+	case MCE_HW_CMD_HEADER:
+		switch (subcmd) {
+		case MCE_CMD_G_REVISION:
+			datasize = 2;
+			break;
+		}
+	case MCE_COMMAND_HEADER:
+		switch (subcmd) {
+		case MCE_CMD_UNKNOWN:
+		case MCE_CMD_S_CARRIER:
+		case MCE_CMD_S_TIMEOUT:
+		case MCE_CMD_G_RXSENSOR:
+			datasize = 2;
+			break;
+		case MCE_CMD_S_TXMASK:
+		case MCE_CMD_S_RXSENSOR:
+			datasize = 1;
+			break;
+		}
+	}
+	return datasize;
+}
+
 static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
-				 int len, bool out)
+				 int offset, int len, bool out)
 {
 {
 	char codes[USB_BUFLEN * 3 + 1];
 	char codes[USB_BUFLEN * 3 + 1];
 	char inout[9];
 	char inout[9];
-	int i;
 	u8 cmd, subcmd, data1, data2;
 	u8 cmd, subcmd, data1, data2;
 	struct device *dev = ir->dev;
 	struct device *dev = ir->dev;
-	int idx = 0;
+	int i, start, skip = 0;
+
+	if (!debug)
+		return;
 
 
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
 	if (ir->flags.microsoft_gen1 && !out)
 	if (ir->flags.microsoft_gen1 && !out)
-		idx = 2;
+		skip = 2;
 
 
-	if (len <= idx)
+	if (len <= skip)
 		return;
 		return;
 
 
 	for (i = 0; i < len && i < USB_BUFLEN; i++)
 	for (i = 0; i < len && i < USB_BUFLEN; i++)
-		snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF);
+		snprintf(codes + i * 3, 4, "%02x ", buf[i + offset] & 0xff);
 
 
-	dev_info(dev, "%sx data: %s (length=%d)\n",
+	dev_info(dev, "%sx data: %s(length=%d)\n",
 		 (out ? "t" : "r"), codes, len);
 		 (out ? "t" : "r"), codes, len);
 
 
 	if (out)
 	if (out)
@@ -335,91 +450,93 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 	else
 	else
 		strcpy(inout, "Got\0");
 		strcpy(inout, "Got\0");
 
 
-	cmd    = buf[idx] & 0xff;
-	subcmd = buf[idx + 1] & 0xff;
-	data1  = buf[idx + 2] & 0xff;
-	data2  = buf[idx + 3] & 0xff;
+	start  = offset + skip;
+	cmd    = buf[start] & 0xff;
+	subcmd = buf[start + 1] & 0xff;
+	data1  = buf[start + 2] & 0xff;
+	data2  = buf[start + 3] & 0xff;
 
 
 	switch (cmd) {
 	switch (cmd) {
-	case 0x00:
-		if (subcmd == 0xff && data1 == 0xaa)
+	case MCE_COMMAND_NULL:
+		if ((subcmd == MCE_HW_CMD_HEADER) &&
+		    (data1 == MCE_CMD_DEVICE_RESET))
 			dev_info(dev, "Device reset requested\n");
 			dev_info(dev, "Device reset requested\n");
 		else
 		else
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 				 cmd, subcmd);
 		break;
 		break;
-	case 0xff:
+	case MCE_HW_CMD_HEADER:
 		switch (subcmd) {
 		switch (subcmd) {
-		case 0x0b:
+		case MCE_CMD_G_REVISION:
 			if (len == 2)
 			if (len == 2)
 				dev_info(dev, "Get hw/sw rev?\n");
 				dev_info(dev, "Get hw/sw rev?\n");
 			else
 			else
 				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
 				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
 					 "0x%02x 0x%02x\n", data1, data2,
 					 "0x%02x 0x%02x\n", data1, data2,
-					 buf[idx + 4], buf[idx + 5]);
+					 buf[start + 4], buf[start + 5]);
 			break;
 			break;
-		case 0xaa:
+		case MCE_CMD_DEVICE_RESET:
 			dev_info(dev, "Device reset requested\n");
 			dev_info(dev, "Device reset requested\n");
 			break;
 			break;
-		case 0xfe:
+		case MCE_RSP_CMD_INVALID:
 			dev_info(dev, "Previous command not supported\n");
 			dev_info(dev, "Previous command not supported\n");
 			break;
 			break;
-		case 0x18:
-		case 0x1b:
+		case MCE_CMD_UNKNOWN7:
+		case MCE_CMD_UNKNOWN9:
 		default:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 				 cmd, subcmd);
 			break;
 			break;
 		}
 		}
 		break;
 		break;
-	case 0x9f:
+	case MCE_COMMAND_HEADER:
 		switch (subcmd) {
 		switch (subcmd) {
-		case 0x03:
+		case MCE_CMD_PING:
 			dev_info(dev, "Ping\n");
 			dev_info(dev, "Ping\n");
 			break;
 			break;
-		case 0x04:
+		case MCE_CMD_UNKNOWN:
 			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
 			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
 				 data1, data2);
 				 data1, data2);
 			break;
 			break;
-		case 0x06:
+		case MCE_CMD_S_CARRIER:
 			dev_info(dev, "%s carrier mode and freq of "
 			dev_info(dev, "%s carrier mode and freq of "
 				 "0x%02x 0x%02x\n", inout, data1, data2);
 				 "0x%02x 0x%02x\n", inout, data1, data2);
 			break;
 			break;
-		case 0x07:
+		case MCE_CMD_G_CARRIER:
 			dev_info(dev, "Get carrier mode and freq\n");
 			dev_info(dev, "Get carrier mode and freq\n");
 			break;
 			break;
-		case 0x08:
+		case MCE_CMD_S_TXMASK:
 			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
 			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
 				 inout, data1);
 				 inout, data1);
 			break;
 			break;
-		case 0x0c:
+		case MCE_CMD_S_TIMEOUT:
 			/* value is in units of 50us, so x*50/100 or x/2 ms */
 			/* value is in units of 50us, so x*50/100 or x/2 ms */
 			dev_info(dev, "%s receive timeout of %d ms\n",
 			dev_info(dev, "%s receive timeout of %d ms\n",
 				 inout, ((data1 << 8) | data2) / 2);
 				 inout, ((data1 << 8) | data2) / 2);
 			break;
 			break;
-		case 0x0d:
+		case MCE_CMD_G_TIMEOUT:
 			dev_info(dev, "Get receive timeout\n");
 			dev_info(dev, "Get receive timeout\n");
 			break;
 			break;
-		case 0x13:
+		case MCE_CMD_G_TXMASK:
 			dev_info(dev, "Get transmit blaster mask\n");
 			dev_info(dev, "Get transmit blaster mask\n");
 			break;
 			break;
-		case 0x14:
+		case MCE_CMD_S_RXSENSOR:
 			dev_info(dev, "%s %s-range receive sensor in use\n",
 			dev_info(dev, "%s %s-range receive sensor in use\n",
 				 inout, data1 == 0x02 ? "short" : "long");
 				 inout, data1 == 0x02 ? "short" : "long");
 			break;
 			break;
-		case 0x15:
+		case MCE_CMD_G_RXSENSOR:
 			if (len == 2)
 			if (len == 2)
 				dev_info(dev, "Get receive sensor\n");
 				dev_info(dev, "Get receive sensor\n");
 			else
 			else
 				dev_info(dev, "Received pulse count is %d\n",
 				dev_info(dev, "Received pulse count is %d\n",
 					 ((data1 << 8) | data2));
 					 ((data1 << 8) | data2));
 			break;
 			break;
-		case 0xfe:
+		case MCE_RSP_CMD_INVALID:
 			dev_info(dev, "Error! Hardware is likely wedged...\n");
 			dev_info(dev, "Error! Hardware is likely wedged...\n");
 			break;
 			break;
-		case 0x05:
-		case 0x09:
-		case 0x0f:
+		case MCE_CMD_UNKNOWN2:
+		case MCE_CMD_UNKNOWN3:
+		case MCE_CMD_UNKNOWN5:
 		default:
 		default:
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
 				 cmd, subcmd);
 				 cmd, subcmd);
@@ -429,6 +546,12 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
 	default:
 	default:
 		break;
 		break;
 	}
 	}
+
+	if (cmd == MCE_IRDATA_TRAILER)
+		dev_info(dev, "End of raw IR data\n");
+	else if ((cmd != MCE_COMMAND_HEADER) &&
+		 ((cmd & MCE_COMMAND_MASK) == MCE_COMMAND_IRDATA))
+		dev_info(dev, "Raw IR data, %d pulse/space samples\n", ir->rem);
 }
 }
 
 
 static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
 static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
@@ -446,9 +569,7 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
 		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
 		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
 			urb->status, len);
 			urb->status, len);
 
 
-		if (debug)
-			mceusb_dev_printdata(ir, urb->transfer_buffer,
-					     len, true);
+		mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
 	}
 	}
 
 
 }
 }
@@ -536,8 +657,8 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	/* MCE tx init header */
 	/* MCE tx init header */
-	cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
-	cmdbuf[cmdcount++] = 0x08;
+	cmdbuf[cmdcount++] = MCE_COMMAND_HEADER;
+	cmdbuf[cmdcount++] = MCE_CMD_S_TXMASK;
 	cmdbuf[cmdcount++] = ir->tx_mask;
 	cmdbuf[cmdcount++] = ir->tx_mask;
 
 
 	/* Generate mce packet data */
 	/* Generate mce packet data */
@@ -551,7 +672,7 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
 			if ((cmdcount < MCE_CMDBUF_SIZE) &&
 			if ((cmdcount < MCE_CMDBUF_SIZE) &&
 			    (cmdcount - MCE_TX_HEADER_LENGTH) %
 			    (cmdcount - MCE_TX_HEADER_LENGTH) %
 			     MCE_CODE_LENGTH == 0)
 			     MCE_CODE_LENGTH == 0)
-				cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
+				cmdbuf[cmdcount++] = MCE_IRDATA_HEADER;
 
 
 			/* Insert mce packet data */
 			/* Insert mce packet data */
 			if (cmdcount < MCE_CMDBUF_SIZE)
 			if (cmdcount < MCE_CMDBUF_SIZE)
@@ -570,7 +691,8 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
 
 
 	/* Fix packet length in last header */
 	/* Fix packet length in last header */
 	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
 	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
-		0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
+		MCE_COMMAND_IRDATA + (cmdcount - MCE_TX_HEADER_LENGTH) %
+		MCE_CODE_LENGTH - 1;
 
 
 	/* Check if we have room for the empty packet at the end */
 	/* Check if we have room for the empty packet at the end */
 	if (cmdcount >= MCE_CMDBUF_SIZE) {
 	if (cmdcount >= MCE_CMDBUF_SIZE) {
@@ -579,7 +701,7 @@ static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
 	}
 	}
 
 
 	/* All mce commands end with an empty packet (0x80) */
 	/* All mce commands end with an empty packet (0x80) */
-	cmdbuf[cmdcount++] = 0x80;
+	cmdbuf[cmdcount++] = MCE_IRDATA_TRAILER;
 
 
 	/* Transmit the command to the mce device */
 	/* Transmit the command to the mce device */
 	mce_async_out(ir, cmdbuf, cmdcount);
 	mce_async_out(ir, cmdbuf, cmdcount);
@@ -608,7 +730,8 @@ static int mceusb_set_tx_mask(void *priv, u32 mask)
 	struct mceusb_dev *ir = priv;
 	struct mceusb_dev *ir = priv;
 
 
 	if (ir->flags.tx_mask_inverted)
 	if (ir->flags.tx_mask_inverted)
-		ir->tx_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1;
+		ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
+				mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
 	else
 	else
 		ir->tx_mask = mask;
 		ir->tx_mask = mask;
 
 
@@ -621,7 +744,8 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 	struct mceusb_dev *ir = priv;
 	struct mceusb_dev *ir = priv;
 	int clk = 10000000;
 	int clk = 10000000;
 	int prescaler = 0, divisor = 0;
 	int prescaler = 0, divisor = 0;
-	unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 };
+	unsigned char cmdbuf[4] = { MCE_COMMAND_HEADER,
+				    MCE_CMD_S_CARRIER, 0x00, 0x00 };
 
 
 	/* Carrier has changed */
 	/* Carrier has changed */
 	if (ir->carrier != carrier) {
 	if (ir->carrier != carrier) {
@@ -629,7 +753,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 		if (carrier == 0) {
 		if (carrier == 0) {
 			ir->carrier = carrier;
 			ir->carrier = carrier;
 			cmdbuf[2] = 0x01;
 			cmdbuf[2] = 0x01;
-			cmdbuf[3] = 0x80;
+			cmdbuf[3] = MCE_IRDATA_TRAILER;
 			dev_dbg(ir->dev, "%s: disabling carrier "
 			dev_dbg(ir->dev, "%s: disabling carrier "
 				"modulation\n", __func__);
 				"modulation\n", __func__);
 			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
 			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
@@ -638,7 +762,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
 
 		for (prescaler = 0; prescaler < 4; ++prescaler) {
 		for (prescaler = 0; prescaler < 4; ++prescaler) {
 			divisor = (clk >> (2 * prescaler)) / carrier;
 			divisor = (clk >> (2 * prescaler)) / carrier;
-			if (divisor <= 0xFF) {
+			if (divisor <= 0xff) {
 				ir->carrier = carrier;
 				ir->carrier = carrier;
 				cmdbuf[2] = prescaler;
 				cmdbuf[2] = prescaler;
 				cmdbuf[3] = divisor;
 				cmdbuf[3] = divisor;
@@ -660,47 +784,36 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
 
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
-	int i, start_index = 0;
-	u8 hdr = MCE_CONTROL_HEADER;
+	DEFINE_IR_RAW_EVENT(rawir);
+	int i = 0;
 
 
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
 	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
 	if (ir->flags.microsoft_gen1)
 	if (ir->flags.microsoft_gen1)
-		start_index = 2;
-
-	for (i = start_index; i < buf_len;) {
-		if (ir->rem == 0) {
-			/* decode mce packets of the form (84),AA,BB,CC,DD */
-			/* IR data packets can span USB messages - rem */
-			hdr = ir->buf_in[i];
-			ir->rem = (hdr & MCE_PACKET_LENGTH_MASK);
-			ir->cmd = (hdr & ~MCE_PACKET_LENGTH_MASK);
-			dev_dbg(ir->dev, "New data. rem: 0x%02x, cmd: 0x%02x\n",
-				ir->rem, ir->cmd);
-			i++;
-		}
-
-		/* don't process MCE commands */
-		if (hdr == MCE_CONTROL_HEADER || hdr == 0xff) {
-			ir->rem = 0;
-			return;
-		}
-
-		for (; (ir->rem > 0) && (i < buf_len); i++) {
+		i = 2;
+
+	for (; i < buf_len; i++) {
+		switch (ir->parser_state) {
+		case SUBCMD:
+			ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
+			mceusb_dev_printdata(ir, ir->buf_in, i - 1,
+					     ir->rem + 2, false);
+			ir->parser_state = CMD_DATA;
+			break;
+		case PARSE_IRDATA:
 			ir->rem--;
 			ir->rem--;
-
 			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
 			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
 			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
 					 * MCE_TIME_UNIT * 1000;
 					 * MCE_TIME_UNIT * 1000;
 
 
 			if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
 			if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
-				if (ir->rawir.pulse == rawir.pulse)
+				if (ir->rawir.pulse == rawir.pulse) {
 					ir->rawir.duration += rawir.duration;
 					ir->rawir.duration += rawir.duration;
-				else {
+				} else {
 					ir->rawir.duration = rawir.duration;
 					ir->rawir.duration = rawir.duration;
 					ir->rawir.pulse = rawir.pulse;
 					ir->rawir.pulse = rawir.pulse;
 				}
 				}
-				continue;
+				if (ir->rem)
+					break;
 			}
 			}
 			rawir.duration += ir->rawir.duration;
 			rawir.duration += ir->rawir.duration;
 			ir->rawir.duration = 0;
 			ir->rawir.duration = 0;
@@ -711,14 +824,40 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 				rawir.duration);
 				rawir.duration);
 
 
 			ir_raw_event_store(ir->idev, &rawir);
 			ir_raw_event_store(ir->idev, &rawir);
+			break;
+		case CMD_DATA:
+			ir->rem--;
+			break;
+		case CMD_HEADER:
+			/* decode mce packets of the form (84),AA,BB,CC,DD */
+			/* IR data packets can span USB messages - rem */
+			ir->cmd = ir->buf_in[i];
+			if ((ir->cmd == MCE_COMMAND_HEADER) ||
+			    ((ir->cmd & MCE_COMMAND_MASK) !=
+			     MCE_COMMAND_IRDATA)) {
+				ir->parser_state = SUBCMD;
+				continue;
+			}
+			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
+			mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false);
+			if (ir->rem) {
+				ir->parser_state = PARSE_IRDATA;
+				break;
+			}
+			/*
+			 * a package with len=0 (e. g. 0x80) means end of
+			 * data. We could use it to do the call to
+			 * ir_raw_event_handle(). For now, we don't need to
+			 * use it.
+			 */
+			break;
 		}
 		}
 
 
-		if (ir->buf_in[i] == 0x80 || ir->buf_in[i] == 0x9f)
-			ir->rem = 0;
-
-		dev_dbg(ir->dev, "calling ir_raw_event_handle\n");
-		ir_raw_event_handle(ir->idev);
+		if (ir->parser_state != CMD_HEADER && !ir->rem)
+			ir->parser_state = CMD_HEADER;
 	}
 	}
+	dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
+	ir_raw_event_handle(ir->idev);
 }
 }
 
 
 static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
@@ -737,9 +876,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 
 
 	buf_len = urb->actual_length;
 	buf_len = urb->actual_length;
 
 
-	if (debug)
-		mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false);
-
 	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
 	if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
 		ir->send_flags = SEND_FLAG_COMPLETE;
 		ir->send_flags = SEND_FLAG_COMPLETE;
 		dev_dbg(ir->dev, "setup answer received %d bytes\n",
 		dev_dbg(ir->dev, "setup answer received %d bytes\n",
@@ -760,6 +896,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
 
 
 	case -EPIPE:
 	case -EPIPE:
 	default:
 	default:
+		dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
 		break;
 		break;
 	}
 	}
 
 
@@ -865,6 +1002,8 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 	struct input_dev *idev;
 	struct input_dev *idev;
 	struct ir_dev_props *props;
 	struct ir_dev_props *props;
 	struct device *dev = ir->dev;
 	struct device *dev = ir->dev;
+	const char *rc_map = RC_MAP_RC6_MCE;
+	const char *name = "Media Center Ed. eHome Infrared Remote Transceiver";
 	int ret = -ENODEV;
 	int ret = -ENODEV;
 
 
 	idev = input_allocate_device();
 	idev = input_allocate_device();
@@ -880,8 +1019,11 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 		goto props_alloc_failed;
 		goto props_alloc_failed;
 	}
 	}
 
 
-	snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
-		 "Infrared Remote Transceiver (%04x:%04x)",
+	if (mceusb_model[ir->model].name)
+		name = mceusb_model[ir->model].name;
+
+	snprintf(ir->name, sizeof(ir->name), "%s (%04x:%04x)",
+		 name,
 		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
 		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
 		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
 		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
 
 
@@ -899,7 +1041,10 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
 
 
 	ir->props = props;
 	ir->props = props;
 
 
-	ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
+	if (mceusb_model[ir->model].rc_map)
+		rc_map = mceusb_model[ir->model].rc_map;
+
+	ret = ir_input_register(idev, rc_map, props, DRIVER_NAME);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(dev, "remote input device register failed\n");
 		dev_err(dev, "remote input device register failed\n");
 		goto irdev_failed;
 		goto irdev_failed;
@@ -926,17 +1071,26 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	struct mceusb_dev *ir = NULL;
 	struct mceusb_dev *ir = NULL;
 	int pipe, maxp, i;
 	int pipe, maxp, i;
 	char buf[63], name[128] = "";
 	char buf[63], name[128] = "";
+	enum mceusb_model_type model = id->driver_info;
 	bool is_gen3;
 	bool is_gen3;
 	bool is_microsoft_gen1;
 	bool is_microsoft_gen1;
 	bool tx_mask_inverted;
 	bool tx_mask_inverted;
+	bool is_polaris;
 
 
 	dev_dbg(&intf->dev, ": %s called\n", __func__);
 	dev_dbg(&intf->dev, ": %s called\n", __func__);
 
 
 	idesc  = intf->cur_altsetting;
 	idesc  = intf->cur_altsetting;
 
 
-	is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
-	is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0;
-	tx_mask_inverted = usb_match_id(intf, std_tx_mask_list) ? 0 : 1;
+	is_gen3 = mceusb_model[model].mce_gen3;
+	is_microsoft_gen1 = mceusb_model[model].mce_gen1;
+	tx_mask_inverted = mceusb_model[model].tx_mask_inverted;
+	is_polaris = mceusb_model[model].is_polaris;
+
+	if (is_polaris) {
+		/* Interface 0 is IR */
+		if (idesc->desc.bInterfaceNumber)
+			return -ENODEV;
+	}
 
 
 	/* step through the endpoints to find first bulk in and out endpoint */
 	/* step through the endpoints to find first bulk in and out endpoint */
 	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
 	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
@@ -997,6 +1151,9 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 	ir->len_in = maxp;
 	ir->len_in = maxp;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 	ir->flags.microsoft_gen1 = is_microsoft_gen1;
 	ir->flags.tx_mask_inverted = tx_mask_inverted;
 	ir->flags.tx_mask_inverted = tx_mask_inverted;
+	ir->model = model;
+
+	init_ir_raw_event(&ir->rawir);
 
 
 	/* Saving usb interface data for use by the transmitter routine */
 	/* Saving usb interface data for use by the transmitter routine */
 	ir->usb_ep_in = ep_in;
 	ir->usb_ep_in = ep_in;

+ 1246 - 0
drivers/media/IR/nuvoton-cir.c

@@ -0,0 +1,1246 @@
+/*
+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
+ *
+ * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
+ * Copyright (C) 2009 Nuvoton PS Team
+ *
+ * Special thanks to Nuvoton for providing hardware, spec sheets and
+ * sample code upon which portions of this driver are based. Indirect
+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
+ * modeled after.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <media/ir-core.h>
+#include <linux/pci_ids.h>
+
+#include "nuvoton-cir.h"
+
+static char *chip_id = "w836x7hg";
+
+/* write val to config reg */
+static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	outb(reg, nvt->cr_efir);
+	outb(val, nvt->cr_efdr);
+}
+
+/* read val from config reg */
+static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg)
+{
+	outb(reg, nvt->cr_efir);
+	return inb(nvt->cr_efdr);
+}
+
+/* update config register bit without changing other bits */
+static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	u8 tmp = nvt_cr_read(nvt, reg) | val;
+	nvt_cr_write(nvt, tmp, reg);
+}
+
+/* clear config register bit without changing other bits */
+static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg)
+{
+	u8 tmp = nvt_cr_read(nvt, reg) & ~val;
+	nvt_cr_write(nvt, tmp, reg);
+}
+
+/* enter extended function mode */
+static inline void nvt_efm_enable(struct nvt_dev *nvt)
+{
+	/* Enabling Extended Function Mode explicitly requires writing 2x */
+	outb(EFER_EFM_ENABLE, nvt->cr_efir);
+	outb(EFER_EFM_ENABLE, nvt->cr_efir);
+}
+
+/* exit extended function mode */
+static inline void nvt_efm_disable(struct nvt_dev *nvt)
+{
+	outb(EFER_EFM_DISABLE, nvt->cr_efir);
+}
+
+/*
+ * When you want to address a specific logical device, write its logical
+ * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing
+ * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN.
+ */
+static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev)
+{
+	outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir);
+	outb(ldev, nvt->cr_efdr);
+}
+
+/* write val to cir config register */
+static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset)
+{
+	outb(val, nvt->cir_addr + offset);
+}
+
+/* read val from cir config register */
+static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset)
+{
+	u8 val;
+
+	val = inb(nvt->cir_addr + offset);
+
+	return val;
+}
+
+/* write val to cir wake register */
+static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt,
+					  u8 val, u8 offset)
+{
+	outb(val, nvt->cir_wake_addr + offset);
+}
+
+/* read val from cir wake config register */
+static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset)
+{
+	u8 val;
+
+	val = inb(nvt->cir_wake_addr + offset);
+
+	return val;
+}
+
+#define pr_reg(text, ...) \
+	printk(KERN_INFO KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+
+/* dump current cir register contents */
+static void cir_dump_regs(struct nvt_dev *nvt)
+{
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+
+	pr_reg("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME);
+	pr_reg(" * CR CIR ACTIVE :   0x%x\n",
+	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
+	pr_reg(" * CR CIR BASE ADDR: 0x%x\n",
+	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
+		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
+	pr_reg(" * CR CIR IRQ NUM:   0x%x\n",
+	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
+
+	nvt_efm_disable(nvt);
+
+	pr_reg("%s: Dump CIR registers:\n", NVT_DRIVER_NAME);
+	pr_reg(" * IRCON:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON));
+	pr_reg(" * IRSTS:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS));
+	pr_reg(" * IREN:      0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN));
+	pr_reg(" * RXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT));
+	pr_reg(" * CP:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CP));
+	pr_reg(" * CC:        0x%x\n", nvt_cir_reg_read(nvt, CIR_CC));
+	pr_reg(" * SLCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH));
+	pr_reg(" * SLCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL));
+	pr_reg(" * FIFOCON:   0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON));
+	pr_reg(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS));
+	pr_reg(" * SRXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO));
+	pr_reg(" * TXFCONT:   0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT));
+	pr_reg(" * STXFIFO:   0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO));
+	pr_reg(" * FCCH:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH));
+	pr_reg(" * FCCL:      0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL));
+	pr_reg(" * IRFSM:     0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM));
+}
+
+/* dump current cir wake register contents */
+static void cir_wake_dump_regs(struct nvt_dev *nvt)
+{
+	u8 i, fifo_len;
+
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+
+	pr_reg("%s: Dump CIR WAKE logical device registers:\n",
+	       NVT_DRIVER_NAME);
+	pr_reg(" * CR CIR WAKE ACTIVE :   0x%x\n",
+	       nvt_cr_read(nvt, CR_LOGICAL_DEV_EN));
+	pr_reg(" * CR CIR WAKE BASE ADDR: 0x%x\n",
+	       (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) |
+		nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO));
+	pr_reg(" * CR CIR WAKE IRQ NUM:   0x%x\n",
+	       nvt_cr_read(nvt, CR_CIR_IRQ_RSRC));
+
+	nvt_efm_disable(nvt);
+
+	pr_reg("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME);
+	pr_reg(" * IRCON:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON));
+	pr_reg(" * IRSTS:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS));
+	pr_reg(" * IREN:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN));
+	pr_reg(" * FIFO CMP DEEP:  0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP));
+	pr_reg(" * FIFO CMP TOL:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL));
+	pr_reg(" * FIFO COUNT:     0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT));
+	pr_reg(" * SLCH:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH));
+	pr_reg(" * SLCL:           0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL));
+	pr_reg(" * FIFOCON:        0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON));
+	pr_reg(" * SRXFSTS:        0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS));
+	pr_reg(" * SAMPLE RX FIFO: 0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO));
+	pr_reg(" * WR FIFO DATA:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA));
+	pr_reg(" * RD FIFO ONLY:   0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
+	pr_reg(" * RD FIFO ONLY IDX: 0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX));
+	pr_reg(" * FIFO IGNORE:    0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE));
+	pr_reg(" * IRFSM:          0x%x\n",
+	       nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM));
+
+	fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT);
+	pr_reg("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len);
+	pr_reg("* Contents = ");
+	for (i = 0; i < fifo_len; i++)
+		printk(KERN_CONT "%02x ",
+		       nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY));
+	printk(KERN_CONT "\n");
+}
+
+/* detect hardware features */
+static int nvt_hw_detect(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	u8 chip_major, chip_minor;
+	int ret = 0;
+
+	nvt_efm_enable(nvt);
+
+	/* Check if we're wired for the alternate EFER setup */
+	chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
+	if (chip_major == 0xff) {
+		nvt->cr_efir = CR_EFIR2;
+		nvt->cr_efdr = CR_EFDR2;
+		nvt_efm_enable(nvt);
+		chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI);
+	}
+
+	chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO);
+	nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor);
+
+	if (chip_major != CHIP_ID_HIGH &&
+	    (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2))
+		ret = -ENODEV;
+
+	nvt_efm_disable(nvt);
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->chip_major = chip_major;
+	nvt->chip_minor = chip_minor;
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	return ret;
+}
+
+static void nvt_cir_ldev_init(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	/* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */
+	val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL);
+	val &= OUTPUT_PIN_SEL_MASK;
+	val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB);
+	nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL);
+
+	/* Select CIR logical device and enable */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI);
+	nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+
+	nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC);
+
+	nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d",
+		nvt->cir_addr, nvt->cir_irq);
+}
+
+static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt)
+{
+	/* Select ACPI logical device, enable it and CIR Wake */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	/* Enable CIR Wake via PSOUT# (Pin60) */
+	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
+
+	/* enable cir interrupt of mouse/keyboard IRQ event */
+	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
+
+	/* enable pme interrupt of cir wakeup event */
+	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
+
+	/* Select CIR Wake logical device and enable */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI);
+	nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO);
+
+	nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC);
+
+	nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d",
+		nvt->cir_wake_addr, nvt->cir_wake_irq);
+}
+
+/* clear out the hardware's cir rx fifo */
+static void nvt_clear_cir_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
+	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
+}
+
+/* clear out the hardware's cir wake rx fifo */
+static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON);
+	nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR,
+			       CIR_WAKE_FIFOCON);
+}
+
+/* clear out the hardware's cir tx fifo */
+static void nvt_clear_tx_fifo(struct nvt_dev *nvt)
+{
+	u8 val;
+
+	val = nvt_cir_reg_read(nvt, CIR_FIFOCON);
+	nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON);
+}
+
+/* enable RX Trigger Level Reach and Packet End interrupts */
+static void nvt_set_cir_iren(struct nvt_dev *nvt)
+{
+	u8 iren;
+
+	iren = CIR_IREN_RTR | CIR_IREN_PE;
+	nvt_cir_reg_write(nvt, iren, CIR_IREN);
+}
+
+static void nvt_cir_regs_init(struct nvt_dev *nvt)
+{
+	/* set sample limit count (PE interrupt raised when reached) */
+	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
+	nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
+
+	/* set fifo irq trigger levels */
+	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
+			  CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
+
+	/*
+	 * Enable TX and RX, specify carrier on = low, off = high, and set
+	 * sample period (currently 50us)
+	 */
+	nvt_cir_reg_write(nvt,
+			  CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+			  CIR_IRCON);
+
+	/* clear hardware rx and tx fifos */
+	nvt_clear_cir_fifo(nvt);
+	nvt_clear_tx_fifo(nvt);
+
+	/* clear any and all stray interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* and finally, enable interrupts */
+	nvt_set_cir_iren(nvt);
+}
+
+static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
+{
+	/* set number of bytes needed for wake key comparison (default 67) */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP);
+
+	/* set tolerance/variance allowed per byte during wake compare */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE,
+			       CIR_WAKE_FIFO_CMP_TOL);
+
+	/* set sample limit count (PE interrupt raised when reached) */
+	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH);
+	nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL);
+
+	/* set cir wake fifo rx trigger level (currently 67) */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV,
+			       CIR_WAKE_FIFOCON);
+
+	/*
+	 * Enable TX and RX, specific carrier on = low, off = high, and set
+	 * sample period (currently 50us)
+	 */
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
+			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
+			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
+			       CIR_WAKE_IRCON);
+
+	/* clear cir wake rx fifo */
+	nvt_clear_cir_wake_fifo(nvt);
+
+	/* clear any and all stray interrupts */
+	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
+}
+
+static void nvt_enable_wake(struct nvt_dev *nvt)
+{
+	nvt_efm_enable(nvt);
+
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI);
+	nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE);
+	nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS);
+	nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2);
+
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN |
+			       CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV |
+			       CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL,
+			       CIR_WAKE_IRCON);
+	nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
+	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
+}
+
+/* rx carrier detect only works in learning mode, must be called w/nvt_lock */
+static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt)
+{
+	u32 count, carrier, duration = 0;
+	int i;
+
+	count = nvt_cir_reg_read(nvt, CIR_FCCL) |
+		nvt_cir_reg_read(nvt, CIR_FCCH) << 8;
+
+	for (i = 0; i < nvt->pkts; i++) {
+		if (nvt->buf[i] & BUF_PULSE_BIT)
+			duration += nvt->buf[i] & BUF_LEN_MASK;
+	}
+
+	duration *= SAMPLE_PERIOD;
+
+	if (!count || !duration) {
+		nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)",
+		       count, duration);
+		return 0;
+	}
+
+	carrier = (count * 1000000) / duration;
+
+	if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER))
+		nvt_dbg("WTF? Carrier frequency out of range!");
+
+	nvt_dbg("Carrier frequency: %u (count %u, duration %u)",
+		carrier, count, duration);
+
+	return carrier;
+}
+
+/*
+ * set carrier frequency
+ *
+ * set carrier on 2 registers: CP & CC
+ * always set CP as 0x81
+ * set CC by SPEC, CC = 3MHz/carrier - 1
+ */
+static int nvt_set_tx_carrier(void *data, u32 carrier)
+{
+	struct nvt_dev *nvt = data;
+	u16 val;
+
+	nvt_cir_reg_write(nvt, 1, CIR_CP);
+	val = 3000000 / (carrier) - 1;
+	nvt_cir_reg_write(nvt, val & 0xff, CIR_CC);
+
+	nvt_dbg("cp: 0x%x cc: 0x%x\n",
+		nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC));
+
+	return 0;
+}
+
+/*
+ * nvt_tx_ir
+ *
+ * 1) clean TX fifo first (handled by AP)
+ * 2) copy data from user space
+ * 3) disable RX interrupts, enable TX interrupts: TTR & TFU
+ * 4) send 9 packets to TX FIFO to open TTR
+ * in interrupt_handler:
+ * 5) send all data out
+ * go back to write():
+ * 6) disable TX interrupts, re-enable RX interupts
+ *
+ * The key problem of this function is user space data may larger than
+ * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to
+ * buf, and keep current copied data buf num in cur_buf_num. But driver's buf
+ * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to
+ * set TXFCONT as 0xff, until buf_count less than 0xff.
+ */
+static int nvt_tx_ir(void *priv, int *txbuf, u32 n)
+{
+	struct nvt_dev *nvt = priv;
+	unsigned long flags;
+	size_t cur_count;
+	unsigned int i;
+	u8 iren;
+	int ret;
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+
+	if (n >= TX_BUF_LEN) {
+		nvt->tx.buf_count = cur_count = TX_BUF_LEN;
+		ret = TX_BUF_LEN;
+	} else {
+		nvt->tx.buf_count = cur_count = n;
+		ret = n;
+	}
+
+	memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count);
+
+	nvt->tx.cur_buf_num = 0;
+
+	/* save currently enabled interrupts */
+	iren = nvt_cir_reg_read(nvt, CIR_IREN);
+
+	/* now disable all interrupts, save TFU & TTR */
+	nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN);
+
+	nvt->tx.tx_state = ST_TX_REPLY;
+
+	nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 |
+			  CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON);
+
+	/* trigger TTR interrupt by writing out ones, (yes, it's ugly) */
+	for (i = 0; i < 9; i++)
+		nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO);
+
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST);
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	nvt->tx.tx_state = ST_TX_NONE;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	/* restore enabled interrupts to prior state */
+	nvt_cir_reg_write(nvt, iren, CIR_IREN);
+
+	return ret;
+}
+
+/* dump contents of the last rx buffer we got from the hw rx fifo */
+static void nvt_dump_rx_buf(struct nvt_dev *nvt)
+{
+	int i;
+
+	printk(KERN_DEBUG "%s (len %d): ", __func__, nvt->pkts);
+	for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++)
+		printk(KERN_CONT "0x%02x ", nvt->buf[i]);
+	printk(KERN_CONT "\n");
+}
+
+/*
+ * Process raw data in rx driver buffer, store it in raw IR event kfifo,
+ * trigger decode when appropriate.
+ *
+ * We get IR data samples one byte at a time. If the msb is set, its a pulse,
+ * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD
+ * (default 50us) intervals for that pulse/space. A discrete signal is
+ * followed by a series of 0x7f packets, then either 0x7<something> or 0x80
+ * to signal more IR coming (repeats) or end of IR, respectively. We store
+ * sample data in the raw event kfifo until we see 0x7<something> (except f)
+ * or 0x80, at which time, we trigger a decode operation.
+ */
+static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
+{
+	DEFINE_IR_RAW_EVENT(rawir);
+	unsigned int count;
+	u32 carrier;
+	u8 sample;
+	int i;
+
+	nvt_dbg_verbose("%s firing", __func__);
+
+	if (debug)
+		nvt_dump_rx_buf(nvt);
+
+	if (nvt->carrier_detect_enabled)
+		carrier = nvt_rx_carrier_detect(nvt);
+
+	count = nvt->pkts;
+	nvt_dbg_verbose("Processing buffer of len %d", count);
+
+	for (i = 0; i < count; i++) {
+		nvt->pkts--;
+		sample = nvt->buf[i];
+
+		rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
+		rawir.duration = (sample & BUF_LEN_MASK)
+					* SAMPLE_PERIOD * 1000;
+
+		if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) {
+			if (nvt->rawir.pulse == rawir.pulse)
+				nvt->rawir.duration += rawir.duration;
+			else {
+				nvt->rawir.duration = rawir.duration;
+				nvt->rawir.pulse = rawir.pulse;
+			}
+			continue;
+		}
+
+		rawir.duration += nvt->rawir.duration;
+
+		init_ir_raw_event(&nvt->rawir);
+		nvt->rawir.duration = 0;
+		nvt->rawir.pulse = rawir.pulse;
+
+		if (sample == BUF_PULSE_BIT)
+			rawir.pulse = false;
+
+		if (rawir.duration) {
+			nvt_dbg("Storing %s with duration %d",
+				rawir.pulse ? "pulse" : "space",
+				rawir.duration);
+
+			ir_raw_event_store(nvt->rdev, &rawir);
+		}
+
+		/*
+		 * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE
+		 * indicates end of IR signal, but new data incoming. In both
+		 * cases, it means we're ready to call ir_raw_event_handle
+		 */
+		if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) &&
+		    (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE))
+			ir_raw_event_handle(nvt->rdev);
+	}
+
+	if (nvt->pkts) {
+		nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
+		nvt->pkts = 0;
+	}
+
+	nvt_dbg_verbose("%s done", __func__);
+}
+
+static void nvt_handle_rx_fifo_overrun(struct nvt_dev *nvt)
+{
+	nvt_pr(KERN_WARNING, "RX FIFO overrun detected, flushing data!");
+
+	nvt->pkts = 0;
+	nvt_clear_cir_fifo(nvt);
+	ir_raw_event_reset(nvt->rdev);
+}
+
+/* copy data from hardware rx fifo into driver buffer */
+static void nvt_get_rx_ir_data(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	u8 fifocount, val;
+	unsigned int b_idx;
+	bool overrun = false;
+	int i;
+
+	/* Get count of how many bytes to read from RX FIFO */
+	fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT);
+	/* if we get 0xff, probably means the logical dev is disabled */
+	if (fifocount == 0xff)
+		return;
+	/* watch out for a fifo overrun condition */
+	else if (fifocount > RX_BUF_LEN) {
+		overrun = true;
+		fifocount = RX_BUF_LEN;
+	}
+
+	nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount);
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+	b_idx = nvt->pkts;
+
+	/* This should never happen, but lets check anyway... */
+	if (b_idx + fifocount > RX_BUF_LEN) {
+		nvt_process_rx_ir_data(nvt);
+		b_idx = 0;
+	}
+
+	/* Read fifocount bytes from CIR Sample RX FIFO register */
+	for (i = 0; i < fifocount; i++) {
+		val = nvt_cir_reg_read(nvt, CIR_SRXFIFO);
+		nvt->buf[b_idx + i] = val;
+	}
+
+	nvt->pkts += fifocount;
+	nvt_dbg("%s: pkts now %d", __func__, nvt->pkts);
+
+	nvt_process_rx_ir_data(nvt);
+
+	if (overrun)
+		nvt_handle_rx_fifo_overrun(nvt);
+
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+}
+
+static void nvt_cir_log_irqs(u8 status, u8 iren)
+{
+	nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s",
+		status, iren,
+		status & CIR_IRSTS_RDR	? " RDR"	: "",
+		status & CIR_IRSTS_RTR	? " RTR"	: "",
+		status & CIR_IRSTS_PE	? " PE"		: "",
+		status & CIR_IRSTS_RFO	? " RFO"	: "",
+		status & CIR_IRSTS_TE	? " TE"		: "",
+		status & CIR_IRSTS_TTR	? " TTR"	: "",
+		status & CIR_IRSTS_TFU	? " TFU"	: "",
+		status & CIR_IRSTS_GH	? " GH"		: "",
+		status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE |
+			   CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR |
+			   CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : "");
+}
+
+static bool nvt_cir_tx_inactive(struct nvt_dev *nvt)
+{
+	unsigned long flags;
+	bool tx_inactive;
+	u8 tx_state;
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	tx_state = nvt->tx.tx_state;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	tx_inactive = (tx_state == ST_TX_NONE);
+
+	return tx_inactive;
+}
+
+/* interrupt service routine for incoming and outgoing CIR data */
+static irqreturn_t nvt_cir_isr(int irq, void *data)
+{
+	struct nvt_dev *nvt = data;
+	u8 status, iren, cur_state;
+	unsigned long flags;
+
+	nvt_dbg_verbose("%s firing", __func__);
+
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_efm_disable(nvt);
+
+	/*
+	 * Get IR Status register contents. Write 1 to ack/clear
+	 *
+	 * bit: reg name      - description
+	 *   7: CIR_IRSTS_RDR - RX Data Ready
+	 *   6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach
+	 *   5: CIR_IRSTS_PE  - Packet End
+	 *   4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set)
+	 *   3: CIR_IRSTS_TE  - TX FIFO Empty
+	 *   2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach
+	 *   1: CIR_IRSTS_TFU - TX FIFO Underrun
+	 *   0: CIR_IRSTS_GH  - Min Length Detected
+	 */
+	status = nvt_cir_reg_read(nvt, CIR_IRSTS);
+	if (!status) {
+		nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__);
+		nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+
+	/* ack/clear all irq flags we've got */
+	nvt_cir_reg_write(nvt, status, CIR_IRSTS);
+	nvt_cir_reg_write(nvt, 0, CIR_IRSTS);
+
+	/* Interrupt may be shared with CIR Wake, bail if CIR not enabled */
+	iren = nvt_cir_reg_read(nvt, CIR_IREN);
+	if (!iren) {
+		nvt_dbg_verbose("%s exiting, CIR not enabled", __func__);
+		return IRQ_RETVAL(IRQ_NONE);
+	}
+
+	if (debug)
+		nvt_cir_log_irqs(status, iren);
+
+	if (status & CIR_IRSTS_RTR) {
+		/* FIXME: add code for study/learn mode */
+		/* We only do rx if not tx'ing */
+		if (nvt_cir_tx_inactive(nvt))
+			nvt_get_rx_ir_data(nvt);
+	}
+
+	if (status & CIR_IRSTS_PE) {
+		if (nvt_cir_tx_inactive(nvt))
+			nvt_get_rx_ir_data(nvt);
+
+		spin_lock_irqsave(&nvt->nvt_lock, flags);
+
+		cur_state = nvt->study_state;
+
+		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+		if (cur_state == ST_STUDY_NONE)
+			nvt_clear_cir_fifo(nvt);
+	}
+
+	if (status & CIR_IRSTS_TE)
+		nvt_clear_tx_fifo(nvt);
+
+	if (status & CIR_IRSTS_TTR) {
+		unsigned int pos, count;
+		u8 tmp;
+
+		spin_lock_irqsave(&nvt->tx.lock, flags);
+
+		pos = nvt->tx.cur_buf_num;
+		count = nvt->tx.buf_count;
+
+		/* Write data into the hardware tx fifo while pos < count */
+		if (pos < count) {
+			nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO);
+			nvt->tx.cur_buf_num++;
+		/* Disable TX FIFO Trigger Level Reach (TTR) interrupt */
+		} else {
+			tmp = nvt_cir_reg_read(nvt, CIR_IREN);
+			nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN);
+		}
+
+		spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	}
+
+	if (status & CIR_IRSTS_TFU) {
+		spin_lock_irqsave(&nvt->tx.lock, flags);
+		if (nvt->tx.tx_state == ST_TX_REPLY) {
+			nvt->tx.tx_state = ST_TX_REQUEST;
+			wake_up(&nvt->tx.queue);
+		}
+		spin_unlock_irqrestore(&nvt->tx.lock, flags);
+	}
+
+	nvt_dbg_verbose("%s done", __func__);
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+/* Interrupt service routine for CIR Wake */
+static irqreturn_t nvt_cir_wake_isr(int irq, void *data)
+{
+	u8 status, iren, val;
+	struct nvt_dev *nvt = data;
+	unsigned long flags;
+
+	nvt_dbg_wake("%s firing", __func__);
+
+	status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS);
+	if (!status)
+		return IRQ_RETVAL(IRQ_NONE);
+
+	if (status & CIR_WAKE_IRSTS_IR_PENDING)
+		nvt_clear_cir_wake_fifo(nvt);
+
+	nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS);
+	nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS);
+
+	/* Interrupt may be shared with CIR, bail if Wake not enabled */
+	iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN);
+	if (!iren) {
+		nvt_dbg_wake("%s exiting, wake not enabled", __func__);
+		return IRQ_RETVAL(IRQ_HANDLED);
+	}
+
+	if ((status & CIR_WAKE_IRSTS_PE) &&
+	    (nvt->wake_state == ST_WAKE_START)) {
+		while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) {
+			val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY);
+			nvt_dbg("setting wake up key: 0x%x", val);
+		}
+
+		nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN);
+		spin_lock_irqsave(&nvt->nvt_lock, flags);
+		nvt->wake_state = ST_WAKE_FINISH;
+		spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+	}
+
+	nvt_dbg_wake("%s done", __func__);
+	return IRQ_RETVAL(IRQ_HANDLED);
+}
+
+static void nvt_enable_cir(struct nvt_dev *nvt)
+{
+	/* set function enable flags */
+	nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+			  CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+			  CIR_IRCON);
+
+	nvt_efm_enable(nvt);
+
+	/* enable the CIR logical device */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	/* clear all pending interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* enable interrupts */
+	nvt_set_cir_iren(nvt);
+}
+
+static void nvt_disable_cir(struct nvt_dev *nvt)
+{
+	/* disable CIR interrupts */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+
+	/* clear any and all pending interrupts */
+	nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+	/* clear all function enable flags */
+	nvt_cir_reg_write(nvt, 0, CIR_IRCON);
+
+	/* clear hardware rx and tx fifos */
+	nvt_clear_cir_fifo(nvt);
+	nvt_clear_tx_fifo(nvt);
+
+	nvt_efm_enable(nvt);
+
+	/* disable the CIR logical device */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+}
+
+static int nvt_open(void *data)
+{
+	struct nvt_dev *nvt = (struct nvt_dev *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->in_use = true;
+	nvt_enable_cir(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	return 0;
+}
+
+static void nvt_close(void *data)
+{
+	struct nvt_dev *nvt = (struct nvt_dev *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->in_use = false;
+	nvt_disable_cir(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+}
+
+/* Allocate memory, probe hardware, and initialize everything */
+static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
+{
+	struct nvt_dev *nvt = NULL;
+	struct input_dev *rdev = NULL;
+	struct ir_dev_props *props = NULL;
+	int ret = -ENOMEM;
+
+	nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL);
+	if (!nvt)
+		return ret;
+
+	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
+	if (!props)
+		goto failure;
+
+	/* input device for IR remote (and tx) */
+	rdev = input_allocate_device();
+	if (!rdev)
+		goto failure;
+
+	ret = -ENODEV;
+	/* validate pnp resources */
+	if (!pnp_port_valid(pdev, 0) ||
+	    pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) {
+		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_irq_valid(pdev, 0)) {
+		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_port_valid(pdev, 1) ||
+	    pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) {
+		dev_err(&pdev->dev, "Wake PNP Port not valid!\n");
+		goto failure;
+	}
+
+	nvt->cir_addr = pnp_port_start(pdev, 0);
+	nvt->cir_irq  = pnp_irq(pdev, 0);
+
+	nvt->cir_wake_addr = pnp_port_start(pdev, 1);
+	/* irq is always shared between cir and cir wake */
+	nvt->cir_wake_irq  = nvt->cir_irq;
+
+	nvt->cr_efir = CR_EFIR;
+	nvt->cr_efdr = CR_EFDR;
+
+	spin_lock_init(&nvt->nvt_lock);
+	spin_lock_init(&nvt->tx.lock);
+	init_ir_raw_event(&nvt->rawir);
+
+	ret = -EBUSY;
+	/* now claim resources */
+	if (!request_region(nvt->cir_addr,
+			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
+			NVT_DRIVER_NAME, (void *)nvt))
+		goto failure;
+
+	if (!request_region(nvt->cir_wake_addr,
+			    CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
+			NVT_DRIVER_NAME, (void *)nvt))
+		goto failure;
+
+	pnp_set_drvdata(pdev, nvt);
+	nvt->pdev = pdev;
+
+	init_waitqueue_head(&nvt->tx.queue);
+
+	ret = nvt_hw_detect(nvt);
+	if (ret)
+		goto failure;
+
+	/* Initialize CIR & CIR Wake Logical Devices */
+	nvt_efm_enable(nvt);
+	nvt_cir_ldev_init(nvt);
+	nvt_cir_wake_ldev_init(nvt);
+	nvt_efm_disable(nvt);
+
+	/* Initialize CIR & CIR Wake Config Registers */
+	nvt_cir_regs_init(nvt);
+	nvt_cir_wake_regs_init(nvt);
+
+	/* Set up ir-core props */
+	props->priv = nvt;
+	props->driver_type = RC_DRIVER_IR_RAW;
+	props->allowed_protos = IR_TYPE_ALL;
+	props->open = nvt_open;
+	props->close = nvt_close;
+#if 0
+	props->min_timeout = XYZ;
+	props->max_timeout = XYZ;
+	props->timeout = XYZ;
+	/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
+	props->rx_resolution = XYZ;
+
+	/* tx bits */
+	props->tx_resolution = XYZ;
+#endif
+	props->tx_ir = nvt_tx_ir;
+	props->s_tx_carrier = nvt_set_tx_carrier;
+
+	rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver";
+	rdev->id.bustype = BUS_HOST;
+	rdev->id.vendor = PCI_VENDOR_ID_WINBOND2;
+	rdev->id.product = nvt->chip_major;
+	rdev->id.version = nvt->chip_minor;
+
+	nvt->props = props;
+	nvt->rdev = rdev;
+
+	device_set_wakeup_capable(&pdev->dev, 1);
+	device_set_wakeup_enable(&pdev->dev, 1);
+
+	ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME);
+	if (ret)
+		goto failure;
+
+	nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n");
+	if (debug) {
+		cir_dump_regs(nvt);
+		cir_wake_dump_regs(nvt);
+	}
+
+	return 0;
+
+failure:
+	if (nvt->cir_irq)
+		free_irq(nvt->cir_irq, nvt);
+	if (nvt->cir_addr)
+		release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
+
+	if (nvt->cir_wake_irq)
+		free_irq(nvt->cir_wake_irq, nvt);
+	if (nvt->cir_wake_addr)
+		release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
+
+	input_free_device(rdev);
+	kfree(props);
+	kfree(nvt);
+
+	return ret;
+}
+
+static void __devexit nvt_remove(struct pnp_dev *pdev)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	/* disable CIR */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+	nvt_disable_cir(nvt);
+	/* enable CIR Wake (for IR power-on) */
+	nvt_enable_wake(nvt);
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	/* free resources */
+	free_irq(nvt->cir_irq, nvt);
+	free_irq(nvt->cir_wake_irq, nvt);
+	release_region(nvt->cir_addr, CIR_IOREG_LENGTH);
+	release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH);
+
+	ir_input_unregister(nvt->rdev);
+
+	kfree(nvt->props);
+	kfree(nvt);
+}
+
+static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	nvt_dbg("%s called", __func__);
+
+	/* zero out misc state tracking */
+	spin_lock_irqsave(&nvt->nvt_lock, flags);
+	nvt->study_state = ST_STUDY_NONE;
+	nvt->wake_state = ST_WAKE_NONE;
+	spin_unlock_irqrestore(&nvt->nvt_lock, flags);
+
+	spin_lock_irqsave(&nvt->tx.lock, flags);
+	nvt->tx.tx_state = ST_TX_NONE;
+	spin_unlock_irqrestore(&nvt->tx.lock, flags);
+
+	/* disable all CIR interrupts */
+	nvt_cir_reg_write(nvt, 0, CIR_IREN);
+
+	nvt_efm_enable(nvt);
+
+	/* disable cir logical dev */
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	/* make sure wake is enabled */
+	nvt_enable_wake(nvt);
+
+	return 0;
+}
+
+static int nvt_resume(struct pnp_dev *pdev)
+{
+	int ret = 0;
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+
+	nvt_dbg("%s called", __func__);
+
+	/* open interrupt */
+	nvt_set_cir_iren(nvt);
+
+	/* Enable CIR logical device */
+	nvt_efm_enable(nvt);
+	nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR);
+	nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN);
+
+	nvt_efm_disable(nvt);
+
+	nvt_cir_regs_init(nvt);
+	nvt_cir_wake_regs_init(nvt);
+
+	return ret;
+}
+
+static void nvt_shutdown(struct pnp_dev *pdev)
+{
+	struct nvt_dev *nvt = pnp_get_drvdata(pdev);
+	nvt_enable_wake(nvt);
+}
+
+static const struct pnp_device_id nvt_ids[] = {
+	{ "WEC0530", 0 },   /* CIR */
+	{ "NTN0530", 0 },   /* CIR for new chip's pnp id*/
+	{ "", 0 },
+};
+
+static struct pnp_driver nvt_driver = {
+	.name		= NVT_DRIVER_NAME,
+	.id_table	= nvt_ids,
+	.flags		= PNP_DRIVER_RES_DO_NOT_CHANGE,
+	.probe		= nvt_probe,
+	.remove		= __devexit_p(nvt_remove),
+	.suspend	= nvt_suspend,
+	.resume		= nvt_resume,
+	.shutdown	= nvt_shutdown,
+};
+
+int nvt_init(void)
+{
+	return pnp_register_driver(&nvt_driver);
+}
+
+void nvt_exit(void)
+{
+	pnp_unregister_driver(&nvt_driver);
+}
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging output");
+
+MODULE_DEVICE_TABLE(pnp, nvt_ids);
+MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver");
+
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_LICENSE("GPL");
+
+module_init(nvt_init);
+module_exit(nvt_exit);

+ 408 - 0
drivers/media/IR/nuvoton-cir.h

@@ -0,0 +1,408 @@
+/*
+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR
+ *
+ * Copyright (C) 2010 Jarod Wilson <jarod@redhat.com>
+ * Copyright (C) 2009 Nuvoton PS Team
+ *
+ * Special thanks to Nuvoton for providing hardware, spec sheets and
+ * sample code upon which portions of this driver are based. Indirect
+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is
+ * modeled after.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <linux/spinlock.h>
+#include <linux/ioctl.h>
+
+/* platform driver name to register */
+#define NVT_DRIVER_NAME "nuvoton-cir"
+
+/* debugging module parameter */
+static int debug;
+
+
+#define nvt_pr(level, text, ...) \
+	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+
+#define nvt_dbg(text, ...) \
+	if (debug) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+#define nvt_dbg_verbose(text, ...) \
+	if (debug > 1) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+#define nvt_dbg_wake(text, ...) \
+	if (debug > 2) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
+
+
+/*
+ * Original lirc driver said min value of 76, and recommended value of 256
+ * for the buffer length, but then used 2048. Never mind that the size of the
+ * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm
+ * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes),
+ * and I don't have TX-capable hardware to test/debug on...
+ */
+#define TX_BUF_LEN 256
+#define RX_BUF_LEN 32
+
+struct nvt_dev {
+	struct pnp_dev *pdev;
+	struct input_dev *rdev;
+	struct ir_dev_props *props;
+	struct ir_raw_event rawir;
+
+	spinlock_t nvt_lock;
+	bool in_use;
+
+	/* for rx */
+	u8 buf[RX_BUF_LEN];
+	unsigned int pkts;
+
+	struct {
+		spinlock_t lock;
+		u8 buf[TX_BUF_LEN];
+		unsigned int buf_count;
+		unsigned int cur_buf_num;
+		wait_queue_head_t queue;
+		u8 tx_state;
+	} tx;
+
+	/* EFER Config register index/data pair */
+	u8 cr_efir;
+	u8 cr_efdr;
+
+	/* hardware I/O settings */
+	unsigned long cir_addr;
+	unsigned long cir_wake_addr;
+	int cir_irq;
+	int cir_wake_irq;
+
+	/* hardware id */
+	u8 chip_major;
+	u8 chip_minor;
+
+	/* hardware features */
+	bool hw_learning_capable;
+	bool hw_tx_capable;
+
+	/* rx settings */
+	bool learning_enabled;
+	bool carrier_detect_enabled;
+
+	/* track cir wake state */
+	u8 wake_state;
+	/* for study */
+	u8 study_state;
+	/* carrier period = 1 / frequency */
+	u32 carrier;
+};
+
+/* study states */
+#define ST_STUDY_NONE      0x0
+#define ST_STUDY_START     0x1
+#define ST_STUDY_CARRIER   0x2
+#define ST_STUDY_ALL_RECV  0x4
+
+/* wake states */
+#define ST_WAKE_NONE	0x0
+#define ST_WAKE_START	0x1
+#define ST_WAKE_FINISH	0x2
+
+/* receive states */
+#define ST_RX_WAIT_7F		0x1
+#define ST_RX_WAIT_HEAD		0x2
+#define ST_RX_WAIT_SILENT_END	0x4
+
+/* send states */
+#define ST_TX_NONE	0x0
+#define ST_TX_REQUEST	0x2
+#define ST_TX_REPLY	0x4
+
+/* buffer packet constants */
+#define BUF_PULSE_BIT	0x80
+#define BUF_LEN_MASK	0x7f
+#define BUF_REPEAT_BYTE	0x70
+#define BUF_REPEAT_MASK	0xf0
+
+/* CIR settings */
+
+/* total length of CIR and CIR WAKE */
+#define CIR_IOREG_LENGTH	0x0f
+
+/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */
+#define CIR_RX_LIMIT_COUNT	0x7d0
+
+/* CIR Regs */
+#define CIR_IRCON	0x00
+#define CIR_IRSTS	0x01
+#define CIR_IREN	0x02
+#define CIR_RXFCONT	0x03
+#define CIR_CP		0x04
+#define CIR_CC		0x05
+#define CIR_SLCH	0x06
+#define CIR_SLCL	0x07
+#define CIR_FIFOCON	0x08
+#define CIR_IRFIFOSTS	0x09
+#define CIR_SRXFIFO	0x0a
+#define CIR_TXFCONT	0x0b
+#define CIR_STXFIFO	0x0c
+#define CIR_FCCH	0x0d
+#define CIR_FCCL	0x0e
+#define CIR_IRFSM	0x0f
+
+/* CIR IRCON settings */
+#define CIR_IRCON_RECV	 0x80
+#define CIR_IRCON_WIREN	 0x40
+#define CIR_IRCON_TXEN	 0x20
+#define CIR_IRCON_RXEN	 0x10
+#define CIR_IRCON_WRXINV 0x08
+#define CIR_IRCON_RXINV	 0x04
+
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_1	0x00
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_25	0x01
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_50	0x02
+#define CIR_IRCON_SAMPLE_PERIOD_SEL_100	0x03
+
+/* FIXME: make this a runtime option */
+/* select sample period as 50us */
+#define CIR_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
+
+/* CIR IRSTS settings */
+#define CIR_IRSTS_RDR	0x80
+#define CIR_IRSTS_RTR	0x40
+#define CIR_IRSTS_PE	0x20
+#define CIR_IRSTS_RFO	0x10
+#define CIR_IRSTS_TE	0x08
+#define CIR_IRSTS_TTR	0x04
+#define CIR_IRSTS_TFU	0x02
+#define CIR_IRSTS_GH	0x01
+
+/* CIR IREN settings */
+#define CIR_IREN_RDR	0x80
+#define CIR_IREN_RTR	0x40
+#define CIR_IREN_PE	0x20
+#define CIR_IREN_RFO	0x10
+#define CIR_IREN_TE	0x08
+#define CIR_IREN_TTR	0x04
+#define CIR_IREN_TFU	0x02
+#define CIR_IREN_GH	0x01
+
+/* CIR FIFOCON settings */
+#define CIR_FIFOCON_TXFIFOCLR		0x80
+
+#define CIR_FIFOCON_TX_TRIGGER_LEV_31	0x00
+#define CIR_FIFOCON_TX_TRIGGER_LEV_24	0x10
+#define CIR_FIFOCON_TX_TRIGGER_LEV_16	0x20
+#define CIR_FIFOCON_TX_TRIGGER_LEV_8	0x30
+
+/* FIXME: make this a runtime option */
+/* select TX trigger level as 16 */
+#define CIR_FIFOCON_TX_TRIGGER_LEV	CIR_FIFOCON_TX_TRIGGER_LEV_16
+
+#define CIR_FIFOCON_RXFIFOCLR		0x08
+
+#define CIR_FIFOCON_RX_TRIGGER_LEV_1	0x00
+#define CIR_FIFOCON_RX_TRIGGER_LEV_8	0x01
+#define CIR_FIFOCON_RX_TRIGGER_LEV_16	0x02
+#define CIR_FIFOCON_RX_TRIGGER_LEV_24	0x03
+
+/* FIXME: make this a runtime option */
+/* select RX trigger level as 24 */
+#define CIR_FIFOCON_RX_TRIGGER_LEV	CIR_FIFOCON_RX_TRIGGER_LEV_24
+
+/* CIR IRFIFOSTS settings */
+#define CIR_IRFIFOSTS_IR_PENDING	0x80
+#define CIR_IRFIFOSTS_RX_GS		0x40
+#define CIR_IRFIFOSTS_RX_FTA		0x20
+#define CIR_IRFIFOSTS_RX_EMPTY		0x10
+#define CIR_IRFIFOSTS_RX_FULL		0x08
+#define CIR_IRFIFOSTS_TX_FTA		0x04
+#define CIR_IRFIFOSTS_TX_EMPTY		0x02
+#define CIR_IRFIFOSTS_TX_FULL		0x01
+
+
+/* CIR WAKE UP Regs */
+#define CIR_WAKE_IRCON			0x00
+#define CIR_WAKE_IRSTS			0x01
+#define CIR_WAKE_IREN			0x02
+#define CIR_WAKE_FIFO_CMP_DEEP		0x03
+#define CIR_WAKE_FIFO_CMP_TOL		0x04
+#define CIR_WAKE_FIFO_COUNT		0x05
+#define CIR_WAKE_SLCH			0x06
+#define CIR_WAKE_SLCL			0x07
+#define CIR_WAKE_FIFOCON		0x08
+#define CIR_WAKE_SRXFSTS		0x09
+#define CIR_WAKE_SAMPLE_RX_FIFO		0x0a
+#define CIR_WAKE_WR_FIFO_DATA		0x0b
+#define CIR_WAKE_RD_FIFO_ONLY		0x0c
+#define CIR_WAKE_RD_FIFO_ONLY_IDX	0x0d
+#define CIR_WAKE_FIFO_IGNORE		0x0e
+#define CIR_WAKE_IRFSM			0x0f
+
+/* CIR WAKE UP IRCON settings */
+#define CIR_WAKE_IRCON_DEC_RST		0x80
+#define CIR_WAKE_IRCON_MODE1		0x40
+#define CIR_WAKE_IRCON_MODE0		0x20
+#define CIR_WAKE_IRCON_RXEN		0x10
+#define CIR_WAKE_IRCON_R		0x08
+#define CIR_WAKE_IRCON_RXINV		0x04
+
+/* FIXME/jarod: make this a runtime option */
+/* select a same sample period like cir register */
+#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL	CIR_IRCON_SAMPLE_PERIOD_SEL_50
+
+/* CIR WAKE IRSTS Bits */
+#define CIR_WAKE_IRSTS_RDR		0x80
+#define CIR_WAKE_IRSTS_RTR		0x40
+#define CIR_WAKE_IRSTS_PE		0x20
+#define CIR_WAKE_IRSTS_RFO		0x10
+#define CIR_WAKE_IRSTS_GH		0x08
+#define CIR_WAKE_IRSTS_IR_PENDING	0x01
+
+/* CIR WAKE UP IREN Bits */
+#define CIR_WAKE_IREN_RDR		0x80
+#define CIR_WAKE_IREN_RTR		0x40
+#define CIR_WAKE_IREN_PE		0x20
+#define CIR_WAKE_IREN_RFO		0x10
+#define CIR_WAKE_IREN_TE		0x08
+#define CIR_WAKE_IREN_TTR		0x04
+#define CIR_WAKE_IREN_TFU		0x02
+#define CIR_WAKE_IREN_GH		0x01
+
+/* CIR WAKE FIFOCON settings */
+#define CIR_WAKE_FIFOCON_RXFIFOCLR	0x08
+
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67	0x00
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66	0x01
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65	0x02
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64	0x03
+
+/* FIXME: make this a runtime option */
+/* select WAKE UP RX trigger level as 67 */
+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV	CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67
+
+/* CIR WAKE SRXFSTS settings */
+#define CIR_WAKE_IRFIFOSTS_RX_GS	0x80
+#define CIR_WAKE_IRFIFOSTS_RX_FTA	0x40
+#define CIR_WAKE_IRFIFOSTS_RX_EMPTY	0x20
+#define CIR_WAKE_IRFIFOSTS_RX_FULL	0x10
+
+/* CIR Wake FIFO buffer is 67 bytes long */
+#define CIR_WAKE_FIFO_LEN		67
+/* CIR Wake byte comparison tolerance */
+#define CIR_WAKE_CMP_TOLERANCE		5
+
+/*
+ * Extended Function Enable Registers:
+ *  Extended Function Index Register
+ *  Extended Function Data Register
+ */
+#define CR_EFIR			0x2e
+#define CR_EFDR			0x2f
+
+/* Possible alternate EFER values, depends on how the chip is wired */
+#define CR_EFIR2		0x4e
+#define CR_EFDR2		0x4f
+
+/* Extended Function Mode enable/disable magic values */
+#define EFER_EFM_ENABLE		0x87
+#define EFER_EFM_DISABLE	0xaa
+
+/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
+#define CHIP_ID_HIGH		0xb4
+#define CHIP_ID_LOW		0x72
+#define CHIP_ID_LOW2		0x73
+
+/* Config regs we need to care about */
+#define CR_SOFTWARE_RESET	0x02
+#define CR_LOGICAL_DEV_SEL	0x07
+#define CR_CHIP_ID_HI		0x20
+#define CR_CHIP_ID_LO		0x21
+#define CR_DEV_POWER_DOWN	0x22 /* bit 2 is CIR power, default power on */
+#define CR_OUTPUT_PIN_SEL	0x27
+#define CR_LOGICAL_DEV_EN	0x30 /* valid for all logical devices */
+/* next three regs valid for both the CIR and CIR_WAKE logical devices */
+#define CR_CIR_BASE_ADDR_HI	0x60
+#define CR_CIR_BASE_ADDR_LO	0x61
+#define CR_CIR_IRQ_RSRC		0x70
+/* next three regs valid only for ACPI logical dev */
+#define CR_ACPI_CIR_WAKE	0xe0
+#define CR_ACPI_IRQ_EVENTS	0xf6
+#define CR_ACPI_IRQ_EVENTS2	0xf7
+
+/* Logical devices that we need to care about */
+#define LOGICAL_DEV_LPT		0x01
+#define LOGICAL_DEV_CIR		0x06
+#define LOGICAL_DEV_ACPI	0x0a
+#define LOGICAL_DEV_CIR_WAKE	0x0e
+
+#define LOGICAL_DEV_DISABLE	0x00
+#define LOGICAL_DEV_ENABLE	0x01
+
+#define CIR_WAKE_ENABLE_BIT	0x08
+#define CIR_INTR_MOUSE_IRQ_BIT	0x80
+#define PME_INTR_CIR_PASS_BIT	0x08
+
+#define OUTPUT_PIN_SEL_MASK	0xbc
+#define OUTPUT_ENABLE_CIR	0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */
+#define OUTPUT_ENABLE_CIRWB	0x40 /* enable wide-band sensor */
+
+/* MCE CIR signal length, related on sample period */
+
+/* MCE CIR controller signal length: about 43ms
+ * 43ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define CONTROLLER_BUF_LEN_MIN 830
+
+/* MCE CIR keyboard signal length: about 26ms
+ * 26ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define KEYBOARD_BUF_LEN_MAX 650
+#define KEYBOARD_BUF_LEN_MIN 610
+
+/* MCE CIR mouse signal length: about 24ms
+ * 24ms / 50us (sample period) * 0.85 (inaccuracy)
+ */
+#define MOUSE_BUF_LEN_MIN 565
+
+#define CIR_SAMPLE_PERIOD 50
+#define CIR_SAMPLE_LOW_INACCURACY 0.85
+
+/* MAX silence time that driver will sent to lirc */
+#define MAX_SILENCE_TIME 60000
+
+#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100
+#define SAMPLE_PERIOD 100
+
+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50
+#define SAMPLE_PERIOD 50
+
+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25
+#define SAMPLE_PERIOD 25
+
+#else
+#define SAMPLE_PERIOD 1
+#endif
+
+/* as VISTA MCE definition, valid carrier value */
+#define MAX_CARRIER 60000
+#define MIN_CARRIER 30000

+ 102 - 274
drivers/media/IR/streamzap.c

@@ -38,7 +38,7 @@
 #include <linux/input.h>
 #include <linux/input.h>
 #include <media/ir-core.h>
 #include <media/ir-core.h>
 
 
-#define DRIVER_VERSION	"1.60"
+#define DRIVER_VERSION	"1.61"
 #define DRIVER_NAME	"streamzap"
 #define DRIVER_NAME	"streamzap"
 #define DRIVER_DESC	"Streamzap Remote Control driver"
 #define DRIVER_DESC	"Streamzap Remote Control driver"
 
 
@@ -61,14 +61,21 @@ static struct usb_device_id streamzap_table[] = {
 
 
 MODULE_DEVICE_TABLE(usb, streamzap_table);
 MODULE_DEVICE_TABLE(usb, streamzap_table);
 
 
-#define STREAMZAP_PULSE_MASK 0xf0
-#define STREAMZAP_SPACE_MASK 0x0f
-#define STREAMZAP_TIMEOUT    0xff
-#define STREAMZAP_RESOLUTION 256
+#define SZ_PULSE_MASK 0xf0
+#define SZ_SPACE_MASK 0x0f
+#define SZ_TIMEOUT    0xff
+#define SZ_RESOLUTION 256
 
 
 /* number of samples buffered */
 /* number of samples buffered */
 #define SZ_BUF_LEN 128
 #define SZ_BUF_LEN 128
 
 
+/* from ir-rc5-sz-decoder.c */
+#ifdef CONFIG_IR_RC5_SZ_DECODER_MODULE
+#define load_rc5_sz_decode()    request_module("ir-rc5-sz-decoder")
+#else
+#define load_rc5_sz_decode()    0
+#endif
+
 enum StreamzapDecoderState {
 enum StreamzapDecoderState {
 	PulseSpace,
 	PulseSpace,
 	FullPulse,
 	FullPulse,
@@ -81,7 +88,6 @@ struct streamzap_ir {
 
 
 	/* ir-core */
 	/* ir-core */
 	struct ir_dev_props *props;
 	struct ir_dev_props *props;
-	struct ir_raw_event rawir;
 
 
 	/* core device info */
 	/* core device info */
 	struct device *dev;
 	struct device *dev;
@@ -98,17 +104,6 @@ struct streamzap_ir {
 	dma_addr_t		dma_in;
 	dma_addr_t		dma_in;
 	unsigned int		buf_in_len;
 	unsigned int		buf_in_len;
 
 
-	/* timer used to support delay buffering */
-	struct timer_list	delay_timer;
-	bool			timer_running;
-	spinlock_t		timer_lock;
-	struct timer_list	flush_timer;
-	bool			flush;
-
-	/* delay buffer */
-	struct kfifo fifo;
-	bool fifo_initialized;
-
 	/* track what state we're in */
 	/* track what state we're in */
 	enum StreamzapDecoderState decoder_state;
 	enum StreamzapDecoderState decoder_state;
 	/* tracks whether we are currently receiving some signal */
 	/* tracks whether we are currently receiving some signal */
@@ -118,7 +113,7 @@ struct streamzap_ir {
 	/* start time of signal; necessary for gap tracking */
 	/* start time of signal; necessary for gap tracking */
 	struct timeval		signal_last;
 	struct timeval		signal_last;
 	struct timeval		signal_start;
 	struct timeval		signal_start;
-	/* bool			timeout_enabled; */
+	bool			timeout_enabled;
 
 
 	char			name[128];
 	char			name[128];
 	char			phys[64];
 	char			phys[64];
@@ -143,122 +138,16 @@ static struct usb_driver streamzap_driver = {
 	.id_table =	streamzap_table,
 	.id_table =	streamzap_table,
 };
 };
 
 
-static void streamzap_stop_timer(struct streamzap_ir *sz)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&sz->timer_lock, flags);
-	if (sz->timer_running) {
-		sz->timer_running = false;
-		spin_unlock_irqrestore(&sz->timer_lock, flags);
-		del_timer_sync(&sz->delay_timer);
-	} else {
-		spin_unlock_irqrestore(&sz->timer_lock, flags);
-	}
-}
-
-static void streamzap_flush_timeout(unsigned long arg)
-{
-	struct streamzap_ir *sz = (struct streamzap_ir *)arg;
-
-	dev_info(sz->dev, "%s: callback firing\n", __func__);
-
-	/* finally start accepting data */
-	sz->flush = false;
-}
-
-static void streamzap_delay_timeout(unsigned long arg)
-{
-	struct streamzap_ir *sz = (struct streamzap_ir *)arg;
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
-	unsigned long flags;
-	int len, ret;
-	static unsigned long delay;
-	bool wake = false;
-
-	/* deliver data every 10 ms */
-	delay = msecs_to_jiffies(10);
-
-	spin_lock_irqsave(&sz->timer_lock, flags);
-
-	if (kfifo_len(&sz->fifo) > 0) {
-		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
-		if (ret != sizeof(rawir))
-			dev_err(sz->dev, "Problem w/kfifo_out...\n");
-		ir_raw_event_store(sz->idev, &rawir);
-		wake = true;
-	}
-
-	len = kfifo_len(&sz->fifo);
-	if (len > 0) {
-		while ((len < SZ_BUF_LEN / 2) &&
-		       (len < SZ_BUF_LEN * sizeof(int))) {
-			ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
-			if (ret != sizeof(rawir))
-				dev_err(sz->dev, "Problem w/kfifo_out...\n");
-			ir_raw_event_store(sz->idev, &rawir);
-			wake = true;
-			len = kfifo_len(&sz->fifo);
-		}
-		if (sz->timer_running)
-			mod_timer(&sz->delay_timer, jiffies + delay);
-
-	} else {
-		sz->timer_running = false;
-	}
-
-	if (wake)
-		ir_raw_event_handle(sz->idev);
-
-	spin_unlock_irqrestore(&sz->timer_lock, flags);
-}
-
-static void streamzap_flush_delay_buffer(struct streamzap_ir *sz)
+static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 {
 {
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
-	bool wake = false;
-	int ret;
-
-	while (kfifo_len(&sz->fifo) > 0) {
-		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
-		if (ret != sizeof(rawir))
-			dev_err(sz->dev, "Problem w/kfifo_out...\n");
-		ir_raw_event_store(sz->idev, &rawir);
-		wake = true;
-	}
-
-	if (wake)
-		ir_raw_event_handle(sz->idev);
-}
-
-static void sz_push(struct streamzap_ir *sz)
-{
-	struct ir_raw_event rawir = { .pulse = false, .duration = 0 };
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&sz->timer_lock, flags);
-	if (kfifo_len(&sz->fifo) >= sizeof(int) * SZ_BUF_LEN) {
-		ret = kfifo_out(&sz->fifo, &rawir, sizeof(rawir));
-		if (ret != sizeof(rawir))
-			dev_err(sz->dev, "Problem w/kfifo_out...\n");
-		ir_raw_event_store(sz->idev, &rawir);
-	}
-
-	kfifo_in(&sz->fifo, &sz->rawir, sizeof(rawir));
-
-	if (!sz->timer_running) {
-		sz->delay_timer.expires = jiffies + (HZ / 10);
-		add_timer(&sz->delay_timer);
-		sz->timer_running = true;
-	}
-
-	spin_unlock_irqrestore(&sz->timer_lock, flags);
+	ir_raw_event_store(sz->idev, &rawir);
 }
 }
 
 
 static void sz_push_full_pulse(struct streamzap_ir *sz,
 static void sz_push_full_pulse(struct streamzap_ir *sz,
 			       unsigned char value)
 			       unsigned char value)
 {
 {
+	DEFINE_IR_RAW_EVENT(rawir);
+
 	if (sz->idle) {
 	if (sz->idle) {
 		long deltv;
 		long deltv;
 
 
@@ -266,57 +155,59 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
 		do_gettimeofday(&sz->signal_start);
 		do_gettimeofday(&sz->signal_start);
 
 
 		deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
 		deltv = sz->signal_start.tv_sec - sz->signal_last.tv_sec;
-		sz->rawir.pulse = false;
+		rawir.pulse = false;
 		if (deltv > 15) {
 		if (deltv > 15) {
 			/* really long time */
 			/* really long time */
-			sz->rawir.duration = IR_MAX_DURATION;
+			rawir.duration = IR_MAX_DURATION;
 		} else {
 		} else {
-			sz->rawir.duration = (int)(deltv * 1000000 +
+			rawir.duration = (int)(deltv * 1000000 +
 				sz->signal_start.tv_usec -
 				sz->signal_start.tv_usec -
 				sz->signal_last.tv_usec);
 				sz->signal_last.tv_usec);
-			sz->rawir.duration -= sz->sum;
-			sz->rawir.duration *= 1000;
-			sz->rawir.duration &= IR_MAX_DURATION;
+			rawir.duration -= sz->sum;
+			rawir.duration *= 1000;
+			rawir.duration &= IR_MAX_DURATION;
 		}
 		}
-		dev_dbg(sz->dev, "ls %u\n", sz->rawir.duration);
-		sz_push(sz);
+		dev_dbg(sz->dev, "ls %u\n", rawir.duration);
+		sz_push(sz, rawir);
 
 
-		sz->idle = 0;
+		sz->idle = false;
 		sz->sum = 0;
 		sz->sum = 0;
 	}
 	}
 
 
-	sz->rawir.pulse = true;
-	sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
-	sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
-	sz->sum += sz->rawir.duration;
-	sz->rawir.duration *= 1000;
-	sz->rawir.duration &= IR_MAX_DURATION;
-	dev_dbg(sz->dev, "p %u\n", sz->rawir.duration);
-	sz_push(sz);
+	rawir.pulse = true;
+	rawir.duration = ((int) value) * SZ_RESOLUTION;
+	rawir.duration += SZ_RESOLUTION / 2;
+	sz->sum += rawir.duration;
+	rawir.duration *= 1000;
+	rawir.duration &= IR_MAX_DURATION;
+	dev_dbg(sz->dev, "p %u\n", rawir.duration);
+	sz_push(sz, rawir);
 }
 }
 
 
 static void sz_push_half_pulse(struct streamzap_ir *sz,
 static void sz_push_half_pulse(struct streamzap_ir *sz,
 			       unsigned char value)
 			       unsigned char value)
 {
 {
-	sz_push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK) >> 4);
+	sz_push_full_pulse(sz, (value & SZ_PULSE_MASK) >> 4);
 }
 }
 
 
 static void sz_push_full_space(struct streamzap_ir *sz,
 static void sz_push_full_space(struct streamzap_ir *sz,
 			       unsigned char value)
 			       unsigned char value)
 {
 {
-	sz->rawir.pulse = false;
-	sz->rawir.duration = ((int) value) * STREAMZAP_RESOLUTION;
-	sz->rawir.duration += STREAMZAP_RESOLUTION / 2;
-	sz->sum += sz->rawir.duration;
-	sz->rawir.duration *= 1000;
-	dev_dbg(sz->dev, "s %u\n", sz->rawir.duration);
-	sz_push(sz);
+	DEFINE_IR_RAW_EVENT(rawir);
+
+	rawir.pulse = false;
+	rawir.duration = ((int) value) * SZ_RESOLUTION;
+	rawir.duration += SZ_RESOLUTION / 2;
+	sz->sum += rawir.duration;
+	rawir.duration *= 1000;
+	dev_dbg(sz->dev, "s %u\n", rawir.duration);
+	sz_push(sz, rawir);
 }
 }
 
 
 static void sz_push_half_space(struct streamzap_ir *sz,
 static void sz_push_half_space(struct streamzap_ir *sz,
 			       unsigned long value)
 			       unsigned long value)
 {
 {
-	sz_push_full_space(sz, value & STREAMZAP_SPACE_MASK);
+	sz_push_full_space(sz, value & SZ_SPACE_MASK);
 }
 }
 
 
 /**
 /**
@@ -330,10 +221,8 @@ static void streamzap_callback(struct urb *urb)
 	struct streamzap_ir *sz;
 	struct streamzap_ir *sz;
 	unsigned int i;
 	unsigned int i;
 	int len;
 	int len;
-	#if 0
-	static int timeout = (((STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) &
+	static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
 				IR_MAX_DURATION) | 0x03000000);
 				IR_MAX_DURATION) | 0x03000000);
-	#endif
 
 
 	if (!urb)
 	if (!urb)
 		return;
 		return;
@@ -356,57 +245,53 @@ static void streamzap_callback(struct urb *urb)
 	}
 	}
 
 
 	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
 	dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
-	if (!sz->flush) {
-		for (i = 0; i < urb->actual_length; i++) {
-			dev_dbg(sz->dev, "%d: %x\n", i,
-				(unsigned char)sz->buf_in[i]);
-			switch (sz->decoder_state) {
-			case PulseSpace:
-				if ((sz->buf_in[i] & STREAMZAP_PULSE_MASK) ==
-				    STREAMZAP_PULSE_MASK) {
-					sz->decoder_state = FullPulse;
-					continue;
-				} else if ((sz->buf_in[i] & STREAMZAP_SPACE_MASK)
-					   == STREAMZAP_SPACE_MASK) {
-					sz_push_half_pulse(sz, sz->buf_in[i]);
-					sz->decoder_state = FullSpace;
-					continue;
-				} else {
-					sz_push_half_pulse(sz, sz->buf_in[i]);
-					sz_push_half_space(sz, sz->buf_in[i]);
-				}
-				break;
-			case FullPulse:
-				sz_push_full_pulse(sz, sz->buf_in[i]);
-				sz->decoder_state = IgnorePulse;
-				break;
-			case FullSpace:
-				if (sz->buf_in[i] == STREAMZAP_TIMEOUT) {
-					sz->idle = 1;
-					streamzap_stop_timer(sz);
-					#if 0
-					if (sz->timeout_enabled) {
-						sz->rawir.pulse = false;
-						sz->rawir.duration = timeout;
-						sz->rawir.duration *= 1000;
-						sz_push(sz);
-					}
-					#endif
-					streamzap_flush_delay_buffer(sz);
-				} else
-					sz_push_full_space(sz, sz->buf_in[i]);
-				sz->decoder_state = PulseSpace;
-				break;
-			case IgnorePulse:
-				if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) ==
-				    STREAMZAP_SPACE_MASK) {
-					sz->decoder_state = FullSpace;
-					continue;
-				}
+	for (i = 0; i < len; i++) {
+		dev_dbg(sz->dev, "sz idx %d: %x\n",
+			i, (unsigned char)sz->buf_in[i]);
+		switch (sz->decoder_state) {
+		case PulseSpace:
+			if ((sz->buf_in[i] & SZ_PULSE_MASK) ==
+				SZ_PULSE_MASK) {
+				sz->decoder_state = FullPulse;
+				continue;
+			} else if ((sz->buf_in[i] & SZ_SPACE_MASK)
+					== SZ_SPACE_MASK) {
+				sz_push_half_pulse(sz, sz->buf_in[i]);
+				sz->decoder_state = FullSpace;
+				continue;
+			} else {
+				sz_push_half_pulse(sz, sz->buf_in[i]);
 				sz_push_half_space(sz, sz->buf_in[i]);
 				sz_push_half_space(sz, sz->buf_in[i]);
-				sz->decoder_state = PulseSpace;
-				break;
 			}
 			}
+			break;
+		case FullPulse:
+			sz_push_full_pulse(sz, sz->buf_in[i]);
+			sz->decoder_state = IgnorePulse;
+			break;
+		case FullSpace:
+			if (sz->buf_in[i] == SZ_TIMEOUT) {
+				DEFINE_IR_RAW_EVENT(rawir);
+
+				rawir.pulse = false;
+				rawir.duration = timeout;
+				sz->idle = true;
+				if (sz->timeout_enabled)
+					sz_push(sz, rawir);
+				ir_raw_event_handle(sz->idev);
+			} else {
+				sz_push_full_space(sz, sz->buf_in[i]);
+			}
+			sz->decoder_state = PulseSpace;
+			break;
+		case IgnorePulse:
+			if ((sz->buf_in[i] & SZ_SPACE_MASK) ==
+				SZ_SPACE_MASK) {
+				sz->decoder_state = FullSpace;
+				continue;
+			}
+			sz_push_half_space(sz, sz->buf_in[i]);
+			sz->decoder_state = PulseSpace;
+			break;
 		}
 		}
 	}
 	}
 
 
@@ -446,12 +331,11 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
 
 
 	props->priv = sz;
 	props->priv = sz;
 	props->driver_type = RC_DRIVER_IR_RAW;
 	props->driver_type = RC_DRIVER_IR_RAW;
-	/* FIXME: not sure about supported protocols, check on this */
-	props->allowed_protos = IR_TYPE_RC5 | IR_TYPE_RC6;
+	props->allowed_protos = IR_TYPE_ALL;
 
 
 	sz->props = props;
 	sz->props = props;
 
 
-	ret = ir_input_register(idev, RC_MAP_RC5_STREAMZAP, props, DRIVER_NAME);
+	ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
 	if (ret < 0) {
 	if (ret < 0) {
 		dev_err(dev, "remote input device register failed\n");
 		dev_err(dev, "remote input device register failed\n");
 		goto irdev_failed;
 		goto irdev_failed;
@@ -467,29 +351,6 @@ idev_alloc_failed:
 	return NULL;
 	return NULL;
 }
 }
 
 
-static int streamzap_delay_buf_init(struct streamzap_ir *sz)
-{
-	int ret;
-
-	ret = kfifo_alloc(&sz->fifo, sizeof(int) * SZ_BUF_LEN,
-			  GFP_KERNEL);
-	if (ret == 0)
-		sz->fifo_initialized = 1;
-
-	return ret;
-}
-
-static void streamzap_start_flush_timer(struct streamzap_ir *sz)
-{
-	sz->flush_timer.expires = jiffies + HZ;
-	sz->flush = true;
-	add_timer(&sz->flush_timer);
-
-	sz->urb_in->dev = sz->usbdev;
-	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
-		dev_err(sz->dev, "urb submit failed\n");
-}
-
 /**
 /**
  *	streamzap_probe
  *	streamzap_probe
  *
  *
@@ -575,35 +436,21 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
 		snprintf(name + strlen(name), sizeof(name) - strlen(name),
 		snprintf(name + strlen(name), sizeof(name) - strlen(name),
 			 " %s", buf);
 			 " %s", buf);
 
 
-	retval = streamzap_delay_buf_init(sz);
-	if (retval) {
-		dev_err(&intf->dev, "%s: delay buffer init failed\n", __func__);
-		goto free_urb_in;
-	}
-
 	sz->idev = streamzap_init_input_dev(sz);
 	sz->idev = streamzap_init_input_dev(sz);
 	if (!sz->idev)
 	if (!sz->idev)
 		goto input_dev_fail;
 		goto input_dev_fail;
 
 
 	sz->idle = true;
 	sz->idle = true;
 	sz->decoder_state = PulseSpace;
 	sz->decoder_state = PulseSpace;
+	/* FIXME: don't yet have a way to set this */
+	sz->timeout_enabled = true;
 	#if 0
 	#if 0
 	/* not yet supported, depends on patches from maxim */
 	/* not yet supported, depends on patches from maxim */
 	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
 	/* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
-	sz->timeout_enabled = false;
-	sz->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
-	sz->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION * 1000;
+	sz->min_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
+	sz->max_timeout = SZ_TIMEOUT * SZ_RESOLUTION * 1000;
 	#endif
 	#endif
 
 
-	init_timer(&sz->delay_timer);
-	sz->delay_timer.function = streamzap_delay_timeout;
-	sz->delay_timer.data = (unsigned long)sz;
-	spin_lock_init(&sz->timer_lock);
-
-	init_timer(&sz->flush_timer);
-	sz->flush_timer.function = streamzap_flush_timeout;
-	sz->flush_timer.data = (unsigned long)sz;
-
 	do_gettimeofday(&sz->signal_start);
 	do_gettimeofday(&sz->signal_start);
 
 
 	/* Complete final initialisations */
 	/* Complete final initialisations */
@@ -615,16 +462,18 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
 
 
 	usb_set_intfdata(intf, sz);
 	usb_set_intfdata(intf, sz);
 
 
-	streamzap_start_flush_timer(sz);
+	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC))
+		dev_err(sz->dev, "urb submit failed\n");
 
 
 	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
 	dev_info(sz->dev, "Registered %s on usb%d:%d\n", name,
 		 usbdev->bus->busnum, usbdev->devnum);
 		 usbdev->bus->busnum, usbdev->devnum);
 
 
+	/* Load the streamzap not-quite-rc5 decoder too */
+	load_rc5_sz_decode();
+
 	return 0;
 	return 0;
 
 
 input_dev_fail:
 input_dev_fail:
-	kfifo_free(&sz->fifo);
-free_urb_in:
 	usb_free_urb(sz->urb_in);
 	usb_free_urb(sz->urb_in);
 free_buf_in:
 free_buf_in:
 	usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
 	usb_free_coherent(usbdev, maxp, sz->buf_in, sz->dma_in);
@@ -654,13 +503,6 @@ static void streamzap_disconnect(struct usb_interface *interface)
 	if (!sz)
 	if (!sz)
 		return;
 		return;
 
 
-	if (sz->flush) {
-		sz->flush = false;
-		del_timer_sync(&sz->flush_timer);
-	}
-
-	streamzap_stop_timer(sz);
-
 	sz->usbdev = NULL;
 	sz->usbdev = NULL;
 	ir_input_unregister(sz->idev);
 	ir_input_unregister(sz->idev);
 	usb_kill_urb(sz->urb_in);
 	usb_kill_urb(sz->urb_in);
@@ -674,13 +516,6 @@ static int streamzap_suspend(struct usb_interface *intf, pm_message_t message)
 {
 {
 	struct streamzap_ir *sz = usb_get_intfdata(intf);
 	struct streamzap_ir *sz = usb_get_intfdata(intf);
 
 
-	if (sz->flush) {
-		sz->flush = false;
-		del_timer_sync(&sz->flush_timer);
-	}
-
-	streamzap_stop_timer(sz);
-
 	usb_kill_urb(sz->urb_in);
 	usb_kill_urb(sz->urb_in);
 
 
 	return 0;
 	return 0;
@@ -690,13 +525,6 @@ static int streamzap_resume(struct usb_interface *intf)
 {
 {
 	struct streamzap_ir *sz = usb_get_intfdata(intf);
 	struct streamzap_ir *sz = usb_get_intfdata(intf);
 
 
-	if (sz->fifo_initialized)
-		kfifo_reset(&sz->fifo);
-
-	sz->flush_timer.expires = jiffies + HZ;
-	sz->flush = true;
-	add_timer(&sz->flush_timer);
-
 	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
 	if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
 		dev_err(sz->dev, "Error sumbiting urb\n");
 		dev_err(sz->dev, "Error sumbiting urb\n");
 		return -EIO;
 		return -EIO;

+ 1 - 1
drivers/media/common/saa7146_fops.c

@@ -56,7 +56,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
 
 
 	BUG_ON(in_interrupt());
 	BUG_ON(in_interrupt());
 
 
-	videobuf_waiton(&buf->vb,0,0);
+	videobuf_waiton(q, &buf->vb, 0, 0);
 	videobuf_dma_unmap(q->dev, dma);
 	videobuf_dma_unmap(q->dev, dma);
 	videobuf_dma_free(dma);
 	videobuf_dma_free(dma);
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;
 	buf->vb.state = VIDEOBUF_NEEDS_INIT;

+ 0 - 1
drivers/media/common/saa7146_i2c.c

@@ -414,7 +414,6 @@ int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c
 		i2c_adapter->dev.parent    = &dev->pci->dev;
 		i2c_adapter->dev.parent    = &dev->pci->dev;
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo	   = &saa7146_algo;
 		i2c_adapter->algo_data     = NULL;
 		i2c_adapter->algo_data     = NULL;
-		i2c_adapter->id		   = I2C_HW_SAA7146;
 		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
 		i2c_adapter->timeout = SAA7146_I2C_TIMEOUT;
 		i2c_adapter->retries = SAA7146_I2C_RETRIES;
 		i2c_adapter->retries = SAA7146_I2C_RETRIES;
 	}
 	}

+ 1 - 1
drivers/media/common/saa7146_vbi.c

@@ -412,7 +412,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
 			    V4L2_BUF_TYPE_VBI_CAPTURE,
 			    V4L2_BUF_TYPE_VBI_CAPTURE,
 			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
 			    V4L2_FIELD_SEQ_TB, // FIXME: does this really work?
 			    sizeof(struct saa7146_buf),
 			    sizeof(struct saa7146_buf),
-			    file);
+			    file, NULL);
 
 
 	init_timer(&fh->vbi_read_timeout);
 	init_timer(&fh->vbi_read_timeout);
 	fh->vbi_read_timeout.function = vbi_read_timeout;
 	fh->vbi_read_timeout.function = vbi_read_timeout;

+ 1 - 1
drivers/media/common/saa7146_video.c

@@ -1386,7 +1386,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
 			    V4L2_FIELD_INTERLACED,
 			    V4L2_FIELD_INTERLACED,
 			    sizeof(struct saa7146_buf),
 			    sizeof(struct saa7146_buf),
-			    file);
+			    file, NULL);
 
 
 	return 0;
 	return 0;
 }
 }

+ 7 - 0
drivers/media/common/tuners/Kconfig

@@ -179,4 +179,11 @@ config MEDIA_TUNER_MAX2165
 	help
 	help
 	  A driver for the silicon tuner MAX2165 from Maxim.
 	  A driver for the silicon tuner MAX2165 from Maxim.
 
 
+config MEDIA_TUNER_TDA18218
+	tristate "NXP TDA18218 silicon tuner"
+	depends on VIDEO_MEDIA && I2C
+	default m if MEDIA_TUNER_CUSTOMISE
+	help
+	  NXP TDA18218 silicon tuner driver.
+
 endif # MEDIA_TUNER_CUSTOMISE
 endif # MEDIA_TUNER_CUSTOMISE

+ 1 - 0
drivers/media/common/tuners/Makefile

@@ -24,6 +24,7 @@ obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 obj-$(CONFIG_MEDIA_TUNER_MXL5007T) += mxl5007t.o
 obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
+obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
 
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends

+ 334 - 0
drivers/media/common/tuners/tda18218.c

@@ -0,0 +1,334 @@
+/*
+ * NXP TDA18218HN silicon tuner driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "tda18218.h"
+#include "tda18218_priv.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+
+/* write multiple registers */
+static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
+{
+	int ret;
+	u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
+	struct i2c_msg msg[1] = {
+		{
+			.addr = priv->cfg->i2c_address,
+			.flags = 0,
+			.buf = buf,
+		}
+	};
+
+	msg_len_max = priv->cfg->i2c_wr_max - 1;
+	quotient = len / msg_len_max;
+	remainder = len % msg_len_max;
+	msg_len = msg_len_max;
+	for (i = 0; (i <= quotient && remainder); i++) {
+		if (i == quotient)  /* set len of the last msg */
+			msg_len = remainder;
+
+		msg[0].len = msg_len + 1;
+		buf[0] = reg + i * msg_len_max;
+		memcpy(&buf[1], &val[i * msg_len_max], msg_len);
+
+		ret = i2c_transfer(priv->i2c, msg, 1);
+		if (ret != 1)
+			break;
+	}
+
+	if (ret == 1) {
+		ret = 0;
+	} else {
+		warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* read multiple registers */
+static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
+{
+	int ret;
+	u8 buf[reg+len]; /* we must start read always from reg 0x00 */
+	struct i2c_msg msg[2] = {
+		{
+			.addr = priv->cfg->i2c_address,
+			.flags = 0,
+			.len = 1,
+			.buf = "\x00",
+		}, {
+			.addr = priv->cfg->i2c_address,
+			.flags = I2C_M_RD,
+			.len = sizeof(buf),
+			.buf = buf,
+		}
+	};
+
+	ret = i2c_transfer(priv->i2c, msg, 2);
+	if (ret == 2) {
+		memcpy(val, &buf[reg], len);
+		ret = 0;
+	} else {
+		warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+		ret = -EREMOTEIO;
+	}
+
+	return ret;
+}
+
+/* write single register */
+static int tda18218_wr_reg(struct tda18218_priv *priv, u8 reg, u8 val)
+{
+	return tda18218_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+
+static int tda18218_rd_reg(struct tda18218_priv *priv, u8 reg, u8 *val)
+{
+	return tda18218_rd_regs(priv, reg, val, 1);
+}
+
+static int tda18218_set_params(struct dvb_frontend *fe,
+	struct dvb_frontend_parameters *params)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	int ret;
+	u8 buf[3], i, BP_Filter, LP_Fc;
+	u32 LO_Frac;
+	/* TODO: find out correct AGC algorithm */
+	u8 agc[][2] = {
+		{ R20_AGC11, 0x60 },
+		{ R23_AGC21, 0x02 },
+		{ R20_AGC11, 0xa0 },
+		{ R23_AGC21, 0x09 },
+		{ R20_AGC11, 0xe0 },
+		{ R23_AGC21, 0x0c },
+		{ R20_AGC11, 0x40 },
+		{ R23_AGC21, 0x01 },
+		{ R20_AGC11, 0x80 },
+		{ R23_AGC21, 0x08 },
+		{ R20_AGC11, 0xc0 },
+		{ R23_AGC21, 0x0b },
+		{ R24_AGC22, 0x1c },
+		{ R24_AGC22, 0x0c },
+	};
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	/* low-pass filter cut-off frequency */
+	switch (params->u.ofdm.bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		LP_Fc = 0;
+		LO_Frac = params->frequency + 4000000;
+		break;
+	case BANDWIDTH_7_MHZ:
+		LP_Fc = 1;
+		LO_Frac = params->frequency + 3500000;
+		break;
+	case BANDWIDTH_8_MHZ:
+	default:
+		LP_Fc = 2;
+		LO_Frac = params->frequency + 4000000;
+		break;
+	}
+
+	/* band-pass filter */
+	if (LO_Frac < 188000000)
+		BP_Filter = 3;
+	else if (LO_Frac < 253000000)
+		BP_Filter = 4;
+	else if (LO_Frac < 343000000)
+		BP_Filter = 5;
+	else
+		BP_Filter = 6;
+
+	buf[0] = (priv->regs[R1A_IF1] & ~7) | BP_Filter; /* BP_Filter */
+	buf[1] = (priv->regs[R1B_IF2] & ~3) | LP_Fc; /* LP_Fc */
+	buf[2] = priv->regs[R1C_AGC2B];
+	ret = tda18218_wr_regs(priv, R1A_IF1, buf, 3);
+	if (ret)
+		goto error;
+
+	buf[0] = (LO_Frac / 1000) >> 12; /* LO_Frac_0 */
+	buf[1] = (LO_Frac / 1000) >> 4; /* LO_Frac_1 */
+	buf[2] = (LO_Frac / 1000) << 4 |
+		(priv->regs[R0C_MD5] & 0x0f); /* LO_Frac_2 */
+	ret = tda18218_wr_regs(priv, R0A_MD3, buf, 3);
+	if (ret)
+		goto error;
+
+	buf[0] = priv->regs[R0F_MD8] | (1 << 6); /* Freq_prog_Start */
+	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
+	if (ret)
+		goto error;
+
+	buf[0] = priv->regs[R0F_MD8] & ~(1 << 6); /* Freq_prog_Start */
+	ret = tda18218_wr_regs(priv, R0F_MD8, buf, 1);
+	if (ret)
+		goto error;
+
+	/* trigger AGC */
+	for (i = 0; i < ARRAY_SIZE(agc); i++) {
+		ret = tda18218_wr_reg(priv, agc[i][0], agc[i][1]);
+		if (ret)
+			goto error;
+	}
+
+error:
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	if (ret)
+		dbg("%s: failed ret:%d", __func__, ret);
+
+	return ret;
+}
+
+static int tda18218_sleep(struct dvb_frontend *fe)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	int ret;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	/* standby */
+	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	if (ret)
+		dbg("%s: failed ret:%d", __func__, ret);
+
+	return ret;
+}
+
+static int tda18218_init(struct dvb_frontend *fe)
+{
+	struct tda18218_priv *priv = fe->tuner_priv;
+	int ret;
+
+	/* TODO: calibrations */
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	ret = tda18218_wr_regs(priv, R00_ID, priv->regs, TDA18218_NUM_REGS);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	if (ret)
+		dbg("%s: failed ret:%d", __func__, ret);
+
+	return ret;
+}
+
+static int tda18218_release(struct dvb_frontend *fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static const struct dvb_tuner_ops tda18218_tuner_ops = {
+	.info = {
+		.name           = "NXP TDA18218",
+
+		.frequency_min  = 174000000,
+		.frequency_max  = 864000000,
+		.frequency_step =      1000,
+	},
+
+	.release       = tda18218_release,
+	.init          = tda18218_init,
+	.sleep         = tda18218_sleep,
+
+	.set_params    = tda18218_set_params,
+};
+
+struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18218_config *cfg)
+{
+	struct tda18218_priv *priv = NULL;
+	u8 val;
+	int ret;
+	/* chip default registers values */
+	static u8 def_regs[] = {
+		0xc0, 0x88, 0x00, 0x8e, 0x03, 0x00, 0x00, 0xd0, 0x00, 0x40,
+		0x00, 0x00, 0x07, 0xff, 0x84, 0x09, 0x00, 0x13, 0x00, 0x00,
+		0x01, 0x84, 0x09, 0xf0, 0x19, 0x0a, 0x8e, 0x69, 0x98, 0x01,
+		0x00, 0x58, 0x10, 0x40, 0x8c, 0x00, 0x0c, 0x48, 0x85, 0xc9,
+		0xa7, 0x00, 0x00, 0x00, 0x30, 0x81, 0x80, 0x00, 0x39, 0x00,
+		0x8a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0xf6
+	};
+
+	priv = kzalloc(sizeof(struct tda18218_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return NULL;
+
+	priv->cfg = cfg;
+	priv->i2c = i2c;
+	fe->tuner_priv = priv;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
+
+	/* check if the tuner is there */
+	ret = tda18218_rd_reg(priv, R00_ID, &val);
+	dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+	if (ret || val != def_regs[R00_ID]) {
+		kfree(priv);
+		return NULL;
+	}
+
+	info("NXP TDA18218HN successfully identified.");
+
+	memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
+		sizeof(struct dvb_tuner_ops));
+	memcpy(priv->regs, def_regs, sizeof(def_regs));
+
+	/* loop-through enabled chip default register values */
+	if (priv->cfg->loop_through) {
+		priv->regs[R17_PD1] = 0xb0;
+		priv->regs[R18_PD2] = 0x59;
+	}
+
+	/* standby */
+	ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
+	if (ret)
+		dbg("%s: failed ret:%d", __func__, ret);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
+
+	return fe;
+}
+EXPORT_SYMBOL(tda18218_attach);
+
+MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");

+ 45 - 0
drivers/media/common/tuners/tda18218.h

@@ -0,0 +1,45 @@
+/*
+ * NXP TDA18218HN silicon tuner driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef TDA18218_H
+#define TDA18218_H
+
+#include "dvb_frontend.h"
+
+struct tda18218_config {
+	u8 i2c_address;
+	u8 i2c_wr_max;
+	u8 loop_through:1;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_TDA18218) || \
+	(defined(CONFIG_MEDIA_TUNER_TDA18218_MODULE) && defined(MODULE))
+extern struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18218_config *cfg);
+#else
+static inline struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
+	struct i2c_adapter *i2c, struct tda18218_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif

+ 106 - 0
drivers/media/common/tuners/tda18218_priv.h

@@ -0,0 +1,106 @@
+/*
+ * NXP TDA18218HN silicon tuner driver
+ *
+ * Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
+ *
+ *    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.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef TDA18218_PRIV_H
+#define TDA18218_PRIV_H
+
+#define LOG_PREFIX "tda18218"
+
+#undef dbg
+#define dbg(f, arg...) \
+	if (debug) \
+		printk(KERN_DEBUG   LOG_PREFIX": " f "\n" , ## arg)
+#undef err
+#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
+#undef info
+#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
+#undef warn
+#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+
+#define R00_ID         0x00	/* ID byte */
+#define R01_R1         0x01	/* Read byte 1 */
+#define R02_R2         0x02	/* Read byte 2 */
+#define R03_R3         0x03	/* Read byte 3 */
+#define R04_R4         0x04	/* Read byte 4 */
+#define R05_R5         0x05	/* Read byte 5 */
+#define R06_R6         0x06	/* Read byte 6 */
+#define R07_MD1        0x07	/* Main divider byte 1 */
+#define R08_PSM1       0x08	/* PSM byte 1 */
+#define R09_MD2        0x09	/* Main divider byte 2 */
+#define R0A_MD3        0x0a	/* Main divider byte 1 */
+#define R0B_MD4        0x0b	/* Main divider byte 4 */
+#define R0C_MD5        0x0c	/* Main divider byte 5 */
+#define R0D_MD6        0x0d	/* Main divider byte 6 */
+#define R0E_MD7        0x0e	/* Main divider byte 7 */
+#define R0F_MD8        0x0f	/* Main divider byte 8 */
+#define R10_CD1        0x10	/* Call divider byte 1 */
+#define R11_CD2        0x11	/* Call divider byte 2 */
+#define R12_CD3        0x12	/* Call divider byte 3 */
+#define R13_CD4        0x13	/* Call divider byte 4 */
+#define R14_CD5        0x14	/* Call divider byte 5 */
+#define R15_CD6        0x15	/* Call divider byte 6 */
+#define R16_CD7        0x16	/* Call divider byte 7 */
+#define R17_PD1        0x17	/* Power-down byte 1 */
+#define R18_PD2        0x18	/* Power-down byte 2 */
+#define R19_XTOUT      0x19	/* XTOUT byte */
+#define R1A_IF1        0x1a	/* IF byte 1 */
+#define R1B_IF2        0x1b	/* IF byte 2 */
+#define R1C_AGC2B      0x1c	/* AGC2b byte */
+#define R1D_PSM2       0x1d	/* PSM byte 2 */
+#define R1E_PSM3       0x1e	/* PSM byte 3 */
+#define R1F_PSM4       0x1f	/* PSM byte 4 */
+#define R20_AGC11      0x20	/* AGC1 byte 1 */
+#define R21_AGC12      0x21	/* AGC1 byte 2 */
+#define R22_AGC13      0x22	/* AGC1 byte 3 */
+#define R23_AGC21      0x23	/* AGC2 byte 1 */
+#define R24_AGC22      0x24	/* AGC2 byte 2 */
+#define R25_AAGC       0x25	/* Analog AGC byte */
+#define R26_RC         0x26	/* RC byte */
+#define R27_RSSI       0x27	/* RSSI byte */
+#define R28_IRCAL1     0x28	/* IR CAL byte 1 */
+#define R29_IRCAL2     0x29	/* IR CAL byte 2 */
+#define R2A_IRCAL3     0x2a	/* IR CAL byte 3 */
+#define R2B_IRCAL4     0x2b	/* IR CAL byte 4 */
+#define R2C_RFCAL1     0x2c	/* RF CAL byte 1 */
+#define R2D_RFCAL2     0x2d	/* RF CAL byte 2 */
+#define R2E_RFCAL3     0x2e	/* RF CAL byte 3 */
+#define R2F_RFCAL4     0x2f	/* RF CAL byte 4 */
+#define R30_RFCAL5     0x30	/* RF CAL byte 5 */
+#define R31_RFCAL6     0x31	/* RF CAL byte 6 */
+#define R32_RFCAL7     0x32	/* RF CAL byte 7 */
+#define R33_RFCAL8     0x33	/* RF CAL byte 8 */
+#define R34_RFCAL9     0x34	/* RF CAL byte 9 */
+#define R35_RFCAL10    0x35	/* RF CAL byte 10 */
+#define R36_RFCALRAM1  0x36	/* RF CAL RAM byte 1 */
+#define R37_RFCALRAM2  0x37	/* RF CAL RAM byte 2 */
+#define R38_MARGIN     0x38	/* Margin byte */
+#define R39_FMAX1      0x39	/* Fmax byte 1 */
+#define R3A_FMAX2      0x3a	/* Fmax byte 2 */
+
+#define TDA18218_NUM_REGS 59
+
+struct tda18218_priv {
+	struct tda18218_config *cfg;
+	struct i2c_adapter *i2c;
+
+	u8 regs[TDA18218_NUM_REGS];
+};
+
+#endif

+ 35 - 26
drivers/media/common/tuners/tda18271-common.c

@@ -193,25 +193,51 @@ int tda18271_write_regs(struct dvb_frontend *fe, int idx, int len)
 	unsigned char *regs = priv->tda18271_regs;
 	unsigned char *regs = priv->tda18271_regs;
 	unsigned char buf[TDA18271_NUM_REGS + 1];
 	unsigned char buf[TDA18271_NUM_REGS + 1];
 	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
 	struct i2c_msg msg = { .addr = priv->i2c_props.addr, .flags = 0,
-			       .buf = buf, .len = len + 1 };
-	int i, ret;
+			       .buf = buf };
+	int i, ret = 1, max;
 
 
 	BUG_ON((len == 0) || (idx + len > sizeof(buf)));
 	BUG_ON((len == 0) || (idx + len > sizeof(buf)));
 
 
-	buf[0] = idx;
-	for (i = 1; i <= len; i++)
-		buf[i] = regs[idx - 1 + i];
+
+	switch (priv->small_i2c) {
+	case TDA18271_03_BYTE_CHUNK_INIT:
+		max = 3;
+		break;
+	case TDA18271_08_BYTE_CHUNK_INIT:
+		max = 8;
+		break;
+	case TDA18271_16_BYTE_CHUNK_INIT:
+		max = 16;
+		break;
+	case TDA18271_39_BYTE_CHUNK_INIT:
+	default:
+		max = 39;
+	}
 
 
 	tda18271_i2c_gate_ctrl(fe, 1);
 	tda18271_i2c_gate_ctrl(fe, 1);
+	while (len) {
+		if (max > len)
+			max = len;
+
+		buf[0] = idx;
+		for (i = 1; i <= max; i++)
+			buf[i] = regs[idx - 1 + i];
 
 
-	/* write registers */
-	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+		msg.len = max + 1;
 
 
+		/* write registers */
+		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);
+		if (ret != 1)
+			break;
+
+		idx += max;
+		len -= max;
+	}
 	tda18271_i2c_gate_ctrl(fe, 0);
 	tda18271_i2c_gate_ctrl(fe, 0);
 
 
 	if (ret != 1)
 	if (ret != 1)
 		tda_err("ERROR: idx = 0x%x, len = %d, "
 		tda_err("ERROR: idx = 0x%x, len = %d, "
-			"i2c_transfer returned: %d\n", idx, len, ret);
+			"i2c_transfer returned: %d\n", idx, max, ret);
 
 
 	return (ret == 1 ? 0 : ret);
 	return (ret == 1 ? 0 : ret);
 }
 }
@@ -326,24 +352,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
 	regs[R_EB22] = 0x48;
 	regs[R_EB22] = 0x48;
 	regs[R_EB23] = 0xb0;
 	regs[R_EB23] = 0xb0;
 
 
-	switch (priv->small_i2c) {
-	case TDA18271_08_BYTE_CHUNK_INIT:
-		tda18271_write_regs(fe, 0x00, 0x08);
-		tda18271_write_regs(fe, 0x08, 0x08);
-		tda18271_write_regs(fe, 0x10, 0x08);
-		tda18271_write_regs(fe, 0x18, 0x08);
-		tda18271_write_regs(fe, 0x20, 0x07);
-		break;
-	case TDA18271_16_BYTE_CHUNK_INIT:
-		tda18271_write_regs(fe, 0x00, 0x10);
-		tda18271_write_regs(fe, 0x10, 0x10);
-		tda18271_write_regs(fe, 0x20, 0x07);
-		break;
-	case TDA18271_39_BYTE_CHUNK_INIT:
-	default:
-		tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
-		break;
-	}
+	tda18271_write_regs(fe, 0x00, TDA18271_NUM_REGS);
 
 
 	/* setup agc1 gain */
 	/* setup agc1 gain */
 	regs[R_EB17] = 0x00;
 	regs[R_EB17] = 0x00;

+ 7 - 9
drivers/media/common/tuners/tda18271-fe.c

@@ -1156,7 +1156,6 @@ static int tda18271_get_id(struct dvb_frontend *fe)
 	struct tda18271_priv *priv = fe->tuner_priv;
 	struct tda18271_priv *priv = fe->tuner_priv;
 	unsigned char *regs = priv->tda18271_regs;
 	unsigned char *regs = priv->tda18271_regs;
 	char *name;
 	char *name;
-	int ret = 0;
 
 
 	mutex_lock(&priv->lock);
 	mutex_lock(&priv->lock);
 	tda18271_read_regs(fe);
 	tda18271_read_regs(fe);
@@ -1172,17 +1171,16 @@ static int tda18271_get_id(struct dvb_frontend *fe)
 		priv->id = TDA18271HDC2;
 		priv->id = TDA18271HDC2;
 		break;
 		break;
 	default:
 	default:
-		name = "Unknown device";
-		ret = -EINVAL;
-		break;
+		tda_info("Unknown device (%i) detected @ %d-%04x, device not supported.\n",
+			 regs[R_ID], i2c_adapter_id(priv->i2c_props.adap),
+			 priv->i2c_props.addr);
+		return -EINVAL;
 	}
 	}
 
 
-	tda_info("%s detected @ %d-%04x%s\n", name,
-		 i2c_adapter_id(priv->i2c_props.adap),
-		 priv->i2c_props.addr,
-		 (0 == ret) ? "" : ", device not supported.");
+	tda_info("%s detected @ %d-%04x\n", name,
+		 i2c_adapter_id(priv->i2c_props.adap), priv->i2c_props.addr);
 
 
-	return ret;
+	return 0;
 }
 }
 
 
 static int tda18271_setup_configuration(struct dvb_frontend *fe,
 static int tda18271_setup_configuration(struct dvb_frontend *fe,

+ 3 - 2
drivers/media/common/tuners/tda18271.h

@@ -80,8 +80,9 @@ enum tda18271_output_options {
 
 
 enum tda18271_small_i2c {
 enum tda18271_small_i2c {
 	TDA18271_39_BYTE_CHUNK_INIT = 0,
 	TDA18271_39_BYTE_CHUNK_INIT = 0,
-	TDA18271_16_BYTE_CHUNK_INIT = 1,
-	TDA18271_08_BYTE_CHUNK_INIT = 2,
+	TDA18271_16_BYTE_CHUNK_INIT = 16,
+	TDA18271_08_BYTE_CHUNK_INIT = 8,
+	TDA18271_03_BYTE_CHUNK_INIT = 3,
 };
 };
 
 
 struct tda18271_config {
 struct tda18271_config {

+ 1 - 1
drivers/media/common/tuners/xc5000.c

@@ -1042,7 +1042,7 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = {
 
 
 struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 				   struct i2c_adapter *i2c,
 				   struct i2c_adapter *i2c,
-				   struct xc5000_config *cfg)
+				   const struct xc5000_config *cfg)
 {
 {
 	struct xc5000_priv *priv = NULL;
 	struct xc5000_priv *priv = NULL;
 	int instance;
 	int instance;

+ 2 - 2
drivers/media/common/tuners/xc5000.h

@@ -53,11 +53,11 @@ struct xc5000_config {
     (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
     (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE))
 extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 extern struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 					  struct i2c_adapter *i2c,
 					  struct i2c_adapter *i2c,
-					  struct xc5000_config *cfg);
+					  const struct xc5000_config *cfg);
 #else
 #else
 static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 static inline struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
 						 struct i2c_adapter *i2c,
 						 struct i2c_adapter *i2c,
-						 struct xc5000_config *cfg)
+						 const struct xc5000_config *cfg)
 {
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 	return NULL;

+ 0 - 3
drivers/media/dvb/b2c2/flexcop-i2c.c

@@ -245,9 +245,6 @@ int flexcop_i2c_init(struct flexcop_device *fc)
 	i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
 	i2c_set_adapdata(&fc->fc_i2c_adap[1].i2c_adap, &fc->fc_i2c_adap[1]);
 	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
 	i2c_set_adapdata(&fc->fc_i2c_adap[2].i2c_adap, &fc->fc_i2c_adap[2]);
 
 
-	fc->fc_i2c_adap[0].i2c_adap.class =
-		fc->fc_i2c_adap[1].i2c_adap.class =
-		fc->fc_i2c_adap[2].i2c_adap.class = I2C_CLASS_TV_DIGITAL;
 	fc->fc_i2c_adap[0].i2c_adap.algo =
 	fc->fc_i2c_adap[0].i2c_adap.algo =
 		fc->fc_i2c_adap[1].i2c_adap.algo =
 		fc->fc_i2c_adap[1].i2c_adap.algo =
 		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;
 		fc->fc_i2c_adap[2].i2c_adap.algo = &flexcop_algo;

+ 0 - 1
drivers/media/dvb/dm1105/dm1105.c

@@ -862,7 +862,6 @@ static int __devinit dm1105_probe(struct pci_dev *pdev,
 	i2c_set_adapdata(&dev->i2c_adap, dev);
 	i2c_set_adapdata(&dev->i2c_adap, dev);
 	strcpy(dev->i2c_adap.name, DRIVER_NAME);
 	strcpy(dev->i2c_adap.name, DRIVER_NAME);
 	dev->i2c_adap.owner = THIS_MODULE;
 	dev->i2c_adap.owner = THIS_MODULE;
-	dev->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
 	dev->i2c_adap.dev.parent = &pdev->dev;
 	dev->i2c_adap.dev.parent = &pdev->dev;
 	dev->i2c_adap.algo = &dm1105_algo;
 	dev->i2c_adap.algo = &dm1105_algo;
 	dev->i2c_adap.algo_data = dev;
 	dev->i2c_adap.algo_data = dev;

+ 2 - 2
drivers/media/dvb/dvb-core/dvb_frontend.c

@@ -702,7 +702,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 
 
 	kthread_stop(fepriv->thread);
 	kthread_stop(fepriv->thread);
 
 
-	init_MUTEX (&fepriv->sem);
+	sema_init(&fepriv->sem, 1);
 	fepriv->state = FESTATE_IDLE;
 	fepriv->state = FESTATE_IDLE;
 
 
 	/* paranoia check in case a signal arrived */
 	/* paranoia check in case a signal arrived */
@@ -2062,7 +2062,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
 	}
 	}
 	fepriv = fe->frontend_priv;
 	fepriv = fe->frontend_priv;
 
 
-	init_MUTEX (&fepriv->sem);
+	sema_init(&fepriv->sem, 1);
 	init_waitqueue_head (&fepriv->wait_queue);
 	init_waitqueue_head (&fepriv->wait_queue);
 	init_waitqueue_head (&fepriv->events.wait_queue);
 	init_waitqueue_head (&fepriv->events.wait_queue);
 	mutex_init(&fepriv->events.mtx);
 	mutex_init(&fepriv->events.mtx);

+ 1 - 1
drivers/media/dvb/dvb-core/dvb_frontend.h

@@ -260,7 +260,7 @@ struct dvb_frontend_ops {
 	int (*init)(struct dvb_frontend* fe);
 	int (*init)(struct dvb_frontend* fe);
 	int (*sleep)(struct dvb_frontend* fe);
 	int (*sleep)(struct dvb_frontend* fe);
 
 
-	int (*write)(struct dvb_frontend* fe, u8* buf, int len);
+	int (*write)(struct dvb_frontend* fe, const u8 buf[], int len);
 
 
 	/* if this is set, it overrides the default swzigzag */
 	/* if this is set, it overrides the default swzigzag */
 	int (*tune)(struct dvb_frontend* fe,
 	int (*tune)(struct dvb_frontend* fe,

+ 12 - 0
drivers/media/dvb/dvb-usb/Kconfig

@@ -314,6 +314,8 @@ config DVB_USB_AF9015
 	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
+	select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
 	help
 	help
 	  Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
 	  Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
 
 
@@ -346,3 +348,13 @@ config DVB_USB_AZ6027
 	select DVB_STB6100 if !DVB_FE_CUSTOMISE
 	select DVB_STB6100 if !DVB_FE_CUSTOMISE
 	help
 	help
 	  Say Y here to support the AZ6027 device
 	  Say Y here to support the AZ6027 device
+
+config DVB_USB_LME2510
+	tristate "LME DM04/QQBOX DVB-S USB2.0 support"
+	depends on DVB_USB
+	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+	select DVB_TDA826X if !DVB_FE_CUSTOMISE
+	select DVB_STV0288 if !DVB_FE_CUSTOMISE
+	select DVB_IX2505V if !DVB_FE_CUSTOMISE
+	help
+	  Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .

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