Browse Source

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

* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (243 commits)
  V4L/DVB: sms: Convert IR support to use the Remote Controller core
  V4L/DVB: sms: properly initialize IR phys and IR name
  V4L/DVB: standardize names at rc-dib0700 tables
  V4L/DVB: smsusb: enable IR port for Hauppauge WinTV MiniStick
  V4L/DVB: dib0700: Fix RC protocol logic to properly handle NEC/NECx and RC-5
  V4L/DVB: dib0700: properly implement IR change_protocol
  V4L/DVB: dib0700: break keytable into NEC and RC-5 variants
  V4L/DVB: dib0700: avoid bad repeat
  V4L/DVB: Port dib0700 to rc-core
  V4L/DVB: Add a keymap file with dib0700 table
  V4L/DVB: dvb-usb: add support for rc-core mode
  V4L/DVB: dvb-usb: prepare drivers for using rc-core
  V4L/DVB: dvb-usb: get rid of struct dvb_usb_rc_key
  V4L/DVB: rj54n1cb0c: fix a comment in the driver
  V4L/DVB: V4L2: sh_vou: VOU does support the full PAL resolution too
  V4L/DVB: V4L2: sh_mobile_camera_ceu: add support for CSI2
  V4L/DVB: V4L2: soc-camera: add a MIPI CSI-2 driver for SH-Mobile platforms
  V4L/DVB: V4L2: soc-camera: export soc-camera bus type for notifications
  V4L/DVB: V4L2: mediabus: add 12-bit Bayer and YUV420 pixel formats
  V4L/DVB: mediabus: fix ambiguous pixel code names
  ...
Linus Torvalds 15 years ago
parent
commit
f63b759c44
100 changed files with 4756 additions and 2592 deletions
  1. 16 3
      Documentation/DocBook/dvb/dvbapi.xml
  2. 1 0
      Documentation/DocBook/dvb/frontend.h.xml
  3. 8 2
      Documentation/DocBook/dvb/frontend.xml
  4. 1 0
      Documentation/DocBook/media-entities.tmpl
  5. 4 4
      Documentation/DocBook/media.tmpl
  6. 235 0
      Documentation/DocBook/v4l/lirc_device_interface.xml
  7. 2 0
      Documentation/DocBook/v4l/remote_controllers.xml
  8. 21 4
      Documentation/dvb/get_dvb_firmware
  9. 0 51
      Documentation/feature-removal-schedule.txt
  10. 3 3
      Documentation/video4linux/CARDLIST.cx23885
  11. 1 0
      Documentation/video4linux/CARDLIST.em28xx
  12. 2 1
      Documentation/video4linux/CARDLIST.saa7134
  13. 8 0
      Documentation/video4linux/gspca.txt
  14. 1 1
      arch/sh/boards/mach-ap325rxa/setup.c
  15. 35 0
      drivers/media/IR/Kconfig
  16. 3 0
      drivers/media/IR/Makefile
  17. 6 5
      drivers/media/IR/imon.c
  18. 54 0
      drivers/media/IR/ir-core-priv.h
  19. 9 143
      drivers/media/IR/ir-jvc-decoder.c
  20. 3 2
      drivers/media/IR/ir-keytable.c
  21. 278 0
      drivers/media/IR/ir-lirc-codec.c
  22. 10 141
      drivers/media/IR/ir-nec-decoder.c
  23. 93 74
      drivers/media/IR/ir-raw-event.c
  24. 16 151
      drivers/media/IR/ir-rc5-decoder.c
  25. 7 146
      drivers/media/IR/ir-rc6-decoder.c
  26. 12 143
      drivers/media/IR/ir-sony-decoder.c
  27. 143 108
      drivers/media/IR/ir-sysfs.c
  28. 4 0
      drivers/media/IR/keymaps/Makefile
  29. 124 0
      drivers/media/IR/keymaps/rc-dib0700-nec.c
  30. 235 0
      drivers/media/IR/keymaps/rc-dib0700-rc5.c
  31. 41 0
      drivers/media/IR/keymaps/rc-lirc.c
  32. 105 0
      drivers/media/IR/keymaps/rc-rc6-mce.c
  33. 764 0
      drivers/media/IR/lirc_dev.c
  34. 1143 0
      drivers/media/IR/mceusb.c
  35. 1 1
      drivers/media/common/saa7146_fops.c
  36. 2 2
      drivers/media/common/saa7146_vbi.c
  37. 2 2
      drivers/media/common/saa7146_video.c
  38. 5 3
      drivers/media/common/tuners/tda18271-fe.c
  39. 0 3
      drivers/media/common/tuners/tuner-simple.c
  40. 28 31
      drivers/media/common/tuners/xc5000.c
  41. 1 1
      drivers/media/dvb/bt8xx/dst_ca.c
  42. 1 1
      drivers/media/dvb/dvb-core/dmxdev.c
  43. 8 2
      drivers/media/dvb/dvb-core/dvb_ca_en50221.c
  44. 3 7
      drivers/media/dvb/dvb-core/dvb_demux.c
  45. 5 5
      drivers/media/dvb/dvb-core/dvb_frontend.c
  46. 7 5
      drivers/media/dvb/dvb-usb/a800.c
  47. 2 2
      drivers/media/dvb/dvb-usb/af9005-remote.c
  48. 16 55
      drivers/media/dvb/dvb-usb/af9005.c
  49. 1 1
      drivers/media/dvb/dvb-usb/af9005.h
  50. 27 15
      drivers/media/dvb/dvb-usb/af9015.c
  51. 9 9
      drivers/media/dvb/dvb-usb/af9015.h
  52. 16 12
      drivers/media/dvb/dvb-usb/anysee.c
  53. 8 5
      drivers/media/dvb/dvb-usb/az6027.c
  54. 7 5
      drivers/media/dvb/dvb-usb/cinergyT2-core.c
  55. 74 54
      drivers/media/dvb/dvb-usb/cxusb.c
  56. 1 0
      drivers/media/dvb/dvb-usb/dib0700.h
  57. 122 144
      drivers/media/dvb/dvb-usb/dib0700_core.c
  58. 230 384
      drivers/media/dvb/dvb-usb/dib0700_devices.c
  59. 1 1
      drivers/media/dvb/dvb-usb/dibusb-common.c
  60. 24 16
      drivers/media/dvb/dvb-usb/dibusb-mb.c
  61. 6 4
      drivers/media/dvb/dvb-usb/dibusb-mc.c
  62. 1 1
      drivers/media/dvb/dvb-usb/dibusb.h
  63. 11 9
      drivers/media/dvb/dvb-usb/digitv.c
  64. 25 17
      drivers/media/dvb/dvb-usb/dtt200u.c
  65. 1 0
      drivers/media/dvb/dvb-usb/dvb-usb-ids.h
  66. 31 29
      drivers/media/dvb/dvb-usb/dvb-usb-init.c
  67. 140 58
      drivers/media/dvb/dvb-usb/dvb-usb-remote.c
  68. 62 30
      drivers/media/dvb/dvb-usb/dvb-usb.h
  69. 38 29
      drivers/media/dvb/dvb-usb/dw2102.c
  70. 1 1
      drivers/media/dvb/dvb-usb/gp8psk-fe.c
  71. 25 19
      drivers/media/dvb/dvb-usb/m920x.c
  72. 8 6
      drivers/media/dvb/dvb-usb/nova-t-usb2.c
  73. 9 7
      drivers/media/dvb/dvb-usb/opera1.c
  74. 8 6
      drivers/media/dvb/dvb-usb/vp702x.c
  75. 8 6
      drivers/media/dvb/dvb-usb/vp7045.c
  76. 1 0
      drivers/media/dvb/frontends/Kconfig
  77. 28 24
      drivers/media/dvb/frontends/af9013.c
  78. 1 1
      drivers/media/dvb/frontends/af9013.h
  79. 5 3
      drivers/media/dvb/frontends/af9013_priv.h
  80. 1 8
      drivers/media/dvb/frontends/dib3000mb.c
  81. 0 4
      drivers/media/dvb/frontends/dib3000mb_priv.h
  82. 1 1
      drivers/media/dvb/frontends/dib3000mc.c
  83. 206 61
      drivers/media/dvb/frontends/lgdt3305.c
  84. 8 2
      drivers/media/dvb/frontends/lgdt3305.h
  85. 10 40
      drivers/media/dvb/frontends/lgs8gxx.c
  86. 0 1
      drivers/media/dvb/frontends/mb86a16.c
  87. 32 11
      drivers/media/dvb/frontends/tda10048.c
  88. 10 4
      drivers/media/dvb/mantis/Kconfig
  89. 1 4
      drivers/media/dvb/mantis/mantis_input.c
  90. 2 0
      drivers/media/dvb/siano/sms-cards.c
  91. 1 1
      drivers/media/dvb/siano/sms-cards.h
  92. 1 3
      drivers/media/dvb/siano/smscoreapi.c
  93. 36 225
      drivers/media/dvb/siano/smsir.c
  94. 13 50
      drivers/media/dvb/siano/smsir.h
  95. 1 2
      drivers/media/dvb/siano/smsusb.c
  96. 1 1
      drivers/media/radio/si470x/radio-si470x-common.c
  97. 10 2
      drivers/media/radio/si4713-i2c.c
  98. 18 165
      drivers/media/video/Kconfig
  99. 3 6
      drivers/media/video/Makefile
  100. 3 3
      drivers/media/video/ak881x.c

+ 16 - 3
Documentation/DocBook/dvb/dvbapi.xml

@@ -12,10 +12,12 @@
 <othername role="mi">O. C.</othername>
 <affiliation><address><email>rjkm@metzlerbros.de</email></address></affiliation>
 </author>
+</authorgroup>
+<authorgroup>
 <author>
 <firstname>Mauro</firstname>
-<surname>Chehab</surname>
 <othername role="mi">Carvalho</othername>
+<surname>Chehab</surname>
 <affiliation><address><email>mchehab@redhat.com</email></address></affiliation>
 <contrib>Ported document to Docbook XML.</contrib>
 </author>
@@ -23,12 +25,23 @@
 <copyright>
 	<year>2002</year>
 	<year>2003</year>
-	<year>2009</year>
 	<holder>Convergence GmbH</holder>
 </copyright>
+<copyright>
+	<year>2009-2010</year>
+	<holder>Mauro Carvalho Chehab</holder>
+</copyright>
 
 <revhistory>
 <!-- Put document revisions here, newest first. -->
+<revision>
+	<revnumber>2.0.3</revnumber>
+	<date>2010-07-03</date>
+	<authorinitials>mcc</authorinitials>
+	<revremark>
+		Add some frontend capabilities flags, present on kernel, but missing at the specs.
+	</revremark>
+</revision>
 <revision>
 	<revnumber>2.0.2</revnumber>
 	<date>2009-10-25</date>
@@ -63,7 +76,7 @@ Added ISDB-T test originally written by Patrick Boettcher
 
 
 <title>LINUX DVB API</title>
-<subtitle>Version 3</subtitle>
+<subtitle>Version 5.2</subtitle>
 <!-- ADD THE CHAPTERS HERE -->
   <chapter id="dvb_introdution">
     &sub-intro;

+ 1 - 0
Documentation/DocBook/dvb/frontend.h.xml

@@ -63,6 +63,7 @@ typedef enum fe_caps {
         FE_CAN_8VSB                     = 0x200000,
         FE_CAN_16VSB                    = 0x400000,
         FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
+        FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
         FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
         FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
         FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */

+ 8 - 2
Documentation/DocBook/dvb/frontend.xml

@@ -64,8 +64,14 @@ a specific frontend type.</para>
 	FE_CAN_BANDWIDTH_AUTO         = 0x40000,
 	FE_CAN_GUARD_INTERVAL_AUTO    = 0x80000,
 	FE_CAN_HIERARCHY_AUTO         = 0x100000,
-	FE_CAN_MUTE_TS                = 0x80000000,
-	FE_CAN_CLEAN_SETUP            = 0x40000000
+	FE_CAN_8VSB                   = 0x200000,
+	FE_CAN_16VSB                  = 0x400000,
+	FE_HAS_EXTENDED_CAPS          = 0x800000,
+	FE_CAN_TURBO_FEC              = 0x8000000,
+	FE_CAN_2G_MODULATION          = 0x10000000,
+	FE_NEEDS_BENDING              = 0x20000000,
+	FE_CAN_RECOVER                = 0x40000000,
+	FE_CAN_MUTE_TS                = 0x80000000
 	} fe_caps_t;
 </programlisting>
 </section>

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

@@ -218,6 +218,7 @@
 <!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
 <!ENTITY sub-driver SYSTEM "v4l/driver.xml">
 <!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
+<!ENTITY sub-lirc_device_interface SYSTEM "v4l/lirc_device_interface.xml">
 <!ENTITY sub-remote_controllers SYSTEM "v4l/remote_controllers.xml">
 <!ENTITY sub-fdl-appendix SYSTEM "v4l/fdl-appendix.xml">
 <!ENTITY sub-close SYSTEM "v4l/func-close.xml">

+ 4 - 4
Documentation/DocBook/media.tmpl

@@ -28,7 +28,7 @@
 <title>LINUX MEDIA INFRASTRUCTURE API</title>
 
 <copyright>
-	<year>2009</year>
+	<year>2009-2010</year>
 	<holder>LinuxTV Developers</holder>
 </copyright>
 
@@ -61,7 +61,7 @@ Foundation. A copy of the license is included in the chapter entitled
 		in fact it covers several different video standards including
 		DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
 		to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
-	<para>The third part covers other API's used by all media infrastructure devices</para>
+	<para>The third part covers Remote Controller API</para>
 	<para>For additional information and for the latest development code,
 		see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
 	<para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
@@ -86,7 +86,7 @@ Foundation. A copy of the license is included in the chapter entitled
 </author>
 </authorgroup>
 <copyright>
-	<year>2009</year>
+	<year>2009-2010</year>
 	<holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
@@ -101,7 +101,7 @@ Foundation. A copy of the license is included in the chapter entitled
 </revhistory>
 </partinfo>
 
-<title>Other API's used by media infrastructure drivers</title>
+<title>Remote Controller API</title>
 <chapter id="remote_controllers">
 &sub-remote_controllers;
 </chapter>

+ 235 - 0
Documentation/DocBook/v4l/lirc_device_interface.xml

@@ -0,0 +1,235 @@
+<section id="lirc_dev">
+<title>LIRC Device Interface</title>
+
+
+<section id="lirc_dev_intro">
+<title>Introduction</title>
+
+<para>The LIRC device interface is a bi-directional interface for
+transporting raw IR data between userspace and kernelspace. Fundamentally,
+it is just a chardev (/dev/lircX, for X = 0, 1, 2, ...), with a number
+of standard struct file_operations defined on it. With respect to
+transporting raw IR data to and fro, the essential fops are read, write
+and ioctl.</para>
+
+<para>Example dmesg output upon a driver registering w/LIRC:</para>
+  <blockquote>
+    <para>$ dmesg |grep lirc_dev</para>
+    <para>lirc_dev: IR Remote Control driver registered, major 248</para>
+    <para>rc rc0: lirc_dev: driver ir-lirc-codec (mceusb) registered at minor = 0</para>
+  </blockquote>
+
+<para>What you should see for a chardev:</para>
+  <blockquote>
+    <para>$ ls -l /dev/lirc*</para>
+    <para>crw-rw---- 1 root root 248, 0 Jul  2 22:20 /dev/lirc0</para>
+  </blockquote>
+</section>
+
+<section id="lirc_read">
+<title>LIRC read fop</title>
+
+<para>The lircd userspace daemon reads raw IR data from the LIRC chardev. The
+exact format of the data depends on what modes a driver supports, and what
+mode has been selected. lircd obtains supported modes and sets the active mode
+via the ioctl interface, detailed at <xref linkend="lirc_ioctl"/>. The generally
+preferred mode is LIRC_MODE_MODE2, in which packets containing an int value
+describing an IR signal are read from the chardev.</para>
+
+<para>See also <ulink url="http://www.lirc.org/html/technical.html">http://www.lirc.org/html/technical.html</ulink> for more info.</para>
+</section>
+
+<section id="lirc_write">
+<title>LIRC write fop</title>
+
+<para>The data written to the chardev is a pulse/space sequence of integer
+values. Pulses and spaces are only marked implicitly by their position. The
+data must start and end with a pulse, therefore, the data must always include
+an unevent number of samples. The write function must block until the data has
+been transmitted by the hardware.</para>
+</section>
+
+<section id="lirc_ioctl">
+<title>LIRC ioctl fop</title>
+
+<para>The LIRC device's ioctl definition is bound by the ioctl function
+definition of struct file_operations, leaving us with an unsigned int
+for the ioctl command and an unsigned long for the arg. For the purposes
+of ioctl portability across 32-bit and 64-bit, these values are capped
+to their 32-bit sizes.</para>
+
+<para>The following ioctls can be used to change specific hardware settings.
+In general each driver should have a default set of settings. The driver
+implementation is expected to re-apply the default settings when the device
+is closed by user-space, so that every application opening the device can rely
+on working with the default settings initially.</para>
+
+<variablelist>
+  <varlistentry>
+    <term>LIRC_GET_FEATURES</term>
+    <listitem>
+      <para>Obviously, get the underlying hardware device's features. If a driver
+      does not announce support of certain features, calling of the corresponding
+      ioctls is undefined.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_SEND_MODE</term>
+    <listitem>
+      <para>Get supported transmit mode. Only LIRC_MODE_PULSE is supported by lircd.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_REC_MODE</term>
+    <listitem>
+      <para>Get supported receive modes. Only LIRC_MODE_MODE2 and LIRC_MODE_LIRCCODE
+      are supported by lircd.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_SEND_CARRIER</term>
+    <listitem>
+      <para>Get carrier frequency (in Hz) currently used for transmit.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_REC_CARRIER</term>
+    <listitem>
+      <para>Get carrier frequency (in Hz) currently used for IR reception.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_{G,S}ET_{SEND,REC}_DUTY_CYCLE</term>
+    <listitem>
+      <para>Get/set the duty cycle (from 0 to 100) of the carrier signal. Currently,
+      no special meaning is defined for 0 or 100, but this could be used to switch
+      off carrier generation in the future, so these values should be reserved.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_REC_RESOLUTION</term>
+    <listitem>
+      <para>Some receiver have maximum resolution which is defined by internal
+      sample rate or data format limitations. E.g. it's common that signals can
+      only be reported in 50 microsecond steps. This integer value is used by
+      lircd to automatically adjust the aeps tolerance value in the lircd
+      config file.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_M{IN,AX}_TIMEOUT</term>
+    <listitem>
+      <para>Some devices have internal timers that can be used to detect when
+      there's no IR activity for a long time. This can help lircd in detecting
+      that a IR signal is finished and can speed up the decoding process.
+      Returns an integer value with the minimum/maximum timeout that can be
+      set. Some devices have a fixed timeout, in that case both ioctls will
+      return the same value even though the timeout cannot be changed.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_M{IN,AX}_FILTER_{PULSE,SPACE}</term>
+    <listitem>
+      <para>Some devices are able to filter out spikes in the incoming signal
+      using given filter rules. These ioctls return the hardware capabilities
+      that describe the bounds of the possible filters. Filter settings depend
+      on the IR protocols that are expected. lircd derives the settings from
+      all protocols definitions found in its config file.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_GET_LENGTH</term>
+    <listitem>
+      <para>Retrieves the code length in bits (only for LIRC_MODE_LIRCCODE).
+      Reads on the device must be done in blocks matching the bit count.
+      The bit could should be rounded up so that it matches full bytes.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_{SEND,REC}_MODE</term>
+    <listitem>
+      <para>Set send/receive mode. Largely obsolete for send, as only
+      LIRC_MODE_PULSE is supported.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_{SEND,REC}_CARRIER</term>
+    <listitem>
+      <para>Set send/receive carrier (in Hz).</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_TRANSMITTER_MASK</term>
+    <listitem>
+      <para>This enables the given set of transmitters. The first transmitter
+      is encoded by the least significant bit, etc. When an invalid bit mask
+      is given, i.e. a bit is set, even though the device does not have so many
+      transitters, then this ioctl returns the number of available transitters
+      and does nothing otherwise.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_REC_TIMEOUT</term>
+    <listitem>
+      <para>Sets the integer value for IR inactivity timeout (cf.
+      LIRC_GET_MIN_TIMEOUT and LIRC_GET_MAX_TIMEOUT). A value of 0 (if
+      supported by the hardware) disables all hardware timeouts and data should
+      be reported as soon as possible. If the exact value cannot be set, then
+      the next possible value _greater_ than the given value should be set.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_REC_TIMEOUT_REPORTS</term>
+    <listitem>
+      <para>Enable (1) or disable (0) timeout reports in LIRC_MODE_MODE2. By
+      default, timeout reports should be turned off.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_REC_FILTER_{,PULSE,SPACE}</term>
+    <listitem>
+      <para>Pulses/spaces shorter than this are filtered out by hardware. If
+      filters cannot be set independently for pulse/space, the corresponding
+      ioctls must return an error and LIRC_SET_REC_FILTER shall be used instead.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_MEASURE_CARRIER_MODE</term>
+    <listitem>
+      <para>Enable (1)/disable (0) measure mode. If enabled, from the next key
+      press on, the driver will send LIRC_MODE2_FREQUENCY packets. By default
+      this should be turned off.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SET_REC_{DUTY_CYCLE,CARRIER}_RANGE</term>
+    <listitem>
+      <para>To set a range use LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE
+      with the lower bound first and later LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER
+      with the upper bound.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_NOTIFY_DECODE</term>
+    <listitem>
+      <para>This ioctl is called by lircd whenever a successful decoding of an
+      incoming IR signal could be done. This can be used by supporting hardware
+      to give visual feedback to the user e.g. by flashing a LED.</para>
+    </listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>LIRC_SETUP_{START,END}</term>
+    <listitem>
+      <para>Setting of several driver parameters can be optimized by encapsulating
+      the according ioctl calls with LIRC_SETUP_START/LIRC_SETUP_END. When a
+      driver receives a LIRC_SETUP_START ioctl it can choose to not commit
+      further setting changes to the hardware until a LIRC_SETUP_END is received.
+      But this is open to the driver implementation and every driver must also
+      handle parameter changes which are not encapsulated by LIRC_SETUP_START
+      and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
+    </listitem>
+  </varlistentry>
+</variablelist>
+
+</section>
+</section>

+ 2 - 0
Documentation/DocBook/v4l/remote_controllers.xml

@@ -173,3 +173,5 @@ keymapping.</para>
 <para>This program demonstrates how to replace the keymap tables.</para>
 &sub-keytable-c;
 </section>
+
+&sub-lirc_device_interface;

+ 21 - 4
Documentation/dvb/get_dvb_firmware

@@ -26,7 +26,7 @@ use IO::Handle;
 		"dec3000s", "vp7041", "dibusb", "nxt2002", "nxt2004",
 		"or51211", "or51132_qam", "or51132_vsb", "bluebird",
 		"opera1", "cx231xx", "cx18", "cx23885", "pvrusb2", "mpc718",
-		"af9015", "ngene");
+		"af9015", "ngene", "az6027");
 
 # Check args
 syntax() if (scalar(@ARGV) != 1);
@@ -518,11 +518,11 @@ sub bluebird {
 sub af9015 {
 	my $sourcefile = "download.ashx?file=57";
 	my $url = "http://www.ite.com.tw/EN/Services/$sourcefile";
-	my $hash = "ff5b096ed47c080870eacdab2de33ad6";
+	my $hash = "e3f08935158038d385ad382442f4bb2d";
 	my $outfile = "dvb-usb-af9015.fw";
 	my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
-	my $fwoffset = 0x22708;
-	my $fwlength = 18225;
+	my $fwoffset = 0x25690;
+	my $fwlength = 18725;
 	my ($chunklength, $buf, $rcount);
 
 	checkstandard();
@@ -567,6 +567,23 @@ sub ngene {
     "$file1, $file2";
 }
 
+sub az6027{
+    my $file = "AZ6027_Linux_Driver.tar.gz";
+    my $url = "http://linux.terratec.de/files/$file";
+    my $firmware = "dvb-usb-az6027-03.fw";
+
+    wgetfile($file, $url);
+
+    #untar
+    if( system("tar xzvf $file $firmware")){
+        die "failed to untar firmware";
+    }
+    if( system("rm $file")){
+        die ("unable to remove unnecessary files");
+    }
+
+    $firmware;
+}
 # ---------------------------------------------------------------
 # Utilities
 

+ 0 - 51
Documentation/feature-removal-schedule.txt

@@ -459,57 +459,6 @@ Who:	Corentin Chary <corentin.chary@gmail.com>
 
 ----------------------------
 
-What:	usbvideo quickcam_messenger driver
-When:	2.6.35
-Files:	drivers/media/video/usbvideo/quickcam_messenger.[ch]
-Why:	obsolete v4l1 driver replaced by gspca_stv06xx
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:	ov511 v4l1 driver
-When:	2.6.35
-Files:	drivers/media/video/ov511.[ch]
-Why:	obsolete v4l1 driver replaced by gspca_ov519
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:	w9968cf v4l1 driver
-When:	2.6.35
-Files:	drivers/media/video/w9968cf*.[ch]
-Why:	obsolete v4l1 driver replaced by gspca_ov519
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:	ovcamchip sensor framework
-When:	2.6.35
-Files:	drivers/media/video/ovcamchip/*
-Why:	Only used by obsoleted v4l1 drivers
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:	stv680 v4l1 driver
-When:	2.6.35
-Files:	drivers/media/video/stv680.[ch]
-Why:	obsolete v4l1 driver replaced by gspca_stv0680
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
-What:	zc0301 v4l driver
-When:	2.6.35
-Files:	drivers/media/video/zc0301/*
-Why:	Duplicate functionality with the gspca_zc3xx driver, zc0301 only
-	supports 2 USB-ID's (because it only supports a limited set of
-	sensors) wich are also supported by the gspca_zc3xx driver
-	(which supports 53 USB-ID's in total)
-Who:	Hans de Goede <hdegoede@redhat.com>
-
-----------------------------
-
 What:	sysfs-class-rfkill state file
 When:	Feb 2014
 Files:	net/rfkill/core.c

+ 3 - 3
Documentation/video4linux/CARDLIST.cx23885

@@ -17,9 +17,9 @@
  16 -> DVBWorld DVB-S2 2005                                [0001:2005]
  17 -> NetUP Dual DVB-S2 CI                                [1b55:2a2c]
  18 -> Hauppauge WinTV-HVR1270                             [0070:2211]
- 19 -> Hauppauge WinTV-HVR1275                             [0070:2215]
- 20 -> Hauppauge WinTV-HVR1255                             [0070:2251]
- 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295]
+ 19 -> Hauppauge WinTV-HVR1275                             [0070:2215,0070:221d,0070:22f2]
+ 20 -> Hauppauge WinTV-HVR1255                             [0070:2251,0070:2259,0070:22f1]
+ 21 -> Hauppauge WinTV-HVR1210                             [0070:2291,0070:2295,0070:2299,0070:229d,0070:22f0,0070:22f3,0070:22f4,0070:22f5]
  22 -> Mygica X8506 DMB-TH                                 [14f1:8651]
  23 -> Magic-Pro ProHDTV Extreme 2                         [14f1:8657]
  24 -> Hauppauge WinTV-HVR1850                             [0070:8541]

+ 1 - 0
Documentation/video4linux/CARDLIST.em28xx

@@ -72,3 +72,4 @@
  73 -> Reddo DVB-C USB TV Box                   (em2870)
  74 -> Actionmaster/LinXcel/Digitus VC211A      (em2800)
  75 -> Dikom DK300                              (em2882)
+ 76 -> KWorld PlusTV 340U or UB435-Q (ATSC)     (em2870)        [1b80:a340]

+ 2 - 1
Documentation/video4linux/CARDLIST.saa7134

@@ -178,4 +178,5 @@
 177 -> Hawell HW-404M7
 178 -> Beholder BeholdTV H7                     [5ace:7190]
 179 -> Beholder BeholdTV A7                     [5ace:7090]
-180 -> Avermedia M733A                          [1461:4155,1461:4255]
+180 -> Avermedia PCI M733A                      [1461:4155,1461:4255]
+181 -> TechoTrend TT-budget T-3000              [13c2:2804]

+ 8 - 0
Documentation/video4linux/gspca.txt

@@ -29,8 +29,12 @@ zc3xx		041e:4029	Creative WebCam Vista Pro
 zc3xx		041e:4034	Creative Instant P0620
 zc3xx		041e:4035	Creative Instant P0620D
 zc3xx		041e:4036	Creative Live !
+sq930x		041e:4038	Creative Joy-IT
 zc3xx		041e:403a	Creative Nx Pro 2
 spca561		041e:403b	Creative Webcam Vista (VF0010)
+sq930x		041e:403c	Creative Live! Ultra
+sq930x		041e:403d	Creative Live! Ultra for Notebooks
+sq930x		041e:4041	Creative Live! Motion
 zc3xx		041e:4051	Creative Live!Cam Notebook Pro (VF0250)
 ov519		041e:4052	Creative Live! VISTA IM
 zc3xx		041e:4053	Creative Live!Cam Video IM
@@ -138,6 +142,7 @@ finepix		04cb:013d	Fujifilm FinePix unknown model
 finepix		04cb:013f	Fujifilm FinePix F420
 sunplus		04f1:1001	JVC GC A50
 spca561		04fc:0561	Flexcam 100
+spca1528	04fc:1528	Sunplus MD80 clone
 sunplus		04fc:500c	Sunplus CA500C
 sunplus		04fc:504a	Aiptek Mini PenCam 1.3
 sunplus		04fc:504b	Maxell MaxPocket LE 1.3
@@ -253,6 +258,7 @@ pac7302		093a:2620	Apollo AC-905
 pac7302		093a:2621	PAC731x
 pac7302		093a:2622	Genius Eye 312
 pac7302		093a:2624	PAC7302
+pac7302		093a:2625	Genius iSlim 310
 pac7302		093a:2626	Labtec 2200
 pac7302		093a:2628	Genius iLook 300
 pac7302		093a:2629	Genious iSlim 300
@@ -362,6 +368,8 @@ sq905c		2770:9052	Disney pix micro 2 (VGA)
 sq905c		2770:905c	All 11 known cameras with this ID
 sq905		2770:9120	All 24 known cameras with this ID
 sq905c		2770:913d	All 4 known cameras with this ID
+sq930x		2770:930b	Sweex Motion Tracking / I-Tec iCam Tracer
+sq930x		2770:930c	Trust WB-3500T / NSG Robbie 2.0
 spca500		2899:012c	Toptro Industrial
 ov519		8020:ef04	ov519
 spca508		8086:0110	Intel Easy PC Camera

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

@@ -316,7 +316,7 @@ static struct soc_camera_platform_info camera_info = {
 	.format_name = "UYVY",
 	.format_depth = 16,
 	.format = {
-		.code = V4L2_MBUS_FMT_YUYV8_2X8_BE,
+		.code = V4L2_MBUS_FMT_UYVY8_2X8,
 		.colorspace = V4L2_COLORSPACE_SMPTE170M,
 		.field = V4L2_FIELD_NONE,
 		.width = 640,

+ 35 - 0
drivers/media/IR/Kconfig

@@ -8,6 +8,17 @@ config VIDEO_IR
 	depends on IR_CORE
 	default IR_CORE
 
+config LIRC
+	tristate
+	default y
+
+	---help---
+	   Enable this option to build the Linux Infrared Remote
+	   Control (LIRC) core device interface driver. The LIRC
+	   interface passes raw IR to and from userspace, where the
+	   LIRC daemon handles protocol decoding for IR reception ann
+	   encoding for IR transmitting (aka "blasting").
+
 source "drivers/media/IR/keymaps/Kconfig"
 
 config IR_NEC_DECODER
@@ -33,6 +44,7 @@ config IR_RC5_DECODER
 config IR_RC6_DECODER
 	tristate "Enable IR raw decoder for the RC6 protocol"
 	depends on IR_CORE
+	select BITREVERSE
 	default y
 
 	---help---
@@ -42,6 +54,7 @@ config IR_RC6_DECODER
 config IR_JVC_DECODER
 	tristate "Enable IR raw decoder for the JVC protocol"
 	depends on IR_CORE
+	select BITREVERSE
 	default y
 
 	---help---
@@ -57,6 +70,16 @@ config IR_SONY_DECODER
 	   Enable this option if you have an infrared remote control which
 	   uses the Sony protocol, and you need software decoding support.
 
+config IR_LIRC_CODEC
+	tristate "Enable IR to LIRC bridge"
+	depends on IR_CORE
+	depends on LIRC
+	default y
+
+	---help---
+	   Enable this option to pass raw IR to and from userspace via
+	   the LIRC interface.
+
 config IR_IMON
 	tristate "SoundGraph iMON Receiver and Display"
 	depends on USB_ARCH_HAS_HCD
@@ -68,3 +91,15 @@ config IR_IMON
 
 	   To compile this driver as a module, choose M here: the
 	   module will be called imon.
+
+config IR_MCEUSB
+	tristate "Windows Media Center Ed. eHome Infrared Transceiver"
+	depends on USB_ARCH_HAS_HCD
+	depends on IR_CORE
+	select USB
+	---help---
+	   Say Y here if you want to use a Windows Media Center Edition
+	   eHome Infrared Transceiver.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called mceusb.

+ 3 - 0
drivers/media/IR/Makefile

@@ -5,11 +5,14 @@ obj-y += keymaps/
 
 obj-$(CONFIG_IR_CORE) += ir-core.o
 obj-$(CONFIG_VIDEO_IR) += ir-common.o
+obj-$(CONFIG_LIRC) += lirc_dev.o
 obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
 obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
 obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
 obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
 obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
+obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_IR_IMON) += imon.o
+obj-$(CONFIG_IR_MCEUSB) += mceusb.o

+ 6 - 5
drivers/media/IR/imon.c

@@ -407,7 +407,7 @@ static int display_close(struct inode *inode, struct file *file)
 	struct imon_context *ictx = NULL;
 	int retval = 0;
 
-	ictx = (struct imon_context *)file->private_data;
+	ictx = file->private_data;
 
 	if (!ictx) {
 		err("%s: no context for device", __func__);
@@ -812,7 +812,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
 	const unsigned char vfd_packet6[] = {
 		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
 
-	ictx = (struct imon_context *)file->private_data;
+	ictx = file->private_data;
 	if (!ictx) {
 		err("%s: no context for device", __func__);
 		return -ENODEV;
@@ -896,7 +896,7 @@ static ssize_t lcd_write(struct file *file, const char *buf,
 	int retval = 0;
 	struct imon_context *ictx;
 
-	ictx = (struct imon_context *)file->private_data;
+	ictx = file->private_data;
 	if (!ictx) {
 		err("%s: no context for device", __func__);
 		return -ENODEV;
@@ -1943,7 +1943,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
 	return ictx;
 
 urb_submit_failed:
-	input_unregister_device(ictx->idev);
+	ir_input_unregister(ictx->idev);
 	input_free_device(ictx->idev);
 idev_setup_failed:
 find_endpoint_failed:
@@ -2067,6 +2067,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
 		detected_display_type = IMON_DISPLAY_TYPE_VFD;
 		break;
 	/* iMON LCD, MCE IR */
+	case 0x9e:
 	case 0x9f:
 		dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
 		detected_display_type = IMON_DISPLAY_TYPE_LCD;
@@ -2306,7 +2307,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
 	if (ifnum == 0) {
 		ictx->dev_present_intf0 = false;
 		usb_kill_urb(ictx->rx_urb_intf0);
-		input_unregister_device(ictx->idev);
+		ir_input_unregister(ictx->idev);
 		if (ictx->display_supported) {
 			if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
 				usb_deregister_dev(interface, &imon_lcd_class);

+ 54 - 0
drivers/media/IR/ir-core-priv.h

@@ -22,17 +22,62 @@
 struct ir_raw_handler {
 	struct list_head list;
 
+	u64 protocols; /* which are handled by this handler */
 	int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
+
+	/* These two should only be used by the lirc decoder */
 	int (*raw_register)(struct input_dev *input_dev);
 	int (*raw_unregister)(struct input_dev *input_dev);
 };
 
 struct ir_raw_event_ctrl {
+	struct list_head		list;		/* to keep track of raw clients */
 	struct work_struct		rx_work;	/* for the rx decoding workqueue */
 	struct kfifo			kfifo;		/* fifo for the pulse/space durations */
 	ktime_t				last_event;	/* when last event occurred */
 	enum raw_event_type		last_type;	/* last event type */
 	struct input_dev		*input_dev;	/* pointer to the parent input_dev */
+	u64				enabled_protocols; /* enabled raw protocol decoders */
+
+	/* raw decoder state follows */
+	struct ir_raw_event prev_ev;
+	struct nec_dec {
+		int state;
+		unsigned count;
+		u32 bits;
+	} nec;
+	struct rc5_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc5;
+	struct rc6_dec {
+		int state;
+		u8 header;
+		u32 body;
+		bool toggle;
+		unsigned count;
+		unsigned wanted_bits;
+	} rc6;
+	struct sony_dec {
+		int state;
+		u32 bits;
+		unsigned count;
+	} sony;
+	struct jvc_dec {
+		int state;
+		u16 bits;
+		u16 old_bits;
+		unsigned count;
+		bool first;
+		bool toggle;
+	} jvc;
+	struct lirc_codec {
+		struct ir_input_dev *ir_dev;
+		struct lirc_driver *drv;
+		int lircdata;
+	} lirc;
 };
 
 /* macros for IR decoders */
@@ -74,6 +119,7 @@ void ir_unregister_class(struct input_dev *input_dev);
 /*
  * Routines from ir-raw-event.c to be used internally and by decoders
  */
+u64 ir_raw_get_allowed_protocols(void);
 int ir_raw_event_register(struct input_dev *input_dev);
 void ir_raw_event_unregister(struct input_dev *input_dev);
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
@@ -123,4 +169,12 @@ void ir_raw_init(void);
 #define load_sony_decode()	0
 #endif
 
+/* from ir-lirc-codec.c */
+#ifdef CONFIG_IR_LIRC_CODEC_MODULE
+#define load_lirc_codec()	request_module("ir-lirc-codec")
+#else
+#define load_lirc_codec()	0
+#endif
+
+
 #endif /* _IR_RAW_EVENT */

+ 9 - 143
drivers/media/IR/ir-jvc-decoder.c

@@ -25,10 +25,6 @@
 #define JVC_TRAILER_PULSE	(1  * JVC_UNIT)
 #define	JVC_TRAILER_SPACE	(35 * JVC_UNIT)
 
-/* Used to register jvc_decoder clients */
-static LIST_HEAD(decoder_list);
-DEFINE_SPINLOCK(decoder_lock);
-
 enum jvc_state {
 	STATE_INACTIVE,
 	STATE_HEADER_SPACE,
@@ -38,87 +34,6 @@ enum jvc_state {
 	STATE_TRAILER_SPACE,
 };
 
-struct decoder_data {
-	struct list_head	list;
-	struct ir_input_dev	*ir_dev;
-	int			enabled:1;
-
-	/* State machine control */
-	enum jvc_state		state;
-	u16			jvc_bits;
-	u16			jvc_old_bits;
-	unsigned		count;
-	bool			first;
-	bool			toggle;
-};
-
-
-/**
- * get_decoder_data()	- gets decoder data
- * @input_dev:	input device
- *
- * Returns the struct decoder_data that corresponds to a device
- */
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
-{
-	struct decoder_data *data = NULL;
-
-	spin_lock(&decoder_lock);
-	list_for_each_entry(data, &decoder_list, list) {
-		if (data->ir_dev == ir_dev)
-			break;
-	}
-	spin_unlock(&decoder_lock);
-	return data;
-}
-
-static ssize_t store_enabled(struct device *d,
-			     struct device_attribute *mattr,
-			     const char *buf,
-			     size_t len)
-{
-	unsigned long value;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &value) || value > 1)
-		return -EINVAL;
-
-	data->enabled = value;
-
-	return len;
-}
-
-static ssize_t show_enabled(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (data->enabled)
-		return sprintf(buf, "1\n");
-	else
-	return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
-
-static struct attribute *decoder_attributes[] = {
-	&dev_attr_enabled.attr,
-	NULL
-};
-
-static struct attribute_group decoder_attribute_group = {
-	.name	= "jvc_decoder",
-	.attrs	= decoder_attributes,
-};
-
 /**
  * ir_jvc_decode() - Decode one JVC pulse or space
  * @input_dev:	the struct input_dev descriptor of the device
@@ -128,14 +43,10 @@ static struct attribute_group decoder_attribute_group = {
  */
 static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
-	struct decoder_data *data;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct jvc_dec *data = &ir_dev->raw->jvc;
 
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return -EINVAL;
-
-	if (!data->enabled)
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
 		return 0;
 
 	if (IS_RESET(ev)) {
@@ -188,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 		if (ev.pulse)
 			break;
 
-		data->jvc_bits <<= 1;
+		data->bits <<= 1;
 		if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
-			data->jvc_bits |= 1;
+			data->bits |= 1;
 			decrease_duration(&ev, JVC_BIT_1_SPACE);
 		} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
 			decrease_duration(&ev, JVC_BIT_0_SPACE);
@@ -223,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 
 		if (data->first) {
 			u32 scancode;
-			scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
-				   (bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
+			scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
+				   (bitrev8((data->bits >> 0) & 0xff) << 0);
 			IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
 			ir_keydown(input_dev, scancode, data->toggle);
 			data->first = false;
-			data->jvc_old_bits = data->jvc_bits;
-		} else if (data->jvc_bits == data->jvc_old_bits) {
+			data->old_bits = data->bits;
+		} else if (data->bits == data->old_bits) {
 			IR_dprintk(1, "JVC repeat\n");
 			ir_repeat(input_dev);
 		} else {
@@ -249,54 +160,9 @@ out:
 	return -EINVAL;
 }
 
-static int ir_jvc_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct decoder_data *data;
-	int rc;
-
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-	if (rc < 0)
-		return rc;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-		return -ENOMEM;
-	}
-
-	data->ir_dev = ir_dev;
-	data->enabled = 1;
-
-	spin_lock(&decoder_lock);
-	list_add_tail(&data->list, &decoder_list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
-static int ir_jvc_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	static struct decoder_data *data;
-
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return 0;
-
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-
-	spin_lock(&decoder_lock);
-	list_del(&data->list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
 static struct ir_raw_handler jvc_handler = {
+	.protocols	= IR_TYPE_JVC,
 	.decode		= ir_jvc_decode,
-	.raw_register	= ir_jvc_register,
-	.raw_unregister	= ir_jvc_unregister,
 };
 
 static int __init ir_jvc_decode_init(void)

+ 3 - 2
drivers/media/IR/ir-keytable.c

@@ -497,8 +497,9 @@ int __ir_input_register(struct input_dev *input_dev,
 				goto out_event;
 		}
 
-	IR_dprintk(1, "Registered input device on %s for %s remote.\n",
-		   driver_name, rc_tab->name);
+	IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
+		   driver_name, rc_tab->name,
+		   ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : "");
 
 	return 0;
 

+ 278 - 0
drivers/media/IR/ir-lirc-codec.c

@@ -0,0 +1,278 @@
+/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
+ *
+ * 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.
+ */
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+#include <media/ir-core.h>
+#include "ir-core-priv.h"
+
+#define LIRCBUF_SIZE 256
+
+/**
+ * ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
+ *		      lircd userspace daemon for decoding.
+ * @input_dev:	the struct input_dev descriptor of the device
+ * @duration:	the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the lirc interfaces aren't wired up.
+ */
+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);
+
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
+		return 0;
+
+	if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
+		return -EINVAL;
+
+	IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
+		   TO_US(ev.duration), TO_STR(ev.pulse));
+
+	ir_dev->raw->lirc.lircdata += ev.duration / 1000;
+	if (ev.pulse)
+		ir_dev->raw->lirc.lircdata |= PULSE_BIT;
+
+	lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+			  (unsigned char *) &ir_dev->raw->lirc.lircdata);
+	wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
+
+	ir_dev->raw->lirc.lircdata = 0;
+
+	return 0;
+}
+
+static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
+				   size_t n, loff_t *ppos)
+{
+	struct lirc_codec *lirc;
+	struct ir_input_dev *ir_dev;
+	int *txbuf; /* buffer with values to transmit */
+	int ret = 0, count;
+
+	lirc = lirc_get_pdata(file);
+	if (!lirc)
+		return -EFAULT;
+
+	if (n % sizeof(int))
+		return -EINVAL;
+
+	count = n / sizeof(int);
+	if (count > LIRCBUF_SIZE || count % 2 == 0)
+		return -EINVAL;
+
+	txbuf = memdup_user(buf, n);
+	if (IS_ERR(txbuf))
+		return PTR_ERR(txbuf);
+
+	ir_dev = lirc->ir_dev;
+	if (!ir_dev) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (ir_dev->props && ir_dev->props->tx_ir)
+		ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
+
+out:
+	kfree(txbuf);
+	return ret;
+}
+
+static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	struct lirc_codec *lirc;
+	struct ir_input_dev *ir_dev;
+	int ret = 0;
+	void *drv_data;
+	unsigned long val;
+
+	lirc = lirc_get_pdata(filep);
+	if (!lirc)
+		return -EFAULT;
+
+	ir_dev = lirc->ir_dev;
+	if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
+		return -EFAULT;
+
+	drv_data = ir_dev->props->priv;
+
+	switch (cmd) {
+	case LIRC_SET_TRANSMITTER_MASK:
+		ret = get_user(val, (unsigned long *)arg);
+		if (ret)
+			return ret;
+
+		if (ir_dev->props && ir_dev->props->s_tx_mask)
+			ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
+		else
+			return -EINVAL;
+		break;
+
+	case LIRC_SET_SEND_CARRIER:
+		ret = get_user(val, (unsigned long *)arg);
+		if (ret)
+			return ret;
+
+		if (ir_dev->props && ir_dev->props->s_tx_carrier)
+			ir_dev->props->s_tx_carrier(drv_data, (u32)val);
+		else
+			return -EINVAL;
+		break;
+
+	case LIRC_GET_SEND_MODE:
+		val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
+		ret = put_user(val, (unsigned long *)arg);
+		break;
+
+	case LIRC_SET_SEND_MODE:
+		ret = get_user(val, (unsigned long *)arg);
+		if (ret)
+			return ret;
+
+		if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
+			return -EINVAL;
+		break;
+
+	default:
+		return lirc_dev_fop_ioctl(filep, cmd, arg);
+	}
+
+	return ret;
+}
+
+static int ir_lirc_open(void *data)
+{
+	return 0;
+}
+
+static void ir_lirc_close(void *data)
+{
+	return;
+}
+
+static struct file_operations lirc_fops = {
+	.owner		= THIS_MODULE,
+	.write		= ir_lirc_transmit_ir,
+	.unlocked_ioctl	= ir_lirc_ioctl,
+	.read		= lirc_dev_fop_read,
+	.poll		= lirc_dev_fop_poll,
+	.open		= lirc_dev_fop_open,
+	.release	= lirc_dev_fop_close,
+};
+
+static int ir_lirc_register(struct input_dev *input_dev)
+{
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct lirc_driver *drv;
+	struct lirc_buffer *rbuf;
+	int rc = -ENOMEM;
+	unsigned long features;
+
+	drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
+	if (!drv)
+		return rc;
+
+	rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+	if (!rbuf)
+		goto rbuf_alloc_failed;
+
+	rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
+	if (rc)
+		goto rbuf_init_failed;
+
+	features = LIRC_CAN_REC_MODE2;
+	if (ir_dev->props->tx_ir) {
+		features |= LIRC_CAN_SEND_PULSE;
+		if (ir_dev->props->s_tx_mask)
+			features |= LIRC_CAN_SET_TRANSMITTER_MASK;
+		if (ir_dev->props->s_tx_carrier)
+			features |= LIRC_CAN_SET_SEND_CARRIER;
+	}
+
+	snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
+		 ir_dev->driver_name);
+	drv->minor = -1;
+	drv->features = features;
+	drv->data = &ir_dev->raw->lirc;
+	drv->rbuf = rbuf;
+	drv->set_use_inc = &ir_lirc_open;
+	drv->set_use_dec = &ir_lirc_close;
+	drv->code_length = sizeof(struct ir_raw_event) * 8;
+	drv->fops = &lirc_fops;
+	drv->dev = &ir_dev->dev;
+	drv->owner = THIS_MODULE;
+
+	drv->minor = lirc_register_driver(drv);
+	if (drv->minor < 0) {
+		rc = -ENODEV;
+		goto lirc_register_failed;
+	}
+
+	ir_dev->raw->lirc.drv = drv;
+	ir_dev->raw->lirc.ir_dev = ir_dev;
+	ir_dev->raw->lirc.lircdata = PULSE_MASK;
+
+	return 0;
+
+lirc_register_failed:
+rbuf_init_failed:
+	kfree(rbuf);
+rbuf_alloc_failed:
+	kfree(drv);
+
+	return rc;
+}
+
+static int ir_lirc_unregister(struct input_dev *input_dev)
+{
+	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct lirc_codec *lirc = &ir_dev->raw->lirc;
+
+	lirc_unregister_driver(lirc->drv->minor);
+	lirc_buffer_free(lirc->drv->rbuf);
+	kfree(lirc->drv);
+
+	return 0;
+}
+
+static struct ir_raw_handler lirc_handler = {
+	.protocols	= IR_TYPE_LIRC,
+	.decode		= ir_lirc_decode,
+	.raw_register	= ir_lirc_register,
+	.raw_unregister	= ir_lirc_unregister,
+};
+
+static int __init ir_lirc_codec_init(void)
+{
+	ir_raw_handler_register(&lirc_handler);
+
+	printk(KERN_INFO "IR LIRC bridge handler initialized\n");
+	return 0;
+}
+
+static void __exit ir_lirc_codec_exit(void)
+{
+	ir_raw_handler_unregister(&lirc_handler);
+}
+
+module_init(ir_lirc_codec_init);
+module_exit(ir_lirc_codec_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
+MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
+MODULE_DESCRIPTION("LIRC IR handler bridge");

+ 10 - 141
drivers/media/IR/ir-nec-decoder.c

@@ -27,10 +27,6 @@
 #define	NEC_TRAILER_PULSE	(1  * NEC_UNIT)
 #define	NEC_TRAILER_SPACE	(10 * NEC_UNIT) /* even longer in reality */
 
-/* Used to register nec_decoder clients */
-static LIST_HEAD(decoder_list);
-static DEFINE_SPINLOCK(decoder_lock);
-
 enum nec_state {
 	STATE_INACTIVE,
 	STATE_HEADER_SPACE,
@@ -40,84 +36,6 @@ enum nec_state {
 	STATE_TRAILER_SPACE,
 };
 
-struct decoder_data {
-	struct list_head	list;
-	struct ir_input_dev	*ir_dev;
-	int			enabled:1;
-
-	/* State machine control */
-	enum nec_state		state;
-	u32			nec_bits;
-	unsigned		count;
-};
-
-
-/**
- * get_decoder_data()	- gets decoder data
- * @input_dev:	input device
- *
- * Returns the struct decoder_data that corresponds to a device
- */
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
-{
-	struct decoder_data *data = NULL;
-
-	spin_lock(&decoder_lock);
-	list_for_each_entry(data, &decoder_list, list) {
-		if (data->ir_dev == ir_dev)
-			break;
-	}
-	spin_unlock(&decoder_lock);
-	return data;
-}
-
-static ssize_t store_enabled(struct device *d,
-			     struct device_attribute *mattr,
-			     const char *buf,
-			     size_t len)
-{
-	unsigned long value;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &value) || value > 1)
-		return -EINVAL;
-
-	data->enabled = value;
-
-	return len;
-}
-
-static ssize_t show_enabled(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (data->enabled)
-		return sprintf(buf, "1\n");
-	else
-	return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
-
-static struct attribute *decoder_attributes[] = {
-	&dev_attr_enabled.attr,
-	NULL
-};
-
-static struct attribute_group decoder_attribute_group = {
-	.name	= "nec_decoder",
-	.attrs	= decoder_attributes,
-};
-
 /**
  * ir_nec_decode() - Decode one NEC pulse or space
  * @input_dev:	the struct input_dev descriptor of the device
@@ -127,16 +45,12 @@ static struct attribute_group decoder_attribute_group = {
  */
 static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
-	struct decoder_data *data;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct nec_dec *data = &ir_dev->raw->nec;
 	u32 scancode;
 	u8 address, not_address, command, not_command;
 
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return -EINVAL;
-
-	if (!data->enabled)
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
 		return 0;
 
 	if (IS_RESET(ev)) {
@@ -191,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 		if (ev.pulse)
 			break;
 
-		data->nec_bits <<= 1;
+		data->bits <<= 1;
 		if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
-			data->nec_bits |= 1;
+			data->bits |= 1;
 		else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
 			break;
 		data->count++;
@@ -222,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 		if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
 			break;
 
-		address     = bitrev8((data->nec_bits >> 24) & 0xff);
-		not_address = bitrev8((data->nec_bits >> 16) & 0xff);
-		command	    = bitrev8((data->nec_bits >>  8) & 0xff);
-		not_command = bitrev8((data->nec_bits >>  0) & 0xff);
+		address     = bitrev8((data->bits >> 24) & 0xff);
+		not_address = bitrev8((data->bits >> 16) & 0xff);
+		command	    = bitrev8((data->bits >>  8) & 0xff);
+		not_command = bitrev8((data->bits >>  0) & 0xff);
 
 		if ((command ^ not_command) != 0xff) {
 			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
-				   data->nec_bits);
+				   data->bits);
 			break;
 		}
 
@@ -256,54 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 	return -EINVAL;
 }
 
-static int ir_nec_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct decoder_data *data;
-	int rc;
-
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-	if (rc < 0)
-		return rc;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-		return -ENOMEM;
-	}
-
-	data->ir_dev = ir_dev;
-	data->enabled = 1;
-
-	spin_lock(&decoder_lock);
-	list_add_tail(&data->list, &decoder_list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
-static int ir_nec_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	static struct decoder_data *data;
-
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return 0;
-
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-
-	spin_lock(&decoder_lock);
-	list_del(&data->list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
 static struct ir_raw_handler nec_handler = {
+	.protocols	= IR_TYPE_NEC,
 	.decode		= ir_nec_decode,
-	.raw_register	= ir_nec_register,
-	.raw_unregister	= ir_nec_unregister,
 };
 
 static int __init ir_nec_decode_init(void)

+ 93 - 74
drivers/media/IR/ir-raw-event.c

@@ -20,35 +20,13 @@
 /* Define the max number of pulse/space transitions to buffer */
 #define MAX_IR_EVENT_SIZE      512
 
+/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
+static LIST_HEAD(ir_raw_client_list);
+
 /* Used to handle IR raw handler extensions */
-static LIST_HEAD(ir_raw_handler_list);
 static DEFINE_SPINLOCK(ir_raw_handler_lock);
-
-/**
- * RUN_DECODER()	- runs an operation on all IR decoders
- * @ops:	IR raw handler operation to be called
- * @arg:	arguments to be passed to the callback
- *
- * Calls ir_raw_handler::ops for all registered IR handlers. It prevents
- * new decode addition/removal while running, by locking ir_raw_handler_lock
- * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum
- * of the return codes.
- */
-#define RUN_DECODER(ops, ...) ({					    \
-	struct ir_raw_handler		*_ir_raw_handler;		    \
-	int _sumrc = 0, _rc;						    \
-	spin_lock(&ir_raw_handler_lock);				    \
-	list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) {  \
-		if (_ir_raw_handler->ops) {				    \
-			_rc = _ir_raw_handler->ops(__VA_ARGS__);	    \
-			if (_rc < 0)					    \
-				break;					    \
-			_sumrc += _rc;					    \
-		}							    \
-	}								    \
-	spin_unlock(&ir_raw_handler_lock);				    \
-	_sumrc;								    \
-})
+static LIST_HEAD(ir_raw_handler_list);
+static u64 available_protocols;
 
 #ifdef MODULE
 /* Used to load the decoders */
@@ -58,57 +36,17 @@ static struct work_struct wq_load;
 static void ir_raw_event_work(struct work_struct *work)
 {
 	struct ir_raw_event ev;
+	struct ir_raw_handler *handler;
 	struct ir_raw_event_ctrl *raw =
 		container_of(work, struct ir_raw_event_ctrl, rx_work);
 
-	while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
-		RUN_DECODER(decode, raw->input_dev, ev);
-}
-
-int ir_raw_event_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-	int rc;
-
-	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
-	if (!ir->raw)
-		return -ENOMEM;
-
-	ir->raw->input_dev = input_dev;
-	INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
-
-	rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
-			 GFP_KERNEL);
-	if (rc < 0) {
-		kfree(ir->raw);
-		ir->raw = NULL;
-		return rc;
-	}
-
-	rc = RUN_DECODER(raw_register, input_dev);
-	if (rc < 0) {
-		kfifo_free(&ir->raw->kfifo);
-		kfree(ir->raw);
-		ir->raw = NULL;
-		return rc;
+	while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
+		spin_lock(&ir_raw_handler_lock);
+		list_for_each_entry(handler, &ir_raw_handler_list, list)
+			handler->decode(raw->input_dev, ev);
+		spin_unlock(&ir_raw_handler_lock);
+		raw->prev_ev = ev;
 	}
-
-	return rc;
-}
-
-void ir_raw_event_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir = input_get_drvdata(input_dev);
-
-	if (!ir->raw)
-		return;
-
-	cancel_work_sync(&ir->raw->rx_work);
-	RUN_DECODER(raw_unregister, input_dev);
-
-	kfifo_free(&ir->raw->kfifo);
-	kfree(ir->raw);
-	ir->raw = NULL;
 }
 
 /**
@@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev)
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_handle);
 
+/* used internally by the sysfs interface */
+u64
+ir_raw_get_allowed_protocols()
+{
+	u64 protocols;
+	spin_lock(&ir_raw_handler_lock);
+	protocols = available_protocols;
+	spin_unlock(&ir_raw_handler_lock);
+	return protocols;
+}
+
+/*
+ * Used to (un)register raw event clients
+ */
+int ir_raw_event_register(struct input_dev *input_dev)
+{
+	struct ir_input_dev *ir = input_get_drvdata(input_dev);
+	int rc;
+	struct ir_raw_handler *handler;
+
+	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
+	if (!ir->raw)
+		return -ENOMEM;
+
+	ir->raw->input_dev = input_dev;
+	INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
+	ir->raw->enabled_protocols = ~0;
+	rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
+			 GFP_KERNEL);
+	if (rc < 0) {
+		kfree(ir->raw);
+		ir->raw = NULL;
+		return rc;
+	}
+
+	spin_lock(&ir_raw_handler_lock);
+	list_add_tail(&ir->raw->list, &ir_raw_client_list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_register)
+			handler->raw_register(ir->raw->input_dev);
+	spin_unlock(&ir_raw_handler_lock);
+
+	return 0;
+}
+
+void ir_raw_event_unregister(struct input_dev *input_dev)
+{
+	struct ir_input_dev *ir = input_get_drvdata(input_dev);
+	struct ir_raw_handler *handler;
+
+	if (!ir->raw)
+		return;
+
+	cancel_work_sync(&ir->raw->rx_work);
+
+	spin_lock(&ir_raw_handler_lock);
+	list_del(&ir->raw->list);
+	list_for_each_entry(handler, &ir_raw_handler_list, list)
+		if (handler->raw_unregister)
+			handler->raw_unregister(ir->raw->input_dev);
+	spin_unlock(&ir_raw_handler_lock);
+
+	kfifo_free(&ir->raw->kfifo);
+	kfree(ir->raw);
+	ir->raw = NULL;
+}
+
 /*
  * Extension interface - used to register the IR decoders
  */
 
 int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
 {
+	struct ir_raw_event_ctrl *raw;
+
 	spin_lock(&ir_raw_handler_lock);
 	list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
+	if (ir_raw_handler->raw_register)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_register(raw->input_dev);
+	available_protocols |= ir_raw_handler->protocols;
 	spin_unlock(&ir_raw_handler_lock);
+
 	return 0;
 }
 EXPORT_SYMBOL(ir_raw_handler_register);
 
 void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
 {
+	struct ir_raw_event_ctrl *raw;
+
 	spin_lock(&ir_raw_handler_lock);
 	list_del(&ir_raw_handler->list);
+	if (ir_raw_handler->raw_unregister)
+		list_for_each_entry(raw, &ir_raw_client_list, list)
+			ir_raw_handler->raw_unregister(raw->input_dev);
+	available_protocols &= ~ir_raw_handler->protocols;
 	spin_unlock(&ir_raw_handler_lock);
 }
 EXPORT_SYMBOL(ir_raw_handler_unregister);
@@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work)
 	load_rc6_decode();
 	load_jvc_decode();
 	load_sony_decode();
+	load_lirc_codec();
 
 	/* If needed, we may later add some init code. In this case,
 	   it is needed to change the CONFIG_MODULE test at ir-core.h

+ 16 - 151
drivers/media/IR/ir-rc5-decoder.c

@@ -30,10 +30,6 @@
 #define RC5_BIT_END		(1 * RC5_UNIT)
 #define RC5X_SPACE		(4 * RC5_UNIT)
 
-/* Used to register rc5_decoder clients */
-static LIST_HEAD(decoder_list);
-static DEFINE_SPINLOCK(decoder_lock);
-
 enum rc5_state {
 	STATE_INACTIVE,
 	STATE_BIT_START,
@@ -42,87 +38,6 @@ enum rc5_state {
 	STATE_FINISHED,
 };
 
-struct decoder_data {
-	struct list_head	list;
-	struct ir_input_dev	*ir_dev;
-	int			enabled:1;
-
-	/* State machine control */
-	enum rc5_state		state;
-	u32			rc5_bits;
-	struct ir_raw_event	prev_ev;
-	unsigned		count;
-	unsigned		wanted_bits;
-};
-
-
-/**
- * get_decoder_data()	- gets decoder data
- * @input_dev:	input device
- *
- * Returns the struct decoder_data that corresponds to a device
- */
-
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
-{
-	struct decoder_data *data = NULL;
-
-	spin_lock(&decoder_lock);
-	list_for_each_entry(data, &decoder_list, list) {
-		if (data->ir_dev == ir_dev)
-			break;
-	}
-	spin_unlock(&decoder_lock);
-	return data;
-}
-
-static ssize_t store_enabled(struct device *d,
-			     struct device_attribute *mattr,
-			     const char *buf,
-			     size_t len)
-{
-	unsigned long value;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &value) || value > 1)
-		return -EINVAL;
-
-	data->enabled = value;
-
-	return len;
-}
-
-static ssize_t show_enabled(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (data->enabled)
-		return sprintf(buf, "1\n");
-	else
-	return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
-
-static struct attribute *decoder_attributes[] = {
-	&dev_attr_enabled.attr,
-	NULL
-};
-
-static struct attribute_group decoder_attribute_group = {
-	.name	= "rc5_decoder",
-	.attrs	= decoder_attributes,
-};
-
 /**
  * ir_rc5_decode() - Decode one RC-5 pulse or space
  * @input_dev:	the struct input_dev descriptor of the device
@@ -132,17 +47,13 @@ static struct attribute_group decoder_attribute_group = {
  */
 static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
-	struct decoder_data *data;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct rc5_dec *data = &ir_dev->raw->rc5;
 	u8 toggle;
 	u32 scancode;
 
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return -EINVAL;
-
-	if (!data->enabled)
-		return 0;
+        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
+                return 0;
 
 	if (IS_RESET(ev)) {
 		data->state = STATE_INACTIVE;
@@ -176,16 +87,15 @@ again:
 		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
 			break;
 
-		data->rc5_bits <<= 1;
+		data->bits <<= 1;
 		if (!ev.pulse)
-			data->rc5_bits |= 1;
+			data->bits |= 1;
 		data->count++;
-		data->prev_ev = ev;
 		data->state = STATE_BIT_END;
 		return 0;
 
 	case STATE_BIT_END:
-		if (!is_transition(&ev, &data->prev_ev))
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
 			break;
 
 		if (data->count == data->wanted_bits)
@@ -217,11 +127,11 @@ again:
 		if (data->wanted_bits == RC5X_NBITS) {
 			/* RC5X */
 			u8 xdata, command, system;
-			xdata    = (data->rc5_bits & 0x0003F) >> 0;
-			command  = (data->rc5_bits & 0x00FC0) >> 6;
-			system   = (data->rc5_bits & 0x1F000) >> 12;
-			toggle   = (data->rc5_bits & 0x20000) ? 1 : 0;
-			command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
+			xdata    = (data->bits & 0x0003F) >> 0;
+			command  = (data->bits & 0x00FC0) >> 6;
+			system   = (data->bits & 0x1F000) >> 12;
+			toggle   = (data->bits & 0x20000) ? 1 : 0;
+			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 16 | command << 8 | xdata;
 
 			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
@@ -230,10 +140,10 @@ again:
 		} else {
 			/* RC5 */
 			u8 command, system;
-			command  = (data->rc5_bits & 0x0003F) >> 0;
-			system   = (data->rc5_bits & 0x007C0) >> 6;
-			toggle   = (data->rc5_bits & 0x00800) ? 1 : 0;
-			command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
+			command  = (data->bits & 0x0003F) >> 0;
+			system   = (data->bits & 0x007C0) >> 6;
+			toggle   = (data->bits & 0x00800) ? 1 : 0;
+			command += (data->bits & 0x01000) ? 0 : 0x40;
 			scancode = system << 8 | command;
 
 			IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
@@ -252,54 +162,9 @@ out:
 	return -EINVAL;
 }
 
-static int ir_rc5_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct decoder_data *data;
-	int rc;
-
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-	if (rc < 0)
-		return rc;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-		return -ENOMEM;
-	}
-
-	data->ir_dev = ir_dev;
-	data->enabled = 1;
-
-	spin_lock(&decoder_lock);
-	list_add_tail(&data->list, &decoder_list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
-static int ir_rc5_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	static struct decoder_data *data;
-
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return 0;
-
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-
-	spin_lock(&decoder_lock);
-	list_del(&data->list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
 static struct ir_raw_handler rc5_handler = {
+	.protocols	= IR_TYPE_RC5,
 	.decode		= ir_rc5_decode,
-	.raw_register	= ir_rc5_register,
-	.raw_unregister	= ir_rc5_unregister,
 };
 
 static int __init ir_rc5_decode_init(void)

+ 7 - 146
drivers/media/IR/ir-rc6-decoder.c

@@ -36,10 +36,6 @@
 #define RC6_STARTBIT_MASK	0x08	/* for the header bits */
 #define RC6_6A_MCE_TOGGLE_MASK	0x8000	/* for the body bits */
 
-/* Used to register rc6_decoder clients */
-static LIST_HEAD(decoder_list);
-static DEFINE_SPINLOCK(decoder_lock);
-
 enum rc6_mode {
 	RC6_MODE_0,
 	RC6_MODE_6A,
@@ -58,89 +54,8 @@ enum rc6_state {
 	STATE_FINISHED,
 };
 
-struct decoder_data {
-	struct list_head	list;
-	struct ir_input_dev	*ir_dev;
-	int			enabled:1;
-
-	/* State machine control */
-	enum rc6_state		state;
-	u8			header;
-	u32			body;
-	struct ir_raw_event	prev_ev;
-	bool			toggle;
-	unsigned		count;
-	unsigned		wanted_bits;
-};
-
-
-/**
- * get_decoder_data()	- gets decoder data
- * @input_dev:	input device
- *
- * Returns the struct decoder_data that corresponds to a device
- */
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
-{
-	struct decoder_data *data = NULL;
-
-	spin_lock(&decoder_lock);
-	list_for_each_entry(data, &decoder_list, list) {
-		if (data->ir_dev == ir_dev)
-			break;
-	}
-	spin_unlock(&decoder_lock);
-	return data;
-}
-
-static ssize_t store_enabled(struct device *d,
-			     struct device_attribute *mattr,
-			     const char *buf,
-			     size_t len)
+static enum rc6_mode rc6_mode(struct rc6_dec *data)
 {
-	unsigned long value;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &value) || value > 1)
-		return -EINVAL;
-
-	data->enabled = value;
-
-	return len;
-}
-
-static ssize_t show_enabled(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (data->enabled)
-		return sprintf(buf, "1\n");
-	else
-	return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
-
-static struct attribute *decoder_attributes[] = {
-	&dev_attr_enabled.attr,
-	NULL
-};
-
-static struct attribute_group decoder_attribute_group = {
-	.name	= "rc6_decoder",
-	.attrs	= decoder_attributes,
-};
-
-static enum rc6_mode rc6_mode(struct decoder_data *data) {
 	switch (data->header & RC6_MODE_MASK) {
 	case 0:
 		return RC6_MODE_0;
@@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
  */
 static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
-	struct decoder_data *data;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct rc6_dec *data = &ir_dev->raw->rc6;
 	u32 scancode;
 	u8 toggle;
 
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return -EINVAL;
-
-	if (!data->enabled)
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
 		return 0;
 
 	if (IS_RESET(ev)) {
@@ -223,12 +134,11 @@ again:
 		if (ev.pulse)
 			data->header |= 1;
 		data->count++;
-		data->prev_ev = ev;
 		data->state = STATE_HEADER_BIT_END;
 		return 0;
 
 	case STATE_HEADER_BIT_END:
-		if (!is_transition(&ev, &data->prev_ev))
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
 			break;
 
 		if (data->count == RC6_HEADER_NBITS)
@@ -244,12 +154,11 @@ again:
 			break;
 
 		data->toggle = ev.pulse;
-		data->prev_ev = ev;
 		data->state = STATE_TOGGLE_END;
 		return 0;
 
 	case STATE_TOGGLE_END:
-		if (!is_transition(&ev, &data->prev_ev) ||
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
 		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
 			break;
 
@@ -259,7 +168,6 @@ again:
 		}
 
 		data->state = STATE_BODY_BIT_START;
-		data->prev_ev = ev;
 		decrease_duration(&ev, RC6_TOGGLE_END);
 		data->count = 0;
 
@@ -291,13 +199,11 @@ again:
 		if (ev.pulse)
 			data->body |= 1;
 		data->count++;
-		data->prev_ev = ev;
-
 		data->state = STATE_BODY_BIT_END;
 		return 0;
 
 	case STATE_BODY_BIT_END:
-		if (!is_transition(&ev, &data->prev_ev))
+		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
 			break;
 
 		if (data->count == data->wanted_bits)
@@ -348,54 +254,9 @@ out:
 	return -EINVAL;
 }
 
-static int ir_rc6_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct decoder_data *data;
-	int rc;
-
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-	if (rc < 0)
-		return rc;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-		return -ENOMEM;
-	}
-
-	data->ir_dev = ir_dev;
-	data->enabled = 1;
-
-	spin_lock(&decoder_lock);
-	list_add_tail(&data->list, &decoder_list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
-static int ir_rc6_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	static struct decoder_data *data;
-
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return 0;
-
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-
-	spin_lock(&decoder_lock);
-	list_del(&data->list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
 static struct ir_raw_handler rc6_handler = {
+	.protocols	= IR_TYPE_RC6,
 	.decode		= ir_rc6_decode,
-	.raw_register	= ir_rc6_register,
-	.raw_unregister	= ir_rc6_unregister,
 };
 
 static int __init ir_rc6_decode_init(void)

+ 12 - 143
drivers/media/IR/ir-sony-decoder.c

@@ -23,10 +23,6 @@
 #define SONY_BIT_SPACE		(1 * SONY_UNIT)
 #define SONY_TRAILER_SPACE	(10 * SONY_UNIT) /* minimum */
 
-/* Used to register sony_decoder clients */
-static LIST_HEAD(decoder_list);
-static DEFINE_SPINLOCK(decoder_lock);
-
 enum sony_state {
 	STATE_INACTIVE,
 	STATE_HEADER_SPACE,
@@ -35,84 +31,6 @@ enum sony_state {
 	STATE_FINISHED,
 };
 
-struct decoder_data {
-	struct list_head	list;
-	struct ir_input_dev	*ir_dev;
-	int			enabled:1;
-
-	/* State machine control */
-	enum sony_state		state;
-	u32			sony_bits;
-	unsigned		count;
-};
-
-
-/**
- * get_decoder_data()	- gets decoder data
- * @input_dev:	input device
- *
- * Returns the struct decoder_data that corresponds to a device
- */
-static struct decoder_data *get_decoder_data(struct  ir_input_dev *ir_dev)
-{
-	struct decoder_data *data = NULL;
-
-	spin_lock(&decoder_lock);
-	list_for_each_entry(data, &decoder_list, list) {
-		if (data->ir_dev == ir_dev)
-			break;
-	}
-	spin_unlock(&decoder_lock);
-	return data;
-}
-
-static ssize_t store_enabled(struct device *d,
-			     struct device_attribute *mattr,
-			     const char *buf,
-			     size_t len)
-{
-	unsigned long value;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (strict_strtoul(buf, 10, &value) || value > 1)
-		return -EINVAL;
-
-	data->enabled = value;
-
-	return len;
-}
-
-static ssize_t show_enabled(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	struct decoder_data *data = get_decoder_data(ir_dev);
-
-	if (!data)
-		return -EINVAL;
-
-	if (data->enabled)
-		return sprintf(buf, "1\n");
-	else
-	return sprintf(buf, "0\n");
-}
-
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
-
-static struct attribute *decoder_attributes[] = {
-	&dev_attr_enabled.attr,
-	NULL
-};
-
-static struct attribute_group decoder_attribute_group = {
-	.name	= "sony_decoder",
-	.attrs	= decoder_attributes,
-};
-
 /**
  * ir_sony_decode() - Decode one Sony pulse or space
  * @input_dev:	the struct input_dev descriptor of the device
@@ -122,16 +40,12 @@ static struct attribute_group decoder_attribute_group = {
  */
 static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 {
-	struct decoder_data *data;
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+	struct sony_dec *data = &ir_dev->raw->sony;
 	u32 scancode;
 	u8 device, subdevice, function;
 
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return -EINVAL;
-
-	if (!data->enabled)
+	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
 		return 0;
 
 	if (IS_RESET(ev)) {
@@ -172,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 		if (!ev.pulse)
 			break;
 
-		data->sony_bits <<= 1;
+		data->bits <<= 1;
 		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
-			data->sony_bits |= 1;
+			data->bits |= 1;
 		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
 			break;
 
@@ -208,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
 
 		switch (data->count) {
 		case 12:
-			device    = bitrev8((data->sony_bits <<  3) & 0xF8);
+			device    = bitrev8((data->bits <<  3) & 0xF8);
 			subdevice = 0;
-			function  = bitrev8((data->sony_bits >>  4) & 0xFE);
+			function  = bitrev8((data->bits >>  4) & 0xFE);
 			break;
 		case 15:
-			device    = bitrev8((data->sony_bits >>  0) & 0xFF);
+			device    = bitrev8((data->bits >>  0) & 0xFF);
 			subdevice = 0;
-			function  = bitrev8((data->sony_bits >>  7) & 0xFD);
+			function  = bitrev8((data->bits >>  7) & 0xFD);
 			break;
 		case 20:
-			device    = bitrev8((data->sony_bits >>  5) & 0xF8);
-			subdevice = bitrev8((data->sony_bits >>  0) & 0xFF);
-			function  = bitrev8((data->sony_bits >> 12) & 0xFE);
+			device    = bitrev8((data->bits >>  5) & 0xF8);
+			subdevice = bitrev8((data->bits >>  0) & 0xFF);
+			function  = bitrev8((data->bits >> 12) & 0xFE);
 			break;
 		default:
 			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
@@ -241,54 +155,9 @@ out:
 	return -EINVAL;
 }
 
-static int ir_sony_register(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct decoder_data *data;
-	int rc;
-
-	rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-	if (rc < 0)
-		return rc;
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-		return -ENOMEM;
-	}
-
-	data->ir_dev = ir_dev;
-	data->enabled = 1;
-
-	spin_lock(&decoder_lock);
-	list_add_tail(&data->list, &decoder_list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
-static int ir_sony_unregister(struct input_dev *input_dev)
-{
-	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	static struct decoder_data *data;
-
-	data = get_decoder_data(ir_dev);
-	if (!data)
-		return 0;
-
-	sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
-
-	spin_lock(&decoder_lock);
-	list_del(&data->list);
-	spin_unlock(&decoder_lock);
-
-	return 0;
-}
-
 static struct ir_raw_handler sony_handler = {
+	.protocols	= IR_TYPE_SONY,
 	.decode		= ir_sony_decode,
-	.raw_register	= ir_sony_register,
-	.raw_unregister	= ir_sony_unregister,
 };
 
 static int __init ir_sony_decode_init(void)

+ 143 - 108
drivers/media/IR/ir-sysfs.c

@@ -33,125 +33,172 @@ static struct class ir_input_class = {
 	.devnode	= ir_devnode,
 };
 
+static struct {
+	u64	type;
+	char	*name;
+} proto_names[] = {
+	{ IR_TYPE_UNKNOWN,	"unknown"	},
+	{ IR_TYPE_RC5,		"rc-5"		},
+	{ IR_TYPE_NEC,		"nec"		},
+	{ IR_TYPE_RC6,		"rc-6"		},
+	{ IR_TYPE_JVC,		"jvc"		},
+	{ IR_TYPE_SONY,		"sony"		},
+	{ IR_TYPE_LIRC,		"lirc"		},
+};
+
+#define PROTO_NONE	"none"
+
 /**
- * show_protocol() - shows the current IR protocol
+ * show_protocols() - shows the current IR protocol(s)
  * @d:		the device descriptor
  * @mattr:	the device attribute struct (unused)
  * @buf:	a pointer to the output buffer
  *
- * This routine is a callback routine for input read the IR protocol type.
- * it is trigged by reading /sys/class/rc/rc?/current_protocol.
- * It returns the protocol name, as understood by the driver.
+ * This routine is a callback routine for input read the IR protocol type(s).
+ * it is trigged by reading /sys/class/rc/rc?/protocols.
+ * It returns the protocol names of supported protocols.
+ * Enabled protocols are printed in brackets.
  */
-static ssize_t show_protocol(struct device *d,
-			     struct device_attribute *mattr, char *buf)
+static ssize_t show_protocols(struct device *d,
+			      struct device_attribute *mattr, char *buf)
 {
-	char *s;
 	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	u64 ir_type = ir_dev->rc_tab.ir_type;
-
-	IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type);
-
-	/* FIXME: doesn't support multiple protocols at the same time */
-	if (ir_type == IR_TYPE_UNKNOWN)
-		s = "Unknown";
-	else if (ir_type == IR_TYPE_RC5)
-		s = "rc-5";
-	else if (ir_type == IR_TYPE_NEC)
-		s = "nec";
-	else if (ir_type == IR_TYPE_RC6)
-		s = "rc6";
-	else if (ir_type == IR_TYPE_JVC)
-		s = "jvc";
-	else if (ir_type == IR_TYPE_SONY)
-		s = "sony";
-	else
-		s = "other";
+	u64 allowed, enabled;
+	char *tmp = buf;
+	int i;
+
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+		enabled = ir_dev->rc_tab.ir_type;
+		allowed = ir_dev->props->allowed_protos;
+	} else {
+		enabled = ir_dev->raw->enabled_protocols;
+		allowed = ir_raw_get_allowed_protocols();
+	}
+
+	IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
+		   (long long)allowed,
+		   (long long)enabled);
 
-	return sprintf(buf, "%s\n", s);
+	for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+		if (allowed & enabled & proto_names[i].type)
+			tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
+		else if (allowed & proto_names[i].type)
+			tmp += sprintf(tmp, "%s ", proto_names[i].name);
+	}
+
+	if (tmp != buf)
+		tmp--;
+	*tmp = '\n';
+	return tmp + 1 - buf;
 }
 
 /**
- * store_protocol() - shows the current IR protocol
+ * store_protocols() - changes the current IR protocol(s)
  * @d:		the device descriptor
  * @mattr:	the device attribute struct (unused)
  * @buf:	a pointer to the input buffer
  * @len:	length of the input buffer
  *
  * This routine is a callback routine for changing the IR protocol type.
- * it is trigged by reading /sys/class/rc/rc?/current_protocol.
- * It changes the IR the protocol name, if the IR type is recognized
- * by the driver.
- * If an unknown protocol name is used, returns -EINVAL.
+ * It is trigged by writing to /sys/class/rc/rc?/protocols.
+ * Writing "+proto" will add a protocol to the list of enabled protocols.
+ * Writing "-proto" will remove a protocol from the list of enabled protocols.
+ * Writing "proto" will enable only "proto".
+ * Writing "none" will disable all protocols.
+ * Returns -EINVAL if an invalid protocol combination or unknown protocol name
+ * is used, otherwise @len.
  */
-static ssize_t store_protocol(struct device *d,
-			      struct device_attribute *mattr,
-			      const char *data,
-			      size_t len)
+static ssize_t store_protocols(struct device *d,
+			       struct device_attribute *mattr,
+			       const char *data,
+			       size_t len)
 {
 	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-	u64 ir_type = 0;
-	int rc = -EINVAL;
+	bool enable, disable;
+	const char *tmp;
+	u64 type;
+	u64 mask;
+	int rc, i, count = 0;
 	unsigned long flags;
-	char *buf;
-
-	while ((buf = strsep((char **) &data, " \n")) != NULL) {
-		if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
-			ir_type |= IR_TYPE_RC5;
-		if (!strcasecmp(buf, "nec"))
-			ir_type |= IR_TYPE_NEC;
-		if (!strcasecmp(buf, "jvc"))
-			ir_type |= IR_TYPE_JVC;
-		if (!strcasecmp(buf, "sony"))
-			ir_type |= IR_TYPE_SONY;
+
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
+		type = ir_dev->rc_tab.ir_type;
+	else
+		type = ir_dev->raw->enabled_protocols;
+
+	while ((tmp = strsep((char **) &data, " \n")) != NULL) {
+		if (!*tmp)
+			break;
+
+		if (*tmp == '+') {
+			enable = true;
+			disable = false;
+			tmp++;
+		} else if (*tmp == '-') {
+			enable = false;
+			disable = true;
+			tmp++;
+		} else {
+			enable = false;
+			disable = false;
+		}
+
+		if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
+			tmp += sizeof(PROTO_NONE);
+			mask = 0;
+			count++;
+		} else {
+			for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
+				if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
+					tmp += strlen(proto_names[i].name);
+					mask = proto_names[i].type;
+					break;
+				}
+			}
+			if (i == ARRAY_SIZE(proto_names)) {
+				IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
+				return -EINVAL;
+			}
+			count++;
+		}
+
+		if (enable)
+			type |= mask;
+		else if (disable)
+			type &= ~mask;
+		else
+			type = mask;
 	}
 
-	if (!ir_type) {
-		IR_dprintk(1, "Unknown protocol\n");
+	if (!count) {
+		IR_dprintk(1, "Protocol not specified\n");
 		return -EINVAL;
 	}
 
-	if (ir_dev->props && ir_dev->props->change_protocol)
+	if (ir_dev->props && ir_dev->props->change_protocol) {
 		rc = ir_dev->props->change_protocol(ir_dev->props->priv,
-						    ir_type);
-
-	if (rc < 0) {
-		IR_dprintk(1, "Error setting protocol to %lld\n",
-			   (long long)ir_type);
-		return -EINVAL;
+						    type);
+		if (rc < 0) {
+			IR_dprintk(1, "Error setting protocols to 0x%llx\n",
+				   (long long)type);
+			return -EINVAL;
+		}
 	}
 
-	spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
-	ir_dev->rc_tab.ir_type = ir_type;
-	spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
+	if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
+		spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
+		ir_dev->rc_tab.ir_type = type;
+		spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
+	} else {
+		ir_dev->raw->enabled_protocols = type;
+	}
 
-	IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
-		   (long long)ir_type);
+	IR_dprintk(1, "Current protocol(s): 0x%llx\n",
+		   (long long)type);
 
 	return len;
 }
 
-static ssize_t show_supported_protocols(struct device *d,
-			     struct device_attribute *mattr, char *buf)
-{
-	char *orgbuf = buf;
-	struct ir_input_dev *ir_dev = dev_get_drvdata(d);
-
-	/* FIXME: doesn't support multiple protocols at the same time */
-	if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
-		buf += sprintf(buf, "unknown ");
-	if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
-		buf += sprintf(buf, "rc-5 ");
-	if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
-		buf += sprintf(buf, "nec ");
-	if (buf == orgbuf)
-		buf += sprintf(buf, "other ");
-
-	buf += sprintf(buf - 1, "\n");
-
-	return buf - orgbuf;
-}
-
 #define ADD_HOTPLUG_VAR(fmt, val...)					\
 	do {								\
 		int err = add_uevent_var(env, fmt, val);		\
@@ -159,7 +206,7 @@ static ssize_t show_supported_protocols(struct device *d,
 			return err;					\
 	} while (0)
 
-static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
+static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 {
 	struct ir_input_dev *ir_dev = dev_get_drvdata(device);
 
@@ -174,34 +221,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 /*
  * Static device attribute struct with the sysfs attributes for IR's
  */
-static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
-		   show_protocol, store_protocol);
+static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
+		   show_protocols, store_protocols);
 
-static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
-		   show_supported_protocols, NULL);
-
-static struct attribute *ir_hw_dev_attrs[] = {
-	&dev_attr_protocol.attr,
-	&dev_attr_supported_protocols.attr,
+static struct attribute *rc_dev_attrs[] = {
+	&dev_attr_protocols.attr,
 	NULL,
 };
 
-static struct attribute_group ir_hw_dev_attr_grp = {
-	.attrs	= ir_hw_dev_attrs,
+static struct attribute_group rc_dev_attr_grp = {
+	.attrs	= rc_dev_attrs,
 };
 
-static const struct attribute_group *ir_hw_dev_attr_groups[] = {
-	&ir_hw_dev_attr_grp,
+static const struct attribute_group *rc_dev_attr_groups[] = {
+	&rc_dev_attr_grp,
 	NULL
 };
 
 static struct device_type rc_dev_type = {
-	.groups		= ir_hw_dev_attr_groups,
-	.uevent		= ir_dev_uevent,
-};
-
-static struct device_type ir_raw_dev_type = {
-	.uevent		= ir_dev_uevent,
+	.groups		= rc_dev_attr_groups,
+	.uevent		= rc_dev_uevent,
 };
 
 /**
@@ -221,11 +260,7 @@ int ir_register_class(struct input_dev *input_dev)
 	if (unlikely(devno < 0))
 		return devno;
 
-	if (ir_dev->props) {
-		if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
-			ir_dev->dev.type = &rc_dev_type;
-	} else
-		ir_dev->dev.type = &ir_raw_dev_type;
+	ir_dev->dev.type = &rc_dev_type;
 
 	ir_dev->dev.class = &ir_input_class;
 	ir_dev->dev.parent = input_dev->dev.parent;

+ 4 - 0
drivers/media/IR/keymaps/Makefile

@@ -14,6 +14,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-budget-ci-old.o \
 			rc-cinergy-1400.o \
 			rc-cinergy.o \
+			rc-dib0700-nec.o \
+			rc-dib0700-rc5.o \
 			rc-dm1105-nec.o \
 			rc-dntv-live-dvb-t.o \
 			rc-dntv-live-dvbt-pro.o \
@@ -37,6 +39,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-kaiomy.o \
 			rc-kworld-315u.o \
 			rc-kworld-plus-tv-analog.o \
+			rc-lirc.o \
 			rc-manli.o \
 			rc-msi-tvanywhere.o \
 			rc-msi-tvanywhere-plus.o \
@@ -57,6 +60,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-pv951.o \
 			rc-rc5-hauppauge-new.o \
 			rc-rc5-tv.o \
+			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
 			rc-tbs-nec.o \
 			rc-terratec-cinergy-xs.o \

+ 124 - 0
drivers/media/IR/keymaps/rc-dib0700-nec.c

@@ -0,0 +1,124 @@
+/* rc-dvb0700-big.c - Keytable for devices in dvb0700
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * TODO: This table is a real mess, as it merges RC codes from several
+ * devices into a big table. It also has both RC-5 and NEC codes inside.
+ * It should be broken into small tables, and the protocols should properly
+ * be indentificated.
+ *
+ * The table were imported from dib0700_devices.c.
+ *
+ * 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 dib0700_nec_table[] = {
+	/* Key codes for the Pixelview SBTVD remote */
+	{ 0x8613, KEY_MUTE },
+	{ 0x8612, KEY_POWER },
+	{ 0x8601, KEY_1 },
+	{ 0x8602, KEY_2 },
+	{ 0x8603, KEY_3 },
+	{ 0x8604, KEY_4 },
+	{ 0x8605, KEY_5 },
+	{ 0x8606, KEY_6 },
+	{ 0x8607, KEY_7 },
+	{ 0x8608, KEY_8 },
+	{ 0x8609, KEY_9 },
+	{ 0x8600, KEY_0 },
+	{ 0x860d, KEY_CHANNELUP },
+	{ 0x8619, KEY_CHANNELDOWN },
+	{ 0x8610, KEY_VOLUMEUP },
+	{ 0x860c, KEY_VOLUMEDOWN },
+
+	{ 0x860a, KEY_CAMERA },
+	{ 0x860b, KEY_ZOOM },
+	{ 0x861b, KEY_BACKSPACE },
+	{ 0x8615, KEY_ENTER },
+
+	{ 0x861d, KEY_UP },
+	{ 0x861e, KEY_DOWN },
+	{ 0x860e, KEY_LEFT },
+	{ 0x860f, KEY_RIGHT },
+
+	{ 0x8618, KEY_RECORD },
+	{ 0x861a, KEY_STOP },
+
+	/* Key codes for the EvolutePC TVWay+ remote */
+	{ 0x7a00, KEY_MENU },
+	{ 0x7a01, KEY_RECORD },
+	{ 0x7a02, KEY_PLAY },
+	{ 0x7a03, KEY_STOP },
+	{ 0x7a10, KEY_CHANNELUP },
+	{ 0x7a11, KEY_CHANNELDOWN },
+	{ 0x7a12, KEY_VOLUMEUP },
+	{ 0x7a13, KEY_VOLUMEDOWN },
+	{ 0x7a40, KEY_POWER },
+	{ 0x7a41, KEY_MUTE },
+
+	/* Key codes for the Elgato EyeTV Diversity silver remote */
+	{ 0x4501, KEY_POWER },
+	{ 0x4502, KEY_MUTE },
+	{ 0x4503, KEY_1 },
+	{ 0x4504, KEY_2 },
+	{ 0x4505, KEY_3 },
+	{ 0x4506, KEY_4 },
+	{ 0x4507, KEY_5 },
+	{ 0x4508, KEY_6 },
+	{ 0x4509, KEY_7 },
+	{ 0x450a, KEY_8 },
+	{ 0x450b, KEY_9 },
+	{ 0x450c, KEY_LAST },
+	{ 0x450d, KEY_0 },
+	{ 0x450e, KEY_ENTER },
+	{ 0x450f, KEY_RED },
+	{ 0x4510, KEY_CHANNELUP },
+	{ 0x4511, KEY_GREEN },
+	{ 0x4512, KEY_VOLUMEDOWN },
+	{ 0x4513, KEY_OK },
+	{ 0x4514, KEY_VOLUMEUP },
+	{ 0x4515, KEY_YELLOW },
+	{ 0x4516, KEY_CHANNELDOWN },
+	{ 0x4517, KEY_BLUE },
+	{ 0x4518, KEY_LEFT }, /* Skip backwards */
+	{ 0x4519, KEY_PLAYPAUSE },
+	{ 0x451a, KEY_RIGHT }, /* Skip forward */
+	{ 0x451b, KEY_REWIND },
+	{ 0x451c, KEY_L }, /* Live */
+	{ 0x451d, KEY_FASTFORWARD },
+	{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
+	{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
+	{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
+	{ 0x4541, KEY_SCREEN }, /*  Full screen toggle, 'Hold' for Teletext */
+	{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
+};
+
+static struct rc_keymap dib0700_nec_map = {
+	.map = {
+		.scan    = dib0700_nec_table,
+		.size    = ARRAY_SIZE(dib0700_nec_table),
+		.ir_type = IR_TYPE_NEC,
+		.name    = RC_MAP_DIB0700_NEC_TABLE,
+	}
+};
+
+static int __init init_rc_map(void)
+{
+	return ir_register_map(&dib0700_nec_map);
+}
+
+static void __exit exit_rc_map(void)
+{
+	ir_unregister_map(&dib0700_nec_map);
+}
+
+module_init(init_rc_map)
+module_exit(exit_rc_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");

+ 235 - 0
drivers/media/IR/keymaps/rc-dib0700-rc5.c

@@ -0,0 +1,235 @@
+/* rc-dvb0700-big.c - Keytable for devices in dvb0700
+ *
+ * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ * TODO: This table is a real mess, as it merges RC codes from several
+ * devices into a big table. It also has both RC-5 and NEC codes inside.
+ * It should be broken into small tables, and the protocols should properly
+ * be indentificated.
+ *
+ * The table were imported from dib0700_devices.c.
+ *
+ * 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 dib0700_rc5_table[] = {
+	/* Key codes for the tiny Pinnacle remote*/
+	{ 0x0700, KEY_MUTE },
+	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
+	{ 0x0739, KEY_POWER },
+	{ 0x0703, KEY_VOLUMEUP },
+	{ 0x0709, KEY_VOLUMEDOWN },
+	{ 0x0706, KEY_CHANNELUP },
+	{ 0x070c, KEY_CHANNELDOWN },
+	{ 0x070f, KEY_1 },
+	{ 0x0715, KEY_2 },
+	{ 0x0710, KEY_3 },
+	{ 0x0718, KEY_4 },
+	{ 0x071b, KEY_5 },
+	{ 0x071e, KEY_6 },
+	{ 0x0711, KEY_7 },
+	{ 0x0721, KEY_8 },
+	{ 0x0712, KEY_9 },
+	{ 0x0727, KEY_0 },
+	{ 0x0724, KEY_SCREEN }, /* 'Square' key */
+	{ 0x072a, KEY_TEXT },   /* 'T' key */
+	{ 0x072d, KEY_REWIND },
+	{ 0x0730, KEY_PLAY },
+	{ 0x0733, KEY_FASTFORWARD },
+	{ 0x0736, KEY_RECORD },
+	{ 0x073c, KEY_STOP },
+	{ 0x073f, KEY_CANCEL }, /* '?' key */
+
+	/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
+	{ 0xeb01, KEY_POWER },
+	{ 0xeb02, KEY_1 },
+	{ 0xeb03, KEY_2 },
+	{ 0xeb04, KEY_3 },
+	{ 0xeb05, KEY_4 },
+	{ 0xeb06, KEY_5 },
+	{ 0xeb07, KEY_6 },
+	{ 0xeb08, KEY_7 },
+	{ 0xeb09, KEY_8 },
+	{ 0xeb0a, KEY_9 },
+	{ 0xeb0b, KEY_VIDEO },
+	{ 0xeb0c, KEY_0 },
+	{ 0xeb0d, KEY_REFRESH },
+	{ 0xeb0f, KEY_EPG },
+	{ 0xeb10, KEY_UP },
+	{ 0xeb11, KEY_LEFT },
+	{ 0xeb12, KEY_OK },
+	{ 0xeb13, KEY_RIGHT },
+	{ 0xeb14, KEY_DOWN },
+	{ 0xeb16, KEY_INFO },
+	{ 0xeb17, KEY_RED },
+	{ 0xeb18, KEY_GREEN },
+	{ 0xeb19, KEY_YELLOW },
+	{ 0xeb1a, KEY_BLUE },
+	{ 0xeb1b, KEY_CHANNELUP },
+	{ 0xeb1c, KEY_VOLUMEUP },
+	{ 0xeb1d, KEY_MUTE },
+	{ 0xeb1e, KEY_VOLUMEDOWN },
+	{ 0xeb1f, KEY_CHANNELDOWN },
+	{ 0xeb40, KEY_PAUSE },
+	{ 0xeb41, KEY_HOME },
+	{ 0xeb42, KEY_MENU }, /* DVD Menu */
+	{ 0xeb43, KEY_SUBTITLE },
+	{ 0xeb44, KEY_TEXT }, /* Teletext */
+	{ 0xeb45, KEY_DELETE },
+	{ 0xeb46, KEY_TV },
+	{ 0xeb47, KEY_DVD },
+	{ 0xeb48, KEY_STOP },
+	{ 0xeb49, KEY_VIDEO },
+	{ 0xeb4a, KEY_AUDIO }, /* Music */
+	{ 0xeb4b, KEY_SCREEN }, /* Pic */
+	{ 0xeb4c, KEY_PLAY },
+	{ 0xeb4d, KEY_BACK },
+	{ 0xeb4e, KEY_REWIND },
+	{ 0xeb4f, KEY_FASTFORWARD },
+	{ 0xeb54, KEY_PREVIOUS },
+	{ 0xeb58, KEY_RECORD },
+	{ 0xeb5c, KEY_NEXT },
+
+	/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e01, KEY_1 },
+	{ 0x1e02, KEY_2 },
+	{ 0x1e03, KEY_3 },
+	{ 0x1e04, KEY_4 },
+	{ 0x1e05, KEY_5 },
+	{ 0x1e06, KEY_6 },
+	{ 0x1e07, KEY_7 },
+	{ 0x1e08, KEY_8 },
+	{ 0x1e09, KEY_9 },
+	{ 0x1e0a, KEY_KPASTERISK },
+	{ 0x1e0b, KEY_RED },
+	{ 0x1e0c, KEY_RADIO },
+	{ 0x1e0d, KEY_MENU },
+	{ 0x1e0e, KEY_GRAVE }, /* # */
+	{ 0x1e0f, KEY_MUTE },
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+	{ 0x1e12, KEY_CHANNEL },
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e18, KEY_VIDEO },
+	{ 0x1e19, KEY_AUDIO },
+	{ 0x1e1a, KEY_MEDIA },
+	{ 0x1e1b, KEY_EPG },
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e1e, KEY_NEXT },
+	{ 0x1e1f, KEY_BACK },
+	{ 0x1e20, KEY_CHANNELUP },
+	{ 0x1e21, KEY_CHANNELDOWN },
+	{ 0x1e24, KEY_LAST }, /* Skip backwards */
+	{ 0x1e25, KEY_OK },
+	{ 0x1e29, KEY_BLUE},
+	{ 0x1e2e, KEY_GREEN },
+	{ 0x1e30, KEY_PAUSE },
+	{ 0x1e32, KEY_REWIND },
+	{ 0x1e34, KEY_FASTFORWARD },
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e36, KEY_STOP },
+	{ 0x1e37, KEY_RECORD },
+	{ 0x1e38, KEY_YELLOW },
+	{ 0x1e3b, KEY_GOTO },
+	{ 0x1e3d, KEY_POWER },
+
+	/* Key codes for the Leadtek Winfast DTV Dongle */
+	{ 0x0042, KEY_POWER },
+	{ 0x077c, KEY_TUNER },
+	{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
+	{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
+	{ 0x0f71, KEY_DOT }, /* frequency */
+	{ 0x0743, KEY_0 },
+	{ 0x0c41, KEY_1 },
+	{ 0x0443, KEY_2 },
+	{ 0x0b7f, KEY_3 },
+	{ 0x0e41, KEY_4 },
+	{ 0x0643, KEY_5 },
+	{ 0x097f, KEY_6 },
+	{ 0x0d7e, KEY_7 },
+	{ 0x057c, KEY_8 },
+	{ 0x0a40, KEY_9 },
+	{ 0x0e4e, KEY_CLEAR },
+	{ 0x047c, KEY_CHANNEL }, /* show channel number */
+	{ 0x0f41, KEY_LAST }, /* recall */
+	{ 0x0342, KEY_MUTE },
+	{ 0x064c, KEY_RESERVED }, /* PIP button*/
+	{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
+	{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
+	{ 0x0b70, KEY_RECORD },
+	{ 0x037d, KEY_VOLUMEUP },
+	{ 0x017d, KEY_VOLUMEDOWN },
+	{ 0x0242, KEY_CHANNELUP },
+	{ 0x007d, KEY_CHANNELDOWN },
+
+	/* Key codes for Nova-TD "credit card" remote control. */
+	{ 0x1d00, KEY_0 },
+	{ 0x1d01, KEY_1 },
+	{ 0x1d02, KEY_2 },
+	{ 0x1d03, KEY_3 },
+	{ 0x1d04, KEY_4 },
+	{ 0x1d05, KEY_5 },
+	{ 0x1d06, KEY_6 },
+	{ 0x1d07, KEY_7 },
+	{ 0x1d08, KEY_8 },
+	{ 0x1d09, KEY_9 },
+	{ 0x1d0a, KEY_TEXT },
+	{ 0x1d0d, KEY_MENU },
+	{ 0x1d0f, KEY_MUTE },
+	{ 0x1d10, KEY_VOLUMEUP },
+	{ 0x1d11, KEY_VOLUMEDOWN },
+	{ 0x1d12, KEY_CHANNEL },
+	{ 0x1d14, KEY_UP },
+	{ 0x1d15, KEY_DOWN },
+	{ 0x1d16, KEY_LEFT },
+	{ 0x1d17, KEY_RIGHT },
+	{ 0x1d1c, KEY_TV },
+	{ 0x1d1e, KEY_NEXT },
+	{ 0x1d1f, KEY_BACK },
+	{ 0x1d20, KEY_CHANNELUP },
+	{ 0x1d21, KEY_CHANNELDOWN },
+	{ 0x1d24, KEY_LAST },
+	{ 0x1d25, KEY_OK },
+	{ 0x1d30, KEY_PAUSE },
+	{ 0x1d32, KEY_REWIND },
+	{ 0x1d34, KEY_FASTFORWARD },
+	{ 0x1d35, KEY_PLAY },
+	{ 0x1d36, KEY_STOP },
+	{ 0x1d37, KEY_RECORD },
+	{ 0x1d3b, KEY_GOTO },
+	{ 0x1d3d, KEY_POWER },
+};
+
+static struct rc_keymap dib0700_rc5_map = {
+	.map = {
+		.scan    = dib0700_rc5_table,
+		.size    = ARRAY_SIZE(dib0700_rc5_table),
+		.ir_type = IR_TYPE_RC5,
+		.name    = RC_MAP_DIB0700_RC5_TABLE,
+	}
+};
+
+static int __init init_rc_map(void)
+{
+	return ir_register_map(&dib0700_rc5_map);
+}
+
+static void __exit exit_rc_map(void)
+{
+	ir_unregister_map(&dib0700_rc5_map);
+}
+
+module_init(init_rc_map)
+module_exit(exit_rc_map)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");

+ 41 - 0
drivers/media/IR/keymaps/rc-lirc.c

@@ -0,0 +1,41 @@
+/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
+ * all raw IR data to the lirc userspace decoder.
+ *
+ * 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/ir-core.h>
+
+static struct ir_scancode lirc[] = {
+	{ },
+};
+
+static struct rc_keymap lirc_map = {
+	.map = {
+		.scan    = lirc,
+		.size    = ARRAY_SIZE(lirc),
+		.ir_type = IR_TYPE_LIRC,
+		.name    = RC_MAP_LIRC,
+	}
+};
+
+static int __init init_rc_map_lirc(void)
+{
+	return ir_register_map(&lirc_map);
+}
+
+static void __exit exit_rc_map_lirc(void)
+{
+	ir_unregister_map(&lirc_map);
+}
+
+module_init(init_rc_map_lirc)
+module_exit(exit_rc_map_lirc)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

+ 105 - 0
drivers/media/IR/keymaps/rc-rc6-mce.c

@@ -0,0 +1,105 @@
+/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
+ * with the Media Center Edition eHome Infrared Transceiver.
+ *
+ * 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 rc6_mce[] = {
+	{ 0x800f0415, KEY_REWIND },
+	{ 0x800f0414, KEY_FASTFORWARD },
+	{ 0x800f041b, KEY_PREVIOUS },
+	{ 0x800f041a, KEY_NEXT },
+
+	{ 0x800f0416, KEY_PLAY },
+	{ 0x800f0418, KEY_PAUSE },
+	{ 0x800f0419, KEY_STOP },
+	{ 0x800f0417, KEY_RECORD },
+
+	{ 0x800f041e, KEY_UP },
+	{ 0x800f041f, KEY_DOWN },
+	{ 0x800f0420, KEY_LEFT },
+	{ 0x800f0421, KEY_RIGHT },
+
+	{ 0x800f040b, KEY_ENTER },
+	{ 0x800f0422, KEY_OK },
+	{ 0x800f0423, KEY_EXIT },
+	{ 0x800f040a, KEY_DELETE },
+
+	{ 0x800f040e, KEY_MUTE },
+	{ 0x800f0410, KEY_VOLUMEUP },
+	{ 0x800f0411, KEY_VOLUMEDOWN },
+	{ 0x800f0412, KEY_CHANNELUP },
+	{ 0x800f0413, KEY_CHANNELDOWN },
+
+	{ 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 },
+	{ 0x800f0447, KEY_AUDIO }, /* My Music */
+	{ 0x800f0448, KEY_PVR }, /* RecordedTV */
+	{ 0x800f0449, KEY_CAMERA },
+	{ 0x800f044a, KEY_VIDEO },
+	{ 0x800f0424, KEY_DVD },
+	{ 0x800f0425, KEY_TUNER }, /* LiveTV */
+	{ 0x800f0450, KEY_RADIO },
+
+	{ 0x800f044c, KEY_LANGUAGE },
+	{ 0x800f0427, KEY_ZOOM }, /* Aspect */
+
+	{ 0x800f045b, KEY_RED },
+	{ 0x800f045c, KEY_GREEN },
+	{ 0x800f045d, KEY_YELLOW },
+	{ 0x800f045e, KEY_BLUE },
+
+	{ 0x800f040f, KEY_INFO },
+	{ 0x800f0426, KEY_EPG }, /* Guide */
+	{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
+	{ 0x800f044d, KEY_TITLE },
+
+	{ 0x800f040c, KEY_POWER },
+	{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
+
+};
+
+static struct rc_keymap rc6_mce_map = {
+	.map = {
+		.scan    = rc6_mce,
+		.size    = ARRAY_SIZE(rc6_mce),
+		.ir_type = IR_TYPE_RC6,
+		.name    = RC_MAP_RC6_MCE,
+	}
+};
+
+static int __init init_rc_map_rc6_mce(void)
+{
+	return ir_register_map(&rc6_mce_map);
+}
+
+static void __exit exit_rc_map_rc6_mce(void)
+{
+	ir_unregister_map(&rc6_mce_map);
+}
+
+module_init(init_rc_map_rc6_mce)
+module_exit(exit_rc_map_rc6_mce)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

+ 764 - 0
drivers/media/IR/lirc_dev.c

@@ -0,0 +1,764 @@
+/*
+ * LIRC base driver
+ *
+ * by Artur Lipowski <alipowski@interia.pl>
+ *
+ *  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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/completion.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/unistd.h>
+#include <linux/kthread.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+
+static int debug;
+
+#define IRCTL_DEV_NAME	"BaseRemoteCtl"
+#define NOPLUG		-1
+#define LOGHEAD		"lirc_dev (%s[%d]): "
+
+static dev_t lirc_base_dev;
+
+struct irctl {
+	struct lirc_driver d;
+	int attached;
+	int open;
+
+	struct mutex irctl_lock;
+	struct lirc_buffer *buf;
+	unsigned int chunk_size;
+
+	struct task_struct *task;
+	long jiffies_to_wait;
+
+	struct cdev cdev;
+};
+
+static DEFINE_MUTEX(lirc_dev_lock);
+
+static struct irctl *irctls[MAX_IRCTL_DEVICES];
+
+/* Only used for sysfs but defined to void otherwise */
+static struct class *lirc_class;
+
+/*  helper function
+ *  initializes the irctl structure
+ */
+static void init_irctl(struct irctl *ir)
+{
+	dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
+		ir->d.name, ir->d.minor);
+	mutex_init(&ir->irctl_lock);
+	ir->d.minor = NOPLUG;
+}
+
+static void cleanup(struct irctl *ir)
+{
+	dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
+
+	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+
+	if (ir->buf != ir->d.rbuf) {
+		lirc_buffer_free(ir->buf);
+		kfree(ir->buf);
+	}
+	ir->buf = NULL;
+}
+
+/*  helper function
+ *  reads key codes from driver and puts them into buffer
+ *  returns 0 on success
+ */
+static int add_to_buf(struct irctl *ir)
+{
+	if (ir->d.add_to_buf) {
+		int res = -ENODATA;
+		int got_data = 0;
+
+		/*
+		 * service the device as long as it is returning
+		 * data and we have space
+		 */
+get_data:
+		res = ir->d.add_to_buf(ir->d.data, ir->buf);
+		if (res == 0) {
+			got_data++;
+			goto get_data;
+		}
+
+		if (res == -ENODEV)
+			kthread_stop(ir->task);
+
+		return got_data ? 0 : res;
+	}
+
+	return 0;
+}
+
+/* main function of the polling thread
+ */
+static int lirc_thread(void *irctl)
+{
+	struct irctl *ir = irctl;
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
+		ir->d.name, ir->d.minor);
+
+	do {
+		if (ir->open) {
+			if (ir->jiffies_to_wait) {
+				set_current_state(TASK_INTERRUPTIBLE);
+				schedule_timeout(ir->jiffies_to_wait);
+			}
+			if (kthread_should_stop())
+				break;
+			if (!add_to_buf(ir))
+				wake_up_interruptible(&ir->buf->wait_poll);
+		} else {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule();
+		}
+	} while (!kthread_should_stop());
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
+		ir->d.name, ir->d.minor);
+
+	return 0;
+}
+
+
+static struct file_operations fops = {
+	.owner		= THIS_MODULE,
+	.read		= lirc_dev_fop_read,
+	.write		= lirc_dev_fop_write,
+	.poll		= lirc_dev_fop_poll,
+	.unlocked_ioctl	= lirc_dev_fop_ioctl,
+	.open		= lirc_dev_fop_open,
+	.release	= lirc_dev_fop_close,
+};
+
+static int lirc_cdev_add(struct irctl *ir)
+{
+	int retval;
+	struct lirc_driver *d = &ir->d;
+
+	if (d->fops) {
+		cdev_init(&ir->cdev, d->fops);
+		ir->cdev.owner = d->owner;
+	} else {
+		cdev_init(&ir->cdev, &fops);
+		ir->cdev.owner = THIS_MODULE;
+	}
+	kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
+
+	retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+	if (retval)
+		kobject_put(&ir->cdev.kobj);
+
+	return retval;
+}
+
+int lirc_register_driver(struct lirc_driver *d)
+{
+	struct irctl *ir;
+	int minor;
+	int bytes_in_key;
+	unsigned int chunk_size;
+	unsigned int buffer_size;
+	int err;
+
+	if (!d) {
+		printk(KERN_ERR "lirc_dev: lirc_register_driver: "
+		       "driver pointer must be not NULL!\n");
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (MAX_IRCTL_DEVICES <= d->minor) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"\"minor\" must be between 0 and %d (%d)!\n",
+			MAX_IRCTL_DEVICES-1, d->minor);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"code length in bits for minor (%d) "
+			"must be less than %d!\n",
+			d->minor, BUFLEN * 8);
+		err = -EBADRQC;
+		goto out;
+	}
+
+	dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
+		d->sample_rate);
+	if (d->sample_rate) {
+		if (2 > d->sample_rate || HZ < d->sample_rate) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"sample_rate must be between 2 and %d!\n", HZ);
+			err = -EBADRQC;
+			goto out;
+		}
+		if (!d->add_to_buf) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"add_to_buf cannot be NULL when "
+				"sample_rate is set\n");
+			err = -EBADRQC;
+			goto out;
+		}
+	} else if (!(d->fops && d->fops->read) && !d->rbuf) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"fops->read and rbuf cannot all be NULL!\n");
+		err = -EBADRQC;
+		goto out;
+	} else if (!d->rbuf) {
+		if (!(d->fops && d->fops->read && d->fops->poll &&
+		      d->fops->unlocked_ioctl)) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"neither read, poll nor unlocked_ioctl can be NULL!\n");
+			err = -EBADRQC;
+			goto out;
+		}
+	}
+
+	mutex_lock(&lirc_dev_lock);
+
+	minor = d->minor;
+
+	if (minor < 0) {
+		/* find first free slot for driver */
+		for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
+			if (!irctls[minor])
+				break;
+		if (MAX_IRCTL_DEVICES == minor) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"no free slots for drivers!\n");
+			err = -ENOMEM;
+			goto out_lock;
+		}
+	} else if (irctls[minor]) {
+		dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+			"minor (%d) just registered!\n", minor);
+		err = -EBUSY;
+		goto out_lock;
+	}
+
+	ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
+	if (!ir) {
+		err = -ENOMEM;
+		goto out_lock;
+	}
+	init_irctl(ir);
+	irctls[minor] = ir;
+	d->minor = minor;
+
+	if (d->sample_rate) {
+		ir->jiffies_to_wait = HZ / d->sample_rate;
+	} else {
+		/* it means - wait for external event in task queue */
+		ir->jiffies_to_wait = 0;
+	}
+
+	/* some safety check 8-) */
+	d->name[sizeof(d->name)-1] = '\0';
+
+	bytes_in_key = BITS_TO_LONGS(d->code_length) +
+			(d->code_length % 8 ? 1 : 0);
+	buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
+	chunk_size  = d->chunk_size  ? d->chunk_size  : bytes_in_key;
+
+	if (d->rbuf) {
+		ir->buf = d->rbuf;
+	} else {
+		ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
+		if (!ir->buf) {
+			err = -ENOMEM;
+			goto out_lock;
+		}
+		err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
+		if (err) {
+			kfree(ir->buf);
+			goto out_lock;
+		}
+	}
+	ir->chunk_size = ir->buf->chunk_size;
+
+	if (d->features == 0)
+		d->features = LIRC_CAN_REC_LIRCCODE;
+
+	ir->d = *d;
+	ir->d.minor = minor;
+
+	device_create(lirc_class, ir->d.dev,
+		      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
+		      "lirc%u", ir->d.minor);
+
+	if (d->sample_rate) {
+		/* try to fire up polling thread */
+		ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
+		if (IS_ERR(ir->task)) {
+			dev_err(d->dev, "lirc_dev: lirc_register_driver: "
+				"cannot run poll thread for minor = %d\n",
+				d->minor);
+			err = -ECHILD;
+			goto out_sysfs;
+		}
+	}
+
+	err = lirc_cdev_add(ir);
+	if (err)
+		goto out_sysfs;
+
+	ir->attached = 1;
+	mutex_unlock(&lirc_dev_lock);
+
+	dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
+		 ir->d.name, ir->d.minor);
+	return minor;
+
+out_sysfs:
+	device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
+out_lock:
+	mutex_unlock(&lirc_dev_lock);
+out:
+	return err;
+}
+EXPORT_SYMBOL(lirc_register_driver);
+
+int lirc_unregister_driver(int minor)
+{
+	struct irctl *ir;
+
+	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);
+		return -EBADRQC;
+	}
+
+	ir = irctls[minor];
+
+	mutex_lock(&lirc_dev_lock);
+
+	if (ir->d.minor != minor) {
+		printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
+		       "minor (%d) device not registered!", minor);
+		mutex_unlock(&lirc_dev_lock);
+		return -ENOENT;
+	}
+
+	/* end up polling thread */
+	if (ir->task)
+		kthread_stop(ir->task);
+
+	dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
+		ir->d.name, ir->d.minor);
+
+	ir->attached = 0;
+	if (ir->open) {
+		dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
+			ir->d.name, ir->d.minor);
+		wake_up_interruptible(&ir->buf->wait_poll);
+		mutex_lock(&ir->irctl_lock);
+		ir->d.set_use_dec(ir->d.data);
+		module_put(ir->d.owner);
+		mutex_unlock(&ir->irctl_lock);
+		cdev_del(&ir->cdev);
+	} else {
+		cleanup(ir);
+		cdev_del(&ir->cdev);
+		kfree(ir);
+		irctls[minor] = NULL;
+	}
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(lirc_unregister_driver);
+
+int lirc_dev_fop_open(struct inode *inode, struct file *file)
+{
+	struct irctl *ir;
+	int retval = 0;
+
+	if (iminor(inode) >= MAX_IRCTL_DEVICES) {
+		printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
+		       iminor(inode));
+		return -ENODEV;
+	}
+
+	if (mutex_lock_interruptible(&lirc_dev_lock))
+		return -ERESTARTSYS;
+
+	ir = irctls[iminor(inode)];
+	if (!ir) {
+		retval = -ENODEV;
+		goto error;
+	}
+	file->private_data = ir;
+
+	dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
+
+	if (ir->d.minor == NOPLUG) {
+		retval = -ENODEV;
+		goto error;
+	}
+
+	if (ir->open) {
+		retval = -EBUSY;
+		goto error;
+	}
+
+	if (try_module_get(ir->d.owner)) {
+		++ir->open;
+		retval = ir->d.set_use_inc(ir->d.data);
+
+		if (retval) {
+			module_put(ir->d.owner);
+			--ir->open;
+		} else {
+			lirc_buffer_clear(ir->buf);
+		}
+		if (ir->task)
+			wake_up_process(ir->task);
+	}
+
+error:
+	if (ir)
+		dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
+			ir->d.name, ir->d.minor, retval);
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return retval;
+}
+EXPORT_SYMBOL(lirc_dev_fop_open);
+
+int lirc_dev_fop_close(struct inode *inode, struct file *file)
+{
+	struct irctl *ir = irctls[iminor(inode)];
+
+	dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
+
+	WARN_ON(mutex_lock_killable(&lirc_dev_lock));
+
+	--ir->open;
+	if (ir->attached) {
+		ir->d.set_use_dec(ir->d.data);
+		module_put(ir->d.owner);
+	} else {
+		cleanup(ir);
+		irctls[ir->d.minor] = NULL;
+		kfree(ir);
+	}
+
+	mutex_unlock(&lirc_dev_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(lirc_dev_fop_close);
+
+unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned int ret;
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
+
+	if (!ir->attached) {
+		mutex_unlock(&ir->irctl_lock);
+		return POLLERR;
+	}
+
+	poll_wait(file, &ir->buf->wait_poll, wait);
+
+	if (ir->buf)
+		if (lirc_buffer_empty(ir->buf))
+			ret = 0;
+		else
+			ret = POLLIN | POLLRDNORM;
+	else
+		ret = POLLERR;
+
+	dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
+		ir->d.name, ir->d.minor, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL(lirc_dev_fop_poll);
+
+long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	unsigned long mode;
+	int result = 0;
+	struct irctl *ir = file->private_data;
+
+	dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
+		ir->d.name, ir->d.minor, cmd);
+
+	if (ir->d.minor == NOPLUG || !ir->attached) {
+		dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
+			ir->d.name, ir->d.minor);
+		return -ENODEV;
+	}
+
+	mutex_lock(&ir->irctl_lock);
+
+	switch (cmd) {
+	case LIRC_GET_FEATURES:
+		result = put_user(ir->d.features, (unsigned long *)arg);
+		break;
+	case LIRC_GET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(LIRC_REC2MODE
+				  (ir->d.features & LIRC_CAN_REC_MASK),
+				  (unsigned long *)arg);
+		break;
+	case LIRC_SET_REC_MODE:
+		if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = get_user(mode, (unsigned long *)arg);
+		if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
+			result = -EINVAL;
+		/*
+		 * FIXME: We should actually set the mode somehow but
+		 * for now, lirc_serial doesn't support mode changing either
+		 */
+		break;
+	case LIRC_GET_LENGTH:
+		result = put_user(ir->d.code_length, (unsigned long *)arg);
+		break;
+	case LIRC_GET_MIN_TIMEOUT:
+		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    ir->d.min_timeout == 0) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(ir->d.min_timeout, (unsigned long *)arg);
+		break;
+	case LIRC_GET_MAX_TIMEOUT:
+		if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
+		    ir->d.max_timeout == 0) {
+			result = -ENOSYS;
+			break;
+		}
+
+		result = put_user(ir->d.max_timeout, (unsigned long *)arg);
+		break;
+	default:
+		result = -EINVAL;
+	}
+
+	dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
+		ir->d.name, ir->d.minor, result);
+
+	mutex_unlock(&ir->irctl_lock);
+
+	return result;
+}
+EXPORT_SYMBOL(lirc_dev_fop_ioctl);
+
+ssize_t lirc_dev_fop_read(struct file *file,
+			  char *buffer,
+			  size_t length,
+			  loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+	unsigned char buf[ir->chunk_size];
+	int ret = 0, written = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
+
+	if (mutex_lock_interruptible(&ir->irctl_lock))
+		return -ERESTARTSYS;
+	if (!ir->attached) {
+		mutex_unlock(&ir->irctl_lock);
+		return -ENODEV;
+	}
+
+	if (length % ir->chunk_size) {
+		dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
+			ir->d.name, ir->d.minor);
+		mutex_unlock(&ir->irctl_lock);
+		return -EINVAL;
+	}
+
+	/*
+	 * we add ourselves to the task queue before buffer check
+	 * to avoid losing scan code (in case when queue is awaken somewhere
+	 * between while condition checking and scheduling)
+	 */
+	add_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	/*
+	 * while we didn't provide 'length' bytes, device is opened in blocking
+	 * mode and 'copy_to_user' is happy, wait for data.
+	 */
+	while (written < length && ret == 0) {
+		if (lirc_buffer_empty(ir->buf)) {
+			/* According to the read(2) man page, 'written' can be
+			 * returned as less than 'length', instead of blocking
+			 * again, returning -EWOULDBLOCK, or returning
+			 * -ERESTARTSYS */
+			if (written)
+				break;
+			if (file->f_flags & O_NONBLOCK) {
+				ret = -EWOULDBLOCK;
+				break;
+			}
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+
+			mutex_unlock(&ir->irctl_lock);
+			schedule();
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (mutex_lock_interruptible(&ir->irctl_lock)) {
+				ret = -ERESTARTSYS;
+				remove_wait_queue(&ir->buf->wait_poll, &wait);
+				set_current_state(TASK_RUNNING);
+				goto out_unlocked;
+			}
+
+			if (!ir->attached) {
+				ret = -ENODEV;
+				break;
+			}
+		} else {
+			lirc_buffer_read(ir->buf, buf);
+			ret = copy_to_user((void *)buffer+written, buf,
+					   ir->buf->chunk_size);
+			written += ir->buf->chunk_size;
+		}
+	}
+
+	remove_wait_queue(&ir->buf->wait_poll, &wait);
+	set_current_state(TASK_RUNNING);
+	mutex_unlock(&ir->irctl_lock);
+
+out_unlocked:
+	dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
+		ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+
+	return ret ? ret : written;
+}
+EXPORT_SYMBOL(lirc_dev_fop_read);
+
+void *lirc_get_pdata(struct file *file)
+{
+	void *data = NULL;
+
+	if (file && file->f_dentry && file->f_dentry->d_inode &&
+	    file->f_dentry->d_inode->i_rdev) {
+		struct irctl *ir;
+		ir = irctls[iminor(file->f_dentry->d_inode)];
+		data = ir->d.data;
+	}
+
+	return data;
+}
+EXPORT_SYMBOL(lirc_get_pdata);
+
+
+ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
+			   size_t length, loff_t *ppos)
+{
+	struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+
+	dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
+
+	if (!ir->attached)
+		return -ENODEV;
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(lirc_dev_fop_write);
+
+
+static int __init lirc_dev_init(void)
+{
+	int retval;
+
+	lirc_class = class_create(THIS_MODULE, "lirc");
+	if (IS_ERR(lirc_class)) {
+		retval = PTR_ERR(lirc_class);
+		printk(KERN_ERR "lirc_dev: class_create failed\n");
+		goto error;
+	}
+
+	retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
+				     IRCTL_DEV_NAME);
+	if (retval) {
+		class_destroy(lirc_class);
+		printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
+		goto error;
+	}
+
+
+	printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
+	       "major %d \n", MAJOR(lirc_base_dev));
+
+error:
+	return retval;
+}
+
+
+
+static void __exit lirc_dev_exit(void)
+{
+	class_destroy(lirc_class);
+	unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
+	printk(KERN_INFO "lirc_dev: module unloaded\n");
+}
+
+module_init(lirc_dev_init);
+module_exit(lirc_dev_exit);
+
+MODULE_DESCRIPTION("LIRC base driver module");
+MODULE_AUTHOR("Artur Lipowski");
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging messages");

+ 1143 - 0
drivers/media/IR/mceusb.c

@@ -0,0 +1,1143 @@
+/*
+ * Driver for USB Windows Media Center Ed. eHome Infrared Transceivers
+ *
+ * Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
+ *
+ * Based on the original lirc_mceusb and lirc_mceusb2 drivers, by Dan
+ * Conti, Martin Blatter and Daniel Melander, the latter of which was
+ * in turn also based on the lirc_atiusb driver by Paul Miller. The
+ * two mce drivers were merged into one by Jarod Wilson, with transmit
+ * support for the 1st-gen device added primarily by Patrick Calhoun,
+ * with a bit of tweaks by Jarod. Debugging improvements and proper
+ * support for what appears to be 3rd-gen hardware added by Jarod.
+ * Initial port from lirc driver to ir-core drivery by Jarod, based
+ * partially on a port to an earlier proposed IR infrastructure by
+ * Jon Smirl, which included enhancements and simplifications to the
+ * incoming IR buffer parsing routines.
+ *
+ *
+ * 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/device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+#include <media/ir-core.h>
+#include <media/ir-common.h>
+
+#define DRIVER_VERSION	"1.91"
+#define DRIVER_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
+#define DRIVER_DESC	"Windows Media Center Ed. eHome Infrared Transceiver " \
+			"device driver"
+#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 */
+
+/* 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 */
+
+
+/* module parameters */
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/* general constants */
+#define SEND_FLAG_IN_PROGRESS	1
+#define SEND_FLAG_COMPLETE	2
+#define RECV_FLAG_IN_PROGRESS	3
+#define RECV_FLAG_COMPLETE	4
+
+#define MCEUSB_RX		1
+#define MCEUSB_TX		2
+
+#define VENDOR_PHILIPS		0x0471
+#define VENDOR_SMK		0x0609
+#define VENDOR_TATUNG		0x1460
+#define VENDOR_GATEWAY		0x107b
+#define VENDOR_SHUTTLE		0x1308
+#define VENDOR_SHUTTLE2		0x051c
+#define VENDOR_MITSUMI		0x03ee
+#define VENDOR_TOPSEED		0x1784
+#define VENDOR_RICAVISION	0x179d
+#define VENDOR_ITRON		0x195d
+#define VENDOR_FIC		0x1509
+#define VENDOR_LG		0x043e
+#define VENDOR_MICROSOFT	0x045e
+#define VENDOR_FORMOSA		0x147a
+#define VENDOR_FINTEK		0x1934
+#define VENDOR_PINNACLE		0x2304
+#define VENDOR_ECS		0x1019
+#define VENDOR_WISTRON		0x0fb8
+#define VENDOR_COMPRO		0x185b
+#define VENDOR_NORTHSTAR	0x04eb
+#define VENDOR_REALTEK		0x0bda
+#define VENDOR_TIVO		0x105a
+
+static struct usb_device_id mceusb_dev_table[] = {
+	/* Original Microsoft MCE IR Transceiver (often HP-branded) */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x006d) },
+	/* Philips Infrared Transceiver - Sahara branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0608) },
+	/* Philips Infrared Transceiver - HP branded */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060c) },
+	/* Philips SRM5100 */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060d) },
+	/* Philips Infrared Transceiver - Omaura */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x060f) },
+	/* Philips Infrared Transceiver - Spinel plus */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0613) },
+	/* Philips eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x0815) },
+	/* Realtek MCE IR Receiver */
+	{ USB_DEVICE(VENDOR_REALTEK, 0x0161) },
+	/* SMK/Toshiba G83C0004D410 */
+	{ USB_DEVICE(VENDOR_SMK, 0x031d) },
+	/* SMK eHome Infrared Transceiver (Sony VAIO) */
+	{ USB_DEVICE(VENDOR_SMK, 0x0322) },
+	/* bundled with Hauppauge PVR-150 */
+	{ USB_DEVICE(VENDOR_SMK, 0x0334) },
+	/* SMK eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SMK, 0x0338) },
+	/* Tatung eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE, 0xc001) },
+	/* Shuttle eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) },
+	/* Gateway eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_GATEWAY, 0x3009) },
+	/* Mitsumi */
+	{ USB_DEVICE(VENDOR_MITSUMI, 0x2501) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0001) },
+	/* Topseed HP eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0006) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
+	/* Topseed eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
+	/* Ricavision internal Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
+	/* Itron ione Libra Q-11 */
+	{ USB_DEVICE(VENDOR_ITRON, 0x7002) },
+	/* FIC eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FIC, 0x9242) },
+	/* LG eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_LG, 0x9803) },
+	/* Microsoft MCE Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) },
+	/* Formosa eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe015) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe016) },
+	/* Formosa aim / Trust MCE Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe017) },
+	/* Formosa Industrial Computing / Beanbag Emulation Device */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe018) },
+	/* Formosa21 / eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03a) },
+	/* Formosa Industrial Computing AIM IR605/A */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
+	/* Formosa Industrial Computing */
+	{ USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+	/* Fintek eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0602) },
+	/* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
+	{ USB_DEVICE(VENDOR_FINTEK, 0x0702) },
+	/* Pinnacle Remote Kit */
+	{ USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
+	/* Elitegroup Computer Systems IR */
+	{ USB_DEVICE(VENDOR_ECS, 0x0f38) },
+	/* Wistron Corp. eHome Infrared Receiver */
+	{ USB_DEVICE(VENDOR_WISTRON, 0x0002) },
+	/* Compro K100 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3020) },
+	/* Compro K100 v2 */
+	{ USB_DEVICE(VENDOR_COMPRO, 0x3082) },
+	/* Northstar Systems, Inc. eHome Infrared Transceiver */
+	{ USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
+	/* TiVo PC IR Receiver */
+	{ USB_DEVICE(VENDOR_TIVO, 0x2000) },
+	/* 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 */
+struct mceusb_dev {
+	/* ir-core bits */
+	struct ir_input_dev *irdev;
+	struct ir_dev_props *props;
+	struct ir_raw_event rawir;
+
+	/* core device bits */
+	struct device *dev;
+	struct input_dev *idev;
+
+	/* usb */
+	struct usb_device *usbdev;
+	struct urb *urb_in;
+	struct usb_endpoint_descriptor *usb_ep_in;
+	struct usb_endpoint_descriptor *usb_ep_out;
+
+	/* buffers and dma */
+	unsigned char *buf_in;
+	unsigned int len_in;
+	u8 cmd;		/* MCE command type */
+	u8 rem;		/* Remaining IR data bytes in packet */
+	dma_addr_t dma_in;
+	dma_addr_t dma_out;
+
+	struct {
+		u32 connected:1;
+		u32 tx_mask_inverted:1;
+		u32 microsoft_gen1:1;
+		u32 reserved:29;
+	} flags;
+
+	/* transmit support */
+	int send_flags;
+	u32 carrier;
+	unsigned char tx_mask;
+
+	char name[128];
+	char phys[64];
+};
+
+/*
+ * MCE Device Command Strings
+ * Device command responses vary from device to device...
+ * - DEVICE_RESET resets the hardware to its default state
+ * - GET_REVISION fetches the hardware/software revision, common
+ *   replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42
+ * - GET_CARRIER_FREQ gets the carrier mode and frequency of the
+ *   device, with replies in the form of 9f 06 MM FF, where MM is 0-3,
+ *   meaning clk of 10000000, 2500000, 625000 or 156250, and FF is
+ *   ((clk / frequency) - 1)
+ * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us,
+ *   response in the form of 9f 0c msb lsb
+ * - GET_TX_BITMASK fetches the transmitter bitmask, replies in
+ *   the form of 9f 08 bm, where bm is the bitmask
+ * - GET_RX_SENSOR fetches the RX sensor setting -- long-range
+ *   general use one or short-range learning one, in the form of
+ *   9f 14 ss, where ss is either 01 for long-range or 02 for short
+ * - SET_CARRIER_FREQ sets a new carrier mode and frequency
+ * - SET_TX_BITMASK sets the transmitter bitmask
+ * - SET_RX_TIMEOUT sets the receiver timeout
+ * - 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};
+/* sub in desired values in lower byte or bytes for full command */
+/* 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 void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
+				 int len, bool out)
+{
+	char codes[USB_BUFLEN * 3 + 1];
+	char inout[9];
+	int i;
+	u8 cmd, subcmd, data1, data2;
+	struct device *dev = ir->dev;
+	int idx = 0;
+
+	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+	if (ir->flags.microsoft_gen1 && !out)
+		idx = 2;
+
+	if (len <= idx)
+		return;
+
+	for (i = 0; i < len && i < USB_BUFLEN; i++)
+		snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF);
+
+	dev_info(dev, "%sx data: %s (length=%d)\n",
+		 (out ? "t" : "r"), codes, len);
+
+	if (out)
+		strcpy(inout, "Request\0");
+	else
+		strcpy(inout, "Got\0");
+
+	cmd    = buf[idx] & 0xff;
+	subcmd = buf[idx + 1] & 0xff;
+	data1  = buf[idx + 2] & 0xff;
+	data2  = buf[idx + 3] & 0xff;
+
+	switch (cmd) {
+	case 0x00:
+		if (subcmd == 0xff && data1 == 0xaa)
+			dev_info(dev, "Device reset requested\n");
+		else
+			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
+				 cmd, subcmd);
+		break;
+	case 0xff:
+		switch (subcmd) {
+		case 0x0b:
+			if (len == 2)
+				dev_info(dev, "Get hw/sw rev?\n");
+			else
+				dev_info(dev, "hw/sw rev 0x%02x 0x%02x "
+					 "0x%02x 0x%02x\n", data1, data2,
+					 buf[idx + 4], buf[idx + 5]);
+			break;
+		case 0xaa:
+			dev_info(dev, "Device reset requested\n");
+			break;
+		case 0xfe:
+			dev_info(dev, "Previous command not supported\n");
+			break;
+		case 0x18:
+		case 0x1b:
+		default:
+			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
+				 cmd, subcmd);
+			break;
+		}
+		break;
+	case 0x9f:
+		switch (subcmd) {
+		case 0x03:
+			dev_info(dev, "Ping\n");
+			break;
+		case 0x04:
+			dev_info(dev, "Resp to 9f 05 of 0x%02x 0x%02x\n",
+				 data1, data2);
+			break;
+		case 0x06:
+			dev_info(dev, "%s carrier mode and freq of "
+				 "0x%02x 0x%02x\n", inout, data1, data2);
+			break;
+		case 0x07:
+			dev_info(dev, "Get carrier mode and freq\n");
+			break;
+		case 0x08:
+			dev_info(dev, "%s transmit blaster mask of 0x%02x\n",
+				 inout, data1);
+			break;
+		case 0x0c:
+			/* value is in units of 50us, so x*50/100 or x/2 ms */
+			dev_info(dev, "%s receive timeout of %d ms\n",
+				 inout, ((data1 << 8) | data2) / 2);
+			break;
+		case 0x0d:
+			dev_info(dev, "Get receive timeout\n");
+			break;
+		case 0x13:
+			dev_info(dev, "Get transmit blaster mask\n");
+			break;
+		case 0x14:
+			dev_info(dev, "%s %s-range receive sensor in use\n",
+				 inout, data1 == 0x02 ? "short" : "long");
+			break;
+		case 0x15:
+			if (len == 2)
+				dev_info(dev, "Get receive sensor\n");
+			else
+				dev_info(dev, "Received pulse count is %d\n",
+					 ((data1 << 8) | data2));
+			break;
+		case 0xfe:
+			dev_info(dev, "Error! Hardware is likely wedged...\n");
+			break;
+		case 0x05:
+		case 0x09:
+		case 0x0f:
+		default:
+			dev_info(dev, "Unknown command 0x%02x 0x%02x\n",
+				 cmd, subcmd);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void usb_async_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (ir) {
+		len = urb->actual_length;
+
+		dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
+			urb->status, len);
+
+		if (debug)
+			mceusb_dev_printdata(ir, urb->transfer_buffer,
+					     len, true);
+	}
+
+}
+
+/* request incoming or send outgoing usb packet - used to initialize remote */
+static void mce_request_packet(struct mceusb_dev *ir,
+			       struct usb_endpoint_descriptor *ep,
+			       unsigned char *data, int size, int urb_type)
+{
+	int res;
+	struct urb *async_urb;
+	struct device *dev = ir->dev;
+	unsigned char *async_buf;
+
+	if (urb_type == MCEUSB_TX) {
+		async_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (unlikely(!async_urb)) {
+			dev_err(dev, "Error, couldn't allocate urb!\n");
+			return;
+		}
+
+		async_buf = kzalloc(size, GFP_KERNEL);
+		if (!async_buf) {
+			dev_err(dev, "Error, couldn't allocate buf!\n");
+			usb_free_urb(async_urb);
+			return;
+		}
+
+		/* outbound data */
+		usb_fill_int_urb(async_urb, ir->usbdev,
+			usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
+			async_buf, size, (usb_complete_t) usb_async_callback,
+			ir, ep->bInterval);
+		memcpy(async_buf, data, size);
+
+	} else if (urb_type == MCEUSB_RX) {
+		/* standard request */
+		async_urb = ir->urb_in;
+		ir->send_flags = RECV_FLAG_IN_PROGRESS;
+
+	} else {
+		dev_err(dev, "Error! Unknown urb type %d\n", urb_type);
+		return;
+	}
+
+	dev_dbg(dev, "receive request called (size=%#x)\n", size);
+
+	async_urb->transfer_buffer_length = size;
+	async_urb->dev = ir->usbdev;
+
+	res = usb_submit_urb(async_urb, GFP_ATOMIC);
+	if (res) {
+		dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
+		return;
+	}
+	dev_dbg(dev, "receive request complete (res=%d)\n", res);
+}
+
+static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
+{
+	mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX);
+}
+
+static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
+{
+	mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX);
+}
+
+/* Send data out the IR blaster port(s) */
+static int mceusb_tx_ir(void *priv, int *txbuf, u32 n)
+{
+	struct mceusb_dev *ir = priv;
+	int i, ret = 0;
+	int count, cmdcount = 0;
+	unsigned char *cmdbuf; /* MCE command buffer */
+	long signal_duration = 0; /* Singnal length in us */
+	struct timeval start_time, end_time;
+
+	do_gettimeofday(&start_time);
+
+	count = n / sizeof(int);
+
+	cmdbuf = kzalloc(sizeof(int) * MCE_CMDBUF_SIZE, GFP_KERNEL);
+	if (!cmdbuf)
+		return -ENOMEM;
+
+	/* MCE tx init header */
+	cmdbuf[cmdcount++] = MCE_CONTROL_HEADER;
+	cmdbuf[cmdcount++] = 0x08;
+	cmdbuf[cmdcount++] = ir->tx_mask;
+
+	/* Generate mce packet data */
+	for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
+		signal_duration += txbuf[i];
+		txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
+
+		do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
+
+			/* Insert mce packet header every 4th entry */
+			if ((cmdcount < MCE_CMDBUF_SIZE) &&
+			    (cmdcount - MCE_TX_HEADER_LENGTH) %
+			     MCE_CODE_LENGTH == 0)
+				cmdbuf[cmdcount++] = MCE_PACKET_HEADER;
+
+			/* Insert mce packet data */
+			if (cmdcount < MCE_CMDBUF_SIZE)
+				cmdbuf[cmdcount++] =
+					(txbuf[i] < MCE_PULSE_BIT ?
+					 txbuf[i] : MCE_MAX_PULSE_LENGTH) |
+					 (i & 1 ? 0x00 : MCE_PULSE_BIT);
+			else {
+				ret = -EINVAL;
+				goto out;
+			}
+
+		} while ((txbuf[i] > MCE_MAX_PULSE_LENGTH) &&
+			 (txbuf[i] -= MCE_MAX_PULSE_LENGTH));
+	}
+
+	/* Fix packet length in last header */
+	cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] =
+		0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1;
+
+	/* Check if we have room for the empty packet at the end */
+	if (cmdcount >= MCE_CMDBUF_SIZE) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* All mce commands end with an empty packet (0x80) */
+	cmdbuf[cmdcount++] = 0x80;
+
+	/* Transmit the command to the mce device */
+	mce_async_out(ir, cmdbuf, cmdcount);
+
+	/*
+	 * The lircd gap calculation expects the write function to
+	 * wait the time it takes for the ircommand to be sent before
+	 * it returns.
+	 */
+	do_gettimeofday(&end_time);
+	signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
+			   (end_time.tv_sec - start_time.tv_sec) * 1000000;
+
+	/* delay with the closest number of ticks */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(usecs_to_jiffies(signal_duration));
+
+out:
+	kfree(cmdbuf);
+	return ret ? ret : n;
+}
+
+/* Sets active IR outputs -- mce devices typically (all?) have two */
+static int mceusb_set_tx_mask(void *priv, u32 mask)
+{
+	struct mceusb_dev *ir = priv;
+
+	if (ir->flags.tx_mask_inverted)
+		ir->tx_mask = (mask != 0x03 ? mask ^ 0x03 : mask) << 1;
+	else
+		ir->tx_mask = mask;
+
+	return 0;
+}
+
+/* Sets the send carrier frequency and mode */
+static int mceusb_set_tx_carrier(void *priv, u32 carrier)
+{
+	struct mceusb_dev *ir = priv;
+	int clk = 10000000;
+	int prescaler = 0, divisor = 0;
+	unsigned char cmdbuf[4] = { 0x9f, 0x06, 0x00, 0x00 };
+
+	/* Carrier has changed */
+	if (ir->carrier != carrier) {
+
+		if (carrier == 0) {
+			ir->carrier = carrier;
+			cmdbuf[2] = 0x01;
+			cmdbuf[3] = 0x80;
+			dev_dbg(ir->dev, "%s: disabling carrier "
+				"modulation\n", __func__);
+			mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+			return carrier;
+		}
+
+		for (prescaler = 0; prescaler < 4; ++prescaler) {
+			divisor = (clk >> (2 * prescaler)) / carrier;
+			if (divisor <= 0xFF) {
+				ir->carrier = carrier;
+				cmdbuf[2] = prescaler;
+				cmdbuf[3] = divisor;
+				dev_dbg(ir->dev, "%s: requesting %u HZ "
+					"carrier\n", __func__, carrier);
+
+				/* Transmit new carrier to mce device */
+				mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
+				return carrier;
+			}
+		}
+
+		return -EINVAL;
+
+	}
+
+	return carrier;
+}
+
+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;
+
+	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
+	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++) {
+			ir->rem--;
+
+			rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
+			rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
+					 * MCE_TIME_UNIT * 1000;
+
+			if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
+				if (ir->rawir.pulse == rawir.pulse)
+					ir->rawir.duration += rawir.duration;
+				else {
+					ir->rawir.duration = rawir.duration;
+					ir->rawir.pulse = rawir.pulse;
+				}
+				continue;
+			}
+			rawir.duration += ir->rawir.duration;
+			ir->rawir.duration = 0;
+			ir->rawir.pulse = rawir.pulse;
+
+			dev_dbg(ir->dev, "Storing %s with duration %d\n",
+				rawir.pulse ? "pulse" : "space",
+				rawir.duration);
+
+			ir_raw_event_store(ir->idev, &rawir);
+		}
+
+		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);
+	}
+}
+
+static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
+{
+	struct mceusb_dev *ir;
+	int buf_len;
+
+	if (!urb)
+		return;
+
+	ir = urb->context;
+	if (!ir) {
+		usb_unlink_urb(urb);
+		return;
+	}
+
+	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) {
+		ir->send_flags = SEND_FLAG_COMPLETE;
+		dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n",
+			buf_len);
+	}
+
+	switch (urb->status) {
+	/* success */
+	case 0:
+		mceusb_process_ir_data(ir, buf_len);
+		break;
+
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		usb_unlink_urb(urb);
+		return;
+
+	case -EPIPE:
+	default:
+		break;
+	}
+
+	usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static void mceusb_gen1_init(struct mceusb_dev *ir)
+{
+	int ret;
+	int maxp = ir->len_in;
+	struct device *dev = ir->dev;
+	char *data;
+
+	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "%s: memory allocation failed!\n", __func__);
+		return;
+	}
+
+	/*
+	 * This is a strange one. Windows issues a set address to the device
+	 * on the receive control pipe and expect a certain value pair back
+	 */
+	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
+			      data, USB_CTRL_MSG_SZ, HZ * 3);
+	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
+	dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
+		__func__, data[0], data[1]);
+
+	/* set feature: bit rate 38400 bps */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+			      0xc04e, 0x0000, NULL, 0, HZ * 3);
+
+	dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
+
+	/* bRequest 4: set char length to 8 bits */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      4, USB_TYPE_VENDOR,
+			      0x0808, 0x0000, NULL, 0, HZ * 3);
+	dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
+
+	/* bRequest 2: set handshaking to use DTR/DSR */
+	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
+			      2, USB_TYPE_VENDOR,
+			      0x0000, 0x0100, NULL, 0, HZ * 3);
+	dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
+
+	/* device reset */
+	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get hw/sw revision? */
+	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
+	mce_sync_in(ir, NULL, maxp);
+
+	kfree(data);
+};
+
+static void mceusb_gen2_init(struct mceusb_dev *ir)
+{
+	int maxp = ir->len_in;
+
+	/* device reset */
+	mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get hw/sw revision? */
+	mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* unknown what the next two actually return... */
+	mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
+	mce_sync_in(ir, NULL, maxp);
+	mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
+	mce_sync_in(ir, NULL, maxp);
+}
+
+static void mceusb_get_parameters(struct mceusb_dev *ir)
+{
+	int maxp = ir->len_in;
+
+	/* get the carrier and frequency */
+	mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get the transmitter bitmask */
+	mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get receiver timeout value */
+	mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
+	mce_sync_in(ir, NULL, maxp);
+
+	/* get receiver sensor setting */
+	mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
+	mce_sync_in(ir, NULL, maxp);
+}
+
+static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
+{
+	struct input_dev *idev;
+	struct ir_dev_props *props;
+	struct ir_input_dev *irdev;
+	struct device *dev = ir->dev;
+	int ret = -ENODEV;
+
+	idev = input_allocate_device();
+	if (!idev) {
+		dev_err(dev, "remote input dev allocation failed\n");
+		goto idev_alloc_failed;
+	}
+
+	ret = -ENOMEM;
+	props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
+	if (!props) {
+		dev_err(dev, "remote ir dev props allocation failed\n");
+		goto props_alloc_failed;
+	}
+
+	irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
+	if (!irdev) {
+		dev_err(dev, "remote ir input dev allocation failed\n");
+		goto ir_dev_alloc_failed;
+	}
+
+	snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
+		 "Infrared Remote Transceiver (%04x:%04x)",
+		 le16_to_cpu(ir->usbdev->descriptor.idVendor),
+		 le16_to_cpu(ir->usbdev->descriptor.idProduct));
+
+	idev->name = ir->name;
+	usb_make_path(ir->usbdev, ir->phys, sizeof(ir->phys));
+	strlcat(ir->phys, "/input0", sizeof(ir->phys));
+	idev->phys = ir->phys;
+
+	props->priv = ir;
+	props->driver_type = RC_DRIVER_IR_RAW;
+	props->allowed_protos = IR_TYPE_ALL;
+	props->s_tx_mask = mceusb_set_tx_mask;
+	props->s_tx_carrier = mceusb_set_tx_carrier;
+	props->tx_ir = mceusb_tx_ir;
+
+	ir->props = props;
+	ir->irdev = irdev;
+
+	input_set_drvdata(idev, irdev);
+
+	ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
+	if (ret < 0) {
+		dev_err(dev, "remote input device register failed\n");
+		goto irdev_failed;
+	}
+
+	return idev;
+
+irdev_failed:
+	kfree(irdev);
+ir_dev_alloc_failed:
+	kfree(props);
+props_alloc_failed:
+	input_free_device(idev);
+idev_alloc_failed:
+	return NULL;
+}
+
+static int __devinit mceusb_dev_probe(struct usb_interface *intf,
+				      const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_host_interface *idesc;
+	struct usb_endpoint_descriptor *ep = NULL;
+	struct usb_endpoint_descriptor *ep_in = NULL;
+	struct usb_endpoint_descriptor *ep_out = NULL;
+	struct usb_host_config *config;
+	struct mceusb_dev *ir = NULL;
+	int pipe, maxp, i;
+	char buf[63], name[128] = "";
+	bool is_gen3;
+	bool is_microsoft_gen1;
+	bool tx_mask_inverted;
+
+	dev_dbg(&intf->dev, ": %s called\n", __func__);
+
+	config = dev->actconfig;
+	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;
+
+	/* step through the endpoints to find first bulk in and out endpoint */
+	for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
+		ep = &idesc->endpoint[i].desc;
+
+		if ((ep_in == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_IN)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			ep_in = ep;
+			ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
+			ep_in->bInterval = 1;
+			dev_dbg(&intf->dev, ": acceptable inbound endpoint "
+				"found\n");
+		}
+
+		if ((ep_out == NULL)
+			&& ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			    == USB_DIR_OUT)
+			&& (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_BULK)
+			|| ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+			    == USB_ENDPOINT_XFER_INT))) {
+
+			ep_out = ep;
+			ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
+			ep_out->bInterval = 1;
+			dev_dbg(&intf->dev, ": acceptable outbound endpoint "
+				"found\n");
+		}
+	}
+	if (ep_in == NULL) {
+		dev_dbg(&intf->dev, ": inbound and/or endpoint not found\n");
+		return -ENODEV;
+	}
+
+	pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress);
+	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL);
+	if (!ir)
+		goto mem_alloc_fail;
+
+	ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in);
+	if (!ir->buf_in)
+		goto buf_in_alloc_fail;
+
+	ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ir->urb_in)
+		goto urb_in_alloc_fail;
+
+	ir->usbdev = dev;
+	ir->dev = &intf->dev;
+	ir->len_in = maxp;
+	ir->flags.microsoft_gen1 = is_microsoft_gen1;
+	ir->flags.tx_mask_inverted = tx_mask_inverted;
+
+	/* Saving usb interface data for use by the transmitter routine */
+	ir->usb_ep_in = ep_in;
+	ir->usb_ep_out = ep_out;
+
+	if (dev->descriptor.iManufacturer
+	    && usb_string(dev, dev->descriptor.iManufacturer,
+			  buf, sizeof(buf)) > 0)
+		strlcpy(name, buf, sizeof(name));
+	if (dev->descriptor.iProduct
+	    && usb_string(dev, dev->descriptor.iProduct,
+			  buf, sizeof(buf)) > 0)
+		snprintf(name + strlen(name), sizeof(name) - strlen(name),
+			 " %s", buf);
+
+	ir->idev = mceusb_init_input_dev(ir);
+	if (!ir->idev)
+		goto input_dev_fail;
+
+	/* flush buffers on the device */
+	mce_sync_in(ir, NULL, maxp);
+	mce_sync_in(ir, NULL, maxp);
+
+	/* wire up inbound data handler */
+	usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
+		maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
+	ir->urb_in->transfer_dma = ir->dma_in;
+	ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* initialize device */
+	if (ir->flags.microsoft_gen1)
+		mceusb_gen1_init(ir);
+	else if (!is_gen3)
+		mceusb_gen2_init(ir);
+
+	mceusb_get_parameters(ir);
+
+	mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
+
+	usb_set_intfdata(intf, ir);
+
+	dev_info(&intf->dev, "Registered %s on usb%d:%d\n", name,
+		 dev->bus->busnum, dev->devnum);
+
+	return 0;
+
+	/* Error-handling path */
+input_dev_fail:
+	usb_free_urb(ir->urb_in);
+urb_in_alloc_fail:
+	usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in);
+buf_in_alloc_fail:
+	kfree(ir);
+mem_alloc_fail:
+	dev_err(&intf->dev, "%s: device setup failed!\n", __func__);
+
+	return -ENOMEM;
+}
+
+
+static void __devexit mceusb_dev_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+
+	usb_set_intfdata(intf, NULL);
+
+	if (!ir)
+		return;
+
+	ir->usbdev = NULL;
+	ir_input_unregister(ir->idev);
+	usb_kill_urb(ir->urb_in);
+	usb_free_urb(ir->urb_in);
+	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
+
+	kfree(ir);
+}
+
+static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	dev_info(ir->dev, "suspend\n");
+	usb_kill_urb(ir->urb_in);
+	return 0;
+}
+
+static int mceusb_dev_resume(struct usb_interface *intf)
+{
+	struct mceusb_dev *ir = usb_get_intfdata(intf);
+	dev_info(ir->dev, "resume\n");
+	if (usb_submit_urb(ir->urb_in, GFP_ATOMIC))
+		return -EIO;
+	return 0;
+}
+
+static struct usb_driver mceusb_dev_driver = {
+	.name =		DRIVER_NAME,
+	.probe =	mceusb_dev_probe,
+	.disconnect =	mceusb_dev_disconnect,
+	.suspend =	mceusb_dev_suspend,
+	.resume =	mceusb_dev_resume,
+	.reset_resume =	mceusb_dev_resume,
+	.id_table =	mceusb_dev_table
+};
+
+static int __init mceusb_dev_init(void)
+{
+	int ret;
+
+	ret = usb_register(&mceusb_dev_driver);
+	if (ret < 0)
+		printk(KERN_ERR DRIVER_NAME
+		       ": usb register failed, result = %d\n", ret);
+
+	return ret;
+}
+
+static void __exit mceusb_dev_exit(void)
+{
+	usb_deregister(&mceusb_dev_driver);
+}
+
+module_init(mceusb_dev_init);
+module_exit(mceusb_dev_exit);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, mceusb_dev_table);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");

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

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

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

@@ -375,7 +375,7 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 
 static int vbi_open(struct saa7146_dev *dev, struct file *file)
 {
-	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+	struct saa7146_fh *fh = file->private_data;
 
 	u32 arbtr_ctrl	= saa7146_read(dev, PCI_BT_V1);
 	int ret = 0;
@@ -437,7 +437,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
 
 static void vbi_close(struct saa7146_dev *dev, struct file *file)
 {
-	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
 

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

@@ -1370,7 +1370,7 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
 
 static int video_open(struct saa7146_dev *dev, struct file *file)
 {
-	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_format *sfmt;
 
 	fh->video_fmt.width = 384;
@@ -1394,7 +1394,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
 
 static void video_close(struct saa7146_dev *dev, struct file *file)
 {
-	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
+	struct saa7146_fh *fh = file->private_data;
 	struct saa7146_vv *vv = dev->vv_data;
 	struct videobuf_queue *q = &fh->video_q;
 	int err;

+ 5 - 3
drivers/media/common/tuners/tda18271-fe.c

@@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
 				     struct tda18271_config *cfg)
 {
 	struct tda18271_priv *priv = NULL;
-	int instance;
+	int instance, ret;
 
 	mutex_lock(&tda18271_list_mutex);
 
@@ -1268,10 +1268,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
 		priv->cal_initialized = false;
 		mutex_init(&priv->lock);
 
-		if (tda_fail(tda18271_get_id(fe)))
+		ret = tda18271_get_id(fe);
+		if (tda_fail(ret))
 			goto fail;
 
-		if (tda_fail(tda18271_assign_map_layout(fe)))
+		ret = tda18271_assign_map_layout(fe);
+		if (tda_fail(ret))
 			goto fail;
 
 		mutex_lock(&priv->lock);

+ 0 - 3
drivers/media/common/tuners/tuner-simple.c

@@ -546,14 +546,11 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
 	struct tuner_simple_priv *priv = fe->tuner_priv;
 	u8 config, cb;
 	u16 div;
-	struct tunertype *tun;
 	u8 buffer[4];
 	int rc, IFPCoff, i;
 	enum param_type desired_type;
 	struct tuner_params *t_params;
 
-	tun = priv->tun;
-
 	/* IFPCoff = Video Intermediate Frequency - Vif:
 		940  =16*58.75  NTSC/J (Japan)
 		732  =16*45.75  M/N STD

+ 28 - 31
drivers/media/common/tuners/xc5000.c

@@ -217,6 +217,7 @@ static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
 	return XC_RESULT_SUCCESS;
 }
 
+#if 0
 /* This routine is never used because the only time we read data from the
    i2c bus is when we read registers, and we want that to be an atomic i2c
    transaction in case we are on a multi-master bus */
@@ -231,6 +232,27 @@ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
 	}
 	return 0;
 }
+#endif
+
+static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
+{
+	u8 buf[2] = { reg >> 8, reg & 0xff };
+	u8 bval[2] = { 0, 0 };
+	struct i2c_msg msg[2] = {
+		{ .addr = priv->i2c_props.addr,
+			.flags = 0, .buf = &buf[0], .len = 2 },
+		{ .addr = priv->i2c_props.addr,
+			.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
+	};
+
+	if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
+		printk(KERN_WARNING "xc5000: I2C read failed\n");
+		return -EREMOTEIO;
+	}
+
+	*val = (bval[0] << 8) | bval[1];
+	return XC_RESULT_SUCCESS;
+}
 
 static void xc_wait(int wait_ms)
 {
@@ -275,20 +297,14 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
 	if (result == XC_RESULT_SUCCESS) {
 		/* wait for busy flag to clear */
 		while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
-			buf[0] = 0;
-			buf[1] = XREG_BUSY;
-
-			result = xc_send_i2c_data(priv, buf, 2);
+			result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
 			if (result == XC_RESULT_SUCCESS) {
-				result = xc_read_i2c_data(priv, buf, 2);
-				if (result == XC_RESULT_SUCCESS) {
-					if ((buf[0] == 0) && (buf[1] == 0)) {
-						/* busy flag cleared */
+				if ((buf[0] == 0) && (buf[1] == 0)) {
+					/* busy flag cleared */
 					break;
-					} else {
-						xc_wait(5); /* wait 5 ms */
-						WatchDogTimer--;
-					}
+				} else {
+					xc_wait(5); /* wait 5 ms */
+					WatchDogTimer--;
 				}
 			}
 		}
@@ -526,25 +542,6 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
 	return found;
 }
 
-static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
-{
-	u8 buf[2] = { reg >> 8, reg & 0xff };
-	u8 bval[2] = { 0, 0 };
-	struct i2c_msg msg[2] = {
-		{ .addr = priv->i2c_props.addr,
-			.flags = 0, .buf = &buf[0], .len = 2 },
-		{ .addr = priv->i2c_props.addr,
-			.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
-	};
-
-	if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
-		printk(KERN_WARNING "xc5000: I2C read failed\n");
-		return -EREMOTEIO;
-	}
-
-	*val = (bval[0] << 8) | bval[1];
-	return XC_RESULT_SUCCESS;
-}
 
 static int xc5000_fwupload(struct dvb_frontend *fe)
 {

+ 1 - 1
drivers/media/dvb/bt8xx/dst_ca.c

@@ -565,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
 	int result = 0;
 
 	lock_kernel();
-	dvbdev = (struct dvb_device *)file->private_data;
+	dvbdev = file->private_data;
 	state = (struct dst_state *)dvbdev->priv;
 	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
 	p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);

+ 1 - 1
drivers/media/dvb/dvb-core/dmxdev.c

@@ -207,7 +207,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
 	}
 	/* TODO */
 	dvbdev->users--;
-	if(dvbdev->users==-1 && dmxdev->exit==1) {
+	if (dvbdev->users == 1 && dmxdev->exit == 1) {
 		fops_put(file->f_op);
 		file->f_op = NULL;
 		mutex_unlock(&dmxdev->mutex);

+ 8 - 2
drivers/media/dvb/dvb-core/dvb_ca_en50221.c

@@ -1318,8 +1318,11 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
 
 		fragbuf[0] = connection_id;
 		fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
-		if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0)
+		status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen);
+		if (status) {
+			status = -EFAULT;
 			goto exit;
+		}
 
 		timeout = jiffies + HZ / 2;
 		written = 0;
@@ -1494,8 +1497,11 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
 
 	hdr[0] = slot;
 	hdr[1] = connection_id;
-	if ((status = copy_to_user(buf, hdr, 2)) != 0)
+	status = copy_to_user(buf, hdr, 2);
+	if (status) {
+		status = -EFAULT;
 		goto exit;
+	}
 	status = pktlen;
 
 exit:

+ 3 - 7
drivers/media/dvb/dvb-core/dvb_demux.c

@@ -1130,13 +1130,9 @@ static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t
 	if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
 		return -EINVAL;
 
-	p = kmalloc(count, GFP_USER);
-	if (!p)
-		return -ENOMEM;
-	if (copy_from_user(p, buf, count)) {
-		kfree(p);
-		return -EFAULT;
-	}
+	p = memdup_user(buf, count);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
 	if (mutex_lock_interruptible(&dvbdemux->mutex)) {
 		kfree(p);
 		return -ERESTARTSYS;

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

@@ -465,7 +465,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
 	if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
 		fepriv->delay = fepriv->min_delay;
 
-		/* peform a tune */
+		/* perform a tune */
 		retval = dvb_frontend_swzigzag_autotune(fe,
 							fepriv->check_wrapped);
 		if (retval < 0) {
@@ -791,7 +791,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
 	return 0;
 }
 
-static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
+static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
 					u32 *freq_min, u32 *freq_max)
 {
 	*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
@@ -815,7 +815,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
 	u32 freq_max;
 
 	/* range check: frequency */
-	dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
+	dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
 	if ((freq_min && parms->frequency < freq_min) ||
 	    (freq_max && parms->frequency > freq_max)) {
 		printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
@@ -1627,7 +1627,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 	case FE_GET_INFO: {
 		struct dvb_frontend_info* info = parg;
 		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
-		dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
+		dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
 
 		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
 		 * do it, it is done for it. */
@@ -1726,7 +1726,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
 			 * (stv0299 for instance) take longer than 8msec to
 			 * respond to a set_voltage command.  Those switches
 			 * need custom routines to switch properly.  For all
-			 * other frontends, the following shoule work ok.
+			 * other frontends, the following should work ok.
 			 * Dish network legacy switches (as used by Dish500)
 			 * are controlled by sending 9-bit command words
 			 * spaced 8msec apart.

+ 7 - 5
drivers/media/dvb/dvb-usb/a800.c

@@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_a800_table[] = {
+static struct ir_scancode ir_codes_a800_table[] = {
 	{ 0x0201, KEY_PROG1 },       /* SOURCE */
 	{ 0x0200, KEY_POWER },       /* POWER */
 	{ 0x0205, KEY_1 },           /* 1 */
@@ -146,10 +146,12 @@ static struct dvb_usb_device_properties a800_properties = {
 	.power_ctrl       = a800_power_ctrl,
 	.identify_state   = a800_identify_state,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_a800_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_a800_table),
-	.rc_query         = a800_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_a800_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_a800_table),
+		.rc_query         = a800_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 

+ 2 - 2
drivers/media/dvb/dvb-usb/af9005-remote.c

@@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug,
 
 #define deb_decode(args...)   dprintk(dvb_usb_af9005_remote_debug,0x01,args)
 
-struct dvb_usb_rc_key ir_codes_af9005_table[] = {
+struct ir_scancode ir_codes_af9005_table[] = {
 
 	{0x01b7, KEY_POWER},
 	{0x01a7, KEY_VOLUMEUP},
@@ -133,7 +133,7 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
 			for (i = 0; i < ir_codes_af9005_table_size; i++) {
 				if (rc5_custom(&ir_codes_af9005_table[i]) == cust
 				    && rc5_data(&ir_codes_af9005_table[i]) == dat) {
-					*event = ir_codes_af9005_table[i].event;
+					*event = ir_codes_af9005_table[i].keycode;
 					*state = REMOTE_KEY_PRESSED;
 					deb_decode
 					    ("key pressed, event %x\n", *event);

+ 16 - 55
drivers/media/dvb/dvb-usb/af9005.c

@@ -54,50 +54,6 @@ struct af9005_device_state {
 	int led_state;
 };
 
-static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen,
-			  u8 *rbuf, u16 rlen, int delay_ms)
-{
-	int actlen, ret = -ENOMEM;
-
-	if (wbuf == NULL || wlen == 0)
-		return -EINVAL;
-
-	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
-		return ret;
-
-	deb_xfer(">>> ");
-	debug_dump(wbuf, wlen, deb_xfer);
-
-	ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
-						    2), wbuf, wlen,
-			   &actlen, 2000);
-
-	if (ret)
-		err("bulk message failed: %d (%d/%d)", ret, wlen, actlen);
-	else
-		ret = actlen != wlen ? -1 : 0;
-
-	/* an answer is expected, and no error before */
-	if (!ret && rbuf && rlen) {
-		if (delay_ms)
-			msleep(delay_ms);
-
-		ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
-							    0x01), rbuf,
-				   rlen, &actlen, 2000);
-
-		if (ret)
-			err("recv bulk message failed: %d", ret);
-		else {
-			deb_xfer("<<< ");
-			debug_dump(rbuf, actlen, deb_xfer);
-		}
-	}
-
-	mutex_unlock(&d->usb_mutex);
-	return ret;
-}
-
 static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
 			      int readwrite, int type, u8 * values, int len)
 {
@@ -146,7 +102,7 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
 		obuf[8] = values[0];
 	obuf[7] = command;
 
-	ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
+	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
 	if (ret)
 		return ret;
 
@@ -534,7 +490,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
 	buf[6] = wlen;
 	for (i = 0; i < wlen; i++)
 		buf[7 + i] = wbuf[i];
-	ret = af9005_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
+	ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
 	if (ret)
 		return ret;
 	if (ibuf[2] != 0x27) {
@@ -581,7 +537,7 @@ int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
 
 	obuf[6] = len;
 	obuf[7] = address;
-	ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
+	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
 	if (ret)
 		return ret;
 	if (ibuf[2] != 0x2b) {
@@ -882,7 +838,7 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
 	obuf[2] = 0x40;		/* read remote */
 	obuf[3] = 1;		/* rest of packet length */
 	obuf[4] = st->sequence++;	/* sequence number */
-	ret = af9005_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
+	ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
 	if (ret) {
 		err("rc query failed");
 		return ret;
@@ -1069,10 +1025,15 @@ static struct dvb_usb_device_properties af9005_properties = {
 
 	.i2c_algo = &af9005_i2c_algo,
 
-	.rc_interval = 200,
-	.rc_key_map = NULL,
-	.rc_key_map_size = 0,
-	.rc_query = af9005_rc_query,
+	.rc.legacy = {
+		.rc_interval = 200,
+		.rc_key_map = NULL,
+		.rc_key_map_size = 0,
+		.rc_query = af9005_rc_query,
+	},
+
+	.generic_bulk_ctrl_endpoint          = 2,
+	.generic_bulk_ctrl_endpoint_response = 1,
 
 	.num_device_descs = 3,
 	.devices = {
@@ -1113,10 +1074,10 @@ static int __init af9005_usb_module_init(void)
 	rc_keys_size = symbol_request(ir_codes_af9005_table_size);
 	if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
 		err("af9005_rc_decode function not found, disabling remote");
-		af9005_properties.rc_query = NULL;
+		af9005_properties.rc.legacy.rc_query = NULL;
 	} else {
-		af9005_properties.rc_key_map = rc_keys;
-		af9005_properties.rc_key_map_size = *rc_keys_size;
+		af9005_properties.rc.legacy.rc_key_map = rc_keys;
+		af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size;
 	}
 
 	return 0;

+ 1 - 1
drivers/media/dvb/dvb-usb/af9005.h

@@ -3490,7 +3490,7 @@ extern u8 regmask[8];
 /* remote control decoder */
 extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
 			    u32 * event, int *state);
-extern struct dvb_usb_rc_key ir_codes_af9005_table[];
+extern struct ir_scancode ir_codes_af9005_table[];
 extern int ir_codes_af9005_table_size;
 
 #endif

+ 27 - 15
drivers/media/dvb/dvb-usb/af9015.c

@@ -735,7 +735,7 @@ error:
 
 struct af9015_setup {
 	unsigned int id;
-	struct dvb_usb_rc_key *rc_key_map;
+	struct ir_scancode *rc_key_map;
 	unsigned int rc_key_map_size;
 	u8 *ir_table;
 	unsigned int ir_table_size;
@@ -847,8 +847,8 @@ static void af9015_set_remote_config(struct usb_device *udev,
 	}
 
 	if (table) {
-		props->rc_key_map = table->rc_key_map;
-		props->rc_key_map_size = table->rc_key_map_size;
+		props->rc.legacy.rc_key_map = table->rc_key_map;
+		props->rc.legacy.rc_key_map_size = table->rc_key_map_size;
 		af9015_config.ir_table = table->ir_table;
 		af9015_config.ir_table_size = table->ir_table_size;
 	}
@@ -878,8 +878,8 @@ static int af9015_read_config(struct usb_device *udev)
 	deb_info("%s: IR mode:%d\n", __func__, val);
 	for (i = 0; i < af9015_properties_count; i++) {
 		if (val == AF9015_IR_MODE_DISABLED) {
-			af9015_properties[i].rc_key_map = NULL;
-			af9015_properties[i].rc_key_map_size  = 0;
+			af9015_properties[i].rc.legacy.rc_key_map = NULL;
+			af9015_properties[i].rc.legacy.rc_key_map_size  = 0;
 		} else
 			af9015_set_remote_config(udev, &af9015_properties[i]);
 	}
@@ -1063,7 +1063,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
 	u8 buf[8];
 	struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf};
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	int i, ret;
 
 	memset(buf, 0, sizeof(buf));
@@ -1075,10 +1075,10 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
 		if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] &&
 		    rc5_data(&keymap[i]) == buf[2]) {
-			*event = keymap[i].event;
+			*event = keymap[i].keycode;
 			*state = REMOTE_KEY_PRESSED;
 			break;
 		}
@@ -1299,6 +1299,7 @@ static struct usb_device_id af9015_usb_table[] = {
 	{USB_DEVICE(USB_VID_LEADTEK,   USB_PID_WINFAST_DTV2000DS)},
 /* 30 */{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_UB383_T)},
 	{USB_DEVICE(USB_VID_KWORLD_2,  USB_PID_KWORLD_395U_4)},
+	{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
 	{0},
 };
 MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1353,8 +1354,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 
 		.identify_state = af9015_identify_state,
 
-		.rc_query         = af9015_rc_query,
-		.rc_interval      = 150,
+		.rc.legacy = {
+			.rc_query         = af9015_rc_query,
+			.rc_interval      = 150,
+		},
 
 		.i2c_algo = &af9015_i2c_algo,
 
@@ -1460,8 +1463,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 
 		.identify_state = af9015_identify_state,
 
-		.rc_query         = af9015_rc_query,
-		.rc_interval      = 150,
+		.rc.legacy = {
+			.rc_query         = af9015_rc_query,
+			.rc_interval      = 150,
+		},
 
 		.i2c_algo = &af9015_i2c_algo,
 
@@ -1567,12 +1572,14 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 
 		.identify_state = af9015_identify_state,
 
-		.rc_query         = af9015_rc_query,
-		.rc_interval      = 150,
+		.rc.legacy = {
+			.rc_query         = af9015_rc_query,
+			.rc_interval      = 150,
+		},
 
 		.i2c_algo = &af9015_i2c_algo,
 
-		.num_device_descs = 8, /* max 9 */
+		.num_device_descs = 9, /* max 9 */
 		.devices = {
 			{
 				.name = "AverMedia AVerTV Volar GPS 805 (A805)",
@@ -1617,6 +1624,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
 				.cold_ids = {&af9015_usb_table[30], NULL},
 				.warm_ids = {NULL},
 			},
+			{
+				.name = "AverMedia AVerTV Volar M (A815Mac)",
+				.cold_ids = {&af9015_usb_table[32], NULL},
+				.warm_ids = {NULL},
+			},
 		}
 	},
 };

+ 9 - 9
drivers/media/dvb/dvb-usb/af9015.h

@@ -123,7 +123,7 @@ enum af9015_remote {
 
 /* LeadTek - Y04G0051 */
 /* Leadtek WinFast DTV Dongle Gold */
-static struct dvb_usb_rc_key ir_codes_af9015_table_leadtek[] = {
+static struct ir_scancode ir_codes_af9015_table_leadtek[] = {
 	{ 0x001e, KEY_1 },
 	{ 0x001f, KEY_2 },
 	{ 0x0020, KEY_3 },
@@ -227,7 +227,7 @@ static u8 af9015_ir_table_leadtek[] = {
 };
 
 /* TwinHan AzureWave AD-TU700(704J) */
-static struct dvb_usb_rc_key ir_codes_af9015_table_twinhan[] = {
+static struct ir_scancode ir_codes_af9015_table_twinhan[] = {
 	{ 0x053f, KEY_POWER },
 	{ 0x0019, KEY_FAVORITES },    /* Favorite List */
 	{ 0x0004, KEY_TEXT },         /* Teletext */
@@ -338,7 +338,7 @@ static u8 af9015_ir_table_twinhan[] = {
 };
 
 /* A-Link DTU(m) */
-static struct dvb_usb_rc_key ir_codes_af9015_table_a_link[] = {
+static struct ir_scancode ir_codes_af9015_table_a_link[] = {
 	{ 0x001e, KEY_1 },
 	{ 0x001f, KEY_2 },
 	{ 0x0020, KEY_3 },
@@ -381,7 +381,7 @@ static u8 af9015_ir_table_a_link[] = {
 };
 
 /* MSI DIGIVOX mini II V3.0 */
-static struct dvb_usb_rc_key ir_codes_af9015_table_msi[] = {
+static struct ir_scancode ir_codes_af9015_table_msi[] = {
 	{ 0x001e, KEY_1 },
 	{ 0x001f, KEY_2 },
 	{ 0x0020, KEY_3 },
@@ -424,7 +424,7 @@ static u8 af9015_ir_table_msi[] = {
 };
 
 /* MYGICTV U718 */
-static struct dvb_usb_rc_key ir_codes_af9015_table_mygictv[] = {
+static struct ir_scancode ir_codes_af9015_table_mygictv[] = {
 	{ 0x003d, KEY_SWITCHVIDEOMODE },
 					  /* TV / AV */
 	{ 0x0545, KEY_POWER },
@@ -550,7 +550,7 @@ static u8 af9015_ir_table_kworld[] = {
 };
 
 /* AverMedia Volar X */
-static struct dvb_usb_rc_key ir_codes_af9015_table_avermedia[] = {
+static struct ir_scancode ir_codes_af9015_table_avermedia[] = {
 	{ 0x053d, KEY_PROG1 },       /* SOURCE */
 	{ 0x0512, KEY_POWER },       /* POWER */
 	{ 0x051e, KEY_1 },           /* 1 */
@@ -656,7 +656,7 @@ static u8 af9015_ir_table_avermedia_ks[] = {
 };
 
 /* Digittrade DVB-T USB Stick */
-static struct dvb_usb_rc_key ir_codes_af9015_table_digittrade[] = {
+static struct ir_scancode ir_codes_af9015_table_digittrade[] = {
 	{ 0x010f, KEY_LAST },	/* RETURN */
 	{ 0x0517, KEY_TEXT },	/* TELETEXT */
 	{ 0x0108, KEY_EPG },	/* EPG */
@@ -719,7 +719,7 @@ static u8 af9015_ir_table_digittrade[] = {
 };
 
 /* TREKSTOR DVB-T USB Stick */
-static struct dvb_usb_rc_key ir_codes_af9015_table_trekstor[] = {
+static struct ir_scancode ir_codes_af9015_table_trekstor[] = {
 	{ 0x0704, KEY_AGAIN },		/* Home */
 	{ 0x0705, KEY_MUTE },		/* Mute */
 	{ 0x0706, KEY_UP },			/* Up */
@@ -782,7 +782,7 @@ static u8 af9015_ir_table_trekstor[] = {
 };
 
 /* MSI DIGIVOX mini III */
-static struct dvb_usb_rc_key ir_codes_af9015_table_msi_digivox_iii[] = {
+static struct ir_scancode ir_codes_af9015_table_msi_digivox_iii[] = {
 	{ 0x0713, KEY_POWER },       /* [red power button] */
 	{ 0x073b, KEY_VIDEO },       /* Source */
 	{ 0x073e, KEY_ZOOM },        /* Zoom */

+ 16 - 12
drivers/media/dvb/dvb-usb/anysee.c

@@ -377,7 +377,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
 	u8 buf[] = {CMD_GET_IR_CODE};
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	u8 ircode[2];
 	int i, ret;
 
@@ -388,10 +388,10 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[0] &&
 		    rc5_data(&keymap[i]) == ircode[1]) {
-			*event = keymap[i].event;
+			*event = keymap[i].keycode;
 			*state = REMOTE_KEY_PRESSED;
 			return 0;
 		}
@@ -399,7 +399,7 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_anysee_table[] = {
+static struct ir_scancode ir_codes_anysee_table[] = {
 	{ 0x0100, KEY_0 },
 	{ 0x0101, KEY_1 },
 	{ 0x0102, KEY_2 },
@@ -463,6 +463,11 @@ static int anysee_probe(struct usb_interface *intf,
 	if (intf->num_altsetting < 1)
 		return -ENODEV;
 
+	/*
+	 * Anysee is always warm (its USB-bridge, Cypress FX2, uploads
+	 * firmware from eeprom).  If dvb_usb_device_init() succeeds that
+	 * means d is a valid pointer.
+	 */
 	ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
 		adapter_nr);
 	if (ret)
@@ -479,10 +484,7 @@ static int anysee_probe(struct usb_interface *intf,
 	if (ret)
 		return ret;
 
-	if (d)
-		ret = anysee_init(d);
-
-	return ret;
+	return anysee_init(d);
 }
 
 static struct usb_device_id anysee_table[] = {
@@ -518,10 +520,12 @@ static struct dvb_usb_device_properties anysee_properties = {
 		}
 	},
 
-	.rc_key_map       = ir_codes_anysee_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_anysee_table),
-	.rc_query         = anysee_rc_query,
-	.rc_interval      = 200,  /* windows driver uses 500ms */
+	.rc.legacy = {
+		.rc_key_map       = ir_codes_anysee_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_anysee_table),
+		.rc_query         = anysee_rc_query,
+		.rc_interval      = 200,  /* windows driver uses 500ms */
+	},
 
 	.i2c_algo         = &anysee_i2c_algo,
 

+ 8 - 5
drivers/media/dvb/dvb-usb/az6027.c

@@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 }
 
 /* keys for the enclosed remote control */
-static struct dvb_usb_rc_key ir_codes_az6027_table[] = {
+static struct ir_scancode ir_codes_az6027_table[] = {
 	{ 0x01, KEY_1 },
 	{ 0x02, KEY_2 },
 };
@@ -1125,10 +1125,13 @@ static struct dvb_usb_device_properties az6027_properties = {
 	.power_ctrl       = az6027_power_ctrl,
 	.read_mac_address = az6027_read_mac_addr,
  */
-	.rc_key_map       = ir_codes_az6027_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_az6027_table),
-	.rc_interval      = 400,
-	.rc_query         = az6027_rc_query,
+	.rc.legacy = {
+		.rc_key_map       = ir_codes_az6027_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_az6027_table),
+		.rc_interval      = 400,
+		.rc_query         = az6027_rc_query,
+	},
+
 	.i2c_algo         = &az6027_i2c_algo,
 
 	.num_device_descs = 5,

+ 7 - 5
drivers/media/dvb/dvb-usb/cinergyT2-core.c

@@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_cinergyt2_table[] = {
+static struct ir_scancode ir_codes_cinergyt2_table[] = {
 	{ 0x0401, KEY_POWER },
 	{ 0x0402, KEY_1 },
 	{ 0x0403, KEY_2 },
@@ -217,10 +217,12 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
 
 	.power_ctrl       = cinergyt2_power_ctrl,
 
-	.rc_interval      = 50,
-	.rc_key_map       = ir_codes_cinergyt2_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_cinergyt2_table),
-	.rc_query         = cinergyt2_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 50,
+		.rc_key_map       = ir_codes_cinergyt2_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_cinergyt2_table),
+		.rc_query         = cinergyt2_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 1,
 

+ 74 - 54
drivers/media/dvb/dvb-usb/cxusb.c

@@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl(
 
 static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	u8 ircode[4];
 	int i;
 
@@ -394,10 +394,10 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[2] &&
 		    rc5_data(&keymap[i]) == ircode[3]) {
-			*event = keymap[i].event;
+			*event = keymap[i].keycode;
 			*state = REMOTE_KEY_PRESSED;
 
 			return 0;
@@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
 				    int *state)
 {
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	u8 ircode[4];
 	int i;
 	struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
@@ -422,10 +422,10 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
 	if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
 		return 0;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[1] &&
 		    rc5_data(&keymap[i]) == ircode[2]) {
-			*event = keymap[i].event;
+			*event = keymap[i].keycode;
 			*state = REMOTE_KEY_PRESSED;
 
 			return 0;
@@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
 static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
 		int *state)
 {
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	u8 ircode[2];
 	int i;
 
@@ -448,10 +448,10 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
 	if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
 		return 0;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
 		if (rc5_custom(&keymap[i]) == ircode[0] &&
 		    rc5_data(&keymap[i]) == ircode[1]) {
-			*event = keymap[i].event;
+			*event = keymap[i].keycode;
 			*state = REMOTE_KEY_PRESSED;
 
 			return 0;
@@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
+static struct ir_scancode ir_codes_dvico_mce_table[] = {
 	{ 0xfe02, KEY_TV },
 	{ 0xfe0e, KEY_MP3 },
 	{ 0xfe1a, KEY_DVD },
@@ -509,7 +509,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
 	{ 0xfe4e, KEY_POWER },
 };
 
-static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
+static struct ir_scancode ir_codes_dvico_portable_table[] = {
 	{ 0xfc02, KEY_SETUP },       /* Profile */
 	{ 0xfc43, KEY_POWER2 },
 	{ 0xfc06, KEY_EPG },
@@ -548,7 +548,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
 	{ 0xfc00, KEY_UNKNOWN },    /* HD */
 };
 
-static struct dvb_usb_rc_key ir_codes_d680_dmb_table[] = {
+static struct ir_scancode ir_codes_d680_dmb_table[] = {
 	{ 0x0038, KEY_UNKNOWN },	/* TV/AV */
 	{ 0x080c, KEY_ZOOM },
 	{ 0x0800, KEY_0 },
@@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
 		return -EIO;
 
 	/* try to determine if there is no IR decoder on the I2C bus */
-	for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
+	for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) {
 		msleep(20);
 		if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
 			goto no_IR;
@@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
 			continue;
 		if (ircode[2] + ircode[3] != 0xff) {
 no_IR:
-			adap->dev->props.rc_key_map = NULL;
+			adap->dev->props.rc.legacy.rc_key_map = NULL;
 			info("No IR receiver detected on this device.");
 			break;
 		}
@@ -1451,10 +1451,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_portable_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_portable_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -1502,10 +1504,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
-	.rc_interval      = 150,
-	.rc_key_map       = ir_codes_dvico_mce_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 150,
+		.rc_key_map       = ir_codes_dvico_mce_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -1561,10 +1565,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_portable_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_portable_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 	.num_device_descs = 1,
@@ -1611,10 +1617,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_portable_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_portable_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -1660,10 +1668,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_mce_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
-	.rc_query         = cxusb_bluebird2_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_mce_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_query         = cxusb_bluebird2_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -1708,10 +1718,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_portable_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
-	.rc_query         = cxusb_bluebird2_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_portable_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_query         = cxusb_bluebird2_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -1758,10 +1770,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_portable_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_portable_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_portable_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -1849,10 +1863,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_dvico_mce_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
-	.rc_query         = cxusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_dvico_mce_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dvico_mce_table),
+		.rc_query         = cxusb_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -1897,10 +1913,12 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_d680_dmb_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
-	.rc_query         = cxusb_d680_dmb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_d680_dmb_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
+		.rc_query         = cxusb_d680_dmb_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -1946,10 +1964,12 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_d680_dmb_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
-	.rc_query         = cxusb_d680_dmb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_d680_dmb_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_d680_dmb_table),
+		.rc_query         = cxusb_d680_dmb_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {

+ 1 - 0
drivers/media/dvb/dvb-usb/dib0700.h

@@ -60,6 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
 extern struct i2c_algorithm dib0700_i2c_algo;
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold);
+extern int dib0700_change_protocol(void *priv, u64 ir_type);
 
 extern int dib0700_device_count;
 extern int dvb_usb_dib0700_ir_proto;

+ 122 - 144
drivers/media/dvb/dvb-usb/dib0700_core.c

@@ -13,10 +13,6 @@ int dvb_usb_dib0700_debug;
 module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
 
-int dvb_usb_dib0700_ir_proto = 1;
-module_param(dvb_usb_dib0700_ir_proto, int, 0644);
-MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
-
 static int nb_packet_buffer_size = 21;
 module_param(nb_packet_buffer_size, int, 0644);
 MODULE_PARM_DESC(nb_packet_buffer_size,
@@ -53,7 +49,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
 	int status;
 
 	deb_data(">>> ");
-	debug_dump(tx,txlen,deb_data);
+	debug_dump(tx, txlen, deb_data);
 
 	status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
 		tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
@@ -98,7 +94,7 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
 		deb_info("ep 0 read error (status = %d)\n",status);
 
 	deb_data("<<< ");
-	debug_dump(rx,rxlen,deb_data);
+	debug_dump(rx, rxlen, deb_data);
 
 	return status; /* length in case of success */
 }
@@ -106,28 +102,29 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
 int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
 {
 	u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
-	return dib0700_ctrl_wr(d,buf,3);
+	return dib0700_ctrl_wr(d, buf, sizeof(buf));
 }
 
 static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
 {
-    struct dib0700_state *st = d->priv;
-    u8 b[3];
-    int ret;
-
-    if (st->fw_version >= 0x10201) {
-	b[0] = REQUEST_SET_USB_XFER_LEN;
-	b[1] = (nb_ts_packets >> 8)&0xff;
-	b[2] = nb_ts_packets & 0xff;
-
-	deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
-
-	ret = dib0700_ctrl_wr(d, b, 3);
-    } else {
-	deb_info("this firmware does not allow to change the USB xfer len\n");
-	ret = -EIO;
-    }
-    return ret;
+	struct dib0700_state *st = d->priv;
+	u8 b[3];
+	int ret;
+
+	if (st->fw_version >= 0x10201) {
+		b[0] = REQUEST_SET_USB_XFER_LEN;
+		b[1] = (nb_ts_packets >> 8) & 0xff;
+		b[2] = nb_ts_packets & 0xff;
+
+		deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
+
+		ret = dib0700_ctrl_wr(d, b, sizeof(b));
+	} else {
+		deb_info("this firmware does not allow to change the USB xfer len\n");
+		ret = -EIO;
+	}
+
+	return ret;
 }
 
 /*
@@ -178,7 +175,8 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
 			value = ((en_start << 7) | (en_stop << 6) |
 				 (msg[i].len & 0x3F)) << 8 | i2c_dest;
 			/* I2C ctrl + FE bus; */
-			index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+			index = ((gen_mode << 6) & 0xC0) |
+				((bus_mode << 4) & 0x30);
 
 			result = usb_control_msg(d->udev,
 						 usb_rcvctrlpipe(d->udev, 0),
@@ -198,11 +196,12 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
 		} else {
 			/* Write request */
 			buf[0] = REQUEST_NEW_I2C_WRITE;
-			buf[1] = (msg[i].addr << 1);
+			buf[1] = msg[i].addr << 1;
 			buf[2] = (en_start << 7) | (en_stop << 6) |
 				(msg[i].len & 0x3F);
 			/* I2C ctrl + FE bus; */
-			buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
+			buf[3] = ((gen_mode << 6) & 0xC0) |
+				 ((bus_mode << 4) & 0x30);
 			/* The Actual i2c payload */
 			memcpy(&buf[4], msg[i].buf, msg[i].len);
 
@@ -240,7 +239,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
 
 	for (i = 0; i < num; i++) {
 		/* fill in the address */
-		buf[1] = (msg[i].addr << 1);
+		buf[1] = msg[i].addr << 1;
 		/* fill the buffer */
 		memcpy(&buf[2], msg[i].buf, msg[i].len);
 
@@ -368,7 +367,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 	u8 buf[260];
 
 	while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
-		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);
+		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
+				hx.addr, hx.len, hx.chk);
 
 		buf[0] = hx.len;
 		buf[1] = (hx.addr >> 8) & 0xff;
@@ -408,16 +408,16 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
 				  REQUEST_GET_VERSION,
 				  USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
 				  b, sizeof(b), USB_CTRL_GET_TIMEOUT);
-	fw_version = (b[8] << 24)  | (b[9] << 16)  | (b[10] << 8) | b[11];
+	fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
 
 	/* set the buffer size - DVB-USB is allocating URB buffers
 	 * only after the firwmare download was successful */
 	for (i = 0; i < dib0700_device_count; i++) {
 		for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
 				adap_num++) {
-			if (fw_version >= 0x10201)
+			if (fw_version >= 0x10201) {
 				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
-			else {
+			} else {
 				/* for fw version older than 1.20.1,
 				 * the buffersize has to be n times 512 */
 				dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
@@ -453,7 +453,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 	if (st->disable_streaming_master_mode == 1)
 		b[2] = 0x00;
 	else
-		b[2] = (0x01 << 4); /* Master mode */
+		b[2] = 0x01 << 4; /* Master mode */
 
 	b[3] = 0x00;
 
@@ -466,11 +466,44 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 
 	b[2] |= st->channel_state;
 
-	deb_info("data for streaming: %x %x\n",b[1],b[2]);
+	deb_info("data for streaming: %x %x\n", b[1], b[2]);
 
 	return dib0700_ctrl_wr(adap->dev, b, 4);
 }
 
+int dib0700_change_protocol(void *priv, u64 ir_type)
+{
+	struct dvb_usb_device *d = priv;
+	struct dib0700_state *st = d->priv;
+	u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
+	int new_proto, ret;
+
+	/* Set the IR mode */
+	if (ir_type == IR_TYPE_RC5)
+		new_proto = 1;
+	else if (ir_type == IR_TYPE_NEC)
+		new_proto = 0;
+	else if (ir_type == IR_TYPE_RC6) {
+		if (st->fw_version < 0x10200)
+			return -EINVAL;
+
+		new_proto = 2;
+	} else
+		return -EINVAL;
+
+	rc_setup[1] = new_proto;
+
+	ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
+	if (ret < 0) {
+		err("ir protocol setup failed");
+		return ret;
+	}
+
+	d->props.rc.core.protocol = ir_type;
+
+	return ret;
+}
+
 /* Number of keypresses to ignore before start repeating */
 #define RC_REPEAT_DELAY_V1_20 10
 
@@ -478,7 +511,13 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 struct dib0700_rc_response {
 	u8 report_id;
 	u8 data_state;
-	u16 system;
+	union {
+		u16 system16;
+		struct {
+			u8 system;
+			u8 not_system;
+		};
+	};
 	u8 data;
 	u8 not_data;
 };
@@ -487,14 +526,10 @@ struct dib0700_rc_response {
 static void dib0700_rc_urb_completion(struct urb *purb)
 {
 	struct dvb_usb_device *d = purb->context;
-	struct dvb_usb_rc_key *keymap;
 	struct dib0700_state *st;
-	struct dib0700_rc_response poll_reply;
-	u8 *buf;
-	int found = 0;
-	u32 event;
-	int state;
-	int i;
+	struct dib0700_rc_response *poll_reply;
+	u32 uninitialized_var(keycode);
+	u8 toggle;
 
 	deb_info("%s()\n", __func__);
 	if (d == NULL)
@@ -506,9 +541,8 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		return;
 	}
 
-	keymap = d->props.rc_key_map;
 	st = d->priv;
-	buf = (u8 *)purb->transfer_buffer;
+	poll_reply = purb->transfer_buffer;
 
 	if (purb->status < 0) {
 		deb_info("discontinuing polling\n");
@@ -521,104 +555,52 @@ static void dib0700_rc_urb_completion(struct urb *purb)
 		goto resubmit;
 	}
 
-	/* Set initial results in case we exit the function early */
-	event = 0;
-	state = REMOTE_NO_KEY_PRESSED;
-
-	deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
-		 buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);
+	deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n",
+		 poll_reply->report_id, poll_reply->data_state,
+		 poll_reply->system, poll_reply->not_system,
+		 poll_reply->data, poll_reply->not_data,
+		 purb->actual_length);
 
-	switch (dvb_usb_dib0700_ir_proto) {
-	case 0:
-		/* NEC Protocol */
-		poll_reply.report_id  = 0;
-		poll_reply.data_state = 1;
-		poll_reply.system     = buf[2];
-		poll_reply.data       = buf[4];
-		poll_reply.not_data   = buf[5];
+	switch (d->props.rc.core.protocol) {
+	case IR_TYPE_NEC:
+		toggle = 0;
 
 		/* NEC protocol sends repeat code as 0 0 0 FF */
-		if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
-		    && (poll_reply.not_data == 0xff)) {
-			poll_reply.data_state = 2;
+		if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
+		    && (poll_reply->not_data == 0xff)) {
+			poll_reply->data_state = 2;
 			break;
 		}
+
+		if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
+			deb_data("NEC extended protocol\n");
+			/* NEC extended code - 24 bits */
+			keycode = poll_reply->system16 << 8 | poll_reply->data;
+		} else {
+			deb_data("NEC normal protocol\n");
+			/* normal NEC code - 16 bits */
+			keycode = poll_reply->system << 8 | poll_reply->data;
+		}
+
 		break;
 	default:
+		deb_data("RC5 protocol\n");
 		/* RC5 Protocol */
-		poll_reply.report_id  = buf[0];
-		poll_reply.data_state = buf[1];
-		poll_reply.system     = (buf[2] << 8) | buf[3];
-		poll_reply.data       = buf[4];
-		poll_reply.not_data   = buf[5];
+		toggle = poll_reply->report_id;
+		keycode = poll_reply->system16 << 8 | poll_reply->data;
+
 		break;
 	}
 
-	if ((poll_reply.data + poll_reply.not_data) != 0xff) {
+	if ((poll_reply->data + poll_reply->not_data) != 0xff) {
 		/* Key failed integrity check */
 		err("key failed integrity check: %04x %02x %02x",
-		    poll_reply.system,
-		    poll_reply.data, poll_reply.not_data);
-		goto resubmit;
-	}
-
-	deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
-		 poll_reply.report_id, poll_reply.data_state,
-		 poll_reply.system, poll_reply.data, poll_reply.not_data);
-
-	/* Find the key in the map */
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
-		if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
-		    rc5_data(&keymap[i]) == poll_reply.data) {
-			event = keymap[i].event;
-			found = 1;
-			break;
-		}
-	}
-
-	if (found == 0) {
-		err("Unknown remote controller key: %04x %02x %02x",
-		    poll_reply.system, poll_reply.data, poll_reply.not_data);
-		d->last_event = 0;
+		    poll_reply->system,
+		    poll_reply->data, poll_reply->not_data);
 		goto resubmit;
 	}
 
-	if (poll_reply.data_state == 1) {
-		/* New key hit */
-		st->rc_counter = 0;
-		event = keymap[i].event;
-		state = REMOTE_KEY_PRESSED;
-		d->last_event = keymap[i].event;
-	} else if (poll_reply.data_state == 2) {
-		/* Key repeated */
-		st->rc_counter++;
-
-		/* prevents unwanted double hits */
-		if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
-			event = d->last_event;
-			state = REMOTE_KEY_PRESSED;
-			st->rc_counter = RC_REPEAT_DELAY_V1_20;
-		}
-	} else {
-		err("Unknown data state [%d]", poll_reply.data_state);
-	}
-
-	switch (state) {
-	case REMOTE_NO_KEY_PRESSED:
-		break;
-	case REMOTE_KEY_PRESSED:
-		deb_info("key pressed\n");
-		d->last_event = event;
-	case REMOTE_KEY_REPEAT:
-		deb_info("key repeated\n");
-		input_event(d->rc_input_dev, EV_KEY, event, 1);
-		input_sync(d->rc_input_dev);
-		input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
-		input_sync(d->rc_input_dev);
-		break;
-	default:
-		break;
-	}
+	ir_keydown(d->rc_input_dev, keycode, toggle);
 
 resubmit:
 	/* Clean the buffer before we requeue */
@@ -631,21 +613,10 @@ resubmit:
 int dib0700_rc_setup(struct dvb_usb_device *d)
 {
 	struct dib0700_state *st = d->priv;
-	u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
 	struct urb *purb;
 	int ret;
-	int i;
-
-	if (d->props.rc_key_map == NULL)
-		return 0;
-
-	/* Set the IR mode */
-	i = dib0700_ctrl_wr(d, rc_setup, 3);
-	if (i<0) {
-		err("ir protocol setup failed");
-		return -1;
-	}
 
+	/* Poll-based. Don't initialize bulk mode */
 	if (st->fw_version < 0x10200)
 		return 0;
 
@@ -653,14 +624,14 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
 	purb = usb_alloc_urb(0, GFP_KERNEL);
 	if (purb == NULL) {
 		err("rc usb alloc urb failed\n");
-		return -1;
+		return -ENOMEM;
 	}
 
 	purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
 	if (purb->transfer_buffer == NULL) {
 		err("rc kzalloc failed\n");
 		usb_free_urb(purb);
-		return -1;
+		return -ENOMEM;
 	}
 
 	purb->status = -EINPROGRESS;
@@ -669,12 +640,10 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
 			  dib0700_rc_urb_completion, d);
 
 	ret = usb_submit_urb(purb, GFP_ATOMIC);
-	if (ret != 0) {
+	if (ret)
 		err("rc submit urb failed\n");
-		return -1;
-	}
 
-	return 0;
+	return ret;
 }
 
 static int dib0700_probe(struct usb_interface *intf,
@@ -698,6 +667,15 @@ static int dib0700_probe(struct usb_interface *intf,
 			st->fw_version = fw_version;
 			st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
 
+			/* Disable polling mode on newer firmwares */
+			if (st->fw_version >= 0x10200)
+				dev->props.rc.core.bulk_mode = true;
+			else
+				dev->props.rc.core.bulk_mode = false;
+
+			/* Need a higher delay, to avoid wrong repeat */
+			dev->rc_input_dev->rep[REP_DELAY] = 500;
+
 			dib0700_rc_setup(dev);
 
 			return 0;

+ 230 - 384
drivers/media/dvb/dvb-usb/dib0700_devices.c

@@ -473,16 +473,19 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
 /* Number of keypresses to ignore before start repeating */
 #define RC_REPEAT_DELAY 6
 
-static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+/*
+ * This function is used only when firmware is < 1.20 version. Newer
+ * firmwares use bulk mode, with functions implemented at dib0700_core,
+ * at dib0700_rc_urb_completion()
+ */
+static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
 {
 	u8 key[4];
+	u32 keycode;
+	u8 toggle;
 	int i;
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
 	struct dib0700_state *st = d->priv;
 
-	*event = 0;
-	*state = REMOTE_NO_KEY_PRESSED;
-
 	if (st->fw_version >= 0x10200) {
 		/* For 1.20 firmware , We need to keep the RC polling
 		   callback so we can reuse the input device setup in
@@ -491,348 +494,45 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 		return 0;
 	}
 
-	i=dib0700_ctrl_rd(d,rc_request,2,key,4);
-	if (i<=0) {
+	i = dib0700_ctrl_rd(d, rc_request, 2, key, 4);
+	if (i <= 0) {
 		err("RC Query Failed");
 		return -1;
 	}
 
 	/* losing half of KEY_0 events from Philipps rc5 remotes.. */
-	if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
+	if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0)
+		return 0;
 
 	/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */
 
 	dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
 
-	switch (dvb_usb_dib0700_ir_proto) {
-	case 0: {
+	d->last_event = 0;
+	switch (d->props.rc.core.protocol) {
+	case IR_TYPE_NEC:
 		/* NEC protocol sends repeat code as 0 0 0 FF */
 		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
-		    (key[3] == 0xFF)) {
-			st->rc_counter++;
-			if (st->rc_counter > RC_REPEAT_DELAY) {
-				*event = d->last_event;
-				*state = REMOTE_KEY_PRESSED;
-				st->rc_counter = RC_REPEAT_DELAY;
-			}
-			return 0;
-		}
-		for (i=0;i<d->props.rc_key_map_size; i++) {
-			if (rc5_custom(&keymap[i]) == key[3-2] &&
-			    rc5_data(&keymap[i]) == key[3-3]) {
-				st->rc_counter = 0;
-				*event = keymap[i].event;
-				*state = REMOTE_KEY_PRESSED;
-				d->last_event = keymap[i].event;
-				return 0;
-			}
+		    (key[3] == 0xff))
+			keycode = d->last_event;
+		else {
+			keycode = key[3-2] << 8 | key[3-3];
+			d->last_event = keycode;
 		}
+
+		ir_keydown(d->rc_input_dev, keycode, 0);
 		break;
-	}
-	default: {
+	default:
 		/* RC-5 protocol changes toggle bit on new keypress */
-		for (i = 0; i < d->props.rc_key_map_size; i++) {
-			if (rc5_custom(&keymap[i]) == key[3-2] &&
-			    rc5_data(&keymap[i]) == key[3-3]) {
-				if (d->last_event == keymap[i].event &&
-					key[3-1] == st->rc_toggle) {
-					st->rc_counter++;
-					/* prevents unwanted double hits */
-					if (st->rc_counter > RC_REPEAT_DELAY) {
-						*event = d->last_event;
-						*state = REMOTE_KEY_PRESSED;
-						st->rc_counter = RC_REPEAT_DELAY;
-					}
-
-					return 0;
-				}
-				st->rc_counter = 0;
-				*event = keymap[i].event;
-				*state = REMOTE_KEY_PRESSED;
-				st->rc_toggle = key[3-1];
-				d->last_event = keymap[i].event;
-				return 0;
-			}
-		}
+		keycode = key[3-2] << 8 | key[3-3];
+		toggle = key[3-1];
+		ir_keydown(d->rc_input_dev, keycode, toggle);
+
 		break;
 	}
-	}
-	err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
-	d->last_event = 0;
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_dib0700_table[] = {
-	/* Key codes for the tiny Pinnacle remote*/
-	{ 0x0700, KEY_MUTE },
-	{ 0x0701, KEY_MENU }, /* Pinnacle logo */
-	{ 0x0739, KEY_POWER },
-	{ 0x0703, KEY_VOLUMEUP },
-	{ 0x0709, KEY_VOLUMEDOWN },
-	{ 0x0706, KEY_CHANNELUP },
-	{ 0x070c, KEY_CHANNELDOWN },
-	{ 0x070f, KEY_1 },
-	{ 0x0715, KEY_2 },
-	{ 0x0710, KEY_3 },
-	{ 0x0718, KEY_4 },
-	{ 0x071b, KEY_5 },
-	{ 0x071e, KEY_6 },
-	{ 0x0711, KEY_7 },
-	{ 0x0721, KEY_8 },
-	{ 0x0712, KEY_9 },
-	{ 0x0727, KEY_0 },
-	{ 0x0724, KEY_SCREEN }, /* 'Square' key */
-	{ 0x072a, KEY_TEXT },   /* 'T' key */
-	{ 0x072d, KEY_REWIND },
-	{ 0x0730, KEY_PLAY },
-	{ 0x0733, KEY_FASTFORWARD },
-	{ 0x0736, KEY_RECORD },
-	{ 0x073c, KEY_STOP },
-	{ 0x073f, KEY_CANCEL }, /* '?' key */
-	/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
-	{ 0xeb01, KEY_POWER },
-	{ 0xeb02, KEY_1 },
-	{ 0xeb03, KEY_2 },
-	{ 0xeb04, KEY_3 },
-	{ 0xeb05, KEY_4 },
-	{ 0xeb06, KEY_5 },
-	{ 0xeb07, KEY_6 },
-	{ 0xeb08, KEY_7 },
-	{ 0xeb09, KEY_8 },
-	{ 0xeb0a, KEY_9 },
-	{ 0xeb0b, KEY_VIDEO },
-	{ 0xeb0c, KEY_0 },
-	{ 0xeb0d, KEY_REFRESH },
-	{ 0xeb0f, KEY_EPG },
-	{ 0xeb10, KEY_UP },
-	{ 0xeb11, KEY_LEFT },
-	{ 0xeb12, KEY_OK },
-	{ 0xeb13, KEY_RIGHT },
-	{ 0xeb14, KEY_DOWN },
-	{ 0xeb16, KEY_INFO },
-	{ 0xeb17, KEY_RED },
-	{ 0xeb18, KEY_GREEN },
-	{ 0xeb19, KEY_YELLOW },
-	{ 0xeb1a, KEY_BLUE },
-	{ 0xeb1b, KEY_CHANNELUP },
-	{ 0xeb1c, KEY_VOLUMEUP },
-	{ 0xeb1d, KEY_MUTE },
-	{ 0xeb1e, KEY_VOLUMEDOWN },
-	{ 0xeb1f, KEY_CHANNELDOWN },
-	{ 0xeb40, KEY_PAUSE },
-	{ 0xeb41, KEY_HOME },
-	{ 0xeb42, KEY_MENU }, /* DVD Menu */
-	{ 0xeb43, KEY_SUBTITLE },
-	{ 0xeb44, KEY_TEXT }, /* Teletext */
-	{ 0xeb45, KEY_DELETE },
-	{ 0xeb46, KEY_TV },
-	{ 0xeb47, KEY_DVD },
-	{ 0xeb48, KEY_STOP },
-	{ 0xeb49, KEY_VIDEO },
-	{ 0xeb4a, KEY_AUDIO }, /* Music */
-	{ 0xeb4b, KEY_SCREEN }, /* Pic */
-	{ 0xeb4c, KEY_PLAY },
-	{ 0xeb4d, KEY_BACK },
-	{ 0xeb4e, KEY_REWIND },
-	{ 0xeb4f, KEY_FASTFORWARD },
-	{ 0xeb54, KEY_PREVIOUS },
-	{ 0xeb58, KEY_RECORD },
-	{ 0xeb5c, KEY_NEXT },
-
-	/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-	{ 0x1e0a, KEY_KPASTERISK },
-	{ 0x1e0b, KEY_RED },
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_GRAVE }, /* # */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_CHANNEL },
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },
-	{ 0x1e19, KEY_AUDIO },
-	{ 0x1e1a, KEY_MEDIA },
-	{ 0x1e1b, KEY_EPG },
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXT },
-	{ 0x1e1f, KEY_BACK },
-	{ 0x1e20, KEY_CHANNELUP },
-	{ 0x1e21, KEY_CHANNELDOWN },
-	{ 0x1e24, KEY_LAST }, /* Skip backwards */
-	{ 0x1e25, KEY_OK },
-	{ 0x1e29, KEY_BLUE},
-	{ 0x1e2e, KEY_GREEN },
-	{ 0x1e30, KEY_PAUSE },
-	{ 0x1e32, KEY_REWIND },
-	{ 0x1e34, KEY_FASTFORWARD },
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },
-	{ 0x1e38, KEY_YELLOW },
-	{ 0x1e3b, KEY_GOTO },
-	{ 0x1e3d, KEY_POWER },
-
-	/* Key codes for the Leadtek Winfast DTV Dongle */
-	{ 0x0042, KEY_POWER },
-	{ 0x077c, KEY_TUNER },
-	{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
-	{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
-	{ 0x0f71, KEY_DOT }, /* frequency */
-	{ 0x0743, KEY_0 },
-	{ 0x0c41, KEY_1 },
-	{ 0x0443, KEY_2 },
-	{ 0x0b7f, KEY_3 },
-	{ 0x0e41, KEY_4 },
-	{ 0x0643, KEY_5 },
-	{ 0x097f, KEY_6 },
-	{ 0x0d7e, KEY_7 },
-	{ 0x057c, KEY_8 },
-	{ 0x0a40, KEY_9 },
-	{ 0x0e4e, KEY_CLEAR },
-	{ 0x047c, KEY_CHANNEL }, /* show channel number */
-	{ 0x0f41, KEY_LAST }, /* recall */
-	{ 0x0342, KEY_MUTE },
-	{ 0x064c, KEY_RESERVED }, /* PIP button*/
-	{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
-	{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
-	{ 0x0b70, KEY_RECORD },
-	{ 0x037d, KEY_VOLUMEUP },
-	{ 0x017d, KEY_VOLUMEDOWN },
-	{ 0x0242, KEY_CHANNELUP },
-	{ 0x007d, KEY_CHANNELDOWN },
-
-	/* Key codes for Nova-TD "credit card" remote control. */
-	{ 0x1d00, KEY_0 },
-	{ 0x1d01, KEY_1 },
-	{ 0x1d02, KEY_2 },
-	{ 0x1d03, KEY_3 },
-	{ 0x1d04, KEY_4 },
-	{ 0x1d05, KEY_5 },
-	{ 0x1d06, KEY_6 },
-	{ 0x1d07, KEY_7 },
-	{ 0x1d08, KEY_8 },
-	{ 0x1d09, KEY_9 },
-	{ 0x1d0a, KEY_TEXT },
-	{ 0x1d0d, KEY_MENU },
-	{ 0x1d0f, KEY_MUTE },
-	{ 0x1d10, KEY_VOLUMEUP },
-	{ 0x1d11, KEY_VOLUMEDOWN },
-	{ 0x1d12, KEY_CHANNEL },
-	{ 0x1d14, KEY_UP },
-	{ 0x1d15, KEY_DOWN },
-	{ 0x1d16, KEY_LEFT },
-	{ 0x1d17, KEY_RIGHT },
-	{ 0x1d1c, KEY_TV },
-	{ 0x1d1e, KEY_NEXT },
-	{ 0x1d1f, KEY_BACK },
-	{ 0x1d20, KEY_CHANNELUP },
-	{ 0x1d21, KEY_CHANNELDOWN },
-	{ 0x1d24, KEY_LAST },
-	{ 0x1d25, KEY_OK },
-	{ 0x1d30, KEY_PAUSE },
-	{ 0x1d32, KEY_REWIND },
-	{ 0x1d34, KEY_FASTFORWARD },
-	{ 0x1d35, KEY_PLAY },
-	{ 0x1d36, KEY_STOP },
-	{ 0x1d37, KEY_RECORD },
-	{ 0x1d3b, KEY_GOTO },
-	{ 0x1d3d, KEY_POWER },
-
-	/* Key codes for the Pixelview SBTVD remote (proto NEC) */
-	{ 0x8613, KEY_MUTE },
-	{ 0x8612, KEY_POWER },
-	{ 0x8601, KEY_1 },
-	{ 0x8602, KEY_2 },
-	{ 0x8603, KEY_3 },
-	{ 0x8604, KEY_4 },
-	{ 0x8605, KEY_5 },
-	{ 0x8606, KEY_6 },
-	{ 0x8607, KEY_7 },
-	{ 0x8608, KEY_8 },
-	{ 0x8609, KEY_9 },
-	{ 0x8600, KEY_0 },
-	{ 0x860d, KEY_CHANNELUP },
-	{ 0x8619, KEY_CHANNELDOWN },
-	{ 0x8610, KEY_VOLUMEUP },
-	{ 0x860c, KEY_VOLUMEDOWN },
-
-	{ 0x860a, KEY_CAMERA },
-	{ 0x860b, KEY_ZOOM },
-	{ 0x861b, KEY_BACKSPACE },
-	{ 0x8615, KEY_ENTER },
-
-	{ 0x861d, KEY_UP },
-	{ 0x861e, KEY_DOWN },
-	{ 0x860e, KEY_LEFT },
-	{ 0x860f, KEY_RIGHT },
-
-	{ 0x8618, KEY_RECORD },
-	{ 0x861a, KEY_STOP },
-
-	/* Key codes for the EvolutePC TVWay+ remote (proto NEC) */
-	{ 0x7a00, KEY_MENU },
-	{ 0x7a01, KEY_RECORD },
-	{ 0x7a02, KEY_PLAY },
-	{ 0x7a03, KEY_STOP },
-	{ 0x7a10, KEY_CHANNELUP },
-	{ 0x7a11, KEY_CHANNELDOWN },
-	{ 0x7a12, KEY_VOLUMEUP },
-	{ 0x7a13, KEY_VOLUMEDOWN },
-	{ 0x7a40, KEY_POWER },
-	{ 0x7a41, KEY_MUTE },
-
-	/* Key codes for the Elgato EyeTV Diversity silver remote,
-	   set dvb_usb_dib0700_ir_proto=0 */
-	{ 0x4501, KEY_POWER },
-	{ 0x4502, KEY_MUTE },
-	{ 0x4503, KEY_1 },
-	{ 0x4504, KEY_2 },
-	{ 0x4505, KEY_3 },
-	{ 0x4506, KEY_4 },
-	{ 0x4507, KEY_5 },
-	{ 0x4508, KEY_6 },
-	{ 0x4509, KEY_7 },
-	{ 0x450a, KEY_8 },
-	{ 0x450b, KEY_9 },
-	{ 0x450c, KEY_LAST },
-	{ 0x450d, KEY_0 },
-	{ 0x450e, KEY_ENTER },
-	{ 0x450f, KEY_RED },
-	{ 0x4510, KEY_CHANNELUP },
-	{ 0x4511, KEY_GREEN },
-	{ 0x4512, KEY_VOLUMEDOWN },
-	{ 0x4513, KEY_OK },
-	{ 0x4514, KEY_VOLUMEUP },
-	{ 0x4515, KEY_YELLOW },
-	{ 0x4516, KEY_CHANNELDOWN },
-	{ 0x4517, KEY_BLUE },
-	{ 0x4518, KEY_LEFT }, /* Skip backwards */
-	{ 0x4519, KEY_PLAYPAUSE },
-	{ 0x451a, KEY_RIGHT }, /* Skip forward */
-	{ 0x451b, KEY_REWIND },
-	{ 0x451c, KEY_L }, /* Live */
-	{ 0x451d, KEY_FASTFORWARD },
-	{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
-	{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
-	{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
-	{ 0x4541, KEY_SCREEN }, /*  Full screen toggle, 'Hold' for Teletext */
-	{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
-};
-
 /* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
 static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
 	BAND_UHF | BAND_VHF,
@@ -2168,10 +1868,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			}
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 2,
@@ -2197,10 +1904,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 2,
@@ -2251,11 +1965,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
-
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 1,
@@ -2288,10 +2008,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			}
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 1,
@@ -2358,11 +2086,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
-
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 1,
@@ -2397,11 +2132,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
-
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 2,
@@ -2431,7 +2173,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			}
 		},
 
-		.num_device_descs = 7,
+		.num_device_descs = 6,
 		.devices = {
 			{   "DiBcom STK7070PD reference design",
 				{ &dib0700_usb_id_table[17], NULL },
@@ -2458,15 +2200,69 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 				{ &dib0700_usb_id_table[44], NULL },
 				{ NULL },
 			},
+		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+		.num_adapters = 2,
+		.adapter = {
+			{
+				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter       = stk70x0p_pid_filter,
+				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = stk7070pd_frontend_attach0,
+				.tuner_attach     = dib7070p_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv     = sizeof(struct dib0700_adapter_state),
+			}, {
+				.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter       = stk70x0p_pid_filter,
+				.pid_filter_ctrl  = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = stk7070pd_frontend_attach1,
+				.tuner_attach     = dib7070p_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+
+				.size_of_priv     = sizeof(struct dib0700_adapter_state),
+			}
+		},
+
+		.num_device_descs = 1,
+		.devices = {
 			{   "Elgato EyeTV Diversity",
 				{ &dib0700_usb_id_table[68], NULL },
 				{ NULL },
 			},
 		},
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 
 		.num_adapters = 1,
@@ -2525,10 +2321,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 				{ NULL },
 			},
 		},
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
 		.adapter = {
@@ -2554,10 +2359,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 				{ NULL },
 			},
 		},
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
 		.adapter = {
@@ -2615,10 +2429,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 				{ NULL },
 			},
 		},
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
 		.adapter = {
@@ -2653,11 +2476,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
-
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_NEC_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 2,
 		.adapter = {
@@ -2697,10 +2527,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
 		.num_adapters = 1,
 		.adapter = {
@@ -2728,10 +2566,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
 			},
 		},
 
-		.rc_interval      = DEFAULT_RC_INTERVAL,
-		.rc_key_map       = ir_codes_dib0700_table,
-		.rc_key_map_size  = ARRAY_SIZE(ir_codes_dib0700_table),
-		.rc_query         = dib0700_rc_query
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.rc_props = {
+				.allowed_protos = IR_TYPE_RC5 |
+						  IR_TYPE_RC6 |
+						  IR_TYPE_NEC,
+				.change_protocol = dib0700_change_protocol,
+			},
+		},
 	},
 };
 

+ 1 - 1
drivers/media/dvb/dvb-usb/dibusb-common.c

@@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
 /*
  * common remote control stuff
  */
-struct dvb_usb_rc_key ir_codes_dibusb_table[] = {
+struct ir_scancode ir_codes_dibusb_table[] = {
 	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
 	{ 0x0016, KEY_POWER },
 	{ 0x0010, KEY_MUTE },

+ 24 - 16
drivers/media/dvb/dvb-usb/dibusb-mb.c

@@ -211,10 +211,12 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
 
 	.power_ctrl       = dibusb_power_ctrl,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_dibusb_table,
-	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-	.rc_query         = dibusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_dibusb_table,
+		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_query         = dibusb_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 
@@ -295,10 +297,12 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
 	},
 	.power_ctrl       = dibusb_power_ctrl,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_dibusb_table,
-	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-	.rc_query         = dibusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_dibusb_table,
+		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_query         = dibusb_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 
@@ -359,10 +363,12 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
 	},
 	.power_ctrl       = dibusb2_0_power_ctrl,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_dibusb_table,
-	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-	.rc_query         = dibusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_dibusb_table,
+		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_query         = dibusb_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 
@@ -416,10 +422,12 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
 	},
 	.power_ctrl       = dibusb2_0_power_ctrl,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_dibusb_table,
-	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
-	.rc_query         = dibusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_dibusb_table,
+		.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
+		.rc_query         = dibusb_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 

+ 6 - 4
drivers/media/dvb/dvb-usb/dibusb-mc.c

@@ -81,10 +81,12 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
 	},
 	.power_ctrl       = dibusb2_0_power_ctrl,
 
-	.rc_interval      = DEFAULT_RC_INTERVAL,
-	.rc_key_map       = ir_codes_dibusb_table,
-	.rc_key_map_size  = 111, /* FIXME */
-	.rc_query         = dibusb_rc_query,
+	.rc.legacy = {
+		.rc_interval      = DEFAULT_RC_INTERVAL,
+		.rc_key_map       = ir_codes_dibusb_table,
+		.rc_key_map_size  = 111, /* FIXME */
+		.rc_query         = dibusb_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 

+ 1 - 1
drivers/media/dvb/dvb-usb/dibusb.h

@@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
 #define DEFAULT_RC_INTERVAL 150
 //#define DEFAULT_RC_INTERVAL 100000
 
-extern struct dvb_usb_rc_key ir_codes_dibusb_table[];
+extern struct ir_scancode ir_codes_dibusb_table[];
 extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
 extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
 

+ 11 - 9
drivers/media/dvb/dvb-usb/digitv.c

@@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_digitv_table[] = {
+static struct ir_scancode ir_codes_digitv_table[] = {
 	{ 0x5f55, KEY_0 },
 	{ 0x6f55, KEY_1 },
 	{ 0x9f55, KEY_2 },
@@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	/* if something is inside the buffer, simulate key press */
 	if (key[1] != 0)
 	{
-		  for (i = 0; i < d->props.rc_key_map_size; i++) {
-			if (rc5_custom(&d->props.rc_key_map[i]) == key[1] &&
-			    rc5_data(&d->props.rc_key_map[i]) == key[2]) {
-				*event = d->props.rc_key_map[i].event;
+		  for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+			if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] &&
+			    rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) {
+				*event = d->props.rc.legacy.rc_key_map[i].keycode;
 				*state = REMOTE_KEY_PRESSED;
 				return 0;
 			}
@@ -310,10 +310,12 @@ static struct dvb_usb_device_properties digitv_properties = {
 	},
 	.identify_state   = digitv_identify_state,
 
-	.rc_interval      = 1000,
-	.rc_key_map       = ir_codes_digitv_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_digitv_table),
-	.rc_query         = digitv_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 1000,
+		.rc_key_map       = ir_codes_digitv_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_digitv_table),
+		.rc_query         = digitv_rc_query,
+	},
 
 	.i2c_algo         = &digitv_i2c_algo,
 

+ 25 - 17
drivers/media/dvb/dvb-usb/dtt200u.c

@@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
 
 /* remote control */
 /* key list for the tiny remote control (Yakumo, don't know about the others) */
-static struct dvb_usb_rc_key ir_codes_dtt200u_table[] = {
+static struct ir_scancode ir_codes_dtt200u_table[] = {
 	{ 0x8001, KEY_MUTE },
 	{ 0x8002, KEY_CHANNELDOWN },
 	{ 0x8003, KEY_VOLUMEDOWN },
@@ -161,10 +161,12 @@ static struct dvb_usb_device_properties dtt200u_properties = {
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
 
-	.rc_interval     = 300,
-	.rc_key_map      = ir_codes_dtt200u_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
-	.rc_query        = dtt200u_rc_query,
+	.rc.legacy = {
+		.rc_interval     = 300,
+		.rc_key_map      = ir_codes_dtt200u_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_query        = dtt200u_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -206,10 +208,12 @@ static struct dvb_usb_device_properties wt220u_properties = {
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
 
-	.rc_interval     = 300,
-	.rc_key_map      = ir_codes_dtt200u_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
-	.rc_query        = dtt200u_rc_query,
+	.rc.legacy = {
+		.rc_interval     = 300,
+		.rc_key_map      = ir_codes_dtt200u_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_query        = dtt200u_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -251,10 +255,12 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
 
-	.rc_interval     = 300,
-	.rc_key_map      = ir_codes_dtt200u_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
-	.rc_query        = dtt200u_rc_query,
+	.rc.legacy = {
+		.rc_interval     = 300,
+		.rc_key_map      = ir_codes_dtt200u_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_query        = dtt200u_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
@@ -296,10 +302,12 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
 	},
 	.power_ctrl      = dtt200u_power_ctrl,
 
-	.rc_interval     = 300,
-	.rc_key_map      = ir_codes_dtt200u_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
-	.rc_query        = dtt200u_rc_query,
+	.rc.legacy = {
+		.rc_interval     = 300,
+		.rc_key_map      = ir_codes_dtt200u_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
+		.rc_query        = dtt200u_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 

+ 1 - 0
drivers/media/dvb/dvb-usb/dvb-usb-ids.h

@@ -197,6 +197,7 @@
 #define USB_PID_AVERMEDIA_A310				0xa310
 #define USB_PID_AVERMEDIA_A850				0x850a
 #define USB_PID_AVERMEDIA_A805				0xa805
+#define USB_PID_AVERMEDIA_A815M				0x815a
 #define USB_PID_TECHNOTREND_CONNECT_S2400               0x3006
 #define USB_PID_TECHNOTREND_CONNECT_CT3650		0x300d
 #define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY	0x005a

+ 31 - 29
drivers/media/dvb/dvb-usb/dvb-usb-init.c

@@ -15,7 +15,7 @@
 
 /* debug */
 int dvb_usb_debug;
-module_param_named(debug,dvb_usb_debug, int, 0644);
+module_param_named(debug, dvb_usb_debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256  (or-able))." DVB_USB_DEBUG_STATUS);
 
 int dvb_usb_disable_rc_polling;
@@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
 static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 {
 	struct dvb_usb_adapter *adap;
-	int ret,n;
+	int ret, n;
 
 	for (n = 0; n < d->props.num_adapters; n++) {
 		adap = &d->adapter[n];
@@ -38,7 +38,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 
 		memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
 
-/* speed - when running at FULL speed we need a HW PID filter */
+		/* speed - when running at FULL speed we need a HW PID filter */
 		if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
 			err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
 			return -ENODEV;
@@ -46,7 +46,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 
 		if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
 			(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
-			info("will use the device's hardware PID filter (table count: %d).",adap->props.pid_filter_count);
+			info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
 			adap->pid_filtering  = 1;
 			adap->max_feed_count = adap->props.pid_filter_count;
 		} else {
@@ -64,9 +64,9 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 		}
 
 		if (adap->props.size_of_priv > 0) {
-			adap->priv = kzalloc(adap->props.size_of_priv,GFP_KERNEL);
+			adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
 			if (adap->priv == NULL) {
-				err("no memory for priv for adapter %d.",n);
+				err("no memory for priv for adapter %d.", n);
 				return -ENOMEM;
 			}
 		}
@@ -86,8 +86,8 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 	 * sometimes a timeout occures, this helps
 	 */
 	if (d->props.generic_bulk_ctrl_endpoint != 0) {
-		usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
-		usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+		usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
+		usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
 	}
 
 	return 0;
@@ -96,6 +96,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
 static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
 {
 	int n;
+
 	for (n = 0; n < d->num_adapters_initialized; n++) {
 		dvb_usb_adapter_frontend_exit(&d->adapter[n]);
 		dvb_usb_adapter_dvb_exit(&d->adapter[n]);
@@ -111,11 +112,11 @@ static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
 /* general initialization functions */
 static int dvb_usb_exit(struct dvb_usb_device *d)
 {
-	deb_info("state before exiting everything: %x\n",d->state);
+	deb_info("state before exiting everything: %x\n", d->state);
 	dvb_usb_remote_exit(d);
 	dvb_usb_adapter_exit(d);
 	dvb_usb_i2c_exit(d);
-	deb_info("state should be zero now: %x\n",d->state);
+	deb_info("state should be zero now: %x\n", d->state);
 	d->state = DVB_USB_STATE_INIT;
 	kfree(d->priv);
 	kfree(d);
@@ -132,14 +133,14 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
 	d->state = DVB_USB_STATE_INIT;
 
 	if (d->props.size_of_priv > 0) {
-		d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
+		d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
 		if (d->priv == NULL) {
 			err("no memory for priv in 'struct dvb_usb_device'");
 			return -ENOMEM;
 		}
 	}
 
-/* check the capabilities and set appropriate variables */
+	/* check the capabilities and set appropriate variables */
 	dvb_usb_device_power_ctrl(d, 1);
 
 	if ((ret = dvb_usb_i2c_init(d)) ||
@@ -157,16 +158,17 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
 }
 
 /* determine the name and the state of the just found USB device */
-static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_device_properties *props, int *cold)
+static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold)
 {
-	int i,j;
+	int i, j;
 	struct dvb_usb_device_description *desc = NULL;
+
 	*cold = -1;
 
 	for (i = 0; i < props->num_device_descs; i++) {
 
 		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
-			deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
+			deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
 			if (props->devices[i].cold_ids[j]->idVendor  == le16_to_cpu(udev->descriptor.idVendor) &&
 				props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
 				*cold = 1;
@@ -179,7 +181,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
 			break;
 
 		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
-			deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
+			deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
 			if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
 				props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
 				*cold = 0;
@@ -190,7 +192,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
 	}
 
 	if (desc != NULL && props->identify_state != NULL)
-		props->identify_state(udev,props,&desc,cold);
+		props->identify_state(udev, props, &desc, cold);
 
 	return desc;
 }
@@ -202,7 +204,7 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
 	else
 		d->powered--;
 
-	if (d->powered == 0 || (onoff && d->powered == 1)) { // when switching from 1 to 0 or from 0 to 1
+	if (d->powered == 0 || (onoff && d->powered == 1)) { /* when switching from 1 to 0 or from 0 to 1 */
 		deb_info("power control: %d\n", onoff);
 		if (d->props.power_ctrl)
 			return d->props.power_ctrl(d, onoff);
@@ -222,32 +224,32 @@ int dvb_usb_device_init(struct usb_interface *intf,
 	struct dvb_usb_device *d = NULL;
 	struct dvb_usb_device_description *desc = NULL;
 
-	int ret = -ENOMEM,cold=0;
+	int ret = -ENOMEM, cold = 0;
 
 	if (du != NULL)
 		*du = NULL;
 
-	if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
+	if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
 		deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
 		return -ENODEV;
 	}
 
 	if (cold) {
-		info("found a '%s' in cold state, will try to load a firmware",desc->name);
-		ret = dvb_usb_download_firmware(udev,props);
+		info("found a '%s' in cold state, will try to load a firmware", desc->name);
+		ret = dvb_usb_download_firmware(udev, props);
 		if (!props->no_reconnect || ret != 0)
 			return ret;
 	}
 
-	info("found a '%s' in warm state.",desc->name);
-		d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+	info("found a '%s' in warm state.", desc->name);
+	d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
 	if (d == NULL) {
 		err("no memory for 'struct dvb_usb_device'");
 		return -ENOMEM;
 	}
 
 	d->udev = udev;
-	memcpy(&d->props,props,sizeof(struct dvb_usb_device_properties));
+	memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
 	d->desc = desc;
 	d->owner = owner;
 
@@ -259,9 +261,9 @@ int dvb_usb_device_init(struct usb_interface *intf,
 	ret = dvb_usb_init(d, adapter_nums);
 
 	if (ret == 0)
-		info("%s successfully initialized and connected.",desc->name);
+		info("%s successfully initialized and connected.", desc->name);
 	else
-		info("%s error while loading driver (%d)",desc->name,ret);
+		info("%s error while loading driver (%d)", desc->name, ret);
 	return ret;
 }
 EXPORT_SYMBOL(dvb_usb_device_init);
@@ -271,12 +273,12 @@ void dvb_usb_device_exit(struct usb_interface *intf)
 	struct dvb_usb_device *d = usb_get_intfdata(intf);
 	const char *name = "generic DVB-USB module";
 
-	usb_set_intfdata(intf,NULL);
+	usb_set_intfdata(intf, NULL);
 	if (d != NULL && d->desc != NULL) {
 		name = d->desc->name;
 		dvb_usb_exit(d);
 	}
-	info("%s successfully deinitialized and disconnected.",name);
+	info("%s successfully deinitialized and disconnected.", name);
 
 }
 EXPORT_SYMBOL(dvb_usb_device_exit);

+ 140 - 58
drivers/media/dvb/dvb-usb/dvb-usb-remote.c

@@ -8,29 +8,29 @@
 #include "dvb-usb-common.h"
 #include <linux/usb/input.h>
 
-static int dvb_usb_getkeycode(struct input_dev *dev,
+static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
 				unsigned int scancode, unsigned int *keycode)
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
 
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	int i;
 
 	/* See if we can match the raw key code. */
-	for (i = 0; i < d->props.rc_key_map_size; i++)
-		if (keymap[i].scan == scancode) {
-			*keycode = keymap[i].event;
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+		if (keymap[i].scancode == scancode) {
+			*keycode = keymap[i].keycode;
 			return 0;
 		}
 
 	/*
 	 * If is there extra space, returns KEY_RESERVED,
-	 * otherwise, input core won't let dvb_usb_setkeycode
+	 * otherwise, input core won't let legacy_dvb_usb_setkeycode
 	 * to work
 	 */
-	for (i = 0; i < d->props.rc_key_map_size; i++)
-		if (keymap[i].event == KEY_RESERVED ||
-		    keymap[i].event == KEY_UNKNOWN) {
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+		if (keymap[i].keycode == KEY_RESERVED ||
+		    keymap[i].keycode == KEY_UNKNOWN) {
 			*keycode = KEY_RESERVED;
 			return 0;
 		}
@@ -38,27 +38,27 @@ static int dvb_usb_getkeycode(struct input_dev *dev,
 	return -EINVAL;
 }
 
-static int dvb_usb_setkeycode(struct input_dev *dev,
+static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
 				unsigned int scancode, unsigned int keycode)
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
 
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	int i;
 
 	/* Search if it is replacing an existing keycode */
-	for (i = 0; i < d->props.rc_key_map_size; i++)
-		if (keymap[i].scan == scancode) {
-			keymap[i].event = keycode;
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+		if (keymap[i].scancode == scancode) {
+			keymap[i].keycode = keycode;
 			return 0;
 		}
 
 	/* Search if is there a clean entry. If so, use it */
-	for (i = 0; i < d->props.rc_key_map_size; i++)
-		if (keymap[i].event == KEY_RESERVED ||
-		    keymap[i].event == KEY_UNKNOWN) {
-			keymap[i].scan = scancode;
-			keymap[i].event = keycode;
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+		if (keymap[i].keycode == KEY_RESERVED ||
+		    keymap[i].keycode == KEY_UNKNOWN) {
+			keymap[i].scancode = scancode;
+			keymap[i].keycode = keycode;
 			return 0;
 		}
 
@@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev,
  *
  * TODO: Fix the repeat rate of the input device.
  */
-static void dvb_usb_read_remote_control(struct work_struct *work)
+static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
 {
 	struct dvb_usb_device *d =
 		container_of(work, struct dvb_usb_device, rc_query_work.work);
@@ -92,7 +92,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
 	if (dvb_usb_disable_rc_polling)
 		return;
 
-	if (d->props.rc_query(d,&event,&state)) {
+	if (d->props.rc.legacy.rc_query(d,&event,&state)) {
 		err("error while querying for an remote control event.");
 		goto schedule;
 	}
@@ -151,18 +151,117 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
 */
 
 schedule:
-	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
+}
+
+static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d,
+				      struct input_dev *input_dev)
+{
+	int i, err, rc_interval;
+
+	input_dev->getkeycode = legacy_dvb_usb_getkeycode;
+	input_dev->setkeycode = legacy_dvb_usb_setkeycode;
+
+	/* set the bits for the keys */
+	deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size);
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
+		deb_rc("setting bit for event %d item %d\n",
+			d->props.rc.legacy.rc_key_map[i].keycode, i);
+		set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit);
+	}
+
+	/* setting these two values to non-zero, we have to manage key repeats */
+	input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
+	input_dev->rep[REP_DELAY]  = d->props.rc.legacy.rc_interval + 150;
+
+	input_set_drvdata(input_dev, d);
+
+	err = input_register_device(input_dev);
+	if (err)
+		input_free_device(input_dev);
+
+	rc_interval = d->props.rc.legacy.rc_interval;
+
+	INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
+
+	info("schedule remote query interval to %d msecs.", rc_interval);
+	schedule_delayed_work(&d->rc_query_work,
+			      msecs_to_jiffies(rc_interval));
+
+	d->state |= DVB_USB_STATE_REMOTE;
+
+	return err;
+}
+
+/* Remote-control poll function - called every dib->rc_query_interval ms to see
+ * whether the remote control has received anything.
+ *
+ * TODO: Fix the repeat rate of the input device.
+ */
+static void dvb_usb_read_remote_control(struct work_struct *work)
+{
+	struct dvb_usb_device *d =
+		container_of(work, struct dvb_usb_device, rc_query_work.work);
+	int err;
+
+	/* TODO: need a lock here.  We can simply skip checking for the remote control
+	   if we're busy. */
+
+	/* when the parameter has been set to 1 via sysfs while the
+	 * driver was running, or when bulk mode is enabled after IR init
+	 */
+	if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
+		return;
+
+	err = d->props.rc.core.rc_query(d);
+	if (err)
+		err("error %d while querying for an remote control event.", err);
+
+	schedule_delayed_work(&d->rc_query_work,
+			      msecs_to_jiffies(d->props.rc.core.rc_interval));
+}
+
+static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
+				       struct input_dev *input_dev)
+{
+	int err, rc_interval;
+
+	d->props.rc.core.rc_props.priv = d;
+	err = ir_input_register(input_dev,
+				 d->props.rc.core.rc_codes,
+				 &d->props.rc.core.rc_props,
+				 d->props.rc.core.module_name);
+	if (err < 0)
+		return err;
+
+	if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
+		return 0;
+
+	/* Polling mode - initialize a work queue for handling it */
+	INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
+
+	rc_interval = d->props.rc.core.rc_interval;
+
+	info("schedule remote query interval to %d msecs.", rc_interval);
+	schedule_delayed_work(&d->rc_query_work,
+			      msecs_to_jiffies(rc_interval));
+
+	return 0;
 }
 
 int dvb_usb_remote_init(struct dvb_usb_device *d)
 {
 	struct input_dev *input_dev;
-	int i;
 	int err;
 
-	if (d->props.rc_key_map == NULL ||
-		d->props.rc_query == NULL ||
-		dvb_usb_disable_rc_polling)
+	if (dvb_usb_disable_rc_polling)
+		return 0;
+
+	if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query)
+		d->props.rc.mode = DVB_RC_LEGACY;
+	else if (d->props.rc.core.rc_codes)
+		d->props.rc.mode = DVB_RC_CORE;
+	else
 		return 0;
 
 	usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
@@ -177,39 +276,19 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
 	input_dev->phys = d->rc_phys;
 	usb_to_input_id(d->udev, &input_dev->id);
 	input_dev->dev.parent = &d->udev->dev;
-	input_dev->getkeycode = dvb_usb_getkeycode;
-	input_dev->setkeycode = dvb_usb_setkeycode;
-
-	/* set the bits for the keys */
-	deb_rc("key map size: %d\n", d->props.rc_key_map_size);
-	for (i = 0; i < d->props.rc_key_map_size; i++) {
-		deb_rc("setting bit for event %d item %d\n",
-			d->props.rc_key_map[i].event, i);
-		set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
-	}
 
 	/* Start the remote-control polling. */
-	if (d->props.rc_interval < 40)
-		d->props.rc_interval = 100; /* default */
-
-	/* setting these two values to non-zero, we have to manage key repeats */
-	input_dev->rep[REP_PERIOD] = d->props.rc_interval;
-	input_dev->rep[REP_DELAY]  = d->props.rc_interval + 150;
-
-	input_set_drvdata(input_dev, d);
-
-	err = input_register_device(input_dev);
-	if (err) {
-		input_free_device(input_dev);
-		return err;
-	}
+	if (d->props.rc.legacy.rc_interval < 40)
+		d->props.rc.legacy.rc_interval = 100; /* default */
 
 	d->rc_input_dev = input_dev;
 
-	INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
-
-	info("schedule remote query interval to %d msecs.", d->props.rc_interval);
-	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+	if (d->props.rc.mode == DVB_RC_LEGACY)
+		err = legacy_dvb_usb_remote_init(d, input_dev);
+	else
+		err = rc_core_dvb_usb_remote_init(d, input_dev);
+	if (err)
+		return err;
 
 	d->state |= DVB_USB_STATE_REMOTE;
 
@@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
 	if (d->state & DVB_USB_STATE_REMOTE) {
 		cancel_rearming_delayed_work(&d->rc_query_work);
 		flush_scheduled_work();
-		input_unregister_device(d->rc_input_dev);
+		if (d->props.rc.mode == DVB_RC_LEGACY)
+			input_unregister_device(d->rc_input_dev);
+		else
+			ir_input_unregister(d->rc_input_dev);
 	}
 	d->state &= ~DVB_USB_STATE_REMOTE;
 	return 0;
@@ -234,7 +316,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
 		u8 keybuf[5], u32 *event, int *state)
 {
 	int i;
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 	switch (keybuf[0]) {
@@ -247,10 +329,10 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
 				break;
 			}
 			/* See if we can match the raw key code. */
-			for (i = 0; i < d->props.rc_key_map_size; i++)
+			for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
 				if (rc5_custom(&keymap[i]) == keybuf[1] &&
 					rc5_data(&keymap[i]) == keybuf[3]) {
-					*event = keymap[i].event;
+					*event = keymap[i].keycode;
 					*state = REMOTE_KEY_PRESSED;
 					return 0;
 				}

+ 62 - 30
drivers/media/dvb/dvb-usb/dvb-usb.h

@@ -14,6 +14,7 @@
 #include <linux/usb.h>
 #include <linux/firmware.h>
 #include <linux/mutex.h>
+#include <media/ir-core.h>
 
 #include "dvb_frontend.h"
 #include "dvb_demux.h"
@@ -74,30 +75,19 @@ struct dvb_usb_device_description {
 	struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
 };
 
-/**
- * struct dvb_usb_rc_key - a remote control key and its input-event
- * @custom: the vendor/custom part of the key
- * @data: the actual key part
- * @event: the input event assigned to key identified by custom and data
- */
-struct dvb_usb_rc_key {
-	u16 scan;
-	u32 event;
-};
-
-static inline u8 rc5_custom(struct dvb_usb_rc_key *key)
+static inline u8 rc5_custom(struct ir_scancode *key)
 {
-	return (key->scan >> 8) & 0xff;
+	return (key->scancode >> 8) & 0xff;
 }
 
-static inline u8 rc5_data(struct dvb_usb_rc_key *key)
+static inline u8 rc5_data(struct ir_scancode *key)
 {
-	return key->scan & 0xff;
+	return key->scancode & 0xff;
 }
 
-static inline u8 rc5_scan(struct dvb_usb_rc_key *key)
+static inline u8 rc5_scan(struct ir_scancode *key)
 {
-	return key->scan & 0xffff;
+	return key->scancode & 0xffff;
 }
 
 struct dvb_usb_device;
@@ -167,6 +157,55 @@ struct dvb_usb_adapter_properties {
 				  unsigned int, void *, unsigned int);
 };
 
+/**
+ * struct dvb_rc_legacy - old properties of remote controller
+ * @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable
+ *  remote control handling).
+ * @rc_key_map_size: number of items in @rc_key_map.
+ * @rc_query: called to query an event event.
+ * @rc_interval: time in ms between two queries.
+ */
+struct dvb_rc_legacy {
+/* remote control properties */
+#define REMOTE_NO_KEY_PRESSED      0x00
+#define REMOTE_KEY_PRESSED         0x01
+#define REMOTE_KEY_REPEAT          0x02
+	struct ir_scancode  *rc_key_map;
+	int rc_key_map_size;
+	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
+	int rc_interval;
+};
+
+/**
+ * struct dvb_rc properties of remote controller, using rc-core
+ * @rc_codes: name of rc codes table
+ * @protocol: type of protocol(s) currently used by the driver
+ * @rc_query: called to query an event event.
+ * @rc_interval: time in ms between two queries.
+ * @rc_props: remote controller properties
+ * @bulk_mode: device supports bulk mode for RC (disable polling mode)
+ */
+struct dvb_rc {
+	char *rc_codes;
+	u64 protocol;
+	char *module_name;
+	int (*rc_query) (struct dvb_usb_device *d);
+	int rc_interval;
+	struct ir_dev_props rc_props;
+	bool bulk_mode;				/* uses bulk mode */
+};
+
+/**
+ * enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one
+ *		       based on rc-core
+ * This is initialized/used only inside dvb-usb-remote.c.
+ * It shouldn't be set by the drivers.
+ */
+enum dvb_usb_mode {
+	DVB_RC_LEGACY,
+	DVB_RC_CORE,
+};
+
 /**
  * struct dvb_usb_device_properties - properties of a dvb-usb-device
  * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
@@ -185,11 +224,7 @@ struct dvb_usb_adapter_properties {
  * @identify_state: called to determine the state (cold or warm), when it
  *  is not distinguishable by the USB IDs.
  *
- * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
- *  remote control handling).
- * @rc_key_map_size: number of items in @rc_key_map.
- * @rc_query: called to query an event event.
- * @rc_interval: time in ms between two queries.
+ * @rc: remote controller properties
  *
  * @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
  *
@@ -233,14 +268,11 @@ struct dvb_usb_device_properties {
 	int (*identify_state)   (struct usb_device *, struct dvb_usb_device_properties *,
 			struct dvb_usb_device_description **, int *);
 
-/* remote control properties */
-#define REMOTE_NO_KEY_PRESSED      0x00
-#define REMOTE_KEY_PRESSED         0x01
-#define REMOTE_KEY_REPEAT          0x02
-	struct dvb_usb_rc_key  *rc_key_map;
-	int rc_key_map_size;
-	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
-	int rc_interval;
+	struct {
+		enum dvb_usb_mode mode;	/* Drivers shouldn't touch on it */
+		struct dvb_rc_legacy legacy;
+		struct dvb_rc core;
+	} rc;
 
 	struct i2c_algorithm *i2c_algo;
 

+ 38 - 29
drivers/media/dvb/dvb-usb/dw2102.c

@@ -74,7 +74,7 @@
 		"on firmware-problems."
 
 struct ir_codes_dvb_usb_table_table {
-	struct dvb_usb_rc_key *rc_keys;
+	struct ir_scancode *rc_keys;
 	int rc_keys_size;
 };
 
@@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
+static struct ir_scancode ir_codes_dw210x_table[] = {
 	{ 0xf80a, KEY_Q },		/*power*/
 	{ 0xf80c, KEY_M },		/*mute*/
 	{ 0xf811, KEY_1 },
@@ -982,7 +982,7 @@ static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
 	{ 0xf81b, KEY_B },		/*recall*/
 };
 
-static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
+static struct ir_scancode ir_codes_tevii_table[] = {
 	{ 0xf80a, KEY_POWER },
 	{ 0xf80c, KEY_MUTE },
 	{ 0xf811, KEY_1 },
@@ -1032,7 +1032,7 @@ static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
 	{ 0xf858, KEY_SWITCHVIDEOMODE },
 };
 
-static struct dvb_usb_rc_key ir_codes_tbs_table[] = {
+static struct ir_scancode ir_codes_tbs_table[] = {
 	{ 0xf884, KEY_POWER },
 	{ 0xf894, KEY_MUTE },
 	{ 0xf887, KEY_1 },
@@ -1075,8 +1075,8 @@ static struct ir_codes_dvb_usb_table_table keys_tables[] = {
 
 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
-	int keymap_size = d->props.rc_key_map_size;
+	struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
+	int keymap_size = d->props.rc.legacy.rc_key_map_size;
 	u8 key[2];
 	struct i2c_msg msg = {
 		.addr = DW2102_RC_QUERY,
@@ -1096,7 +1096,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 		for (i = 0; i < keymap_size ; i++) {
 			if (rc5_data(&keymap[i]) == msg.buf[0]) {
 				*state = REMOTE_KEY_PRESSED;
-				*event = keymap[i].event;
+				*event = keymap[i].keycode;
 				break;
 			}
 
@@ -1185,13 +1185,13 @@ static int dw2102_load_firmware(struct usb_device *dev,
 		/* init registers */
 		switch (dev->descriptor.idProduct) {
 		case USB_PID_PROF_1100:
-			s6x0_properties.rc_key_map = ir_codes_tbs_table;
-			s6x0_properties.rc_key_map_size =
+			s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table;
+			s6x0_properties.rc.legacy.rc_key_map_size =
 					ARRAY_SIZE(ir_codes_tbs_table);
 			break;
 		case USB_PID_TEVII_S650:
-			dw2104_properties.rc_key_map = ir_codes_tevii_table;
-			dw2104_properties.rc_key_map_size =
+			dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table;
+			dw2104_properties.rc.legacy.rc_key_map_size =
 					ARRAY_SIZE(ir_codes_tevii_table);
 		case USB_PID_DW2104:
 			reset = 1;
@@ -1255,10 +1255,13 @@ static struct dvb_usb_device_properties dw2102_properties = {
 	.no_reconnect = 1,
 
 	.i2c_algo = &dw2102_serit_i2c_algo,
-	.rc_key_map = ir_codes_dw210x_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
-	.rc_interval = 150,
-	.rc_query = dw2102_rc_query,
+
+	.rc.legacy = {
+		.rc_key_map = ir_codes_dw210x_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_interval = 150,
+		.rc_query = dw2102_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x81,
 	/* parameter for the MPEG2-data transfer */
@@ -1306,10 +1309,12 @@ static struct dvb_usb_device_properties dw2104_properties = {
 	.no_reconnect = 1,
 
 	.i2c_algo = &dw2104_i2c_algo,
-	.rc_key_map = ir_codes_dw210x_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
-	.rc_interval = 150,
-	.rc_query = dw2102_rc_query,
+	.rc.legacy = {
+		.rc_key_map = ir_codes_dw210x_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_interval = 150,
+		.rc_query = dw2102_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x81,
 	/* parameter for the MPEG2-data transfer */
@@ -1353,10 +1358,12 @@ static struct dvb_usb_device_properties dw3101_properties = {
 	.no_reconnect = 1,
 
 	.i2c_algo = &dw3101_i2c_algo,
-	.rc_key_map = ir_codes_dw210x_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
-	.rc_interval = 150,
-	.rc_query = dw2102_rc_query,
+	.rc.legacy = {
+		.rc_key_map = ir_codes_dw210x_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
+		.rc_interval = 150,
+		.rc_query = dw2102_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x81,
 	/* parameter for the MPEG2-data transfer */
@@ -1396,10 +1403,12 @@ static struct dvb_usb_device_properties s6x0_properties = {
 	.no_reconnect = 1,
 
 	.i2c_algo = &s6x0_i2c_algo,
-	.rc_key_map = ir_codes_tevii_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
-	.rc_interval = 150,
-	.rc_query = dw2102_rc_query,
+	.rc.legacy = {
+		.rc_key_map = ir_codes_tevii_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
+		.rc_interval = 150,
+		.rc_query = dw2102_rc_query,
+	},
 
 	.generic_bulk_ctrl_endpoint = 0x81,
 	.num_adapters = 1,
@@ -1459,8 +1468,8 @@ static int dw2102_probe(struct usb_interface *intf,
 	/* fill only different fields */
 	p7500->firmware = "dvb-usb-p7500.fw";
 	p7500->devices[0] = d7500;
-	p7500->rc_key_map = ir_codes_tbs_table;
-	p7500->rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
+	p7500->rc.legacy.rc_key_map = ir_codes_tbs_table;
+	p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
 	p7500->adapter->frontend_attach = prof_7500_frontend_attach;
 
 	if (0 == dvb_usb_device_init(intf, &dw2102_properties,

+ 1 - 1
drivers/media/dvb/dvb-usb/gp8psk-fe.c

@@ -349,7 +349,7 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
 			 * FE_CAN_QAM_16 is for compatibility
 			 * (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
 			 */
-			FE_CAN_QPSK | FE_CAN_QAM_16
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC
 	},
 
 	.release = gp8psk_fe_release,

+ 25 - 19
drivers/media/dvb/dvb-usb/m920x.c

@@ -69,7 +69,7 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
 	int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
 
 	/* Remote controller init. */
-	if (d->props.rc_query) {
+	if (d->props.rc.legacy.rc_query) {
 		deb("Initialising remote control\n");
 		while (rc_seq->address) {
 			if ((ret = m920x_write(d->udev, M9206_CORE,
@@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
 		goto unlock;
 
-	for (i = 0; i < d->props.rc_key_map_size; i++)
-		if (rc5_data(&d->props.rc_key_map[i]) == rc_state[1]) {
-			*event = d->props.rc_key_map[i].event;
+	for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
+		if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) {
+			*event = d->props.rc.legacy.rc_key_map[i].keycode;
 
 			switch(rc_state[0]) {
 			case 0x80:
@@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = {
 };
 
 /* ir keymaps */
-static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
+static struct ir_scancode ir_codes_megasky_table[] = {
 	{ 0x0012, KEY_POWER },
 	{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
 	{ 0x0002, KEY_CHANNELUP },
@@ -608,7 +608,7 @@ static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
 	{ 0x000e, KEY_COFFEE }, /* "MTS" */
 };
 
-static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
+static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
 	{ 0x0001, KEY_ZOOM }, /* Full Screen */
 	{ 0x0002, KEY_CAMERA }, /* snapshot */
 	{ 0x0003, KEY_MUTE },
@@ -628,7 +628,7 @@ static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
 	{ 0x001e, KEY_VOLUMEUP },
 };
 
-static struct dvb_usb_rc_key ir_codes_pinnacle310e_table[] = {
+static struct ir_scancode ir_codes_pinnacle310e_table[] = {
 	{ 0x16, KEY_POWER },
 	{ 0x17, KEY_FAVORITES },
 	{ 0x0f, KEY_TEXT },
@@ -784,10 +784,12 @@ static struct dvb_usb_device_properties megasky_properties = {
 	.firmware = "dvb-usb-megasky-02.fw",
 	.download_firmware = m920x_firmware_download,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_megasky_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_megasky_table),
-	.rc_query         = m920x_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_megasky_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_megasky_table),
+		.rc_query         = m920x_rc_query,
+	},
 
 	.size_of_priv     = sizeof(struct m920x_state),
 
@@ -885,10 +887,12 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
 	.firmware = "dvb-usb-tvwalkert.fw",
 	.download_firmware = m920x_firmware_download,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_tvwalkertwin_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
-	.rc_query         = m920x_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_tvwalkertwin_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
+		.rc_query         = m920x_rc_query,
+	},
 
 	.size_of_priv     = sizeof(struct m920x_state),
 
@@ -992,10 +996,12 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
 	.usb_ctrl = DEVICE_SPECIFIC,
 	.download_firmware = NULL,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_pinnacle310e_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_pinnacle310e_table),
-	.rc_query         = m920x_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_pinnacle310e_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_pinnacle310e_table),
+		.rc_query         = m920x_rc_query,
+	},
 
 	.size_of_priv     = sizeof(struct m920x_state),
 

+ 8 - 6
drivers/media/dvb/dvb-usb/nova-t-usb2.c

@@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 #define deb_ee(args...) dprintk(debug,0x02,args)
 
 /* Hauppauge NOVA-T USB2 keys */
-static struct dvb_usb_rc_key ir_codes_haupp_table [] = {
+static struct ir_scancode ir_codes_haupp_table[] = {
 	{ 0x1e00, KEY_0 },
 	{ 0x1e01, KEY_1 },
 	{ 0x1e02, KEY_2 },
@@ -98,7 +98,7 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 					deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]),
 								 rc5_custom(&ir_codes_haupp_table[i]));
 
-					*event = ir_codes_haupp_table[i].event;
+					*event = ir_codes_haupp_table[i].keycode;
 					*state = REMOTE_KEY_PRESSED;
 					if (st->old_toggle == toggle) {
 						if (st->last_repeat_count++ < 2)
@@ -195,10 +195,12 @@ static struct dvb_usb_device_properties nova_t_properties = {
 	.power_ctrl       = dibusb2_0_power_ctrl,
 	.read_mac_address = nova_t_read_mac_address,
 
-	.rc_interval      = 100,
-	.rc_key_map       = ir_codes_haupp_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_haupp_table),
-	.rc_query         = nova_t_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 100,
+		.rc_key_map       = ir_codes_haupp_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_haupp_table),
+		.rc_query         = nova_t_rc_query,
+	},
 
 	.i2c_algo         = &dibusb_i2c_algo,
 

+ 9 - 7
drivers/media/dvb/dvb-usb/opera1.c

@@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
 	return 0;
 }
 
-static struct dvb_usb_rc_key ir_codes_opera1_table[] = {
+static struct ir_scancode ir_codes_opera1_table[] = {
 	{0x5fa0, KEY_1},
 	{0x51af, KEY_2},
 	{0x5da2, KEY_3},
@@ -407,9 +407,9 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
 		for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) {
 			if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) {
 				*state = REMOTE_KEY_PRESSED;
-				*event = ir_codes_opera1_table[i].event;
+				*event = ir_codes_opera1_table[i].keycode;
 				opst->last_key_pressed =
-					ir_codes_opera1_table[i].event;
+					ir_codes_opera1_table[i].keycode;
 				break;
 			}
 			opst->last_key_pressed = 0;
@@ -498,10 +498,12 @@ static struct dvb_usb_device_properties opera1_properties = {
 	.power_ctrl = opera1_power_ctrl,
 	.i2c_algo = &opera1_i2c_algo,
 
-	.rc_key_map = ir_codes_opera1_table,
-	.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
-	.rc_interval = 200,
-	.rc_query = opera1_rc_query,
+	.rc.legacy = {
+		.rc_key_map = ir_codes_opera1_table,
+		.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
+		.rc_interval = 200,
+		.rc_query = opera1_rc_query,
+	},
 	.read_mac_address = opera1_read_mac_address,
 	.generic_bulk_ctrl_endpoint = 0x00,
 	/* parameter for the MPEG2-data transfer */

+ 8 - 6
drivers/media/dvb/dvb-usb/vp702x.c

@@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 }
 
 /* keys for the enclosed remote control */
-static struct dvb_usb_rc_key ir_codes_vp702x_table[] = {
+static struct ir_scancode ir_codes_vp702x_table[] = {
 	{ 0x0001, KEY_1 },
 	{ 0x0002, KEY_2 },
 };
@@ -200,7 +200,7 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
 		if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
 			*state = REMOTE_KEY_PRESSED;
-			*event = ir_codes_vp702x_table[i].event;
+			*event = ir_codes_vp702x_table[i].keycode;
 			break;
 		}
 	return 0;
@@ -283,10 +283,12 @@ static struct dvb_usb_device_properties vp702x_properties = {
 	},
 	.read_mac_address = vp702x_read_mac_addr,
 
-	.rc_key_map       = ir_codes_vp702x_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp702x_table),
-	.rc_interval      = 400,
-	.rc_query         = vp702x_rc_query,
+	.rc.legacy = {
+		.rc_key_map       = ir_codes_vp702x_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp702x_table),
+		.rc_interval      = 400,
+		.rc_query         = vp702x_rc_query,
+	},
 
 	.num_device_descs = 1,
 	.devices = {

+ 8 - 6
drivers/media/dvb/dvb-usb/vp7045.c

@@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
 
 /* The keymapping struct. Somehow this should be loaded to the driver, but
  * currently it is hardcoded. */
-static struct dvb_usb_rc_key ir_codes_vp7045_table[] = {
+static struct ir_scancode ir_codes_vp7045_table[] = {
 	{ 0x0016, KEY_POWER },
 	{ 0x0010, KEY_MUTE },
 	{ 0x0003, KEY_1 },
@@ -168,7 +168,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 	for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++)
 		if (rc5_data(&ir_codes_vp7045_table[i]) == key) {
 			*state = REMOTE_KEY_PRESSED;
-			*event = ir_codes_vp7045_table[i].event;
+			*event = ir_codes_vp7045_table[i].keycode;
 			break;
 		}
 	return 0;
@@ -259,10 +259,12 @@ static struct dvb_usb_device_properties vp7045_properties = {
 	.power_ctrl       = vp7045_power_ctrl,
 	.read_mac_address = vp7045_read_mac_addr,
 
-	.rc_interval      = 400,
-	.rc_key_map       = ir_codes_vp7045_table,
-	.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp7045_table),
-	.rc_query         = vp7045_rc_query,
+	.rc.legacy = {
+		.rc_interval      = 400,
+		.rc_key_map       = ir_codes_vp7045_table,
+		.rc_key_map_size  = ARRAY_SIZE(ir_codes_vp7045_table),
+		.rc_query         = vp7045_rc_query,
+	},
 
 	.num_device_descs = 2,
 	.devices = {

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

@@ -584,6 +584,7 @@ config DVB_LGS8GL5
 config DVB_LGS8GXX
 	tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
 	depends on DVB_CORE && I2C
+	select FW_LOADER
 	default m if DVB_FE_CUSTOMISE
 	help
 	  A DMB-TH tuner module. Say Y when you want to support this frontend.

+ 28 - 24
drivers/media/dvb/frontends/af9013.c

@@ -1,5 +1,5 @@
 /*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
  *
@@ -761,6 +761,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
 
 	state->frequency = params->frequency;
 
+	/* program tuner */
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, params);
+
 	/* program CFOE coefficients */
 	ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
 	if (ret)
@@ -791,10 +795,6 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
 	if (ret)
 		goto error;
 
-	/* program tuner */
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe, params);
-
 	/* program TPS and bandwidth, check if auto mode needed */
 	ret = af9013_set_ofdm_params(state, &params->u.ofdm, &auto_mode);
 	if (ret)
@@ -1184,45 +1184,49 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
 	u8 tmp;
 	*status = 0;
 
-	/* TPS lock */
-	ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
-	if (ret)
-		goto error;
-	if (tmp)
-		*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
-
 	/* MPEG2 lock */
 	ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
 	if (ret)
 		goto error;
 	if (tmp)
-		*status |= FE_HAS_SYNC | FE_HAS_LOCK;
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
+			FE_HAS_SYNC | FE_HAS_LOCK;
 
-	if (!(*status & FE_HAS_SIGNAL)) {
-		/* AGC lock */
-		ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
+	if (!*status) {
+		/* TPS lock */
+		ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
 		if (ret)
 			goto error;
 		if (tmp)
-			*status |= FE_HAS_SIGNAL;
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
+				FE_HAS_VITERBI;
 	}
 
-	if (!(*status & FE_HAS_CARRIER)) {
+	if (!*status) {
 		/* CFO lock */
 		ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
 		if (ret)
 			goto error;
 		if (tmp)
-			*status |= FE_HAS_CARRIER;
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
 	}
 
-	if (!(*status & FE_HAS_CARRIER)) {
+	if (!*status) {
 		/* SFOE lock */
 		ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
 		if (ret)
 			goto error;
 		if (tmp)
-			*status |= FE_HAS_CARRIER;
+			*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+	}
+
+	if (!*status) {
+		/* AGC lock */
+		ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
+		if (ret)
+			goto error;
+		if (tmp)
+			*status |= FE_HAS_SIGNAL;
 	}
 
 	ret = af9013_update_statistics(fe);
@@ -1574,7 +1578,7 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 {
 	int ret;
 	struct af9013_state *state = NULL;
-	u8 buf[3], i;
+	u8 buf[4], i;
 
 	/* allocate memory for the internal state */
 	state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
@@ -1607,12 +1611,12 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 	}
 
 	/* firmware version */
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < 4; i++) {
 		ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
 		if (ret)
 			goto error;
 	}
-	info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]);
+	info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
 
 	/* settings for mp2if */
 	if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {

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

@@ -1,5 +1,5 @@
 /*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
  *

+ 5 - 3
drivers/media/dvb/frontends/af9013_priv.h

@@ -1,5 +1,5 @@
 /*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ * Afatech AF9013 demodulator driver
  *
  * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
  *
@@ -132,6 +132,8 @@ static struct regdesc ofsm_init[] = {
 	{ 0xd740, 2, 1, 0x00 },
 	{ 0xd740, 3, 1, 0x01 },
 	{ 0xd3c1, 4, 1, 0x01 },
+	{ 0x9124, 0, 8, 0x58 },
+	{ 0x9125, 0, 2, 0x02 },
 	{ 0xd3a2, 0, 8, 0x00 },
 	{ 0xd3a3, 0, 8, 0x04 },
 	{ 0xd305, 0, 8, 0x32 },
@@ -143,7 +145,7 @@ static struct regdesc ofsm_init[] = {
 	{ 0x911b, 0, 1, 0x01 },
 	{ 0x9bce, 0, 4, 0x02 },
 	{ 0x9116, 0, 1, 0x01 },
-	{ 0x9bd1, 0, 1, 0x01 },
+	{ 0x9122, 0, 8, 0xd0 },
 	{ 0xd2e0, 0, 8, 0xd0 },
 	{ 0xd2e9, 0, 4, 0x0d },
 	{ 0xd38c, 0, 8, 0xfc },
@@ -165,7 +167,6 @@ static struct regdesc ofsm_init[] = {
 	{ 0xd081, 4, 4, 0x09 },
 	{ 0xd098, 4, 4, 0x0f },
 	{ 0xd098, 0, 4, 0x03 },
-	{ 0xdbc0, 3, 1, 0x01 },
 	{ 0xdbc0, 4, 1, 0x01 },
 	{ 0xdbc7, 0, 8, 0x08 },
 	{ 0xdbc8, 4, 4, 0x00 },
@@ -179,6 +180,7 @@ static struct regdesc ofsm_init[] = {
 	{ 0xd0f0, 0, 7, 0x1a },
 	{ 0xd0f1, 4, 1, 0x01 },
 	{ 0xd0f2, 0, 8, 0x0c },
+	{ 0xd101, 5, 3, 0x06 },
 	{ 0xd103, 0, 4, 0x08 },
 	{ 0xd0f8, 0, 7, 0x20 },
 	{ 0xd111, 5, 1, 0x00 },

+ 1 - 8
drivers/media/dvb/frontends/dib3000mb.c

@@ -38,11 +38,10 @@
 #define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
 #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
 
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
-#endif
+
 #define deb_info(args...) dprintk(0x01,args)
 #define deb_i2c(args...)  dprintk(0x02,args)
 #define deb_srch(args...) dprintk(0x04,args)
@@ -51,12 +50,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
 #define deb_setf(args...) dprintk(0x04,args)
 #define deb_getf(args...) dprintk(0x08,args)
 
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
-#endif
-
 static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
 {
 	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };

+ 0 - 4
drivers/media/dvb/frontends/dib3000mb_priv.h

@@ -37,12 +37,8 @@
 
 /* debug */
 
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
 #define dprintk(level,args...) \
     do { if ((debug & level)) { printk(args); } } while (0)
-#else
-#define dprintk(args...) do { } while (0)
-#endif
 
 /* mask for enabling a specific pid for the pid_filter */
 #define DIB3000_ACTIVATE_PID_FILTERING	(0x2000)

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

@@ -822,7 +822,7 @@ int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defa
 
 	dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
 	if (dmcst == NULL)
-		return -ENODEV;
+		return -ENOMEM;
 
 	dmcst->i2c_adap = i2c;
 

+ 206 - 61
drivers/media/dvb/frontends/lgdt3305.c

@@ -1,7 +1,9 @@
 /*
- *    Support for LGDT3305 - VSB/QAM
+ *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
  *
- *    Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
+ *    Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *    LGDT3304 support 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
@@ -65,6 +67,8 @@ struct lgdt3305_state {
 
 /* ------------------------------------------------------------------------ */
 
+/* FIXME: verify & document the LGDT3304 registers */
+
 #define LGDT3305_GEN_CTRL_1                   0x0000
 #define LGDT3305_GEN_CTRL_2                   0x0001
 #define LGDT3305_GEN_CTRL_3                   0x0002
@@ -358,7 +362,12 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
 	case QAM_256:
 		agcdelay = 0x046b;
 		rfbw     = 0x8889;
-		ifbw     = 0x8888;
+		/* FIXME: investigate optimal ifbw & rfbw values for the
+		 *        DT3304 and re-write this switch..case block */
+		if (state->cfg->demod_chip == LGDT3304)
+			ifbw = 0x6666;
+		else /* (state->cfg->demod_chip == LGDT3305) */
+			ifbw = 0x8888;
 		break;
 	default:
 		return -EINVAL;
@@ -410,8 +419,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
 	lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
 
 	/* control agc function */
-	lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
-	lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
+	switch (state->cfg->demod_chip) {
+	case LGDT3304:
+		lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
+		lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
+		break;
+	case LGDT3305:
+		lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
+		lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
+		break;
+	default:
+		return -EINVAL;
+	}
 
 	return lgdt3305_rfagc_loop(state, param);
 }
@@ -577,61 +596,79 @@ static int lgdt3305_init(struct dvb_frontend *fe)
 	struct lgdt3305_state *state = fe->demodulator_priv;
 	int ret;
 
+	static struct lgdt3305_reg lgdt3304_init_data[] = {
+		{ .reg = LGDT3305_GEN_CTRL_1,           .val = 0x03, },
+		{ .reg = 0x000d,                        .val = 0x02, },
+		{ .reg = 0x000e,                        .val = 0x02, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_1,       .val = 0x32, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_2,       .val = 0xc4, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_1,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_2,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_3,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_4,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTRL_7,            .val = 0xf9, },
+		{ .reg = 0x0112,                        .val = 0x17, },
+		{ .reg = 0x0113,                        .val = 0x15, },
+		{ .reg = 0x0114,                        .val = 0x18, },
+		{ .reg = 0x0115,                        .val = 0xff, },
+		{ .reg = 0x0116,                        .val = 0x3c, },
+		{ .reg = 0x0214,                        .val = 0x67, },
+		{ .reg = 0x0424,                        .val = 0x8d, },
+		{ .reg = 0x0427,                        .val = 0x12, },
+		{ .reg = 0x0428,                        .val = 0x4f, },
+		{ .reg = LGDT3305_IFBW_1,               .val = 0x80, },
+		{ .reg = LGDT3305_IFBW_2,               .val = 0x00, },
+		{ .reg = 0x030a,                        .val = 0x08, },
+		{ .reg = 0x030b,                        .val = 0x9b, },
+		{ .reg = 0x030d,                        .val = 0x00, },
+		{ .reg = 0x030e,                        .val = 0x1c, },
+		{ .reg = 0x0314,                        .val = 0xe1, },
+		{ .reg = 0x000d,                        .val = 0x82, },
+		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
+		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x5b, },
+	};
+
 	static struct lgdt3305_reg lgdt3305_init_data[] = {
-		{ .reg = LGDT3305_GEN_CTRL_1,
-		  .val = 0x03, },
-		{ .reg = LGDT3305_GEN_CTRL_2,
-		  .val = 0xb0, },
-		{ .reg = LGDT3305_GEN_CTRL_3,
-		  .val = 0x01, },
-		{ .reg = LGDT3305_GEN_CONTROL,
-		  .val = 0x6f, },
-		{ .reg = LGDT3305_GEN_CTRL_4,
-		  .val = 0x03, },
-		{ .reg = LGDT3305_DGTL_AGC_REF_1,
-		  .val = 0x32, },
-		{ .reg = LGDT3305_DGTL_AGC_REF_2,
-		  .val = 0xc4, },
-		{ .reg = LGDT3305_CR_CTR_FREQ_1,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_CR_CTR_FREQ_2,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_CR_CTR_FREQ_3,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_CR_CTR_FREQ_4,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_CR_CTRL_7,
-		  .val = 0x79, },
-		{ .reg = LGDT3305_AGC_POWER_REF_1,
-		  .val = 0x32, },
-		{ .reg = LGDT3305_AGC_POWER_REF_2,
-		  .val = 0xc4, },
-		{ .reg = LGDT3305_AGC_DELAY_PT_1,
-		  .val = 0x0d, },
-		{ .reg = LGDT3305_AGC_DELAY_PT_2,
-		  .val = 0x30, },
-		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1,
-		  .val = 0x80, },
-		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_IFBW_1,
-		  .val = 0x80, },
-		{ .reg = LGDT3305_IFBW_2,
-		  .val = 0x00, },
-		{ .reg = LGDT3305_AGC_CTRL_1,
-		  .val = 0x30, },
-		{ .reg = LGDT3305_AGC_CTRL_4,
-		  .val = 0x61, },
-		{ .reg = LGDT3305_FEC_BLOCK_CTRL,
-		  .val = 0xff, },
-		{ .reg = LGDT3305_TP_CTRL_1,
-		  .val = 0x1b, },
+		{ .reg = LGDT3305_GEN_CTRL_1,           .val = 0x03, },
+		{ .reg = LGDT3305_GEN_CTRL_2,           .val = 0xb0, },
+		{ .reg = LGDT3305_GEN_CTRL_3,           .val = 0x01, },
+		{ .reg = LGDT3305_GEN_CONTROL,          .val = 0x6f, },
+		{ .reg = LGDT3305_GEN_CTRL_4,           .val = 0x03, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_1,       .val = 0x32, },
+		{ .reg = LGDT3305_DGTL_AGC_REF_2,       .val = 0xc4, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_1,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_2,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_3,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTR_FREQ_4,        .val = 0x00, },
+		{ .reg = LGDT3305_CR_CTRL_7,            .val = 0x79, },
+		{ .reg = LGDT3305_AGC_POWER_REF_1,      .val = 0x32, },
+		{ .reg = LGDT3305_AGC_POWER_REF_2,      .val = 0xc4, },
+		{ .reg = LGDT3305_AGC_DELAY_PT_1,       .val = 0x0d, },
+		{ .reg = LGDT3305_AGC_DELAY_PT_2,       .val = 0x30, },
+		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },
+		{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },
+		{ .reg = LGDT3305_IFBW_1,               .val = 0x80, },
+		{ .reg = LGDT3305_IFBW_2,               .val = 0x00, },
+		{ .reg = LGDT3305_AGC_CTRL_1,           .val = 0x30, },
+		{ .reg = LGDT3305_AGC_CTRL_4,           .val = 0x61, },
+		{ .reg = LGDT3305_FEC_BLOCK_CTRL,       .val = 0xff, },
+		{ .reg = LGDT3305_TP_CTRL_1,            .val = 0x1b, },
 	};
 
 	lg_dbg("\n");
 
-	ret = lgdt3305_write_regs(state, lgdt3305_init_data,
-				  ARRAY_SIZE(lgdt3305_init_data));
+	switch (state->cfg->demod_chip) {
+	case LGDT3304:
+		ret = lgdt3305_write_regs(state, lgdt3304_init_data,
+					  ARRAY_SIZE(lgdt3304_init_data));
+		break;
+	case LGDT3305:
+		ret = lgdt3305_write_regs(state, lgdt3305_init_data,
+					  ARRAY_SIZE(lgdt3305_init_data));
+		break;
+	default:
+		ret = -EINVAL;
+	}
 	if (lg_fail(ret))
 		goto fail;
 
@@ -640,6 +677,76 @@ fail:
 	return ret;
 }
 
+static int lgdt3304_set_parameters(struct dvb_frontend *fe,
+				   struct dvb_frontend_parameters *param)
+{
+	struct lgdt3305_state *state = fe->demodulator_priv;
+	int ret;
+
+	lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
+
+	if (fe->ops.tuner_ops.set_params) {
+		ret = fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+		if (lg_fail(ret))
+			goto fail;
+		state->current_frequency = param->frequency;
+	}
+
+	ret = lgdt3305_set_modulation(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_passband_digital_agc(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	ret = lgdt3305_agc_setup(state, param);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
+	switch (param->u.vsb.modulation) {
+	case VSB_8:
+		lgdt3305_write_reg(state, 0x030d, 0x00);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
+		lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
+		break;
+	case QAM_64:
+	case QAM_256:
+		lgdt3305_write_reg(state, 0x030d, 0x14);
+		ret = lgdt3305_set_if(state, param);
+		if (lg_fail(ret))
+			goto fail;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+
+	ret = lgdt3305_spectral_inversion(state, param,
+					  state->cfg->spectral_inversion
+					  ? 1 : 0);
+	if (lg_fail(ret))
+		goto fail;
+
+	state->current_modulation = param->u.vsb.modulation;
+
+	ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
+	if (lg_fail(ret))
+		goto fail;
+
+	/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
+	ret = lgdt3305_mpeg_mode_polarity(state,
+					  state->cfg->tpclk_edge,
+					  state->cfg->tpvalid_polarity);
+fail:
+	return ret;
+}
+
 static int lgdt3305_set_parameters(struct dvb_frontend *fe,
 				   struct dvb_frontend_parameters *param)
 {
@@ -848,6 +955,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
 	switch (state->current_modulation) {
 	case QAM_256:
 	case QAM_64:
+		/* signal bit is unreliable on the DT3304 in QAM mode */
+		if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
+			*status |= FE_HAS_SIGNAL;
+
 		ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
 		if (lg_fail(ret))
 			goto fail;
@@ -993,6 +1104,7 @@ static void lgdt3305_release(struct dvb_frontend *fe)
 	kfree(state);
 }
 
+static struct dvb_frontend_ops lgdt3304_ops;
 static struct dvb_frontend_ops lgdt3305_ops;
 
 struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
@@ -1013,11 +1125,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
 	state->cfg = config;
 	state->i2c_adap = i2c_adap;
 
-	memcpy(&state->frontend.ops, &lgdt3305_ops,
-	       sizeof(struct dvb_frontend_ops));
+	switch (config->demod_chip) {
+	case LGDT3304:
+		memcpy(&state->frontend.ops, &lgdt3304_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	case LGDT3305:
+		memcpy(&state->frontend.ops, &lgdt3305_ops,
+		       sizeof(struct dvb_frontend_ops));
+		break;
+	default:
+		goto fail;
+	}
 	state->frontend.demodulator_priv = state;
 
-	/* verify that we're talking to a lg dt3305 */
+	/* verify that we're talking to a lg dt3304/5 */
 	ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
 	if ((lg_fail(ret)) | (val == 0))
 		goto fail;
@@ -1036,12 +1158,35 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
 
 	return &state->frontend;
 fail:
-	lg_warn("unable to detect LGDT3305 hardware\n");
+	lg_warn("unable to detect %s hardware\n",
+		config->demod_chip ? "LGDT3304" : "LGDT3305");
 	kfree(state);
 	return NULL;
 }
 EXPORT_SYMBOL(lgdt3305_attach);
 
+static struct dvb_frontend_ops lgdt3304_ops = {
+	.info = {
+		.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
+		.type               = FE_ATSC,
+		.frequency_min      = 54000000,
+		.frequency_max      = 858000000,
+		.frequency_stepsize = 62500,
+		.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+	.i2c_gate_ctrl        = lgdt3305_i2c_gate_ctrl,
+	.init                 = lgdt3305_init,
+	.set_frontend         = lgdt3304_set_parameters,
+	.get_frontend         = lgdt3305_get_frontend,
+	.get_tune_settings    = lgdt3305_get_tune_settings,
+	.read_status          = lgdt3305_read_status,
+	.read_ber             = lgdt3305_read_ber,
+	.read_signal_strength = lgdt3305_read_signal_strength,
+	.read_snr             = lgdt3305_read_snr,
+	.read_ucblocks        = lgdt3305_read_ucblocks,
+	.release              = lgdt3305_release,
+};
+
 static struct dvb_frontend_ops lgdt3305_ops = {
 	.info = {
 		.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
@@ -1065,10 +1210,10 @@ static struct dvb_frontend_ops lgdt3305_ops = {
 	.release              = lgdt3305_release,
 };
 
-MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
+MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.1");
+MODULE_VERSION("0.2");
 
 /*
  * Local variables:

+ 8 - 2
drivers/media/dvb/frontends/lgdt3305.h

@@ -1,7 +1,7 @@
 /*
- *    Support for LGDT3305 - VSB/QAM
+ *    Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
  *
- *    Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
+ *    Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity {
 	LGDT3305_TP_VALID_HIGH = 1,
 };
 
+enum lgdt_demod_chip_type {
+	LGDT3305 = 0,
+	LGDT3304 = 1,
+};
+
 struct lgdt3305_config {
 	u8 i2c_addr;
 
@@ -65,6 +70,7 @@ struct lgdt3305_config {
 	enum lgdt3305_mpeg_mode mpeg_mode;
 	enum lgdt3305_tp_clock_edge tpclk_edge;
 	enum lgdt3305_tp_valid_polarity tpvalid_polarity;
+	enum lgdt_demod_chip_type demod_chip;
 };
 
 #if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \

+ 10 - 40
drivers/media/dvb/frontends/lgs8gxx.c

@@ -24,6 +24,7 @@
  */
 
 #include <asm/div64.h>
+#include <linux/firmware.h>
 
 #include "dvb_frontend.h"
 
@@ -46,42 +47,6 @@ module_param(fake_signal_str, int, 0644);
 MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
 "Signal strength calculation is slow.(default:on).");
 
-static const u8 lgs8g75_initdat[] = {
-	0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5,
-	0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50,
-	0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5,
-	0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01,
-	0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90,
-	0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23,
-	0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90,
-	0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D,
-	0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60,
-	0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12,
-	0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD,
-	0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60,
-	0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12,
-	0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B,
-	0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60,
-	0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74,
-	0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74,
-	0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2,
-	0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09,
-	0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00,
-	0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90,
-	0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08,
-	0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9,
-	0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80,
-	0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80,
-	0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22
-};
-
 /* LGS8GXX internal helper functions */
 
 static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
@@ -627,9 +592,14 @@ static int lgs8913_init(struct lgs8gxx_state *priv)
 
 static int lgs8g75_init_data(struct lgs8gxx_state *priv)
 {
-	const u8 *p = lgs8g75_initdat;
+	const struct firmware *fw;
+	int rc;
 	int i;
 
+	rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev);
+	if (rc)
+		return rc;
+
 	lgs8gxx_write_reg(priv, 0xC6, 0x40);
 
 	lgs8gxx_write_reg(priv, 0x3D, 0x04);
@@ -640,16 +610,16 @@ static int lgs8g75_init_data(struct lgs8gxx_state *priv)
 	lgs8gxx_write_reg(priv, 0x3B, 0x00);
 	lgs8gxx_write_reg(priv, 0x38, 0x00);
 
-	for (i = 0; i < sizeof(lgs8g75_initdat); i++) {
+	for (i = 0; i < fw->size; i++) {
 		lgs8gxx_write_reg(priv, 0x38, 0x00);
 		lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
 		lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
-		lgs8gxx_write_reg(priv, 0x3C, *p);
-		p++;
+		lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
 	}
 
 	lgs8gxx_write_reg(priv, 0x38, 0x00);
 
+	release_firmware(fw);
 	return 0;
 }
 

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

@@ -1833,7 +1833,6 @@ static struct dvb_frontend_ops mb86a16_ops = {
 
 	.get_frontend_algo		= mb86a16_frontend_algo,
 	.search				= mb86a16_search,
-	.read_status			= mb86a16_read_status,
 	.init				= mb86a16_init,
 	.sleep				= mb86a16_sleep,
 	.read_status			= mb86a16_read_status,

+ 32 - 11
drivers/media/dvb/frontends/tda10048.c

@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/math64.h>
 #include <asm/div64.h>
 #include "dvb_frontend.h"
 #include "dvb_math.h"
@@ -49,8 +50,8 @@
 #define TDA10048_CONF_C4_1         0x1E
 #define TDA10048_CONF_C4_2         0x1F
 #define TDA10048_CODE_IN_RAM       0x20
-#define TDA10048_CHANNEL_INFO_1_R  0x22
-#define TDA10048_CHANNEL_INFO_2_R  0x23
+#define TDA10048_CHANNEL_INFO1_R   0x22
+#define TDA10048_CHANNEL_INFO2_R   0x23
 #define TDA10048_CHANNEL_INFO1     0x24
 #define TDA10048_CHANNEL_INFO2     0x25
 #define TDA10048_TIME_ERROR_R      0x26
@@ -63,8 +64,8 @@
 #define TDA10048_IT_STAT           0x32
 #define TDA10048_DSP_AD_LSB        0x3C
 #define TDA10048_DSP_AD_MSB        0x3D
-#define TDA10048_DSP_REF_LSB       0x3E
-#define TDA10048_DSP_REF_MSB       0x3F
+#define TDA10048_DSP_REG_LSB       0x3E
+#define TDA10048_DSP_REG_MSB       0x3F
 #define TDA10048_CONF_TRISTATE1    0x44
 #define TDA10048_CONF_TRISTATE2    0x45
 #define TDA10048_CONF_POLARITY     0x46
@@ -112,7 +113,7 @@
 #define TDA10048_FREE_REG_1        0xB2
 #define TDA10048_FREE_REG_2        0xB3
 #define TDA10048_CONF_C3_1         0xC0
-#define TDA10048_CYBER_CTRL        0xC2
+#define TDA10048_CVBER_CTRL        0xC2
 #define TDA10048_CBER_NMAX_LSB     0xC4
 #define TDA10048_CBER_NMAX_MSB     0xC5
 #define TDA10048_CBER_LSB          0xC6
@@ -120,7 +121,7 @@
 #define TDA10048_VBER_LSB          0xC8
 #define TDA10048_VBER_MID          0xC9
 #define TDA10048_VBER_MSB          0xCA
-#define TDA10048_CYBER_LUT         0xCC
+#define TDA10048_CVBER_LUT         0xCC
 #define TDA10048_UNCOR_CTRL        0xCD
 #define TDA10048_UNCOR_CPT_LSB     0xCE
 #define TDA10048_UNCOR_CPT_MSB     0xCF
@@ -183,7 +184,7 @@ static struct init_tab {
 	{ TDA10048_AGC_IF_MAX, 0xff },
 	{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
 	{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
-	{ TDA10048_CYBER_CTRL, 0x38 },
+	{ TDA10048_CVBER_CTRL, 0x38 },
 	{ TDA10048_AGC_GAINS, 0x12 },
 	{ TDA10048_CONF_XO, 0x00 },
 	{ TDA10048_CONF_TS1, 0x07 },
@@ -688,7 +689,7 @@ static int tda10048_get_tps(struct tda10048_state *state,
 		p->guard_interval =  GUARD_INTERVAL_1_4;
 		break;
 	}
-	switch (val & 0x02) {
+	switch (val & 0x03) {
 	case 0:
 		p->transmission_mode = TRANSMISSION_MODE_2K;
 		break;
@@ -765,6 +766,8 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
 
 	/* Enable demod TPS auto detection and begin acquisition */
 	tda10048_writereg(state, TDA10048_AUTO, 0x57);
+	/* trigger cber and vber acquisition */
+	tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B);
 
 	return 0;
 }
@@ -830,12 +833,27 @@ static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
 static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
 	struct tda10048_state *state = fe->demodulator_priv;
+	static u32 cber_current;
+	u32 cber_nmax;
+	u64 cber_tmp;
 
 	dprintk(1, "%s()\n", __func__);
 
-	/* TODO: A reset may be required here */
-	*ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
-		tda10048_readreg(state, TDA10048_CBER_LSB);
+	/* update cber on interrupt */
+	if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) {
+		cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
+			tda10048_readreg(state, TDA10048_CBER_LSB);
+		cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 |
+			tda10048_readreg(state, TDA10048_CBER_NMAX_LSB);
+		cber_tmp *= 100000000;
+		cber_tmp *= 2;
+		cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1);
+		cber_current = (u32)cber_tmp;
+		/* retrigger cber acquisition */
+		tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39);
+	}
+	/* actual cber is (*ber)/1e8 */
+	*ber = cber_current;
 
 	return 0;
 }
@@ -1015,6 +1033,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 
 	*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
 		tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
+	/* clear the uncorrected TS packets counter when saturated */
+	if (*ucblocks == 0xFFFF)
+		tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80);
 
 	return 0;
 }

+ 10 - 4
drivers/media/dvb/mantis/Kconfig

@@ -10,9 +10,15 @@ config MANTIS_CORE
 config DVB_MANTIS
 	tristate "MANTIS based cards"
 	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-	select DVB_MB86A16
-	select DVB_ZL10353
-	select DVB_STV0299
+	select DVB_MB86A16 if !DVB_FE_CUSTOMISE
+	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
+	select DVB_STB6100 if !DVB_FE_CUSTOMISE
+	select DVB_TDA665x if !DVB_FE_CUSTOMISE
+	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
 	select DVB_PLL
 	help
 	  Support for PCI cards based on the Mantis PCI bridge.
@@ -23,7 +29,7 @@ config DVB_MANTIS
 config DVB_HOPPER
 	tristate "HOPPER based cards"
 	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-	select DVB_ZL10353
+	select DVB_ZL10353 if !DVB_FE_CUSTOMISE
 	select DVB_PLL
 	help
 	  Support for PCI cards based on the Hopper  PCI bridge.

+ 1 - 4
drivers/media/dvb/mantis/mantis_input.c

@@ -19,7 +19,7 @@
 */
 
 #include <linux/input.h>
-#include <media/ir-common.h>
+#include <media/ir-core.h>
 #include <linux/pci.h>
 
 #include "dmxdev.h"
@@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(ir_mantis);
 int mantis_input_init(struct mantis_pci *mantis)
 {
 	struct input_dev *rc;
-	struct ir_input_state rc_state;
 	char name[80], dev[80];
 	int err;
 
@@ -120,8 +119,6 @@ int mantis_input_init(struct mantis_pci *mantis)
 	rc->name = name;
 	rc->phys = dev;
 
-	ir_input_init(rc, &rc_state, IR_TYPE_OTHER);
-
 	rc->id.bustype	= BUS_PCI;
 	rc->id.vendor	= mantis->vendor_id;
 	rc->id.product	= mantis->device_id;

+ 2 - 0
drivers/media/dvb/siano/sms-cards.c

@@ -64,9 +64,11 @@ static struct sms_board sms_boards[] = {
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
 		.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
+		.rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW,
 		.board_cfg.leds_power = 26,
 		.board_cfg.led0 = 27,
 		.board_cfg.led1 = 28,
+		.board_cfg.ir = 9,
 		.led_power = 26,
 		.led_lo    = 27,
 		.led_hi    = 28,

+ 1 - 1
drivers/media/dvb/siano/sms-cards.h

@@ -75,7 +75,7 @@ struct sms_board {
 	enum sms_device_type_st type;
 	char *name, *fw[DEVICE_MODE_MAX];
 	struct sms_board_gpio_cfg board_cfg;
-	enum ir_kb_type ir_kb_type;
+	char *rc_codes;				/* Name of IR codes table */
 
 	/* gpios */
 	int led_power, led_hi, led_lo, lna_ctrl, rf_switch;

+ 1 - 3
drivers/media/dvb/siano/smscoreapi.c

@@ -116,9 +116,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
 			return entry;
 		}
 	}
-	entry = (struct smscore_registry_entry_t *)
-			kmalloc(sizeof(struct smscore_registry_entry_t),
-				GFP_KERNEL);
+	entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
 	if (entry) {
 		entry->mode = default_mode;
 		strcpy(entry->devpath, devpath);

+ 36 - 225
drivers/media/dvb/siano/smsir.c

@@ -4,6 +4,11 @@
  MDTV receiver kernel modules.
  Copyright (C) 2006-2009, Uri Shkolnik
 
+ Copyright (c) 2010 - Mauro Carvalho Chehab
+	- Ported the driver to use rc-core
+	- IR raw event decoding is now done at rc-core
+	- Code almost re-written
+
  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
@@ -27,226 +32,28 @@
 #include "smsir.h"
 #include "sms-cards.h"
 
-/* In order to add new IR remote control -
- * 1) Add it to the <enum ir_kb_type> @ smsir,h,
- * 2) Add its map to keyboard_layout_maps below
- * 3) Set your board (sms-cards sub-module) to use it
- */
-
-static struct keyboard_layout_map_t keyboard_layout_maps[] = {
-		[SMS_IR_KB_DEFAULT_TV] = {
-			.ir_protocol = IR_RC5,
-			.rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
-			.keyboard_layout_map = {
-					KEY_0, KEY_1, KEY_2,
-					KEY_3, KEY_4, KEY_5,
-					KEY_6, KEY_7, KEY_8,
-					KEY_9, 0, 0, KEY_POWER,
-					KEY_MUTE, 0, 0,
-					KEY_VOLUMEUP, KEY_VOLUMEDOWN,
-					KEY_BRIGHTNESSUP,
-					KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
-					KEY_CHANNELDOWN,
-					0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0, 0, 0, 0, 0, 0, 0,
-					0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-			}
-		},
-		[SMS_IR_KB_HCW_SILVER] = {
-			.ir_protocol = IR_RC5,
-			.rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
-			.keyboard_layout_map = {
-					KEY_0, KEY_1, KEY_2,
-					KEY_3, KEY_4, KEY_5,
-					KEY_6, KEY_7, KEY_8,
-					KEY_9, KEY_TEXT, KEY_RED,
-					KEY_RADIO, KEY_MENU,
-					KEY_SUBTITLE,
-					KEY_MUTE, KEY_VOLUMEUP,
-					KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
-					KEY_UP, KEY_DOWN, KEY_LEFT,
-					KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
-					KEY_MHP, KEY_EPG, KEY_TV,
-					0, KEY_NEXTSONG, KEY_EXIT,
-					KEY_CHANNELUP, 	KEY_CHANNELDOWN,
-					KEY_CHANNEL, 0,
-					KEY_PREVIOUSSONG, KEY_ENTER,
-					KEY_SLEEP, 0, 0, KEY_BLUE,
-					0, 0, 0, 0, KEY_GREEN, 0,
-					KEY_PAUSE, 0, KEY_REWIND,
-					0, KEY_FASTFORWARD, KEY_PLAY,
-					KEY_STOP, KEY_RECORD,
-					KEY_YELLOW, 0, 0, KEY_SELECT,
-					KEY_ZOOM, KEY_POWER, 0, 0
-			}
-		},
-		{ } /* Terminating entry */
-};
-
-static u32 ir_pos;
-static u32 ir_word;
-static u32 ir_toggle;
-
-#define RC5_PUSH_BIT(dst, bit, pos)	\
-	{ dst <<= 1; dst |= bit; pos++; }
-
-
-static void sms_ir_rc5_event(struct smscore_device_t *coredev,
-				u32 toggle, u32 addr, u32 cmd)
-{
-	bool toggle_changed;
-	u16 keycode;
-
-	sms_log("IR RC5 word: address %d, command %d, toggle %d",
-				addr, cmd, toggle);
-
-	toggle_changed = ir_toggle != toggle;
-	/* keep toggle */
-	ir_toggle = toggle;
-
-	if (addr !=
-		keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
-		return; /* Check for valid address */
-
-	keycode =
-		keyboard_layout_maps
-		[coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
+#define MODULE_NAME "smsmdtv"
 
-	if (!toggle_changed &&
-			(keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
-		return; /* accept only repeated volume, reject other keys */
-
-	sms_log("kernel input keycode (from ir) %d", keycode);
-	input_report_key(coredev->ir.input_dev, keycode, 1);
-	input_sync(coredev->ir.input_dev);
-
-}
-
-/* decode raw bit pattern to RC5 code */
-/* taken from ir-functions.c */
-static u32 ir_rc5_decode(unsigned int code)
+void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
 {
-/*	unsigned int org_code = code;*/
-	unsigned int pair;
-	unsigned int rc5 = 0;
 	int i;
+	const s32 *samples = (const void *)buf;
 
-	for (i = 0; i < 14; ++i) {
-		pair = code & 0x3;
-		code >>= 2;
-
-		rc5 <<= 1;
-		switch (pair) {
-		case 0:
-		case 2:
-			break;
-		case 1:
-			rc5 |= 1;
-			break;
-		case 3:
-/*	dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
-			sms_log("bad code");
-			return 0;
-		}
-	}
-/*
-	dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
-		toggle=%x, address=%x, "
-		"instr=%x\n", rc5, org_code, RC5_START(rc5),
-		RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
-*/
-	return rc5;
-}
-
-static void sms_rc5_parse_word(struct smscore_device_t *coredev)
-{
-	#define RC5_START(x)    (((x)>>12)&3)
-	#define RC5_TOGGLE(x)   (((x)>>11)&1)
-	#define RC5_ADDR(x)     (((x)>>6)&0x1F)
-	#define RC5_INSTR(x)    ((x)&0x3F)
-
-	int i, j;
-	u32 rc5_word = 0;
-
-	/* Reverse the IR word direction */
-	for (i = 0 ; i < 28 ; i++)
-		RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
-
-	rc5_word = ir_rc5_decode(rc5_word);
-	/* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
-
-	sms_ir_rc5_event(coredev,
-				RC5_TOGGLE(rc5_word),
-				RC5_ADDR(rc5_word),
-				RC5_INSTR(rc5_word));
-}
-
-
-static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
-		s32 ir_sample)
-{
-	#define RC5_TIME_GRANULARITY	200
-	#define RC5_DEF_BIT_TIME		889
-	#define RC5_MAX_SAME_BIT_CONT	4
-	#define RC5_WORD_LEN			27 /* 28 bit */
-
-	u32 i, j;
-	s32 delta_time;
-	u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
-	u32 level = (ir_sample < 0) ? 0 : 1;
-
-	for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
-		delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
-		if (delta_time < 0)
-			continue; /* not so many consecutive bits */
-		if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
-			/* timeout */
-			if (ir_pos == (RC5_WORD_LEN-1))
-				/* complete last bit */
-				RC5_PUSH_BIT(ir_word, level, ir_pos)
-
-			if (ir_pos == RC5_WORD_LEN)
-				sms_rc5_parse_word(coredev);
-			else if (ir_pos) /* timeout within a word */
-				sms_log("IR error parsing a word");
+	for (i = 0; i < len >> 2; i++) {
+		struct ir_raw_event ev;
 
-			ir_pos = 0;
-			ir_word = 0;
-			/* sms_log("timeout %d", time); */
-			break;
-		}
-		/* The time is within the range of this number of bits */
-		for (j = 0 ; j < i ; j++)
-			RC5_PUSH_BIT(ir_word, level, ir_pos)
+		ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
+		ev.pulse = (samples[i] > 0) ? false : true;
 
-		break;
+		ir_raw_event_store(coredev->ir.input_dev, &ev);
 	}
-}
-
-void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
-{
-	#define IR_DATA_RECEIVE_MAX_LEN	520 /* 128*4 + 4 + 4 */
-	u32 i;
-	enum ir_protocol ir_protocol =
-			keyboard_layout_maps[coredev->ir.ir_kb_type]
-					     .ir_protocol;
-	s32 *samples;
-	int count = len>>2;
-
-	samples = (s32 *)buf;
-/*	sms_log("IR buffer received, length = %d", count);*/
-
-	for (i = 0; i < count; i++)
-		if (ir_protocol == IR_RC5)
-			sms_rc5_accumulate_bits(coredev, samples[i]);
-	/*  IR_RCMM not implemented */
+	ir_raw_event_handle(coredev->ir.input_dev);
 }
 
 int sms_ir_init(struct smscore_device_t *coredev)
 {
 	struct input_dev *input_dev;
+	int board_id = smscore_get_board_id(coredev);
 
 	sms_log("Allocating input device");
 	input_dev = input_allocate_device();
@@ -256,33 +63,38 @@ int sms_ir_init(struct smscore_device_t *coredev)
 	}
 
 	coredev->ir.input_dev = input_dev;
-	coredev->ir.ir_kb_type =
-		sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
-	coredev->ir.keyboard_layout_map =
-		keyboard_layout_maps[coredev->ir.ir_kb_type].
-				keyboard_layout_map;
-	sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
 
 	coredev->ir.controller = 0;	/* Todo: vega/nova SPI number */
 	coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
 	sms_log("IR port %d, timeout %d ms",
 			coredev->ir.controller, coredev->ir.timeout);
 
-	snprintf(coredev->ir.name,
-				IR_DEV_NAME_MAX_LEN,
-				"SMS IR w/kbd type %d",
-				coredev->ir.ir_kb_type);
+	snprintf(coredev->ir.name, sizeof(coredev->ir.name),
+		 "SMS IR (%s)", sms_get_board(board_id)->name);
+
+	strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
+	strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
+
 	input_dev->name = coredev->ir.name;
-	input_dev->phys = coredev->ir.name;
+	input_dev->phys = coredev->ir.phys;
 	input_dev->dev.parent = coredev->device;
 
-	/* Key press events only */
-	input_dev->evbit[0] = BIT_MASK(EV_KEY);
-	input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
+#if 0
+	/* TODO: properly initialize the parameters bellow */
+	input_dev->id.bustype = BUS_USB;
+	input_dev->id.version = 1;
+	input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+	input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+#endif
+
+	coredev->ir.props.priv = coredev;
+	coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
+	coredev->ir.props.allowed_protos = IR_TYPE_ALL;
 
 	sms_log("Input device (IR) %s is set for key events", input_dev->name);
 
-	if (input_register_device(input_dev)) {
+	if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
+			      &coredev->ir.props, MODULE_NAME)) {
 		sms_err("Failed to register device");
 		input_free_device(input_dev);
 		return -EACCES;
@@ -294,8 +106,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
 	if (coredev->ir.input_dev)
-		input_unregister_device(coredev->ir.input_dev);
+		ir_input_unregister(coredev->ir.input_dev);
 
 	sms_log("");
 }
-

+ 13 - 50
drivers/media/dvb/siano/smsir.h

@@ -4,6 +4,11 @@ Siano Mobile Silicon, Inc.
 MDTV receiver kernel modules.
 Copyright (C) 2006-2009, Uri Shkolnik
 
+ Copyright (c) 2010 - Mauro Carvalho Chehab
+	- Ported the driver to use rc-core
+	- IR raw event decoding is now done at rc-core
+	- Code almost re-written
+
 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
@@ -23,63 +28,21 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define __SMS_IR_H__
 
 #include <linux/input.h>
+#include <media/ir-core.h>
 
-#define IR_DEV_NAME_MAX_LEN		23 /* "SMS IR kbd type nn\0" */
-#define IR_KEYBOARD_LAYOUT_SIZE	64
 #define IR_DEFAULT_TIMEOUT		100
 
-enum ir_kb_type {
-	SMS_IR_KB_DEFAULT_TV,
-	SMS_IR_KB_HCW_SILVER
-};
-
-enum rc5_keyboard_address {
-	KEYBOARD_ADDRESS_TV1 = 0,
-	KEYBOARD_ADDRESS_TV2 = 1,
-	KEYBOARD_ADDRESS_TELETEXT = 2,
-	KEYBOARD_ADDRESS_VIDEO = 3,
-	KEYBOARD_ADDRESS_LV1 = 4,
-	KEYBOARD_ADDRESS_VCR1 = 5,
-	KEYBOARD_ADDRESS_VCR2 = 6,
-	KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
-	KEYBOARD_ADDRESS_SAT1 = 8,
-	KEYBOARD_ADDRESS_CAMERA = 9,
-	KEYBOARD_ADDRESS_SAT2 = 10,
-	KEYBOARD_ADDRESS_CDV = 12,
-	KEYBOARD_ADDRESS_CAMCORDER = 13,
-	KEYBOARD_ADDRESS_PRE_AMP = 16,
-	KEYBOARD_ADDRESS_TUNER = 17,
-	KEYBOARD_ADDRESS_RECORDER1 = 18,
-	KEYBOARD_ADDRESS_PRE_AMP1 = 19,
-	KEYBOARD_ADDRESS_CD_PLAYER = 20,
-	KEYBOARD_ADDRESS_PHONO = 21,
-	KEYBOARD_ADDRESS_SATA = 22,
-	KEYBOARD_ADDRESS_RECORDER2 = 23,
-	KEYBOARD_ADDRESS_CDR = 26,
-	KEYBOARD_ADDRESS_LIGHTING = 29,
-	KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
-	KEYBOARD_ADDRESS_PHONE = 31,
-	KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
-};
-
-enum ir_protocol {
-	IR_RC5,
-	IR_RCMM
-};
-
-struct keyboard_layout_map_t {
-	enum ir_protocol ir_protocol;
-	enum rc5_keyboard_address rc5_kbd_address;
-	u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
-};
-
 struct smscore_device_t;
 
 struct ir_t {
 	struct input_dev *input_dev;
-	enum ir_kb_type ir_kb_type;
-	char name[IR_DEV_NAME_MAX_LEN+1];
-	u16 *keyboard_layout_map;
+	char name[40];
+	char phys[32];
+
+	char *rc_codes;
+	u64 protocol;
+	struct ir_dev_props props;
+
 	u32 timeout;
 	u32 controller;
 };

+ 1 - 2
drivers/media/dvb/siano/smsusb.c

@@ -352,8 +352,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
 	params.num_buffers = MAX_BUFFERS;
 	params.sendrequest_handler = smsusb_sendrequest;
 	params.context = dev;
-	snprintf(params.devpath, sizeof(params.devpath),
-		 "usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
+	usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
 
 	/* register in smscore */
 	rc = smscore_register_device(&params, &dev->coredev);

+ 1 - 1
drivers/media/radio/si470x/radio-si470x-common.c

@@ -748,7 +748,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
 		struct v4l2_tuner *tuner)
 {
 	struct si470x_device *radio = video_drvdata(file);
-	int retval = -EINVAL;
+	int retval = 0;
 
 	/* safety checks */
 	retval = si470x_disconnect_check(radio);

+ 10 - 2
drivers/media/radio/si4713-i2c.c

@@ -1009,8 +1009,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
 			goto exit;
 		}
 		rval = copy_from_user(ps_name, control->string, len);
-		if (rval < 0)
+		if (rval) {
+			rval = -EFAULT;
 			goto exit;
+		}
 		ps_name[len] = '\0';
 
 		if (strlen(ps_name) % vqc.step) {
@@ -1031,8 +1033,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
 			goto exit;
 		}
 		rval = copy_from_user(radio_text, control->string, len);
-		if (rval < 0)
+		if (rval) {
+			rval = -EFAULT;
 			goto exit;
+		}
 		radio_text[len] = '\0';
 
 		if (strlen(radio_text) % vqc.step) {
@@ -1367,6 +1371,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
 		}
 		rval = copy_to_user(control->string, sdev->rds_info.ps_name,
 					strlen(sdev->rds_info.ps_name) + 1);
+		if (rval)
+			rval = -EFAULT;
 		break;
 
 	case V4L2_CID_RDS_TX_RADIO_TEXT:
@@ -1377,6 +1383,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
 		}
 		rval = copy_to_user(control->string, sdev->rds_info.radio_text,
 					strlen(sdev->rds_info.radio_text) + 1);
+		if (rval)
+			rval = -EFAULT;
 		break;
 
 	default:

+ 18 - 165
drivers/media/video/Kconfig

@@ -517,19 +517,6 @@ config VIDEO_UPD64083
 
 endmenu # encoder / decoder chips
 
-config DISPLAY_DAVINCI_DM646X_EVM
-	tristate "DM646x EVM Video Display"
-	depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
-	select VIDEOBUF_DMA_CONTIG
-	select VIDEO_DAVINCI_VPIF
-	select VIDEO_ADV7343
-	select VIDEO_THS7303
-	help
-	  Support for DM6467 based display device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vpif_display.
-
 config VIDEO_SH_VOU
 	tristate "SuperH VOU video output driver"
 	depends on VIDEO_DEV && ARCH_SHMOBILE
@@ -537,29 +524,22 @@ config VIDEO_SH_VOU
 	help
 	  Support for the Video Output Unit (VOU) on SuperH SoCs.
 
-config CAPTURE_DAVINCI_DM646X_EVM
-	tristate "DM646x EVM Video Capture"
-	depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
+config VIDEO_VIU
+	tristate "Freescale VIU Video Driver"
+	depends on VIDEO_V4L2 && PPC_MPC512x
 	select VIDEOBUF_DMA_CONTIG
-	select VIDEO_DAVINCI_VPIF
-	help
-	  Support for DM6467 based capture device.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vpif_capture.
-
-config VIDEO_DAVINCI_VPIF
-	tristate "DaVinci VPIF Driver"
-	depends on DISPLAY_DAVINCI_DM646X_EVM
-	help
-	  Support for DaVinci VPIF Driver.
+	default y
+	---help---
+	  Support for Freescale VIU video driver. This device captures
+	  video data, or overlays video on DIU frame buffer.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called vpif.
+	  Say Y here if you want to enable VIU device on MPC5121e Rev2+.
+	  In doubt, say N.
 
 config VIDEO_VIVI
 	tristate "Virtual Video Driver"
-	depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS
+	depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
+	depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS
 	select FONT_8x16
 	select VIDEOBUF_VMALLOC
 	default n
@@ -570,66 +550,7 @@ config VIDEO_VIVI
 	  Say Y here if you want to test video apps or debug V4L devices.
 	  In doubt, say N.
 
-config VIDEO_VPSS_SYSTEM
-	tristate "VPSS System module driver"
-	depends on ARCH_DAVINCI
-	help
-	  Support for vpss system module for video driver
-
-config VIDEO_VPFE_CAPTURE
-	tristate "VPFE Video Capture Driver"
-	depends on VIDEO_V4L2 && ARCH_DAVINCI
-	select VIDEOBUF_DMA_CONTIG
-	help
-	  Support for DMXXXX VPFE based frame grabber. This is the
-	  common V4L2 module for following DMXXX SoCs from Texas
-	  Instruments:- DM6446 & DM355.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called vpfe-capture.
-
-config VIDEO_DM6446_CCDC
-	tristate "DM6446 CCDC HW module"
-	depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE
-	select VIDEO_VPSS_SYSTEM
-	default y
-	help
-	   Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
-	   with decoder modules such as TVP5146 over BT656 or
-	   sensor module such as MT9T001 over a raw interface. This
-	   module configures the interface and CCDC/ISIF to do
-	   video frame capture from slave decoders.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called vpfe.
-
-config VIDEO_DM355_CCDC
-	tristate "DM355 CCDC HW module"
-	depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
-	select VIDEO_VPSS_SYSTEM
-	default y
-	help
-	   Enables DM355 CCD hw module. DM355 CCDC hw interfaces
-	   with decoder modules such as TVP5146 over BT656 or
-	   sensor module such as MT9T001 over a raw interface. This
-	   module configures the interface and CCDC/ISIF to do
-	   video frame capture from a slave decoders
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called vpfe.
-
-config VIDEO_ISIF
-	tristate "ISIF HW module"
-	depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
-	select VIDEO_VPSS_SYSTEM
-	default y
-	help
-	   Enables ISIF hw module. This is the hardware module for
-	   configuring ISIF in VPFE to capture Raw Bayer RGB data  from
-	   a image sensor or YUV data from a YUV source.
-
-	   To compile this driver as a module, choose M here: the
-	   module will be called vpfe.
+source "drivers/media/video/davinci/Kconfig"
 
 source "drivers/media/video/omap/Kconfig"
 
@@ -955,6 +876,12 @@ config VIDEO_PXA27x
 	---help---
 	  This is a v4l2 driver for the PXA27x Quick Capture Interface
 
+config VIDEO_SH_MOBILE_CSI2
+	tristate "SuperH Mobile MIPI CSI-2 Interface driver"
+	depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+	---help---
+	  This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
+
 config VIDEO_SH_MOBILE_CEU
 	tristate "SuperH Mobile CEU Interface driver"
 	depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
@@ -1013,61 +940,6 @@ source "drivers/media/video/usbvideo/Kconfig"
 
 source "drivers/media/video/et61x251/Kconfig"
 
-config VIDEO_OVCAMCHIP
-	tristate "OmniVision Camera Chip support (DEPRECATED)"
-	depends on I2C && VIDEO_V4L1
-	default n
-	---help---
-	  This driver is DEPRECATED please use the gspca ov519 module
-	  instead. Note that for the ov511 / ov518 support of the gspca module
-	  you need atleast version 0.6.0 of libv4l and for the w9968cf
-	  atleast version 0.6.3 of libv4l.
-
-	  Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
-	  This driver is intended to be used with the ov511 and w9968cf USB
-	  camera drivers.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ovcamchip.
-
-config USB_W9968CF
-	tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)"
-	depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
-	default n
-	---help---
-	  This driver is DEPRECATED please use the gspca ov519 module
-	  instead. Note that for the w9968cf support of the gspca module
-	  you need atleast version 0.6.3 of libv4l.
-
-	  Say Y here if you want support for cameras based on OV681 or
-	  Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
-
-	  This driver has an optional plugin, which is distributed as a
-	  separate module only (released under GPL). It allows to use higher
-	  resolutions and framerates, but cannot be included in the official
-	  Linux kernel for performance purposes.
-
-	  See <file:Documentation/video4linux/w9968cf.txt> for more info.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called w9968cf.
-
-config USB_OV511
-	tristate "USB OV511 Camera support (DEPRECATED)"
-	depends on VIDEO_V4L1
-	default n
-	---help---
-	  This driver is DEPRECATED please use the gspca ov519 module
-	  instead. Note that for the ov511 / ov518 support of the gspca module
-	  you need atleast version 0.6.0 of libv4l.
-
-	  Say Y here if you want to connect this type of camera to your
-	  computer's USB port. See <file:Documentation/video4linux/ov511.txt>
-	  for more information and for a list of supported cameras.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ov511.
-
 config USB_SE401
 	tristate "USB SE401 Camera support"
 	depends on VIDEO_V4L1
@@ -1081,25 +953,6 @@ config USB_SE401
 
 source "drivers/media/video/sn9c102/Kconfig"
 
-config USB_STV680
-	tristate "USB STV680 (Pencam) Camera support (DEPRECATED)"
-	depends on VIDEO_V4L1
-	default n
-	---help---
-	  This driver is DEPRECATED please use the gspca stv0680 module
-	  instead. Note that for the gspca stv0680 module you need
-	  atleast version 0.6.3 of libv4l.
-
-	  Say Y here if you want to connect this type of camera to your
-	  computer's USB port. This includes the Pencam line of cameras.
-	  See <file:Documentation/video4linux/stv680.txt> for more information
-	  and for a list of supported cameras.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called stv680.
-
-source "drivers/media/video/zc0301/Kconfig"
-
 source "drivers/media/video/pwc/Kconfig"
 
 config USB_ZR364XX

+ 3 - 6
drivers/media/video/Makefile

@@ -105,7 +105,6 @@ obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
 obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
-obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
 obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
@@ -127,17 +126,13 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
-obj-$(CONFIG_USB_OV511)         += ov511.o
 obj-$(CONFIG_USB_SE401)         += se401.o
-obj-$(CONFIG_USB_STV680)        += stv680.o
-obj-$(CONFIG_USB_W9968CF)       += w9968cf.o
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
 obj-$(CONFIG_USB_SN9C102)       += sn9c102/
 obj-$(CONFIG_USB_ET61X251)      += et61x251/
 obj-$(CONFIG_USB_PWC)           += pwc/
-obj-$(CONFIG_USB_ZC0301)        += zc0301/
 obj-$(CONFIG_USB_GSPCA)         += gspca/
 
 obj-$(CONFIG_VIDEO_HDPVR)	+= hdpvr/
@@ -151,6 +146,7 @@ obj-$(CONFIG_USB_S2255)		+= s2255drv.o
 obj-$(CONFIG_VIDEO_IVTV) += ivtv/
 obj-$(CONFIG_VIDEO_CX18) += cx18/
 
+obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
@@ -165,6 +161,7 @@ obj-$(CONFIG_VIDEO_MX1)			+= mx1_camera.o
 obj-$(CONFIG_VIDEO_MX2)			+= mx2_camera.o
 obj-$(CONFIG_VIDEO_MX3)			+= mx3_camera.o
 obj-$(CONFIG_VIDEO_PXA27x)		+= pxa_camera.o
+obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)	+= sh_mobile_csi2.o
 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)	+= sh_mobile_ceu_camera.o
 
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
@@ -178,7 +175,7 @@ obj-$(CONFIG_VIDEO_SAA7164)     += saa7164/
 
 obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
 
-obj-$(CONFIG_ARCH_DAVINCI)	+= davinci/
+obj-y	+= davinci/
 
 obj-$(CONFIG_ARCH_OMAP)	+= omap/
 

+ 3 - 3
drivers/media/video/ak881x.c

@@ -126,7 +126,7 @@ static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
 	v4l_bound_align_image(&mf->width, 0, 720, 2,
 			      &mf->height, 0, ak881x->lines, 1, 0);
 	mf->field	= V4L2_FIELD_INTERLACED;
-	mf->code	= V4L2_MBUS_FMT_YUYV8_2X8_LE;
+	mf->code	= V4L2_MBUS_FMT_YUYV8_2X8;
 	mf->colorspace	= V4L2_COLORSPACE_SMPTE170M;
 
 	return 0;
@@ -136,7 +136,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
 			     struct v4l2_mbus_framefmt *mf)
 {
 	if (mf->field != V4L2_FIELD_INTERLACED ||
-	    mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE)
+	    mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
 		return -EINVAL;
 
 	return ak881x_try_g_mbus_fmt(sd, mf);
@@ -148,7 +148,7 @@ static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
 	if (index)
 		return -EINVAL;
 
-	*code = V4L2_MBUS_FMT_YUYV8_2X8_LE;
+	*code = V4L2_MBUS_FMT_YUYV8_2X8;
 	return 0;
 }
 

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