Blob Blame History Raw
v4l/dvb/rc media_tree updates from 2.6.39

commit f9d088784131609419595b51beb701d0f3aa6afc
Author: Jarod Wilson <jarod@redhat.com>
Date:   Tue Mar 22 17:23:15 2011 -0300

    [media] rc: interim support for 32-bit NEC-ish scancodes
    
    The Apple and TiVo remotes I've got use an NEC-ish protocol, but rather
    than a command/not_command pair, they have what appear to be vendor ID
    bytes. This change makes the NEC decoder warn if the command/not_command
    checksum fails, but then passes along a full 32-bit scancode for keymap
    lookup. This change should make no difference for existing keymaps,
    since they simply won't have 32-bit scancodes, but allows for a 32-bit
    keymap. At the moment, that'll have to be uploaded by the user, but I've
    got Apple and TiVo remote keymaps forthcoming.
    
    In the long run (2.6.40, hopefully), we should probably just always use
    all 32 bits for all NEC keymaps, but this should get us by for 2.6.39.
    
    (Note that a few of the TiVo keys actuallly *do* pass the command
    checksum, so for now, the keymap for this remote will have to be a mix
    of 24-bit and 32-bit scancodes, but so be it).
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 4568844fff1dc46b8adb7364ac3a844aa34d1e38
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Mar 4 20:20:47 2011 -0300

    [media] mceusb: topseed 0x0011 needs gen3 init for tx to work
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 514c3ef0671bdbdb1ae3708c63cce12e6f4b55f0
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Mar 4 19:53:05 2011 -0300

    [media] lirc_zilog: error out if buffer read bytes != chunk size
    
    Give it a few tries, then exit. Prevents a possible endless loop
    situation.
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 7f72453889801675b825083d7ebddc341ccbb331
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Mar 4 17:57:24 2011 -0300

    [media] lirc: silence some compile warnings
    
    Both lirc_imon and lirc_sasem were causing gcc to complain about the
    possible use of uninitialized variables.
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 37bda6318295a3412e191f1a5cb5a5bea2db59a5
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Mar 4 17:31:11 2011 -0300

    [media] hdpvr: use same polling interval as other OS
    
    The hdpvr's IR part, in short, sucks. As observed with a usb traffic
    sniffer, the Windows software for it uses a polling interval of 405ms.
    Its still not behaving as well as I'd like even with this change, but
    this inches us closer and closer to that point...
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 6ba973db97845b0b7322d1a0cd5348d3024d7387
Author: Jarod Wilson <jarod@redhat.com>
Date:   Fri Mar 4 17:30:17 2011 -0300

    [media] ir-kbd-i2c: pass device code w/key in hauppauge case
    
    The new hauppauge key tables use both device code button code.
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 246286a63b4820c1c039a836025c52ec79d18a2f
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 22:23:08 2011 -0300

    [media] rc/keymaps: Remove the obsolete rc-rc5-tv keymap
    
    This keymap were used for the Hauppauge Black remote controller
    only. It also contains some keycodes not found there. As the
    Hauppauge Black is now part of the hauppauge keymap, just remove
    it.
    
    Also, remove the modprobe hacks to select between the Gray
    and the Black versions of the remote controller as:
     - Both are supported by default by the keymap;
     - If the user just wants one keyboard supported,
       it is just a matter of changing the keymap via
       the userspace tool (ir-keytable), removing
       the keys that he doesn't desire. As ir-keytable
       auto-loads the keys via udev, this is better than
       obscure modprobe parameters.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit af2a42cc5eec9659bac301885ac795be81d019c8
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:48 2011 -0300

    [media] remove the old RC_MAP_HAUPPAUGE_NEW RC map
    
    The rc-hauppauge-new map is a messy thing, as it bundles 3
    
    different remote controllers as if they were just one,
    discarding the address byte. Also, some key maps are wrong.
    
    With the conversion to the new rc-core, it is likely that
    most of the devices won't be working properly, as the i2c
    driver and the raw decoders are now providing 16 bits for
    the remote, instead of just 8.
    
     delete mode 100644 drivers/media/rc/keymaps/rc-hauppauge-new.c
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 1ef571252ec29a8b3674deb746bfaa8ad1b034c3
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:47 2011 -0300

    [media] rc/keymaps: Rename Hauppauge table as rc-hauppauge
    
    There are two "hauppauge-new" keymaps, one with protocol
    unknown, and the other with the protocol marked accordingly.
    However, both tables are miss-named.
    
    Also, the old rc-hauppauge-new is broken, as it mixes
    three different controllers as if they were just one.
    
    This patch solves half of the problem by renaming the
    correct keycode table as just rc-hauppauge. This table
    contains the codes for the four different types of
    remote controllers found on Hauppauge cards, properly
    mapped with their different addresses.
    
     create mode 100644 drivers/media/rc/keymaps/rc-hauppauge.c
     delete mode 100644 drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
    [Jarod: fix up RC_MAP_HAUPPAUGE defines]
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 41abb2ee0ac34ecd8769b2ddd84caf67414ca0f7
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:45 2011 -0300

    [media] rc-rc5-hauppauge-new: Fix Hauppauge Grey mapping
    
    The keys for the old black were messed with the ones for the
    hauppauge grey. Fix it.
    
    Also, fixes some keycodes and order the keys according with
    the way they appear inside the remote controller.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 80daad9d9ece3bbfd0f7cc13dbefc92e3ebb1f6f
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:44 2011 -0300

    [media] rc-rc5-hauppauge-new: Add support for the old Black RC
    
    Hans borrowed me an old Black Hauppauge RC. Thanks to that, we
    can fix the RC5 table for Hauppauge.
    
    Thanks-to: Hans Verkuil <hverkuil@xs4all.nl>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 9ba542ee399a091a56711d5bc1f778f39768a26d
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:43 2011 -0300

    [media] rc-rc5-hauppauge-new: Add the old control to the table
    
    Adds the old grey remote controller to Hauppauge table.
    
    Hans borrowed me an old gray Hauppauge RC. Thanks to that, we
    can fix the RC5 table for Hauppauge.
    
    Thanks-to: Hans Verkuil <hverkuil@xs4all.nl>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 8d198df40f2d6fe2bfb3b8818dce974b40a614e9
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:43 2011 -0300

    [media] rc-winfast: Fix the keycode tables
    
    One of the remotes has a picture available at:
    	http://lirc.sourceforge.net/remotes/leadtek/Y04G0004.jpg
    
    As there's one variant with a set direction keys plus vol/chann
    keys, and the same table is used for both models, change it to
    represent all keys, avoiding the usage of weird function keys.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 434e6519a292096ee29303d74688ced038606842
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:42 2011 -0300

    [media] a800: Fix a few wrong IR key assignments
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 674ff915ca5d7b40d710eb910afcf7f490b76ab0
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:41 2011 -0300

    [media] opera1: Use multimedia keys instead of an app-specific mapping
    
    This driver uses an app-specific keymap for one of the tables. This
    is wrong. Instead, use the standard keycodes.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit d59b1eedf5d5108cc90b9cfaf17f7845bad4f806
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:40 2011 -0300

    [media] dw2102: Use multimedia keys instead of an app-specific mapping
    
    This driver uses an app-specific keymap for one of the tables. This
    is wrong. Instead, use the standard keycodes.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 651cef86ff15697ad8a5659ecc9bc43f16ca07ba
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:39 2011 -0300

    [media] rc/keymaps: Use KEY_LEFTMETA were pertinent
    
    Using xev and testing the "Windows" key on a normal keyboard, it
    is mapped as KEY_LEFTMETA. So, as this is the standard code for
    it, use it, instead of a generic, meaningless KEY_PROG1.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit bb8aeecec52791eacc727d8400ced9e1b230ec49
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:38 2011 -0300

    [media] rc/keymaps: Fix most KEY_PROG[n] keycodes
    
    Those KEY_PROG[n] keys were used on places where the developer
    didn't know for sure what key should be used. On several cases,
    using KEY_RED, KEY_GREEN, KEY_YELLOW would be enough. On others,
    there are specific keys for that already.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 84c122769cca37480fbcd7de5a102f6221874247
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:37 2011 -0300

    [media] rc/keymaps: Use KEY_VIDEO for Video Source
    
    Each keyboard map were using a different definition for
    the Source/Video Source key.
    Behold Columbus were the only one using KEY_PROPS.
    
    As we want to standardize those keys at X11 and at
    userspace applications, we need to use just one code
    for it.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit ea35a76538a45e78cee889d2c462df71a9b34e4c
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Mon Jan 24 12:18:36 2011 -0300

    [media] rc/keymaps: use KEY_CAMERA for snapshots
    
    On a few places, KEY_MHP were used for snapshots. However, KEY_CAMERA
    is used for it on all the other keyboards that have a snapshot/Picture
    button.
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit d33d27b1745fc72b042b6431dd29ee484fdabbcc
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Feb 17 21:32:06 2011 -0300

    [media] lirc_zilog: Update TODO list based on work completed and revised plans
    
    Update the TODO.lirc_zilog based on what has been completed.  Also revised
    the development plan for lirc_zilog to not try and split Tx/Rx for one IR
    transceiver unit between lirc_zilog and ir-kbd-i2c, since that would be a
    ref-counting nightmare.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 1a9cb97924e71b33a5d1a59facd58e1a584daa97
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Feb 17 21:14:13 2011 -0300

    [media] lirc_zilog: Fix somewhat confusing information messages in ir_probe()
    
    The total sequence of messages emitted by the ir_porbe() calls
    for a transceiver's two i2c_clients was confusing.  Clean it up a bit.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit cf141c455938cb245b6bf489c832d0c2e3833686
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Feb 17 20:50:38 2011 -0300

    [media] lirc_zilog: Add locking of the i2c_clients when in use
    
    Lock the i2c_client pointers and prevent i2c_client removal when
    lirc_zilog is perfoming a series of operations that require valid
    i2c_client pointers.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 6f4276ac6e98a05833aa7e49e438fec198e537e8
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Mon Feb 7 22:30:55 2011 -0300

    [media] lirc_zilog: Add ref counting of struct IR, IR_tx, and IR_rx
    
    This is a major change to add pointer reference counting for
    struct IR, struct IR_tx, and struct IR_rx object instances.
    This ref counting gets lirc_zilog closer to gracefully handling
    bridge drivers and hot-unplugged USB devices disappearing out from
    under lirc_zilog when the /dev/lircN node is still open.  (mutexes
    to protect the i2c_client pointers in struct IR_tx and struct IR_rx
    still need to be added.)
    
    This reference counting also helps lirc_zilog clean up properly
    when the i2c_clients disappear.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit f3bc78dbb5942f1827a97329b1c095903329aa8b
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Jan 27 23:02:20 2011 -0300

    [media] lirc_zilog: Move constants from ir_probe() into the lirc_driver template
    
    ir_probe() makes a number of constant assignments into the lirc_driver
    object after copying in a template.  Make better use of the template.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 6f61cb53e2b8f6c65cf2c6b3e3710233c643e6ce
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Jan 27 22:32:44 2011 -0300

    [media] lirc_zilog: Always allocate a Rx lirc_buffer object
    
    Always allocate a lirc_buffer object, instead of just upon setup of
    the Rx i2c_client.  If we do not allocate a lirc_buffer object, because
    we are not handling the Rx i2c_client, lirc_dev will allocate its own
    lirc_buffer anyway and not tell us about its location.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 8941d66476b33d339408f66898766e0d8ac2cb0a
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Jan 27 02:34:13 2011 -0300

    [media] lirc_zilog: Remove unneeded rx->buf_lock
    
    Remove the rx->buf_lock that protected the rx->buf lirc_buffer.  The
    underlying operations on the objects within the lirc_buffer are already
    protected by spinlocks, or the objects are constant (e.g. chunk_size).
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit fa2d70732b5699cd3bc9fc0e82c154e1410857e4
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Jan 27 02:10:42 2011 -0300

    [media] lirc_zilog: Don't acquire the rx->buf_lock in the poll() function
    
    There is no need to take the rx->buf_lock in the the poll() function
    as all the underling calls made on objects in the rx->buf lirc_buffer object
    are protected by spinlocks.
    
    Corrected a bad error return value in poll(): return POLLERR instead
    of -ENODEV.
    
    Added some comments to poll() for when, in the future, I forget what
    poll() and poll_wait() are supposed to do.
    
    [Jarod: minor debug spew fix]
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 45a0dd2e9575f72693c94920e8d189ea395d5b5d
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Thu Jan 27 00:04:15 2011 -0300

    [media] lirc_zilog: Use kernel standard methods for marking device non-seekable
    
    lirc_zilog had its own llseek stub that returned -ESPIPE.  Get rid of
    it and use the kernel's no_llseek() and nonseekable_open() functions
    instead.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit c4c4362e1e1bd1a39f186b96ba5b0df74470f101
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Wed Jan 26 22:04:24 2011 -0300

    [media] lirc_zilog: Convert the instance open count to an atomic_t
    
    The open count is simply used for deciding if the Rx polling thread
    needs to poll the IR chip for userspace.  Simplify the manipulation
    of the open count by using an atomic_t and not requiring a lock
    The polling thread errantly didn't try to take the lock anyway.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 7f94125db5889c202b95e717ccbe9e35de63c14a
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Wed Jan 26 21:48:32 2011 -0300

    [media] lirc_zilog: Convert ir_device instance array to a linked list
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit d2a47dc2e351e6cf33b98f0d3339d6d39fd8ed8b
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Wed Jan 26 21:25:47 2011 -0300

    [media] lirc_zilog: Remove broken, ineffective reference counting
    
    The set_use_inc() and set_use_dec() functions tried to lock
    the underlying bridge driver device instance in memory by
    changing the use count on the device's i2c_clients.  This
    worked for PCI devices (ivtv, cx18, bttv).  It doesn't
    work for hot-pluggable usb devices (pvrusb2 and hdpvr).
    With usb device instances, the driver may get locked into
    memory, but the unplugged hardware is gone.
    
    The set_use_inc() set_use_dec() functions also tried to have
    lirc_zilog change its own module refernce count, which is
    racy and not guaranteed to work.  The lirc_dev module does
    actually perform proper module ref count manipulation on the
    lirc_zilog module, so there is need for lirc_zilog to
    attempt a buggy module get on itself anyway.
    
    lirc_zilog also errantly called these functions on itself
    in open() and close(), but lirc_dev did that already too.
    
    So let's just gut the bodies of the set_use_*() functions,
    and remove the extra calls to them from within lirc_zilog.
    
    Proper reference counting of the struct IR, IR_rx, and IR_tx
    objects -- to handle the case when the underlying
    bttv, ivtv, cx18, hdpvr, or pvrusb2 bridge driver module or
    device instance goes away -- will be added in subsequent
    patches.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 767dd925f017bd0f0363f827509cebfaf0bb2b57
Author: Andy Walls <awalls@md.metrocast.net>
Date:   Wed Jan 26 21:06:43 2011 -0300

    [media] lirc_zilog: Restore checks for existence of the IR_tx object
    
    This reverts commit 8090232a237ab62e22307fc060097da1a283dd66 and
    adds an additional check for ir->tx == NULL.
    
    The user may need us to handle an RX only unit.  Apparently
    there are TV capture units in existence with Rx only wiring
    and/or RX only firmware for the on-board Zilog Z8 IR unit.
    
    Signed-off-by: Andy Walls <awalls@md.metrocast.net>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 91f27e09d7bba99341bd8ce035995ae21ff493f7
Author: Jarod Wilson <jarod@redhat.com>
Date:   Wed Mar 2 13:23:52 2011 -0300

    [media] hdpvr: i2c master enhancements
    
    Make the hdpvr's i2c master implementation more closely mirror that of
    the pvrusb2 driver. Currently makes no significant difference in IR
    reception behavior with ir-kbd-i2c (i.e., it still sucks).
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit c1ba04cf3a0626f725795e3a853654928596d522
Author: Jarod Wilson <jarod@redhat.com>
Date:   Tue Feb 1 16:27:05 2011 -0300

    [media] imon: add more panel scancode mappings
    
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 9cd4f638d57b01c5d901f73c94b08fad4aa0b295
Author: Jarod Wilson <jarod@redhat.com>
Date:   Mon Jan 24 18:22:12 2011 -0300

    [media] docs: fix typo in lirc_device_interface.xml
    
    Reported-by: Daniel Burr <dburr@topcon.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 97ad124749a060d8c4f5461111911474db3b555f
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Tue Mar 22 17:17:56 2011 -0300

    ite-cir: Fix a breakage caused by my cleanup patch
    
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit a38fc7a384bd679f2550e2a2323ff3e690d4ffd7
Author: Juan J. Garcia de Soria <skandalfo@gmail.com>
Date:   Wed Mar 16 17:14:53 2011 -0300

    [media] lirc: remove staging lirc_it87 and lirc_ite8709 drivers
    
    Remove older drivers lirc_it87 and lirc_ite8709 from the LIRC staging area,
    since they're now superceded by ite-cir.
    
    Signed-off-by: Juan J. Garcia de Soria <skandalfo@gmail.com>
    Tested-by: Stephan Raue <stephan@openelec.tv>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit e1bede3475c792a5c4793ec3cc929efa24aaae64
Author: Mauro Carvalho Chehab <mchehab@redhat.com>
Date:   Tue Mar 22 15:12:40 2011 -0300

    [media] ite-cir: Fix some CodingStyle issues
    
    Cc: Juan J. Garcia de Soria <skandalfo@gmail.com>
    Cc: Stephan Raue <stephan@openelec.tv>
    Cc: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

commit 9e8739744ccc917011a91e489339278d7bb14eac
Author: Juan J. Garcia de Soria <skandalfo@gmail.com>
Date:   Wed Mar 16 17:14:52 2011 -0300

    [media] rc: New rc-based ite-cir driver for several ITE CIRs
    
    This is a second version of an rc-core based driver for the ITE Tech IT8712F
    CIR and now for a pair of other variants of the IT8512 CIR too.
    
    This driver should replace the lirc_it87 and lirc_ite8709 currently living in
    the LIRC staging directory.
    
    The driver should support the ITE8704, ITE8713, ITE8708 and ITE8709 (this last
    one yet untested) PNP ID's.
    
    The code doesn'te reuse code from the pre-existing LIRC drivers, but has been
    written from scratch using the nuvoton.cir driver as a skeleton.
    
    This new driver shouldn't exhibit timing problems when running under load (or
    with interrupts disabled for relatively long times). It works OOTB with the
    RC6 MCE remote bundled with the ASUS EEEBox. TX support is implemented, but
    I'm unable to test it since my hardware lacks TX capability.
    
    Signed-off-by: Juan J. Garcia de Soria <skandalfo@gmail.com>
    Tested-by: Stephan Raue <stephan@openelec.tv>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
 .../DocBook/v4l/lirc_device_interface.xml          |    2 +-
 drivers/media/dvb/dvb-usb/a800.c                   |    8 +-
 drivers/media/dvb/dvb-usb/digitv.c                 |    2 +-
 drivers/media/dvb/dvb-usb/dw2102.c                 |   40 +-
 drivers/media/dvb/dvb-usb/opera1.c                 |   33 +-
 drivers/media/dvb/siano/sms-cards.c                |    2 +-
 drivers/media/dvb/ttpci/budget-ci.c                |   15 +-
 drivers/media/rc/Kconfig                           |   13 +
 drivers/media/rc/Makefile                          |    1 +
 drivers/media/rc/imon.c                            |   11 +-
 drivers/media/rc/ir-nec-decoder.c                  |   10 +-
 drivers/media/rc/ite-cir.c                         | 1736 ++++++++++++++++++++
 drivers/media/rc/ite-cir.h                         |  481 ++++++
 drivers/media/rc/keymaps/Makefile                  |    4 +-
 drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c    |    6 +-
 drivers/media/rc/keymaps/rc-avermedia-dvbt.c       |    4 +-
 drivers/media/rc/keymaps/rc-avermedia-m135a.c      |    2 +-
 .../media/rc/keymaps/rc-avermedia-m733a-rm-k6.c    |    2 +-
 drivers/media/rc/keymaps/rc-avermedia-rm-ks.c      |    2 +-
 drivers/media/rc/keymaps/rc-behold-columbus.c      |    2 +-
 drivers/media/rc/keymaps/rc-behold.c               |    2 +-
 drivers/media/rc/keymaps/rc-budget-ci-old.c        |    3 +-
 drivers/media/rc/keymaps/rc-cinergy.c              |    2 +-
 drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c      |    2 +-
 drivers/media/rc/keymaps/rc-encore-enltv.c         |    4 +-
 drivers/media/rc/keymaps/rc-encore-enltv2.c        |    2 +-
 drivers/media/rc/keymaps/rc-flydvb.c               |    4 +-
 drivers/media/rc/keymaps/rc-hauppauge-new.c        |  100 --
 drivers/media/rc/keymaps/rc-hauppauge.c            |  241 +++
 drivers/media/rc/keymaps/rc-imon-mce.c             |    2 +-
 drivers/media/rc/keymaps/rc-imon-pad.c             |    2 +-
 drivers/media/rc/keymaps/rc-kworld-315u.c          |    2 +-
 .../media/rc/keymaps/rc-kworld-plus-tv-analog.c    |    2 +-
 drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c  |    2 +-
 drivers/media/rc/keymaps/rc-nebula.c               |    2 +-
 drivers/media/rc/keymaps/rc-norwood.c              |    2 +-
 drivers/media/rc/keymaps/rc-pctv-sedna.c           |    2 +-
 drivers/media/rc/keymaps/rc-pixelview-mk12.c       |    2 +-
 drivers/media/rc/keymaps/rc-pixelview-new.c        |    2 +-
 drivers/media/rc/keymaps/rc-pixelview.c            |    2 +-
 drivers/media/rc/keymaps/rc-pv951.c                |    4 +-
 drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c    |  141 --
 drivers/media/rc/keymaps/rc-rc5-tv.c               |   81 -
 drivers/media/rc/keymaps/rc-rc6-mce.c              |    2 +-
 .../media/rc/keymaps/rc-real-audio-220-32-keys.c   |    2 +-
 drivers/media/rc/keymaps/rc-winfast.c              |   22 +-
 drivers/media/rc/mceusb.c                          |    4 +-
 drivers/media/video/cx18/cx18-i2c.c                |    2 +-
 drivers/media/video/cx23885/cx23885-input.c        |    2 +-
 drivers/media/video/cx88/cx88-input.c              |    4 +-
 drivers/media/video/em28xx/em28xx-cards.c          |   10 +-
 drivers/media/video/hdpvr/hdpvr-i2c.c              |   72 +-
 drivers/media/video/ir-kbd-i2c.c                   |   18 +-
 drivers/media/video/ivtv/ivtv-i2c.c                |    5 +-
 drivers/media/video/pvrusb2/pvrusb2-i2c-core.c     |    4 +-
 drivers/media/video/saa7134/saa7134-input.c        |    2 +-
 drivers/staging/lirc/Kconfig                       |   12 -
 drivers/staging/lirc/Makefile                      |    2 -
 drivers/staging/lirc/TODO.lirc_zilog               |   51 +-
 drivers/staging/lirc/lirc_imon.c                   |    2 +-
 drivers/staging/lirc/lirc_it87.c                   | 1027 ------------
 drivers/staging/lirc/lirc_it87.h                   |  116 --
 drivers/staging/lirc/lirc_ite8709.c                |  542 ------
 drivers/staging/lirc/lirc_sasem.c                  |    2 +-
 drivers/staging/lirc/lirc_zilog.c                  |  814 ++++++----
 include/media/rc-map.h                             |    4 +-
 include/media/soc_camera.h                         |    2 +
 67 files changed, 3128 insertions(+), 2513 deletions(-)

---
diff --git a/Documentation/DocBook/v4l/lirc_device_interface.xml b/Documentation/DocBook/v4l/lirc_device_interface.xml
index 68134c0..0e0453f 100644
--- a/Documentation/DocBook/v4l/lirc_device_interface.xml
+++ b/Documentation/DocBook/v4l/lirc_device_interface.xml
@@ -45,7 +45,7 @@ describing an IR signal are read from the chardev.</para>
 <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
+an uneven number of samples. The write function must block until the data has
 been transmitted by the hardware.</para>
 </section>
 
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index 53b93a4..f8e9bf1 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -38,8 +38,8 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
 }
 
 static struct rc_map_table rc_map_a800_table[] = {
-	{ 0x0201, KEY_PROG1 },       /* SOURCE */
-	{ 0x0200, KEY_POWER },       /* POWER */
+	{ 0x0201, KEY_MODE },      /* SOURCE */
+	{ 0x0200, KEY_POWER2 },      /* POWER */
 	{ 0x0205, KEY_1 },           /* 1 */
 	{ 0x0206, KEY_2 },           /* 2 */
 	{ 0x0207, KEY_3 },           /* 3 */
@@ -52,8 +52,8 @@ static struct rc_map_table rc_map_a800_table[] = {
 	{ 0x0212, KEY_LEFT },        /* L / DISPLAY */
 	{ 0x0211, KEY_0 },           /* 0 */
 	{ 0x0213, KEY_RIGHT },       /* R / CH RTN */
-	{ 0x0217, KEY_PROG2 },       /* SNAP SHOT */
-	{ 0x0210, KEY_PROG3 },       /* 16-CH PREV */
+	{ 0x0217, KEY_CAMERA },      /* SNAP SHOT */
+	{ 0x0210, KEY_LAST },        /* 16-CH PREV */
 	{ 0x021e, KEY_VOLUMEDOWN },  /* VOL DOWN */
 	{ 0x020c, KEY_ZOOM },        /* FULL SCREEN */
 	{ 0x021f, KEY_VOLUMEUP },    /* VOL UP */
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index f2dbce7..f6344cd 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -176,7 +176,7 @@ static struct rc_map_table rc_map_digitv_table[] = {
 	{ 0xaf59, KEY_AUX },
 	{ 0x5f5a, KEY_DVD },
 	{ 0x6f5a, KEY_POWER },
-	{ 0x9f5a, KEY_MHP },     /* labelled 'Picture' */
+	{ 0x9f5a, KEY_CAMERA },     /* labelled 'Picture' */
 	{ 0xaf5a, KEY_AUDIO },
 	{ 0x5f65, KEY_INFO },
 	{ 0x6f65, KEY_F13 },     /* 16:9 */
diff --git a/drivers/media/dvb/dvb-usb/dw2102.c b/drivers/media/dvb/dvb-usb/dw2102.c
index 98cf302..f5b9da1 100644
--- a/drivers/media/dvb/dvb-usb/dw2102.c
+++ b/drivers/media/dvb/dvb-usb/dw2102.c
@@ -1224,8 +1224,8 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
 }
 
 static struct rc_map_table rc_map_dw210x_table[] = {
-	{ 0xf80a, KEY_Q },		/*power*/
-	{ 0xf80c, KEY_M },		/*mute*/
+	{ 0xf80a, KEY_POWER2 },		/*power*/
+	{ 0xf80c, KEY_MUTE },		/*mute*/
 	{ 0xf811, KEY_1 },
 	{ 0xf812, KEY_2 },
 	{ 0xf813, KEY_3 },
@@ -1236,25 +1236,25 @@ static struct rc_map_table rc_map_dw210x_table[] = {
 	{ 0xf818, KEY_8 },
 	{ 0xf819, KEY_9 },
 	{ 0xf810, KEY_0 },
-	{ 0xf81c, KEY_PAGEUP },	/*ch+*/
-	{ 0xf80f, KEY_PAGEDOWN },	/*ch-*/
-	{ 0xf81a, KEY_O },		/*vol+*/
-	{ 0xf80e, KEY_Z },		/*vol-*/
-	{ 0xf804, KEY_R },		/*rec*/
-	{ 0xf809, KEY_D },		/*fav*/
-	{ 0xf808, KEY_BACKSPACE },	/*rewind*/
-	{ 0xf807, KEY_A },		/*fast*/
-	{ 0xf80b, KEY_P },		/*pause*/
-	{ 0xf802, KEY_ESC },	/*cancel*/
-	{ 0xf803, KEY_G },		/*tab*/
+	{ 0xf81c, KEY_CHANNELUP },	/*ch+*/
+	{ 0xf80f, KEY_CHANNELDOWN },	/*ch-*/
+	{ 0xf81a, KEY_VOLUMEUP },	/*vol+*/
+	{ 0xf80e, KEY_VOLUMEDOWN },	/*vol-*/
+	{ 0xf804, KEY_RECORD },		/*rec*/
+	{ 0xf809, KEY_FAVORITES },	/*fav*/
+	{ 0xf808, KEY_REWIND },		/*rewind*/
+	{ 0xf807, KEY_FASTFORWARD },	/*fast*/
+	{ 0xf80b, KEY_PAUSE },		/*pause*/
+	{ 0xf802, KEY_ESC },		/*cancel*/
+	{ 0xf803, KEY_TAB },		/*tab*/
 	{ 0xf800, KEY_UP },		/*up*/
-	{ 0xf81f, KEY_ENTER },	/*ok*/
-	{ 0xf801, KEY_DOWN },	/*down*/
-	{ 0xf805, KEY_C },		/*cap*/
-	{ 0xf806, KEY_S },		/*stop*/
-	{ 0xf840, KEY_F },		/*full*/
-	{ 0xf81e, KEY_W },		/*tvmode*/
-	{ 0xf81b, KEY_B },		/*recall*/
+	{ 0xf81f, KEY_OK },		/*ok*/
+	{ 0xf801, KEY_DOWN },		/*down*/
+	{ 0xf805, KEY_CAMERA },		/*cap*/
+	{ 0xf806, KEY_STOP },		/*stop*/
+	{ 0xf840, KEY_ZOOM },		/*full*/
+	{ 0xf81e, KEY_TV },		/*tvmode*/
+	{ 0xf81b, KEY_LAST },		/*recall*/
 };
 
 static struct rc_map_table rc_map_tevii_table[] = {
diff --git a/drivers/media/dvb/dvb-usb/opera1.c b/drivers/media/dvb/dvb-usb/opera1.c
index 1f1b7d6..7e569f4 100644
--- a/drivers/media/dvb/dvb-usb/opera1.c
+++ b/drivers/media/dvb/dvb-usb/opera1.c
@@ -342,23 +342,22 @@ static struct rc_map_table rc_map_opera1_table[] = {
 	{0x49b6, KEY_8},
 	{0x05fa, KEY_9},
 	{0x45ba, KEY_0},
-	{0x09f6, KEY_UP},	/*chanup */
-	{0x1be5, KEY_DOWN},	/*chandown */
-	{0x5da3, KEY_LEFT},	/*voldown */
-	{0x5fa1, KEY_RIGHT},	/*volup */
-	{0x07f8, KEY_SPACE},	/*tab */
-	{0x1fe1, KEY_ENTER},	/*play ok */
-	{0x1be4, KEY_Z},	/*zoom */
-	{0x59a6, KEY_M},	/*mute */
-	{0x5ba5, KEY_F},	/*tv/f */
-	{0x19e7, KEY_R},	/*rec */
-	{0x01fe, KEY_S},	/*Stop */
-	{0x03fd, KEY_P},	/*pause */
-	{0x03fc, KEY_W},	/*<- -> */
-	{0x07f9, KEY_C},	/*capture */
-	{0x47b9, KEY_Q},	/*exit */
-	{0x43bc, KEY_O},	/*power */
-
+	{0x09f6, KEY_CHANNELUP},	/*chanup */
+	{0x1be5, KEY_CHANNELDOWN},	/*chandown */
+	{0x5da3, KEY_VOLUMEDOWN},	/*voldown */
+	{0x5fa1, KEY_VOLUMEUP},		/*volup */
+	{0x07f8, KEY_SPACE},		/*tab */
+	{0x1fe1, KEY_OK},		/*play ok */
+	{0x1be4, KEY_ZOOM},		/*zoom */
+	{0x59a6, KEY_MUTE},		/*mute */
+	{0x5ba5, KEY_RADIO},		/*tv/f */
+	{0x19e7, KEY_RECORD},		/*rec */
+	{0x01fe, KEY_STOP},		/*Stop */
+	{0x03fd, KEY_PAUSE},		/*pause */
+	{0x03fc, KEY_SCREEN},		/*<- -> */
+	{0x07f9, KEY_CAMERA},		/*capture */
+	{0x47b9, KEY_ESC},		/*exit */
+	{0x43bc, KEY_POWER2},		/*power */
 };
 
 static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c
index 25b43e5..af121db 100644
--- a/drivers/media/dvb/siano/sms-cards.c
+++ b/drivers/media/dvb/siano/sms-cards.c
@@ -64,7 +64,7 @@ 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,
+		.rc_codes = RC_MAP_HAUPPAUGE,
 		.board_cfg.leds_power = 26,
 		.board_cfg.led0 = 27,
 		.board_cfg.led1 = 28,
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index b82756d..1d79ada 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -26,7 +26,7 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  *
  *
- * the project's page is at http://www.linuxtv.org/ 
+ * the project's page is at http://www.linuxtv.org/
  */
 
 #include <linux/module.h>
@@ -102,6 +102,7 @@ struct budget_ci_ir {
 	int rc5_device;
 	u32 ir_key;
 	bool have_command;
+	bool full_rc5;		/* Outputs a full RC5 code */
 };
 
 struct budget_ci {
@@ -154,11 +155,18 @@ static void msp430_ir_interrupt(unsigned long data)
 		return;
 	budget_ci->ir.have_command = false;
 
-	/* FIXME: We should generate complete scancodes with device info */
 	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
 	    budget_ci->ir.rc5_device != (command & 0x1f))
 		return;
 
+	if (budget_ci->ir.full_rc5) {
+		rc_keydown(dev,
+			   budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
+			   (command & 0x20) ? 1 : 0);
+		return;
+	}
+
+	/* FIXME: We should generate complete scancodes for all devices */
 	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
 }
 
@@ -206,7 +214,8 @@ static int msp430_ir_init(struct budget_ci *budget_ci)
 	case 0x1011:
 	case 0x1012:
 		/* The hauppauge keymap is a superset of these remotes */
-		dev->map_name = RC_MAP_HAUPPAUGE_NEW;
+		dev->map_name = RC_MAP_HAUPPAUGE;
+		budget_ci->ir.full_rc5 = true;
 
 		if (rc5_device < 0)
 			budget_ci->ir.rc5_device = 0x1f;
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 1143845..7f03142 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -135,6 +135,19 @@ config IR_MCEUSB
 	   To compile this driver as a module, choose M here: the
 	   module will be called mceusb.
 
+config IR_ITE_CIR
+	tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
+	depends on PNP
+	depends on RC_CORE
+	---help---
+	   Say Y here to enable support for integrated infrared receivers
+	   /transceivers made by ITE Tech Inc. These are found in
+	   several ASUS devices, like the ASUS Digimatrix or the ASUS
+	   EEEBox 1501U.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called ite-cir.
+
 config IR_NUVOTON
 	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
 	depends on PNP
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 67b4f7f..c6cfe70 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
 
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_IR_IMON) += imon.o
+obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
 obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
 obj-$(CONFIG_IR_ENE) += ene_ir.o
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index e7dc6b4..f714e1a 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -277,12 +277,21 @@ static const struct {
 	u64 hw_code;
 	u32 keycode;
 } imon_panel_key_table[] = {
-	{ 0x000000000f00ffeell, KEY_PROG1 }, /* Go */
+	{ 0x000000000f00ffeell, KEY_MEDIA }, /* Go */
+	{ 0x000000001200ffeell, KEY_UP },
+	{ 0x000000001300ffeell, KEY_DOWN },
+	{ 0x000000001400ffeell, KEY_LEFT },
+	{ 0x000000001500ffeell, KEY_RIGHT },
+	{ 0x000000001600ffeell, KEY_ENTER },
+	{ 0x000000001700ffeell, KEY_ESC },
 	{ 0x000000001f00ffeell, KEY_AUDIO },
 	{ 0x000000002000ffeell, KEY_VIDEO },
 	{ 0x000000002100ffeell, KEY_CAMERA },
 	{ 0x000000002700ffeell, KEY_DVD },
 	{ 0x000000002300ffeell, KEY_TV },
+	{ 0x000000002b00ffeell, KEY_EXIT },
+	{ 0x000000002c00ffeell, KEY_SELECT },
+	{ 0x000000002d00ffeell, KEY_MENU },
 	{ 0x000000000500ffeell, KEY_PREVIOUS },
 	{ 0x000000000700ffeell, KEY_REWIND },
 	{ 0x000000000400ffeell, KEY_STOP },
diff --git a/drivers/media/rc/ir-nec-decoder.c b/drivers/media/rc/ir-nec-decoder.c
index 7b58b4a..63ee722 100644
--- a/drivers/media/rc/ir-nec-decoder.c
+++ b/drivers/media/rc/ir-nec-decoder.c
@@ -49,6 +49,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 	struct nec_dec *data = &dev->raw->nec;
 	u32 scancode;
 	u8 address, not_address, command, not_command;
+	bool send_32bits = false;
 
 	if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
 		return 0;
@@ -164,10 +165,15 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
 		if ((command ^ not_command) != 0xff) {
 			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
 				   data->bits);
-			break;
+			send_32bits = true;
 		}
 
-		if ((address ^ not_address) != 0xff) {
+		if (send_32bits) {
+			/* NEC transport, but modified protocol, used by at
+			 * least Apple and TiVo remotes */
+			scancode = data->bits;
+			IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);
+		} else if ((address ^ not_address) != 0xff) {
 			/* Extended NEC */
 			scancode = address     << 16 |
 				   not_address <<  8 |
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
new file mode 100644
index 0000000..9be6a83
--- /dev/null
+++ b/drivers/media/rc/ite-cir.c
@@ -0,0 +1,1736 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR
+ *
+ * Copyright (C) 2010 Juan Jesús García de Soria <skandalfo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * Inspired by the original lirc_it87 and lirc_ite8709 drivers, on top of the
+ * skeleton provided by the nuvoton-cir driver.
+ *
+ * The lirc_it87 driver was originally written by Hans-Gunter Lutke Uphues
+ * <hg_lu@web.de> in 2001, with enhancements by Christoph Bartelmus
+ * <lirc@bartelmus.de>, Andrew Calkin <r_tay@hotmail.com> and James Edwards
+ * <jimbo-lirc@edwardsclan.net>.
+ *
+ * The lirc_ite8709 driver was written by Grégory Lardière
+ * <spmf2004-lirc@yahoo.fr> in 2008.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/bitops.h>
+#include <media/rc-core.h>
+#include <linux/pci_ids.h>
+
+#include "ite-cir.h"
+
+/* module parameters */
+
+/* debug level */
+static int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging output");
+
+/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_low_carrier_freq;
+module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, "
+		 "0 for no RX demodulation");
+
+/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_high_carrier_freq;
+module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, "
+		 "Hz, 0 for no RX demodulation");
+
+/* override tx carrier frequency */
+static int tx_carrier_freq;
+module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz");
+
+/* override tx duty cycle */
+static int tx_duty_cycle;
+module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100");
+
+/* override default sample period */
+static long sample_period;
+module_param(sample_period, long, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_period, "Override carrier sample period, us");
+
+/* override detected model id */
+static int model_number = -1;
+module_param(model_number, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(model_number, "Use this model number, don't autodetect");
+
+
+/* HW-independent code functions */
+
+/* check whether carrier frequency is high frequency */
+static inline bool ite_is_high_carrier_freq(unsigned int freq)
+{
+	return freq >= ITE_HCF_MIN_CARRIER_FREQ;
+}
+
+/* get the bits required to program the carrier frequency in CFQ bits,
+ * unshifted */
+static u8 ite_get_carrier_freq_bits(unsigned int freq)
+{
+	if (ite_is_high_carrier_freq(freq)) {
+		if (freq < 425000)
+			return ITE_CFQ_400;
+
+		else if (freq < 465000)
+			return ITE_CFQ_450;
+
+		else if (freq < 490000)
+			return ITE_CFQ_480;
+
+		else
+			return ITE_CFQ_500;
+	} else {
+			/* trim to limits */
+		if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+			freq = ITE_LCF_MIN_CARRIER_FREQ;
+		if (freq > ITE_LCF_MAX_CARRIER_FREQ)
+			freq = ITE_LCF_MAX_CARRIER_FREQ;
+
+		/* convert to kHz and subtract the base freq */
+		freq =
+		    DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ,
+				      1000);
+
+		return (u8) freq;
+	}
+}
+
+/* get the bits required to program the pulse with in TXMPW */
+static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle)
+{
+	unsigned long period_ns, on_ns;
+
+	/* sanitize freq into range */
+	if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+		freq = ITE_LCF_MIN_CARRIER_FREQ;
+	if (freq > ITE_HCF_MAX_CARRIER_FREQ)
+		freq = ITE_HCF_MAX_CARRIER_FREQ;
+
+	period_ns = 1000000000UL / freq;
+	on_ns = period_ns * duty_cycle / 100;
+
+	if (ite_is_high_carrier_freq(freq)) {
+		if (on_ns < 750)
+			return ITE_TXMPW_A;
+
+		else if (on_ns < 850)
+			return ITE_TXMPW_B;
+
+		else if (on_ns < 950)
+			return ITE_TXMPW_C;
+
+		else if (on_ns < 1080)
+			return ITE_TXMPW_D;
+
+		else
+			return ITE_TXMPW_E;
+	} else {
+		if (on_ns < 6500)
+			return ITE_TXMPW_A;
+
+		else if (on_ns < 7850)
+			return ITE_TXMPW_B;
+
+		else if (on_ns < 9650)
+			return ITE_TXMPW_C;
+
+		else if (on_ns < 11950)
+			return ITE_TXMPW_D;
+
+		else
+			return ITE_TXMPW_E;
+	}
+}
+
+/* decode raw bytes as received by the hardware, and push them to the ir-core
+ * layer */
+static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int
+			     length)
+{
+	u32 sample_period;
+	unsigned long *ldata;
+	unsigned int next_one, next_zero, size;
+	DEFINE_IR_RAW_EVENT(ev);
+
+	if (length == 0)
+		return;
+
+	sample_period = dev->params.sample_period;
+	ldata = (unsigned long *)data;
+	size = length << 3;
+	next_one = generic_find_next_le_bit(ldata, size, 0);
+	if (next_one > 0) {
+		ev.pulse = true;
+		ev.duration =
+		    ITE_BITS_TO_NS(next_one, sample_period);
+		ir_raw_event_store_with_filter(dev->rdev, &ev);
+	}
+
+	while (next_one < size) {
+		next_zero = generic_find_next_zero_le_bit(ldata, size, next_one + 1);
+		ev.pulse = false;
+		ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period);
+		ir_raw_event_store_with_filter(dev->rdev, &ev);
+
+		if (next_zero < size) {
+			next_one =
+			    generic_find_next_le_bit(ldata,
+						     size,
+						     next_zero + 1);
+			ev.pulse = true;
+			ev.duration =
+			    ITE_BITS_TO_NS(next_one - next_zero,
+					   sample_period);
+			ir_raw_event_store_with_filter
+			    (dev->rdev, &ev);
+		} else
+			next_one = size;
+	}
+
+	ir_raw_event_handle(dev->rdev);
+
+	ite_dbg_verbose("decoded %d bytes.", length);
+}
+
+/* set all the rx/tx carrier parameters; this must be called with the device
+ * spinlock held */
+static void ite_set_carrier_params(struct ite_dev *dev)
+{
+	unsigned int freq, low_freq, high_freq;
+	int allowance;
+	bool use_demodulator;
+	bool for_tx = dev->transmitting;
+
+	ite_dbg("%s called", __func__);
+
+	if (for_tx) {
+		/* we don't need no stinking calculations */
+		freq = dev->params.tx_carrier_freq;
+		allowance = ITE_RXDCR_DEFAULT;
+		use_demodulator = false;
+	} else {
+		low_freq = dev->params.rx_low_carrier_freq;
+		high_freq = dev->params.rx_high_carrier_freq;
+
+		if (low_freq == 0) {
+			/* don't demodulate */
+			freq =
+			ITE_DEFAULT_CARRIER_FREQ;
+			allowance = ITE_RXDCR_DEFAULT;
+			use_demodulator = false;
+		} else {
+			/* calculate the middle freq */
+			freq = (low_freq + high_freq) / 2;
+
+			/* calculate the allowance */
+			allowance =
+			    DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq),
+					      ITE_RXDCR_PER_10000_STEP
+					      * (high_freq + low_freq));
+
+			if (allowance < 1)
+				allowance = 1;
+
+			if (allowance > ITE_RXDCR_MAX)
+				allowance = ITE_RXDCR_MAX;
+		}
+	}
+
+	/* set the carrier parameters in a device-dependent way */
+	dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq),
+		 use_demodulator, ite_get_carrier_freq_bits(freq), allowance,
+		 ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle));
+}
+
+/* interrupt service routine for incoming and outgoing CIR data */
+static irqreturn_t ite_cir_isr(int irq, void *data)
+{
+	struct ite_dev *dev = data;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
+	u8 rx_buf[ITE_RX_FIFO_LEN];
+	int rx_bytes;
+	int iflags;
+
+	ite_dbg_verbose("%s firing", __func__);
+
+	/* grab the spinlock */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* read the interrupt flags */
+	iflags = dev->params.get_irq_causes(dev);
+
+	/* check for the receive interrupt */
+	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
+		/* read the FIFO bytes */
+		rx_bytes =
+			dev->params.get_rx_bytes(dev, rx_buf,
+					     ITE_RX_FIFO_LEN);
+
+		if (rx_bytes > 0) {
+			/* drop the spinlock, since the ir-core layer
+			 * may call us back again through
+			 * ite_s_idle() */
+			spin_unlock_irqrestore(&dev->
+									 lock,
+									 flags);
+
+			/* decode the data we've just received */
+			ite_decode_bytes(dev, rx_buf,
+								   rx_bytes);
+
+			/* reacquire the spinlock */
+			spin_lock_irqsave(&dev->lock,
+								    flags);
+
+			/* mark the interrupt as serviced */
+			ret = IRQ_RETVAL(IRQ_HANDLED);
+		}
+	} else if (iflags & ITE_IRQ_TX_FIFO) {
+		/* FIFO space available interrupt */
+		ite_dbg_verbose("got interrupt for TX FIFO");
+
+		/* wake any sleeping transmitter */
+		wake_up_interruptible(&dev->tx_queue);
+
+		/* mark the interrupt as serviced */
+		ret = IRQ_RETVAL(IRQ_HANDLED);
+	}
+
+	/* drop the spinlock */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	ite_dbg_verbose("%s done returning %d", __func__, (int)ret);
+
+	return ret;
+}
+
+/* set the rx carrier freq range, guess it's in Hz... */
+static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32
+				    carrier_high)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.rx_low_carrier_freq = carrier_low;
+	dev->params.rx_high_carrier_freq = carrier_high;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* set the tx carrier freq, guess it's in Hz... */
+static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.tx_carrier_freq = carrier;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* set the tx duty cycle by controlling the pulse width */
+static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.tx_duty_cycle = duty_cycle;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* transmit out IR pulses; what you get here is a batch of alternating
+ * pulse/space/pulse/space lengths that we should write out completely through
+ * the FIFO, blocking on a full FIFO */
+static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+	bool is_pulse = false;
+	int remaining_us, fifo_avail, fifo_remaining, last_idx = 0;
+	int max_rle_us, next_rle_us;
+	int ret = n;
+	u8 last_sent[ITE_TX_FIFO_LEN];
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* clear the array just in case */
+	memset(last_sent, 0, ARRAY_SIZE(last_sent));
+
+	/* n comes in bytes; convert to ints */
+	n /= sizeof(int);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* let everybody know we're now transmitting */
+	dev->transmitting = true;
+
+	/* and set the carrier values for transmission */
+	ite_set_carrier_params(dev);
+
+	/* calculate how much time we can send in one byte */
+	max_rle_us =
+	    (ITE_BAUDRATE_DIVISOR * dev->params.sample_period *
+	     ITE_TX_MAX_RLE) / 1000;
+
+	/* disable the receiver */
+	dev->params.disable_rx(dev);
+
+	/* this is where we'll begin filling in the FIFO, until it's full.
+	 * then we'll just activate the interrupt, wait for it to wake us up
+	 * again, disable it, continue filling the FIFO... until everything
+	 * has been pushed out */
+	fifo_avail =
+	    ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+	while (n > 0 && dev->in_use) {
+		/* transmit the next sample */
+		is_pulse = !is_pulse;
+		remaining_us = *(txbuf++);
+		n--;
+
+		ite_dbg("%s: %ld",
+				      ((is_pulse) ? "pulse" : "space"),
+				      (long int)
+				      remaining_us);
+
+		/* repeat while the pulse is non-zero length */
+		while (remaining_us > 0 && dev->in_use) {
+			if (remaining_us > max_rle_us)
+				next_rle_us = max_rle_us;
+
+			else
+				next_rle_us = remaining_us;
+
+			remaining_us -= next_rle_us;
+
+			/* check what's the length we have to pump out */
+			val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us;
+
+			/* put it into the sent buffer */
+			last_sent[last_idx++] = val;
+			last_idx &= (ITE_TX_FIFO_LEN);
+
+			/* encode it for 7 bits */
+			val = (val - 1) & ITE_TX_RLE_MASK;
+
+			/* take into account pulse/space prefix */
+			if (is_pulse)
+				val |= ITE_TX_PULSE;
+
+			else
+				val |= ITE_TX_SPACE;
+
+			/*
+			 * if we get to 0 available, read again, just in case
+			 * some other slot got freed
+			 */
+			if (fifo_avail <= 0)
+				fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+			/* if it's still full */
+			if (fifo_avail <= 0) {
+				/* enable the tx interrupt */
+				dev->params.
+				enable_tx_interrupt(dev);
+
+				/* drop the spinlock */
+				spin_unlock_irqrestore(&dev->lock, flags);
+
+				/* wait for the FIFO to empty enough */
+				wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8);
+
+				/* get the spinlock again */
+				spin_lock_irqsave(&dev->lock, flags);
+
+				/* disable the tx interrupt again. */
+				dev->params.
+				disable_tx_interrupt(dev);
+			}
+
+			/* now send the byte through the FIFO */
+			dev->params.put_tx_byte(dev, val);
+			fifo_avail--;
+		}
+	}
+
+	/* wait and don't return until the whole FIFO has been sent out;
+	 * otherwise we could configure the RX carrier params instead of the
+	 * TX ones while the transmission is still being performed! */
+	fifo_remaining = dev->params.get_tx_used_slots(dev);
+	remaining_us = 0;
+	while (fifo_remaining > 0) {
+		fifo_remaining--;
+		last_idx--;
+		last_idx &= (ITE_TX_FIFO_LEN - 1);
+		remaining_us += last_sent[last_idx];
+	}
+	remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE);
+
+	/* drop the spinlock while we sleep */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* sleep remaining_us microseconds */
+	mdelay(DIV_ROUND_UP(remaining_us, 1000));
+
+	/* reacquire the spinlock */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* now we're not transmitting anymore */
+	dev->transmitting = false;
+
+	/* and set the carrier values for reception */
+	ite_set_carrier_params(dev);
+
+	/* reenable the receiver */
+	if (dev->in_use)
+		dev->params.enable_rx(dev);
+
+	/* notify transmission end */
+	wake_up_interruptible(&dev->tx_ended);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return ret;
+}
+
+/* idle the receiver if needed */
+static void ite_s_idle(struct rc_dev *rcdev, bool enable)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	ite_dbg("%s called", __func__);
+
+	if (enable) {
+		spin_lock_irqsave(&dev->lock, flags);
+		dev->params.idle_rx(dev);
+		spin_unlock_irqrestore(&dev->lock, flags);
+	}
+}
+
+
+/* IT8712F HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it87_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II;
+
+	switch (iflags) {
+	case IT87_II_RXDS:
+		ret = ITE_IRQ_RX_FIFO;
+		break;
+	case IT87_II_RXFO:
+		ret = ITE_IRQ_RX_FIFO_OVERRUN;
+		break;
+	case IT87_II_TXLDL:
+		ret = ITE_IRQ_TX_FIFO;
+		break;
+	}
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				    bool use_demodulator,
+				    u8 carrier_freq_bits, u8 allowance_bits,
+				    u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* program the RCR register */
+	val = inb(dev->cir_addr + IT87_RCR)
+		& ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR);
+
+	if (high_freq)
+		val |= IT87_HCFS;
+
+	if (use_demodulator)
+		val |= IT87_RXEND;
+
+	val |= allowance_bits;
+
+	outb(val, dev->cir_addr + IT87_RCR);
+
+	/* program the TCR2 register */
+	outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits,
+		dev->cir_addr + IT87_TCR2);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it87_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = inb(dev->cir_addr + IT87_DR);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it87_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return inb(dev->cir_addr + IT87_TSR) & IT87_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it87_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	outb(value, dev->cir_addr + IT87_DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it87_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT,
+		dev->cir_addr + IT87_RCR);
+
+	/* clear the FIFO */
+	outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR,
+		dev->cir_addr + IT87_TCR1);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it87_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE),
+		dev->cir_addr + IT87_IER);
+
+	/* disable the receiver */
+	outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN,
+		dev->cir_addr + IT87_RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	* in the previous outb() call) */
+	it87_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it87_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN,
+		dev->cir_addr + IT87_RCR);
+
+	/* just prepare it to idle for the next reception */
+	it87_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT87_IER) | IT87_RDAIE | IT87_RFOIE | IT87_IEC,
+		dev->cir_addr + IT87_IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE,
+		dev->cir_addr + IT87_IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT87_IER) | IT87_TLDLIE | IT87_IEC,
+		dev->cir_addr + IT87_IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it87_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	outb(inb(dev->cir_addr + IT87_IER) &
+		~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE),
+		dev->cir_addr + IT87_IER);
+
+	/* disable the receiver */
+	it87_disable_rx(dev);
+
+	/* erase the FIFO */
+	outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1),
+		dev->cir_addr + IT87_TCR1);
+}
+
+/* initialize the hardware */
+static void it87_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable just the baud rate divisor register,
+	disabling all the interrupts at the same time */
+	outb((inb(dev->cir_addr + IT87_IER) &
+		~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR,
+		dev->cir_addr + IT87_IER);
+
+	/* write out the baud rate divisor */
+	outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR);
+	outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR);
+
+	/* disable the baud rate divisor register again */
+	outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR,
+		dev->cir_addr + IT87_IER);
+
+	/* program the RCR register defaults */
+	outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR);
+
+	/* program the TCR1 register */
+	outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE
+		| IT87_FIFOTL_DEFAULT | IT87_FIFOCLR,
+		dev->cir_addr + IT87_TCR1);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8708 HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8708_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = inb(dev->cir_addr + IT8708_C0IIR);
+
+	if (iflags & IT85_TLDLI)
+		ret |= ITE_IRQ_TX_FIFO;
+	if (iflags & IT85_RDAI)
+		ret |= ITE_IRQ_RX_FIFO;
+	if (iflags & IT85_RFOI)
+		ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				      bool use_demodulator,
+				      u8 carrier_freq_bits, u8 allowance_bits,
+				      u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* program the C0CFR register, with HRAE=1 */
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+		dev->cir_addr + IT8708_BANKSEL);
+
+	val = (inb(dev->cir_addr + IT8708_C0CFR)
+		& ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits;
+
+	if (high_freq)
+		val |= IT85_HCFS;
+
+	outb(val, dev->cir_addr + IT8708_C0CFR);
+
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+		   dev->cir_addr + IT8708_BANKSEL);
+
+	/* program the C0RCR register */
+	val = inb(dev->cir_addr + IT8708_C0RCR)
+		& ~(IT85_RXEND | IT85_RXDCR);
+
+	if (use_demodulator)
+		val |= IT85_RXEND;
+
+	val |= allowance_bits;
+
+	outb(val, dev->cir_addr + IT8708_C0RCR);
+
+	/* program the C0TCR register */
+	val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW;
+	val |= pulse_width_bits;
+	outb(val, dev->cir_addr + IT8708_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8708_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = inb(dev->cir_addr + IT8708_C0DR);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8708_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8708_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	outb(value, dev->cir_addr + IT8708_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it8708_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* clear the FIFO */
+	outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR,
+		dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8708_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_RDAIE | IT85_RFOIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* disable the receiver */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	 * in the previous outb() call) */
+	it8708_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8708_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* just prepare it to idle for the next reception */
+	it8708_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT8708_C0IER)
+		|IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT8708_C0IER)
+		|IT85_TLDLIE | IT85_IEC,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8708_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* disable the receiver */
+	it8708_disable_rx(dev);
+
+	/* erase the FIFO */
+	outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR),
+		dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8708_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable all the interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* program the baud rate divisor */
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+		dev->cir_addr + IT8708_BANKSEL);
+
+	outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR);
+	outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+		   dev->cir_addr + IT8708_C0BDHR);
+
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+		   dev->cir_addr + IT8708_BANKSEL);
+
+	/* program the C0MSTCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0MSTCR) &
+			~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL |
+			  IT85_FIFOCLR | IT85_RESET)) |
+		       IT85_FIFOTL_DEFAULT,
+		       dev->cir_addr + IT8708_C0MSTCR);
+
+	/* program the C0RCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0RCR) &
+			~(IT85_RXEN | IT85_RDWOS | IT85_RXEND |
+			  IT85_RXACT | IT85_RXDCR)) |
+		       ITE_RXDCR_DEFAULT,
+		       dev->cir_addr + IT8708_C0RCR);
+
+	/* program the C0TCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0TCR) &
+			~(IT85_TXMPM | IT85_TXMPW))
+		       |IT85_TXRLE | IT85_TXENDF |
+		       IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT,
+		       dev->cir_addr + IT8708_C0TCR);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8709 HW-specific functions */
+
+/* read a byte from the SRAM module */
+static inline u8 it8709_rm(struct ite_dev *dev, int index)
+{
+	outb(index, dev->cir_addr + IT8709_RAM_IDX);
+	return inb(dev->cir_addr + IT8709_RAM_VAL);
+}
+
+/* write a byte to the SRAM module */
+static inline void it8709_wm(struct ite_dev *dev, u8 val, int index)
+{
+	outb(index, dev->cir_addr + IT8709_RAM_IDX);
+	outb(val, dev->cir_addr + IT8709_RAM_VAL);
+}
+
+static void it8709_wait(struct ite_dev *dev)
+{
+	int i = 0;
+	/*
+	 * loop until device tells it's ready to continue
+	 * iterations count is usually ~750 but can sometimes achieve 13000
+	 */
+	for (i = 0; i < 15000; i++) {
+		udelay(2);
+		if (it8709_rm(dev, IT8709_MODE) == IT8709_IDLE)
+			break;
+	}
+}
+
+/* read the value of a CIR register */
+static u8 it8709_rr(struct ite_dev *dev, int index)
+{
+	/* just wait in case the previous access was a write */
+	it8709_wait(dev);
+	it8709_wm(dev, index, IT8709_REG_IDX);
+	it8709_wm(dev, IT8709_READ, IT8709_MODE);
+
+	/* wait for the read data to be available */
+	it8709_wait(dev);
+
+	/* return the read value */
+	return it8709_rm(dev, IT8709_REG_VAL);
+}
+
+/* write the value of a CIR register */
+static void it8709_wr(struct ite_dev *dev, u8 val, int index)
+{
+	/* we wait before writing, and not afterwards, since this allows us to
+	 * pipeline the host CPU with the microcontroller */
+	it8709_wait(dev);
+	it8709_wm(dev, val, IT8709_REG_VAL);
+	it8709_wm(dev, index, IT8709_REG_IDX);
+	it8709_wm(dev, IT8709_WRITE, IT8709_MODE);
+}
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8709_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = it8709_rm(dev, IT8709_IIR);
+
+	if (iflags & IT85_TLDLI)
+		ret |= ITE_IRQ_TX_FIFO;
+	if (iflags & IT85_RDAI)
+		ret |= ITE_IRQ_RX_FIFO;
+	if (iflags & IT85_RFOI)
+		ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8709_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				      bool use_demodulator,
+				      u8 carrier_freq_bits, u8 allowance_bits,
+				      u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	val = (it8709_rr(dev, IT85_C0CFR)
+		     &~(IT85_HCFS | IT85_CFQ)) |
+	    carrier_freq_bits;
+
+	if (high_freq)
+		val |= IT85_HCFS;
+
+	it8709_wr(dev, val, IT85_C0CFR);
+
+	/* program the C0RCR register */
+	val = it8709_rr(dev, IT85_C0RCR)
+		& ~(IT85_RXEND | IT85_RXDCR);
+
+	if (use_demodulator)
+		val |= IT85_RXEND;
+
+	val |= allowance_bits;
+
+	it8709_wr(dev, val, IT85_C0RCR);
+
+	/* program the C0TCR register */
+	val = it8709_rr(dev, IT85_C0TCR) & ~IT85_TXMPW;
+	val |= pulse_width_bits;
+	it8709_wr(dev, val, IT85_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8709_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = it8709_rm(dev, IT8709_RFSR) & IT85_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = it8709_rm(dev, IT8709_FIFO + read);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	/* 'clear' the FIFO by setting the writing index to 0; this is
+	 * completely bound to be racy, but we can't help it, since it's a
+	 * limitation of the protocol */
+	it8709_wm(dev, 0, IT8709_RFSR);
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8709_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return it8709_rr(dev, IT85_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8709_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	it8709_wr(dev, value, IT85_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it8709_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXACT,
+			    IT85_C0RCR);
+
+	/* clear the FIFO */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0MSTCR) | IT85_FIFOCLR,
+			    IT85_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8709_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER) &
+			    ~(IT85_RDAIE | IT85_RFOIE),
+			    IT85_C0IER);
+
+	/* disable the receiver */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) & ~IT85_RXEN,
+			    IT85_C0RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	 * in the previous it8709_wr(dev, ) call) */
+	it8709_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8709_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXEN,
+			    IT85_C0RCR);
+
+	/* just prepare it to idle for the next reception */
+	it8709_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+			    |IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+			    IT85_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~IT85_TLDLIE,
+			    IT85_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+			    |IT85_TLDLIE | IT85_IEC,
+			    IT85_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8709_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	it8709_wr(dev,
+			    it8709_rr(dev,
+				      IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+						      IT85_RDAIE |
+						      IT85_TLDLIE), IT85_C0IER);
+
+	/* disable the receiver */
+	it8709_disable_rx(dev);
+
+	/* erase the FIFO */
+	it8709_wr(dev, IT85_FIFOCLR | it8709_rr(dev, IT85_C0MSTCR),
+			    IT85_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8709_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable all the interrupts */
+	it8709_wr(dev,
+			    it8709_rr(dev,
+				      IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+						      IT85_RDAIE |
+						      IT85_TLDLIE), IT85_C0IER);
+
+	/* program the baud rate divisor */
+	it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR);
+	it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+			IT85_C0BDHR);
+
+	/* program the C0MSTCR register defaults */
+	it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL |
+								   IT85_ILE
+								   | IT85_FIFOTL
+								   |
+								   IT85_FIFOCLR
+								   |
+								   IT85_RESET))
+			    | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR);
+
+	/* program the C0RCR register defaults */
+	it8709_wr(dev,
+			    (it8709_rr(dev, IT85_C0RCR) &
+			     ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND
+			       | IT85_RXACT | IT85_RXDCR)) |
+			    ITE_RXDCR_DEFAULT, IT85_C0RCR);
+
+	/* program the C0TCR register defaults */
+	it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR)
+				  &~(IT85_TXMPM | IT85_TXMPW))
+			    |IT85_TXRLE | IT85_TXENDF |
+			    IT85_TXMPM_DEFAULT |
+			    IT85_TXMPW_DEFAULT, IT85_C0TCR);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+
+/* generic hardware setup/teardown code */
+
+/* activate the device for use */
+static int ite_open(struct rc_dev *rcdev)
+{
+	struct ite_dev *dev = rcdev->priv;
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->in_use = true;
+
+	/* enable the receiver */
+	dev->params.enable_rx(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* deactivate the device for use */
+static void ite_close(struct rc_dev *rcdev)
+{
+	struct ite_dev *dev = rcdev->priv;
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->in_use = false;
+
+	/* wait for any transmission to end */
+	spin_unlock_irqrestore(&dev->lock, flags);
+	wait_event_interruptible(dev->tx_ended, !dev->transmitting);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+/* supported models and their parameters */
+static const struct ite_dev_params ite_dev_descs[] = {
+	{	/* 0: ITE8704 */
+	       .model = "ITE8704 CIR transceiver",
+	       .io_region_size = IT87_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it87_get_irq_causes,
+	       .enable_rx = it87_enable_rx,
+	       .idle_rx = it87_idle_rx,
+	       .disable_rx = it87_idle_rx,
+	       .get_rx_bytes = it87_get_rx_bytes,
+	       .enable_tx_interrupt = it87_enable_tx_interrupt,
+	       .disable_tx_interrupt = it87_disable_tx_interrupt,
+	       .get_tx_used_slots = it87_get_tx_used_slots,
+	       .put_tx_byte = it87_put_tx_byte,
+	       .disable = it87_disable,
+	       .init_hardware = it87_init_hardware,
+	       .set_carrier_params = it87_set_carrier_params,
+	       },
+	{	/* 1: ITE8713 */
+	       .model = "ITE8713 CIR transceiver",
+	       .io_region_size = IT87_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it87_get_irq_causes,
+	       .enable_rx = it87_enable_rx,
+	       .idle_rx = it87_idle_rx,
+	       .disable_rx = it87_idle_rx,
+	       .get_rx_bytes = it87_get_rx_bytes,
+	       .enable_tx_interrupt = it87_enable_tx_interrupt,
+	       .disable_tx_interrupt = it87_disable_tx_interrupt,
+	       .get_tx_used_slots = it87_get_tx_used_slots,
+	       .put_tx_byte = it87_put_tx_byte,
+	       .disable = it87_disable,
+	       .init_hardware = it87_init_hardware,
+	       .set_carrier_params = it87_set_carrier_params,
+	       },
+	{	/* 2: ITE8708 */
+	       .model = "ITE8708 CIR transceiver",
+	       .io_region_size = IT8708_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it8708_get_irq_causes,
+	       .enable_rx = it8708_enable_rx,
+	       .idle_rx = it8708_idle_rx,
+	       .disable_rx = it8708_idle_rx,
+	       .get_rx_bytes = it8708_get_rx_bytes,
+	       .enable_tx_interrupt = it8708_enable_tx_interrupt,
+	       .disable_tx_interrupt =
+	       it8708_disable_tx_interrupt,
+	       .get_tx_used_slots = it8708_get_tx_used_slots,
+	       .put_tx_byte = it8708_put_tx_byte,
+	       .disable = it8708_disable,
+	       .init_hardware = it8708_init_hardware,
+	       .set_carrier_params = it8708_set_carrier_params,
+	       },
+	{	/* 3: ITE8709 */
+	       .model = "ITE8709 CIR transceiver",
+	       .io_region_size = IT8709_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it8709_get_irq_causes,
+	       .enable_rx = it8709_enable_rx,
+	       .idle_rx = it8709_idle_rx,
+	       .disable_rx = it8709_idle_rx,
+	       .get_rx_bytes = it8709_get_rx_bytes,
+	       .enable_tx_interrupt = it8709_enable_tx_interrupt,
+	       .disable_tx_interrupt =
+	       it8709_disable_tx_interrupt,
+	       .get_tx_used_slots = it8709_get_tx_used_slots,
+	       .put_tx_byte = it8709_put_tx_byte,
+	       .disable = it8709_disable,
+	       .init_hardware = it8709_init_hardware,
+	       .set_carrier_params = it8709_set_carrier_params,
+	       },
+};
+
+static const struct pnp_device_id ite_ids[] = {
+	{"ITE8704", 0},		/* Default model */
+	{"ITE8713", 1},		/* CIR found in EEEBox 1501U */
+	{"ITE8708", 2},		/* Bridged IT8512 */
+	{"ITE8709", 3},		/* SRAM-Bridged IT8512 */
+	{"", 0},
+};
+
+/* allocate memory, probe hardware, and initialize everything */
+static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+		     *dev_id)
+{
+	const struct ite_dev_params *dev_desc = NULL;
+	struct ite_dev *itdev = NULL;
+	struct rc_dev *rdev = NULL;
+	int ret = -ENOMEM;
+	int model_no;
+
+	ite_dbg("%s called", __func__);
+
+	itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL);
+	if (!itdev)
+		return ret;
+
+	/* input device for IR remote (and tx) */
+	rdev = rc_allocate_device();
+	if (!rdev)
+		goto failure;
+
+	ret = -ENODEV;
+
+	/* get the model number */
+	model_no = (int)dev_id->driver_data;
+	ite_pr(KERN_NOTICE, "Auto-detected model: %s\n",
+		ite_dev_descs[model_no].model);
+
+	if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) {
+		model_no = model_number;
+		ite_pr(KERN_NOTICE, "The model has been fixed by a module "
+			"parameter.");
+	}
+
+	ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model);
+
+	/* get the description for the device */
+	dev_desc = &ite_dev_descs[model_no];
+
+	/* validate pnp resources */
+	if (!pnp_port_valid(pdev, 0) ||
+	    pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
+		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_irq_valid(pdev, 0)) {
+		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
+		goto failure;
+	}
+
+	/* store resource values */
+	itdev->cir_addr = pnp_port_start(pdev, 0);
+	itdev->cir_irq = pnp_irq(pdev, 0);
+
+	/* initialize spinlocks */
+	spin_lock_init(&itdev->lock);
+
+	/* initialize raw event */
+	init_ir_raw_event(&itdev->rawir);
+
+	ret = -EBUSY;
+	/* now claim resources */
+	if (!request_region(itdev->cir_addr,
+				dev_desc->io_region_size, ITE_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
+			ITE_DRIVER_NAME, (void *)itdev))
+		goto failure;
+
+	/* set driver data into the pnp device */
+	pnp_set_drvdata(pdev, itdev);
+	itdev->pdev = pdev;
+
+	/* initialize waitqueues for transmission */
+	init_waitqueue_head(&itdev->tx_queue);
+	init_waitqueue_head(&itdev->tx_ended);
+
+	/* copy model-specific parameters */
+	itdev->params = *dev_desc;
+
+	/* apply any overrides */
+	if (sample_period > 0)
+		itdev->params.sample_period = sample_period;
+
+	if (tx_carrier_freq > 0)
+		itdev->params.tx_carrier_freq = tx_carrier_freq;
+
+	if (tx_duty_cycle > 0 && tx_duty_cycle <= 100)
+		itdev->params.tx_duty_cycle = tx_duty_cycle;
+
+	if (rx_low_carrier_freq > 0)
+		itdev->params.rx_low_carrier_freq = rx_low_carrier_freq;
+
+	if (rx_high_carrier_freq > 0)
+		itdev->params.rx_high_carrier_freq = rx_high_carrier_freq;
+
+	/* print out parameters */
+	ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int)
+			 itdev->params.hw_tx_capable);
+	ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long)
+		     itdev->params.sample_period);
+	ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int)
+		     itdev->params.tx_carrier_freq);
+	ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int)
+		     itdev->params.tx_duty_cycle);
+	ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int)
+		     itdev->params.rx_low_carrier_freq);
+	ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int)
+		     itdev->params.rx_high_carrier_freq);
+
+	/* set up hardware initial state */
+	itdev->params.init_hardware(itdev);
+
+	/* set up ir-core props */
+	rdev->priv = itdev;
+	rdev->driver_type = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->open = ite_open;
+	rdev->close = ite_close;
+	rdev->s_idle = ite_s_idle;
+	rdev->s_rx_carrier_range = ite_set_rx_carrier_range;
+	rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT;
+	rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT;
+	rdev->timeout = ITE_IDLE_TIMEOUT;
+	rdev->rx_resolution = ITE_BAUDRATE_DIVISOR *
+				itdev->params.sample_period;
+	rdev->tx_resolution = ITE_BAUDRATE_DIVISOR *
+				itdev->params.sample_period;
+
+	/* set up transmitter related values if needed */
+	if (itdev->params.hw_tx_capable) {
+		rdev->tx_ir = ite_tx_ir;
+		rdev->s_tx_carrier = ite_set_tx_carrier;
+		rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle;
+	}
+
+	rdev->input_name = dev_desc->model;
+	rdev->input_id.bustype = BUS_HOST;
+	rdev->input_id.vendor = PCI_VENDOR_ID_ITE;
+	rdev->input_id.product = 0;
+	rdev->input_id.version = 0;
+	rdev->driver_name = ITE_DRIVER_NAME;
+	rdev->map_name = RC_MAP_RC6_MCE;
+
+	ret = rc_register_device(rdev);
+	if (ret)
+		goto failure;
+
+	itdev->rdev = rdev;
+	ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
+
+	return 0;
+
+failure:
+	if (itdev->cir_irq)
+		free_irq(itdev->cir_irq, itdev);
+
+	if (itdev->cir_addr)
+		release_region(itdev->cir_addr, itdev->params.io_region_size);
+
+	rc_free_device(rdev);
+	kfree(itdev);
+
+	return ret;
+}
+
+static void __devexit ite_remove(struct pnp_dev *pdev)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable hardware */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* free resources */
+	free_irq(dev->cir_irq, dev);
+	release_region(dev->cir_addr, dev->params.io_region_size);
+
+	rc_unregister_device(dev->rdev);
+
+	kfree(dev);
+}
+
+static int ite_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable all interrupts */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int ite_resume(struct pnp_dev *pdev)
+{
+	int ret = 0;
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (dev->transmitting) {
+		/* wake up the transmitter */
+		wake_up_interruptible(&dev->tx_queue);
+	} else {
+		/* enable the receiver */
+		dev->params.enable_rx(dev);
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return ret;
+}
+
+static void ite_shutdown(struct pnp_dev *pdev)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable all interrupts */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static struct pnp_driver ite_driver = {
+	.name		= ITE_DRIVER_NAME,
+	.id_table	= ite_ids,
+	.probe		= ite_probe,
+	.remove		= __devexit_p(ite_remove),
+	.suspend	= ite_suspend,
+	.resume		= ite_resume,
+	.shutdown	= ite_shutdown,
+};
+
+int ite_init(void)
+{
+	return pnp_register_driver(&ite_driver);
+}
+
+void ite_exit(void)
+{
+	pnp_unregister_driver(&ite_driver);
+}
+
+MODULE_DEVICE_TABLE(pnp, ite_ids);
+MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver");
+
+MODULE_AUTHOR("Juan J. Garcia de Soria <skandalfo@gmail.com>");
+MODULE_LICENSE("GPL");
+
+module_init(ite_init);
+module_exit(ite_exit);
diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h
new file mode 100644
index 0000000..16a19f5
--- /dev/null
+++ b/drivers/media/rc/ite-cir.h
@@ -0,0 +1,481 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR
+ *
+ * Copyright (C) 2010 Juan Jesús García de Soria <skandalfo@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/* platform driver name to register */
+#define ITE_DRIVER_NAME "ite-cir"
+
+/* logging macros */
+#define ite_pr(level, text, ...) \
+	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+#define ite_dbg(text, ...) do { \
+	if (debug) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
+} while (0)
+
+#define ite_dbg_verbose(text, ...) do {\
+	if (debug > 1) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
+} while (0)
+
+/* FIFO sizes */
+#define ITE_TX_FIFO_LEN 32
+#define ITE_RX_FIFO_LEN 32
+
+/* interrupt types */
+#define ITE_IRQ_TX_FIFO        1
+#define ITE_IRQ_RX_FIFO        2
+#define ITE_IRQ_RX_FIFO_OVERRUN    4
+
+/* forward declaration */
+struct ite_dev;
+
+/* struct for storing the parameters of different recognized devices */
+struct ite_dev_params {
+	/* model of the device */
+	const char *model;
+
+	/* size of the I/O region */
+	int io_region_size;
+
+	/* true if the hardware supports transmission */
+	bool hw_tx_capable;
+
+	/* base sampling period, in ns */
+	u32 sample_period;
+
+	/* rx low carrier frequency, in Hz, 0 means no demodulation */
+	unsigned int rx_low_carrier_freq;
+
+	/* tx high carrier frequency, in Hz, 0 means no demodulation */
+	unsigned int rx_high_carrier_freq;
+
+	/* tx carrier frequency, in Hz */
+	unsigned int tx_carrier_freq;
+
+	/* duty cycle, 0-100 */
+	int tx_duty_cycle;
+
+	/* hw-specific operation function pointers; most of these must be
+	 * called while holding the spin lock, except for the TX FIFO length
+	 * one */
+	/* get pending interrupt causes */
+	int (*get_irq_causes) (struct ite_dev *dev);
+
+	/* enable rx */
+	void (*enable_rx) (struct ite_dev *dev);
+
+	/* make rx enter the idle state; keep listening for a pulse, but stop
+	 * streaming space bytes */
+	void (*idle_rx) (struct ite_dev *dev);
+
+	/* disable rx completely */
+	void (*disable_rx) (struct ite_dev *dev);
+
+	/* read bytes from RX FIFO; return read count */
+	int (*get_rx_bytes) (struct ite_dev *dev, u8 *buf, int buf_size);
+
+	/* enable tx FIFO space available interrupt */
+	void (*enable_tx_interrupt) (struct ite_dev *dev);
+
+	/* disable tx FIFO space available interrupt */
+	void (*disable_tx_interrupt) (struct ite_dev *dev);
+
+	/* get number of full TX FIFO slots */
+	int (*get_tx_used_slots) (struct ite_dev *dev);
+
+	/* put a byte to the TX FIFO */
+	void (*put_tx_byte) (struct ite_dev *dev, u8 value);
+
+	/* disable hardware completely */
+	void (*disable) (struct ite_dev *dev);
+
+	/* initialize the hardware */
+	void (*init_hardware) (struct ite_dev *dev);
+
+	/* set the carrier parameters */
+	void (*set_carrier_params) (struct ite_dev *dev, bool high_freq,
+				    bool use_demodulator, u8 carrier_freq_bits,
+				    u8 allowance_bits, u8 pulse_width_bits);
+};
+
+/* ITE CIR device structure */
+struct ite_dev {
+	struct pnp_dev *pdev;
+	struct rc_dev *rdev;
+	struct ir_raw_event rawir;
+
+	/* sync data */
+	spinlock_t lock;
+	bool in_use, transmitting;
+
+	/* transmit support */
+	int tx_fifo_allowance;
+	wait_queue_head_t tx_queue, tx_ended;
+
+	/* hardware I/O settings */
+	unsigned long cir_addr;
+	int cir_irq;
+
+	/* overridable copy of model parameters */
+	struct ite_dev_params params;
+};
+
+/* common values for all kinds of hardware */
+
+/* baud rate divisor default */
+#define ITE_BAUDRATE_DIVISOR		1
+
+/* low-speed carrier frequency limits (Hz) */
+#define ITE_LCF_MIN_CARRIER_FREQ	27000
+#define ITE_LCF_MAX_CARRIER_FREQ	58000
+
+/* high-speed carrier frequency limits (Hz) */
+#define ITE_HCF_MIN_CARRIER_FREQ	400000
+#define ITE_HCF_MAX_CARRIER_FREQ	500000
+
+/* default carrier freq for when demodulator is off (Hz) */
+#define ITE_DEFAULT_CARRIER_FREQ	38000
+
+/* default idling timeout in ns (0.2 seconds) */
+#define ITE_IDLE_TIMEOUT		200000000UL
+
+/* limit timeout values */
+#define ITE_MIN_IDLE_TIMEOUT		100000000UL
+#define ITE_MAX_IDLE_TIMEOUT		1000000000UL
+
+/* convert bits to us */
+#define ITE_BITS_TO_NS(bits, sample_period) \
+((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period))
+
+/*
+ * n in RDCR produces a tolerance of +/- n * 6.25% around the center
+ * carrier frequency...
+ *
+ * From two limit frequencies, L (low) and H (high), we can get both the
+ * center frequency F = (L + H) / 2 and the variation from the center
+ * frequency A = (H - L) / (H + L). We can use this in order to honor the
+ * s_rx_carrier_range() call in ir-core. We'll suppose that any request
+ * setting L=0 means we must shut down the demodulator.
+ */
+#define ITE_RXDCR_PER_10000_STEP 625
+
+/* high speed carrier freq values */
+#define ITE_CFQ_400		0x03
+#define ITE_CFQ_450		0x08
+#define ITE_CFQ_480		0x0b
+#define ITE_CFQ_500		0x0d
+
+/* values for pulse widths */
+#define ITE_TXMPW_A		0x02
+#define ITE_TXMPW_B		0x03
+#define ITE_TXMPW_C		0x04
+#define ITE_TXMPW_D		0x05
+#define ITE_TXMPW_E		0x06
+
+/* values for demodulator carrier range allowance */
+#define ITE_RXDCR_DEFAULT	0x01	/* default carrier range */
+#define ITE_RXDCR_MAX		0x07	/* default carrier range */
+
+/* DR TX bits */
+#define ITE_TX_PULSE		0x00
+#define ITE_TX_SPACE		0x80
+#define ITE_TX_MAX_RLE		0x80
+#define ITE_TX_RLE_MASK		0x7f
+
+/*
+ * IT8712F
+ *
+ * hardware data obtained from:
+ *
+ * IT8712F
+ * Environment Control – Low Pin Count Input / Output
+ * (EC - LPC I/O)
+ * Preliminary Specification V0. 81
+ */
+
+/* register offsets */
+#define IT87_DR		0x00	/* data register */
+#define IT87_IER	0x01	/* interrupt enable register */
+#define IT87_RCR	0x02	/* receiver control register */
+#define IT87_TCR1	0x03	/* transmitter control register 1 */
+#define IT87_TCR2	0x04	/* transmitter control register 2 */
+#define IT87_TSR	0x05	/* transmitter status register */
+#define IT87_RSR	0x06	/* receiver status register */
+#define IT87_BDLR	0x05	/* baud rate divisor low byte register */
+#define IT87_BDHR	0x06	/* baud rate divisor high byte register */
+#define IT87_IIR	0x07	/* interrupt identification register */
+
+#define IT87_IOREG_LENGTH 0x08	/* length of register file */
+
+/* IER bits */
+#define IT87_TLDLIE	0x01	/* transmitter low data interrupt enable */
+#define IT87_RDAIE	0x02	/* receiver data available interrupt enable */
+#define IT87_RFOIE	0x04	/* receiver FIFO overrun interrupt enable */
+#define IT87_IEC	0x08	/* interrupt enable control */
+#define IT87_BR		0x10	/* baud rate register enable */
+#define IT87_RESET	0x20	/* reset */
+
+/* RCR bits */
+#define IT87_RXDCR	0x07	/* receiver demodulation carrier range mask */
+#define IT87_RXACT	0x08	/* receiver active */
+#define IT87_RXEND	0x10	/* receiver demodulation enable */
+#define IT87_RXEN	0x20	/* receiver enable */
+#define IT87_HCFS	0x40	/* high-speed carrier frequency select */
+#define IT87_RDWOS	0x80	/* receiver data without sync */
+
+/* TCR1 bits */
+#define IT87_TXMPM	0x03	/* transmitter modulation pulse mode mask */
+#define IT87_TXMPM_DEFAULT 0x00	/* modulation pulse mode default */
+#define IT87_TXENDF	0x04	/* transmitter deferral */
+#define IT87_TXRLE	0x08	/* transmitter run length enable */
+#define IT87_FIFOTL	0x30	/* FIFO level threshold mask */
+#define IT87_FIFOTL_DEFAULT 0x20	/* FIFO level threshold default
+					 * 0x00 -> 1, 0x10 -> 7, 0x20 -> 17,
+					 * 0x30 -> 25 */
+#define IT87_ILE	0x40	/* internal loopback enable */
+#define IT87_FIFOCLR	0x80	/* FIFO clear bit */
+
+/* TCR2 bits */
+#define IT87_TXMPW	0x07	/* transmitter modulation pulse width mask */
+#define IT87_TXMPW_DEFAULT 0x04	/* default modulation pulse width */
+#define IT87_CFQ	0xf8	/* carrier frequency mask */
+#define IT87_CFQ_SHIFT	3	/* carrier frequency bit shift */
+
+/* TSR bits */
+#define IT87_TXFBC	0x3f	/* transmitter FIFO byte count mask */
+
+/* RSR bits */
+#define IT87_RXFBC	0x3f	/* receiver FIFO byte count mask */
+#define IT87_RXFTO	0x80	/* receiver FIFO time-out */
+
+/* IIR bits */
+#define IT87_IP		0x01	/* interrupt pending */
+#define IT87_II		0x06	/* interrupt identification mask */
+#define IT87_II_NOINT	0x00	/* no interrupt */
+#define IT87_II_TXLDL	0x02	/* transmitter low data level */
+#define IT87_II_RXDS	0x04	/* receiver data stored */
+#define IT87_II_RXFO	0x06	/* receiver FIFO overrun */
+
+/*
+ * IT8512E/F
+ *
+ * Hardware data obtained from:
+ *
+ * IT8512E/F
+ * Embedded Controller
+ * Preliminary Specification V0.4.1
+ *
+ * Note that the CIR registers are not directly available to the host, because
+ * they only are accessible to the integrated microcontroller. Thus, in order
+ * use it, some kind of bridging is required. As the bridging may depend on
+ * the controller firmware in use, we are going to use the PNP ID in order to
+ * determine the strategy and ports available. See after these generic
+ * IT8512E/F register definitions for register definitions for those
+ * strategies.
+ */
+
+/* register offsets */
+#define IT85_C0DR	0x00	/* data register */
+#define IT85_C0MSTCR	0x01	/* master control register */
+#define IT85_C0IER	0x02	/* interrupt enable register */
+#define IT85_C0IIR	0x03	/* interrupt identification register */
+#define IT85_C0CFR	0x04	/* carrier frequency register */
+#define IT85_C0RCR	0x05	/* receiver control register */
+#define IT85_C0TCR	0x06	/* transmitter control register */
+#define IT85_C0SCK	0x07	/* slow clock control register */
+#define IT85_C0BDLR	0x08	/* baud rate divisor low byte register */
+#define IT85_C0BDHR	0x09	/* baud rate divisor high byte register */
+#define IT85_C0TFSR	0x0a	/* transmitter FIFO status register */
+#define IT85_C0RFSR	0x0b	/* receiver FIFO status register */
+#define IT85_C0WCL	0x0d	/* wakeup code length register */
+#define IT85_C0WCR	0x0e	/* wakeup code read/write register */
+#define IT85_C0WPS	0x0f	/* wakeup power control/status register */
+
+#define IT85_IOREG_LENGTH 0x10	/* length of register file */
+
+/* C0MSTCR bits */
+#define IT85_RESET	0x01	/* reset */
+#define IT85_FIFOCLR	0x02	/* FIFO clear bit */
+#define IT85_FIFOTL	0x0c	/* FIFO level threshold mask */
+#define IT85_FIFOTL_DEFAULT 0x08	/* FIFO level threshold default
+					 * 0x00 -> 1, 0x04 -> 7, 0x08 -> 17,
+					 * 0x0c -> 25 */
+#define IT85_ILE	0x10	/* internal loopback enable */
+#define IT85_ILSEL	0x20	/* internal loopback select */
+
+/* C0IER bits */
+#define IT85_TLDLIE	0x01	/* TX low data level interrupt enable */
+#define IT85_RDAIE	0x02	/* RX data available interrupt enable */
+#define IT85_RFOIE	0x04	/* RX FIFO overrun interrupt enable */
+#define IT85_IEC	0x80	/* interrupt enable function control */
+
+/* C0IIR bits */
+#define IT85_TLDLI	0x01	/* transmitter low data level interrupt */
+#define IT85_RDAI	0x02	/* receiver data available interrupt */
+#define IT85_RFOI	0x04	/* receiver FIFO overrun interrupt */
+#define IT85_NIP	0x80	/* no interrupt pending */
+
+/* C0CFR bits */
+#define IT85_CFQ	0x1f	/* carrier frequency mask */
+#define IT85_HCFS	0x20	/* high speed carrier frequency select */
+
+/* C0RCR bits */
+#define IT85_RXDCR	0x07	/* receiver demodulation carrier range mask */
+#define IT85_RXACT	0x08	/* receiver active */
+#define IT85_RXEND	0x10	/* receiver demodulation enable */
+#define IT85_RDWOS	0x20	/* receiver data without sync */
+#define IT85_RXEN	0x80	/* receiver enable */
+
+/* C0TCR bits */
+#define IT85_TXMPW	0x07	/* transmitter modulation pulse width mask */
+#define IT85_TXMPW_DEFAULT 0x04	/* default modulation pulse width */
+#define IT85_TXMPM	0x18	/* transmitter modulation pulse mode mask */
+#define IT85_TXMPM_DEFAULT 0x00	/* modulation pulse mode default */
+#define IT85_TXENDF	0x20	/* transmitter deferral */
+#define IT85_TXRLE	0x40	/* transmitter run length enable */
+
+/* C0SCK bits */
+#define IT85_SCKS	0x01	/* slow clock select */
+#define IT85_TXDCKG	0x02	/* TXD clock gating */
+#define IT85_DLL1P8E	0x04	/* DLL 1.8432M enable */
+#define IT85_DLLTE	0x08	/* DLL test enable */
+#define IT85_BRCM	0x70	/* baud rate count mode */
+#define IT85_DLLOCK	0x80	/* DLL lock */
+
+/* C0TFSR bits */
+#define IT85_TXFBC	0x3f	/* transmitter FIFO count mask */
+
+/* C0RFSR bits */
+#define IT85_RXFBC	0x3f	/* receiver FIFO count mask */
+#define IT85_RXFTO	0x80	/* receiver FIFO time-out */
+
+/* C0WCL bits */
+#define IT85_WCL	0x3f	/* wakeup code length mask */
+
+/* C0WPS bits */
+#define IT85_CIRPOSIE	0x01	/* power on/off status interrupt enable */
+#define IT85_CIRPOIS	0x02	/* power on/off interrupt status */
+#define IT85_CIRPOII	0x04	/* power on/off interrupt identification */
+#define IT85_RCRST	0x10	/* wakeup code reading counter reset bit */
+#define IT85_WCRST	0x20	/* wakeup code writing counter reset bit */
+
+/*
+ * ITE8708
+ *
+ * Hardware data obtained from hacked driver for IT8512 in this forum post:
+ *
+ *  http://ubuntuforums.org/showthread.php?t=1028640
+ *
+ * Although there's no official documentation for that driver, analysis would
+ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks,
+ * selectable by a single bank-select bit that's mapped onto both banks. The
+ * IT8512 registers are mapped in a different order, so that the first bank
+ * maps the ones that are used more often, and two registers that share a
+ * reserved high-order bit are placed at the same offset in both banks in
+ * order to reuse the reserved bit as the bank select bit.
+ */
+
+/* register offsets */
+
+/* mapped onto both banks */
+#define IT8708_BANKSEL	0x07	/* bank select register */
+#define IT8708_HRAE	0x80	/* high registers access enable */
+
+/* mapped onto the low bank */
+#define IT8708_C0DR	0x00	/* data register */
+#define IT8708_C0MSTCR	0x01	/* master control register */
+#define IT8708_C0IER	0x02	/* interrupt enable register */
+#define IT8708_C0IIR	0x03	/* interrupt identification register */
+#define IT8708_C0RFSR	0x04	/* receiver FIFO status register */
+#define IT8708_C0RCR	0x05	/* receiver control register */
+#define IT8708_C0TFSR	0x06	/* transmitter FIFO status register */
+#define IT8708_C0TCR	0x07	/* transmitter control register */
+
+/* mapped onto the high bank */
+#define IT8708_C0BDLR	0x01	/* baud rate divisor low byte register */
+#define IT8708_C0BDHR	0x02	/* baud rate divisor high byte register */
+#define IT8708_C0CFR	0x04	/* carrier frequency register */
+
+/* registers whose bank mapping we don't know, since they weren't being used
+ * in the hacked driver... most probably they belong to the high bank too,
+ * since they fit in the holes the other registers leave */
+#define IT8708_C0SCK	0x03	/* slow clock control register */
+#define IT8708_C0WCL	0x05	/* wakeup code length register */
+#define IT8708_C0WCR	0x06	/* wakeup code read/write register */
+#define IT8708_C0WPS	0x07	/* wakeup power control/status register */
+
+#define IT8708_IOREG_LENGTH 0x08	/* length of register file */
+
+/* two more registers that are defined in the hacked driver, but can't be
+ * found in the data sheets; no idea what they are or how they are accessed,
+ * since the hacked driver doesn't seem to use them */
+#define IT8708_CSCRR	0x00
+#define IT8708_CGPINTR	0x01
+
+/* CSCRR bits */
+#define IT8708_CSCRR_SCRB 0x3f
+#define IT8708_CSCRR_PM	0x80
+
+/* CGPINTR bits */
+#define IT8708_CGPINT	0x01
+
+/*
+ * ITE8709
+ *
+ * Hardware interfacing data obtained from the original lirc_ite8709 driver.
+ * Verbatim from its sources:
+ *
+ * The ITE8709 device seems to be the combination of IT8512 superIO chip and
+ * a specific firmware running on the IT8512's embedded micro-controller.
+ * In addition of the embedded micro-controller, the IT8512 chip contains a
+ * CIR module and several other modules. A few modules are directly accessible
+ * by the host CPU, but most of them are only accessible by the
+ * micro-controller. The CIR module is only accessible by the
+ * micro-controller.
+ *
+ * The battery-backed SRAM module is accessible by the host CPU and the
+ * micro-controller. So one of the MC's firmware role is to act as a bridge
+ * between the host CPU and the CIR module. The firmware implements a kind of
+ * communication protocol using the SRAM module as a shared memory. The IT8512
+ * specification is publicly available on ITE's web site, but the
+ * communication protocol is not, so it was reverse-engineered.
+ */
+
+/* register offsets */
+#define IT8709_RAM_IDX	0x00	/* index into the SRAM module bytes */
+#define IT8709_RAM_VAL	0x01	/* read/write data to the indexed byte */
+
+#define IT8709_IOREG_LENGTH 0x02	/* length of register file */
+
+/* register offsets inside the SRAM module */
+#define IT8709_MODE	0x1a	/* request/ack byte */
+#define IT8709_REG_IDX	0x1b	/* index of the CIR register to access */
+#define IT8709_REG_VAL	0x1c	/* value read/to be written */
+#define IT8709_IIR	0x1e	/* interrupt identification register */
+#define IT8709_RFSR	0x1f	/* receiver FIFO status register */
+#define IT8709_FIFO	0x20	/* start of in RAM RX FIFO copy */
+
+/* MODE values */
+#define IT8709_IDLE	0x00
+#define IT8709_WRITE	0x01
+#define IT8709_READ	0x02
diff --git a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile
index cb72121..85cac7d 100644
--- a/drivers/media/rc/keymaps/Makefile
+++ b/drivers/media/rc/keymaps/Makefile
@@ -37,7 +37,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-gadmei-rm008z.o \
 			rc-genius-tvgo-a11mce.o \
 			rc-gotview7135.o \
-			rc-hauppauge-new.o \
 			rc-imon-mce.o \
 			rc-imon-pad.o \
 			rc-iodata-bctv7e.o \
@@ -68,8 +67,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
 			rc-proteus-2309.o \
 			rc-purpletv.o \
 			rc-pv951.o \
-			rc-rc5-hauppauge-new.o \
-			rc-rc5-tv.o \
+			rc-hauppauge.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
 			rc-streamzap.o \
diff --git a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
index 136d395..9a8752f 100644
--- a/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
+++ b/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
@@ -50,9 +50,9 @@ static struct rc_map_table adstech_dvb_t_pci[] = {
 	{ 0x13, KEY_TUNER },		/* Live */
 	{ 0x0a, KEY_A },
 	{ 0x12, KEY_B },
-	{ 0x03, KEY_PROG1 },		/* 1 */
-	{ 0x01, KEY_PROG2 },		/* 2 */
-	{ 0x00, KEY_PROG3 },		/* 3 */
+	{ 0x03, KEY_RED },		/* 1 */
+	{ 0x01, KEY_GREEN },		/* 2 */
+	{ 0x00, KEY_YELLOW },		/* 3 */
 	{ 0x06, KEY_DVD },
 	{ 0x48, KEY_AUX },		/* Photo */
 	{ 0x40, KEY_VIDEO },
diff --git a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
index 3ddb41b..c25809d 100644
--- a/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
+++ b/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
@@ -26,12 +26,12 @@ static struct rc_map_table avermedia_dvbt[] = {
 	{ 0x16, KEY_8 },		/* '8' / 'down arrow' */
 	{ 0x36, KEY_9 },		/* '9' */
 
-	{ 0x20, KEY_LIST },		/* 'source' */
+	{ 0x20, KEY_VIDEO },		/* 'source' */
 	{ 0x10, KEY_TEXT },		/* 'teletext' */
 	{ 0x00, KEY_POWER },		/* 'power' */
 	{ 0x04, KEY_AUDIO },		/* 'audio' */
 	{ 0x06, KEY_ZOOM },		/* 'full screen' */
-	{ 0x18, KEY_VIDEO },		/* 'display' */
+	{ 0x18, KEY_SWITCHVIDEOMODE },	/* 'display' */
 	{ 0x38, KEY_SEARCH },		/* 'loop' */
 	{ 0x08, KEY_INFO },		/* 'preview' */
 	{ 0x2a, KEY_REWIND },		/* 'backward <<' */
diff --git a/drivers/media/rc/keymaps/rc-avermedia-m135a.c b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
index 357fea5..3d2cbe4 100644
--- a/drivers/media/rc/keymaps/rc-avermedia-m135a.c
+++ b/drivers/media/rc/keymaps/rc-avermedia-m135a.c
@@ -108,7 +108,7 @@ static struct rc_map_table avermedia_m135a[] = {
 	{ 0x0414, KEY_TEXT },
 	{ 0x0415, KEY_EPG },
 	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
+	{ 0x041b, KEY_CAMERA },      /* Snapshot */
 
 	{ 0x0417, KEY_RECORD },
 	{ 0x0416, KEY_PLAYPAUSE },
diff --git a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
index e694e6e..8cd7f28 100644
--- a/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
+++ b/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
@@ -56,7 +56,7 @@ static struct rc_map_table avermedia_m733a_rm_k6[] = {
 	{ 0x0414, KEY_TEXT },
 	{ 0x0415, KEY_EPG },
 	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
+	{ 0x041b, KEY_CAMERA },      /* Snapshot */
 
 	{ 0x0417, KEY_RECORD },
 	{ 0x0416, KEY_PLAYPAUSE },
diff --git a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
index f4ca1ff..9d68af2 100644
--- a/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
+++ b/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
@@ -31,7 +31,7 @@ static struct rc_map_table avermedia_rm_ks[] = {
 	{ 0x0505, KEY_VOLUMEDOWN },
 	{ 0x0506, KEY_MUTE },
 	{ 0x0507, KEY_RIGHT },
-	{ 0x0508, KEY_PROG1 },
+	{ 0x0508, KEY_RED },
 	{ 0x0509, KEY_1 },
 	{ 0x050a, KEY_2 },
 	{ 0x050b, KEY_3 },
diff --git a/drivers/media/rc/keymaps/rc-behold-columbus.c b/drivers/media/rc/keymaps/rc-behold-columbus.c
index 4b787fa..8bf058f 100644
--- a/drivers/media/rc/keymaps/rc-behold-columbus.c
+++ b/drivers/media/rc/keymaps/rc-behold-columbus.c
@@ -28,7 +28,7 @@ static struct rc_map_table behold_columbus[] = {
 	 *                             */
 
 	{ 0x13, KEY_MUTE },
-	{ 0x11, KEY_PROPS },
+	{ 0x11, KEY_VIDEO },
 	{ 0x1C, KEY_TUNER },	/* KEY_TV/KEY_RADIO	*/
 	{ 0x12, KEY_POWER },
 
diff --git a/drivers/media/rc/keymaps/rc-behold.c b/drivers/media/rc/keymaps/rc-behold.c
index 0ee1f14..c909a23 100644
--- a/drivers/media/rc/keymaps/rc-behold.c
+++ b/drivers/media/rc/keymaps/rc-behold.c
@@ -97,7 +97,7 @@ static struct rc_map_table behold[] = {
 	{ 0x6b861a, KEY_STOP },
 	{ 0x6b860e, KEY_TEXT },
 	{ 0x6b861f, KEY_RED },	/*XXX KEY_AUDIO	*/
-	{ 0x6b861e, KEY_YELLOW },	/*XXX KEY_SOURCE	*/
+	{ 0x6b861e, KEY_VIDEO },
 
 	/*  0x1d   0x13     0x19  *
 	 * SLEEP  PREVIEW   DVB   *
diff --git a/drivers/media/rc/keymaps/rc-budget-ci-old.c b/drivers/media/rc/keymaps/rc-budget-ci-old.c
index 97fc386..2f66e43 100644
--- a/drivers/media/rc/keymaps/rc-budget-ci-old.c
+++ b/drivers/media/rc/keymaps/rc-budget-ci-old.c
@@ -12,7 +12,8 @@
 
 #include <media/rc-map.h>
 
-/* From reading the following remotes:
+/*
+ * From reading the following remotes:
  * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
  * Hauppauge (from NOVA-CI-s box product)
  * This is a "middle of the road" approach, differences are noted
diff --git a/drivers/media/rc/keymaps/rc-cinergy.c b/drivers/media/rc/keymaps/rc-cinergy.c
index 99520ff..cf3a6bf 100644
--- a/drivers/media/rc/keymaps/rc-cinergy.c
+++ b/drivers/media/rc/keymaps/rc-cinergy.c
@@ -25,7 +25,7 @@ static struct rc_map_table cinergy[] = {
 	{ 0x09, KEY_9 },
 
 	{ 0x0a, KEY_POWER },
-	{ 0x0b, KEY_PROG1 },		/* app */
+	{ 0x0b, KEY_MEDIA },		/* app */
 	{ 0x0c, KEY_ZOOM },		/* zoom/fullscreen */
 	{ 0x0d, KEY_CHANNELUP },	/* channel */
 	{ 0x0e, KEY_CHANNELDOWN },	/* channel- */
diff --git a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
index 43912bd..82c0200 100644
--- a/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
+++ b/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
@@ -32,7 +32,7 @@ static struct rc_map_table dntv_live_dvb_t[] = {
 	{ 0x0c, KEY_SEARCH },		/* scan */
 	{ 0x0d, KEY_STOP },
 	{ 0x0e, KEY_PAUSE },
-	{ 0x0f, KEY_LIST },		/* source */
+	{ 0x0f, KEY_VIDEO },		/* source */
 
 	{ 0x10, KEY_MUTE },
 	{ 0x11, KEY_REWIND },		/* backward << */
diff --git a/drivers/media/rc/keymaps/rc-encore-enltv.c b/drivers/media/rc/keymaps/rc-encore-enltv.c
index afa4e92..e56ac6e 100644
--- a/drivers/media/rc/keymaps/rc-encore-enltv.c
+++ b/drivers/media/rc/keymaps/rc-encore-enltv.c
@@ -24,7 +24,7 @@ static struct rc_map_table encore_enltv[] = {
 	{ 0x1e, KEY_TV },
 	{ 0x00, KEY_VIDEO },
 	{ 0x01, KEY_AUDIO },		/* music */
-	{ 0x02, KEY_MHP },		/* picture */
+	{ 0x02, KEY_CAMERA },		/* picture */
 
 	{ 0x1f, KEY_1 },
 	{ 0x03, KEY_2 },
@@ -77,7 +77,7 @@ static struct rc_map_table encore_enltv[] = {
 	{ 0x50, KEY_SLEEP },		/* shutdown */
 	{ 0x51, KEY_MODE },		/* stereo > main */
 	{ 0x52, KEY_SELECT },		/* stereo > sap */
-	{ 0x53, KEY_PROG1 },		/* teletext */
+	{ 0x53, KEY_TEXT },		/* teletext */
 
 
 	{ 0x59, KEY_RED },		/* AP1 */
diff --git a/drivers/media/rc/keymaps/rc-encore-enltv2.c b/drivers/media/rc/keymaps/rc-encore-enltv2.c
index 7d5b00e..b6264f1 100644
--- a/drivers/media/rc/keymaps/rc-encore-enltv2.c
+++ b/drivers/media/rc/keymaps/rc-encore-enltv2.c
@@ -32,7 +32,7 @@ static struct rc_map_table encore_enltv2[] = {
 	{ 0x64, KEY_LAST },		/* +100 */
 	{ 0x4e, KEY_AGAIN },		/* Recall */
 
-	{ 0x6c, KEY_SWITCHVIDEOMODE },	/* Video Source */
+	{ 0x6c, KEY_VIDEO },		/* Video Source */
 	{ 0x5e, KEY_MENU },
 	{ 0x56, KEY_SCREEN },
 	{ 0x7a, KEY_SETUP },
diff --git a/drivers/media/rc/keymaps/rc-flydvb.c b/drivers/media/rc/keymaps/rc-flydvb.c
index aea2f4a..a8b0f66 100644
--- a/drivers/media/rc/keymaps/rc-flydvb.c
+++ b/drivers/media/rc/keymaps/rc-flydvb.c
@@ -37,8 +37,8 @@ static struct rc_map_table flydvb[] = {
 	{ 0x13, KEY_CHANNELDOWN },	/* CH- */
 	{ 0x1d, KEY_ENTER },		/* Enter */
 
-	{ 0x1a, KEY_MODE },		/* PIP */
-	{ 0x18, KEY_TUNER },		/* Source */
+	{ 0x1a, KEY_TV2 },		/* PIP */
+	{ 0x18, KEY_VIDEO },		/* Source */
 
 	{ 0x1e, KEY_RECORD },		/* Record/Pause */
 	{ 0x15, KEY_ANGLE },		/* Swap (no label on key) */
diff --git a/drivers/media/rc/keymaps/rc-hauppauge-new.c b/drivers/media/rc/keymaps/rc-hauppauge-new.c
deleted file mode 100644
index bd11da4..0000000
--- a/drivers/media/rc/keymaps/rc-hauppauge-new.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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>
-
-/* Hauppauge: the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- * almost rc5 coding, but some non-standard keys */
-
-static struct rc_map_table hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x0b, KEY_RED },		/* red button */
-	{ 0x0c, KEY_RADIO },
-	{ 0x0d, KEY_MENU },
-	{ 0x0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x0f, KEY_MUTE },
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x14, KEY_UP },
-	{ 0x15, KEY_DOWN },
-	{ 0x16, KEY_LEFT },
-	{ 0x17, KEY_RIGHT },
-	{ 0x18, KEY_VIDEO },		/* Videos */
-	{ 0x19, KEY_AUDIO },		/* Music */
-	/* 0x1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1a, KEY_MHP },
-
-	{ 0x1b, KEY_EPG },		/* Guide */
-	{ 0x1c, KEY_TV },
-	{ 0x1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1f, KEY_EXIT },		/* back/exit */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x25, KEY_ENTER },		/* OK */
-	{ 0x26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x29, KEY_BLUE },		/* blue key */
-	{ 0x2e, KEY_GREEN },		/* green button */
-	{ 0x30, KEY_PAUSE },		/* pause */
-	{ 0x32, KEY_REWIND },		/* backward << */
-	{ 0x34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x38, KEY_YELLOW },		/* yellow key */
-	{ 0x3b, KEY_SELECT },		/* top right button */
-	{ 0x3c, KEY_ZOOM },		/* full */
-	{ 0x3d, KEY_POWER },		/* system power (green button) */
-};
-
-static struct rc_map_list hauppauge_new_map = {
-	.map = {
-		.scan    = hauppauge_new,
-		.size    = ARRAY_SIZE(hauppauge_new),
-		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_hauppauge_new(void)
-{
-	return rc_map_register(&hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_hauppauge_new(void)
-{
-	rc_map_unregister(&hauppauge_new_map);
-}
-
-module_init(init_rc_map_hauppauge_new)
-module_exit(exit_rc_map_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-hauppauge.c b/drivers/media/rc/keymaps/rc-hauppauge.c
new file mode 100644
index 0000000..cd3db77
--- /dev/null
+++ b/drivers/media/rc/keymaps/rc-hauppauge.c
@@ -0,0 +1,241 @@
+/* rc-hauppauge.c - Keytable for Hauppauge Remote Controllers
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * This map currently contains the code for four different RCs:
+ *	- New Hauppauge Gray;
+ *	- Old Hauppauge Gray (with a golden screen for media keys);
+ *	- Hauppauge Black;
+ *	- DSR-0112 remote bundled with Haupauge MiniStick.
+ *
+ * Copyright (c) 2010-2011 by Mauro Carvalho Chehab <mchehab@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>
+
+/*
+ * Hauppauge:the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ *
+ * This table contains the complete RC5 code, instead of just the data part
+ */
+
+static struct rc_map_table rc5_hauppauge_new[] = {
+	/*
+	 * Remote Controller Hauppauge Gray found on modern devices
+	 * Keycodes start with address = 0x1e
+	 */
+
+	{ 0x1e3b, KEY_SELECT },		/* GO / house symbol */
+	{ 0x1e3d, KEY_POWER2 },		/* system power (green button) */
+
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e18, KEY_VIDEO },		/* Videos */
+	{ 0x1e19, KEY_AUDIO },		/* Music */
+	{ 0x1e1a, KEY_CAMERA },		/* Pictures */
+
+	{ 0x1e1b, KEY_EPG },		/* Guide */
+	{ 0x1e0c, KEY_RADIO },
+
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e25, KEY_OK },		/* OK */
+
+	{ 0x1e1f, KEY_EXIT },		/* back/exit */
+	{ 0x1e0d, KEY_MENU },
+
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+
+	{ 0x1e12, KEY_PREVIOUS },	/* previous channel */
+	{ 0x1e0f, KEY_MUTE },
+
+	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
+
+	{ 0x1e37, KEY_RECORD },		/* recording */
+	{ 0x1e36, KEY_STOP },
+
+	{ 0x1e32, KEY_REWIND },		/* backward << */
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
+
+	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1e30, KEY_PAUSE },		/* pause */
+	{ 0x1e1e, KEY_NEXTSONG },	/* skip >| */
+
+	{ 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_TEXT },		/* keypad asterisk as well */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e0e, KEY_SUBTITLE },	/* also the Pound key (#) */
+
+	{ 0x1e0b, KEY_RED },		/* red button */
+	{ 0x1e2e, KEY_GREEN },		/* green button */
+	{ 0x1e38, KEY_YELLOW },		/* yellow key */
+	{ 0x1e29, KEY_BLUE },		/* blue key */
+
+	/*
+	 * Old Remote Controller Hauppauge Gray with a golden screen
+	 * Keycodes start with address = 0x1f
+	 */
+	{ 0x1f3d, KEY_POWER2 },		/* system power (green button) */
+	{ 0x1f3b, KEY_SELECT },		/* GO */
+
+	/* Keys 0 to 9 */
+	{ 0x1f00, KEY_0 },
+	{ 0x1f01, KEY_1 },
+	{ 0x1f02, KEY_2 },
+	{ 0x1f03, KEY_3 },
+	{ 0x1f04, KEY_4 },
+	{ 0x1f05, KEY_5 },
+	{ 0x1f06, KEY_6 },
+	{ 0x1f07, KEY_7 },
+	{ 0x1f08, KEY_8 },
+	{ 0x1f09, KEY_9 },
+
+	{ 0x1f1f, KEY_EXIT },		/* back/exit */
+	{ 0x1f0d, KEY_MENU },
+
+	{ 0x1f10, KEY_VOLUMEUP },
+	{ 0x1f11, KEY_VOLUMEDOWN },
+	{ 0x1f20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1f21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x1f25, KEY_ENTER },		/* OK */
+
+	{ 0x1f0b, KEY_RED },		/* red button */
+	{ 0x1f2e, KEY_GREEN },		/* green button */
+	{ 0x1f38, KEY_YELLOW },		/* yellow key */
+	{ 0x1f29, KEY_BLUE },		/* blue key */
+
+	{ 0x1f0f, KEY_MUTE },
+	{ 0x1f0c, KEY_RADIO },		/* There's no indicator on this key */
+	{ 0x1f3c, KEY_ZOOM },		/* full */
+
+	{ 0x1f32, KEY_REWIND },		/* backward << */
+	{ 0x1f35, KEY_PLAY },
+	{ 0x1f34, KEY_FASTFORWARD },	/* forward >> */
+
+	{ 0x1f37, KEY_RECORD },		/* recording */
+	{ 0x1f36, KEY_STOP },
+	{ 0x1f30, KEY_PAUSE },		/* pause */
+
+	{ 0x1f24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1f1e, KEY_NEXTSONG },	/* skip >| */
+
+	/*
+	 * Keycodes for DSR-0112 remote bundled with Haupauge MiniStick
+	 * Keycodes start with address = 0x1d
+	 */
+	{ 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_PREVIOUS },        /* Prev.Ch .. ??? */
+	{ 0x1d14, KEY_UP },
+	{ 0x1d15, KEY_DOWN },
+	{ 0x1d16, KEY_LEFT },
+	{ 0x1d17, KEY_RIGHT },
+	{ 0x1d1c, KEY_TV },
+	{ 0x1d1e, KEY_NEXT },           /* >|             */
+	{ 0x1d1f, KEY_EXIT },
+	{ 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 },
+	{ 0x1d3f, KEY_HOME },
+
+	/*
+	 * Keycodes for the old Black Remote Controller
+	 * This one also uses RC-5 protocol
+	 * Keycodes start with address = 0x00
+	 */
+	{ 0x001f, KEY_TV },
+	{ 0x0020, KEY_CHANNELUP },
+	{ 0x000c, KEY_RADIO },
+
+	{ 0x0011, KEY_VOLUMEDOWN },
+	{ 0x002e, KEY_ZOOM },		/* full screen */
+	{ 0x0010, KEY_VOLUMEUP },
+
+	{ 0x000d, KEY_MUTE },
+	{ 0x0021, KEY_CHANNELDOWN },
+	{ 0x0022, KEY_VIDEO },		/* source */
+
+	{ 0x0001, KEY_1 },
+	{ 0x0002, KEY_2 },
+	{ 0x0003, KEY_3 },
+
+	{ 0x0004, KEY_4 },
+	{ 0x0005, KEY_5 },
+	{ 0x0006, KEY_6 },
+
+	{ 0x0007, KEY_7 },
+	{ 0x0008, KEY_8 },
+	{ 0x0009, KEY_9 },
+
+	{ 0x001e, KEY_RED },	/* Reserved */
+	{ 0x0000, KEY_0 },
+	{ 0x0026, KEY_SLEEP },	/* Minimize */
+};
+
+static struct rc_map_list rc5_hauppauge_new_map = {
+	.map = {
+		.scan    = rc5_hauppauge_new,
+		.size    = ARRAY_SIZE(rc5_hauppauge_new),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_HAUPPAUGE,
+	}
+};
+
+static int __init init_rc_map_rc5_hauppauge_new(void)
+{
+	return rc_map_register(&rc5_hauppauge_new_map);
+}
+
+static void __exit exit_rc_map_rc5_hauppauge_new(void)
+{
+	rc_map_unregister(&rc5_hauppauge_new_map);
+}
+
+module_init(init_rc_map_rc5_hauppauge_new)
+module_exit(exit_rc_map_rc5_hauppauge_new)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-imon-mce.c b/drivers/media/rc/keymaps/rc-imon-mce.c
index cb67184..937a819 100644
--- a/drivers/media/rc/keymaps/rc-imon-mce.c
+++ b/drivers/media/rc/keymaps/rc-imon-mce.c
@@ -111,7 +111,7 @@ static struct rc_map_table imon_mce[] = {
 	{ 0x800ff44d, KEY_TITLE },
 
 	{ 0x800ff40c, KEY_POWER },
-	{ 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */
+	{ 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */
 
 };
 
diff --git a/drivers/media/rc/keymaps/rc-imon-pad.c b/drivers/media/rc/keymaps/rc-imon-pad.c
index eef46b7..63d42bd 100644
--- a/drivers/media/rc/keymaps/rc-imon-pad.c
+++ b/drivers/media/rc/keymaps/rc-imon-pad.c
@@ -125,7 +125,7 @@ static struct rc_map_table imon_pad[] = {
 	{ 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
 	{ 0x02000065, KEY_COMPOSE }, /* RightMenu */
 	{ 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
-	{ 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */
+	{ 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */
 	{ 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
 };
 
diff --git a/drivers/media/rc/keymaps/rc-kworld-315u.c b/drivers/media/rc/keymaps/rc-kworld-315u.c
index 3ce6ef7..7f33edb 100644
--- a/drivers/media/rc/keymaps/rc-kworld-315u.c
+++ b/drivers/media/rc/keymaps/rc-kworld-315u.c
@@ -17,7 +17,7 @@
 
 static struct rc_map_table kworld_315u[] = {
 	{ 0x6143, KEY_POWER },
-	{ 0x6101, KEY_TUNER },		/* source */
+	{ 0x6101, KEY_VIDEO },		/* source */
 	{ 0x610b, KEY_ZOOM },
 	{ 0x6103, KEY_POWER2 },		/* shutdown */
 
diff --git a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
index e45f0b8..08d1831 100644
--- a/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
+++ b/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
@@ -17,7 +17,7 @@
  */
 
 static struct rc_map_table kworld_plus_tv_analog[] = {
-	{ 0x0c, KEY_PROG1 },		/* Kworld key */
+	{ 0x0c, KEY_LEFTMETA },		/* Kworld key */
 	{ 0x16, KEY_CLOSECD },		/* -> ) */
 	{ 0x1d, KEY_POWER2 },
 
diff --git a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
index fa8fd0a..8e9969d 100644
--- a/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
+++ b/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
@@ -62,7 +62,7 @@ static struct rc_map_table msi_tvanywhere_plus[] = {
 	{ 0x13, KEY_AGAIN },		/* Recall */
 
 	{ 0x1e, KEY_POWER },		/* Power */
-	{ 0x07, KEY_TUNER },		/* Source */
+	{ 0x07, KEY_VIDEO },		/* Source */
 	{ 0x1c, KEY_SEARCH },		/* Scan */
 	{ 0x18, KEY_MUTE },		/* Mute */
 
diff --git a/drivers/media/rc/keymaps/rc-nebula.c b/drivers/media/rc/keymaps/rc-nebula.c
index 3e6f077..ddae20e 100644
--- a/drivers/media/rc/keymaps/rc-nebula.c
+++ b/drivers/media/rc/keymaps/rc-nebula.c
@@ -27,7 +27,7 @@ static struct rc_map_table nebula[] = {
 	{ 0x0b, KEY_AUX },
 	{ 0x0c, KEY_DVD },
 	{ 0x0d, KEY_POWER },
-	{ 0x0e, KEY_MHP },	/* labelled 'Picture' */
+	{ 0x0e, KEY_CAMERA },	/* labelled 'Picture' */
 	{ 0x0f, KEY_AUDIO },
 	{ 0x10, KEY_INFO },
 	{ 0x11, KEY_F13 },	/* 16:9 */
diff --git a/drivers/media/rc/keymaps/rc-norwood.c b/drivers/media/rc/keymaps/rc-norwood.c
index 629ee9d..f1c1281 100644
--- a/drivers/media/rc/keymaps/rc-norwood.c
+++ b/drivers/media/rc/keymaps/rc-norwood.c
@@ -29,7 +29,7 @@ static struct rc_map_table norwood[] = {
 	{ 0x28, KEY_8 },
 	{ 0x29, KEY_9 },
 
-	{ 0x78, KEY_TUNER },		/* Video Source        */
+	{ 0x78, KEY_VIDEO },		/* Video Source        */
 	{ 0x2c, KEY_EXIT },		/* Open/Close software */
 	{ 0x2a, KEY_SELECT },		/* 2 Digit Select      */
 	{ 0x69, KEY_AGAIN },		/* Recall              */
diff --git a/drivers/media/rc/keymaps/rc-pctv-sedna.c b/drivers/media/rc/keymaps/rc-pctv-sedna.c
index fa5ae59..7cdef6e 100644
--- a/drivers/media/rc/keymaps/rc-pctv-sedna.c
+++ b/drivers/media/rc/keymaps/rc-pctv-sedna.c
@@ -36,7 +36,7 @@ static struct rc_map_table pctv_sedna[] = {
 	{ 0x0e, KEY_STOP },
 	{ 0x0f, KEY_PREVIOUSSONG },
 	{ 0x10, KEY_ZOOM },
-	{ 0x11, KEY_TUNER },	/* Source */
+	{ 0x11, KEY_VIDEO },	/* Source */
 	{ 0x12, KEY_POWER },
 	{ 0x13, KEY_MUTE },
 	{ 0x15, KEY_CHANNELDOWN },
diff --git a/drivers/media/rc/keymaps/rc-pixelview-mk12.c b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
index 8d9f664..125fc39 100644
--- a/drivers/media/rc/keymaps/rc-pixelview-mk12.c
+++ b/drivers/media/rc/keymaps/rc-pixelview-mk12.c
@@ -34,7 +34,7 @@ static struct rc_map_table pixelview_mk12[] = {
 	{ 0x866b13, KEY_AGAIN },	/* loop */
 	{ 0x866b10, KEY_DIGITS },	/* +100 */
 
-	{ 0x866b00, KEY_MEDIA },	/* source */
+	{ 0x866b00, KEY_VIDEO },		/* source */
 	{ 0x866b18, KEY_MUTE },		/* mute */
 	{ 0x866b19, KEY_CAMERA },	/* snapshot */
 	{ 0x866b1a, KEY_SEARCH },	/* scan */
diff --git a/drivers/media/rc/keymaps/rc-pixelview-new.c b/drivers/media/rc/keymaps/rc-pixelview-new.c
index 777a700..bd78d6a 100644
--- a/drivers/media/rc/keymaps/rc-pixelview-new.c
+++ b/drivers/media/rc/keymaps/rc-pixelview-new.c
@@ -33,7 +33,7 @@ static struct rc_map_table pixelview_new[] = {
 	{ 0x3e, KEY_0 },
 
 	{ 0x1c, KEY_AGAIN },		/* LOOP	*/
-	{ 0x3f, KEY_MEDIA },		/* Source */
+	{ 0x3f, KEY_VIDEO },		/* Source */
 	{ 0x1f, KEY_LAST },		/* +100 */
 	{ 0x1b, KEY_MUTE },
 
diff --git a/drivers/media/rc/keymaps/rc-pixelview.c b/drivers/media/rc/keymaps/rc-pixelview.c
index 0ec5988..06187e7 100644
--- a/drivers/media/rc/keymaps/rc-pixelview.c
+++ b/drivers/media/rc/keymaps/rc-pixelview.c
@@ -15,7 +15,7 @@
 static struct rc_map_table pixelview[] = {
 
 	{ 0x1e, KEY_POWER },	/* power */
-	{ 0x07, KEY_MEDIA },	/* source */
+	{ 0x07, KEY_VIDEO },	/* source */
 	{ 0x1c, KEY_SEARCH },	/* scan */
 
 
diff --git a/drivers/media/rc/keymaps/rc-pv951.c b/drivers/media/rc/keymaps/rc-pv951.c
index 83a418d..5e8beee 100644
--- a/drivers/media/rc/keymaps/rc-pv951.c
+++ b/drivers/media/rc/keymaps/rc-pv951.c
@@ -46,10 +46,10 @@ static struct rc_map_table pv951[] = {
 	{ 0x0c, KEY_SEARCH },		/* AUTOSCAN */
 
 	/* Not sure what to do with these ones! */
-	{ 0x0f, KEY_SELECT },		/* SOURCE */
+	{ 0x0f, KEY_VIDEO },		/* SOURCE */
 	{ 0x0a, KEY_KPPLUS },		/* +100 */
 	{ 0x14, KEY_EQUAL },		/* SYNC */
-	{ 0x1c, KEY_MEDIA },		/* PC/TV */
+	{ 0x1c, KEY_TV },		/* PC/TV */
 };
 
 static struct rc_map_list pv951_map = {
diff --git a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c b/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
deleted file mode 100644
index dfc9b15..0000000
--- a/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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>
-
-/*
- * Hauppauge:the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- *
- * This table contains the complete RC5 code, instead of just the data part
- */
-
-static struct rc_map_table rc5_hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 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_TEXT },		/* keypad asterisk as well */
-	{ 0x1e0b, KEY_RED },		/* red button */
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },		/* Videos */
-	{ 0x1e19, KEY_AUDIO },		/* Music */
-	/* 0x1e1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1e1a, KEY_MHP },
-
-	{ 0x1e1b, KEY_EPG },		/* Guide */
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1e1f, KEY_EXIT },		/* back/exit */
-	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x1e25, KEY_ENTER },		/* OK */
-	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x1e29, KEY_BLUE },		/* blue key */
-	{ 0x1e2e, KEY_GREEN },		/* green button */
-	{ 0x1e30, KEY_PAUSE },		/* pause */
-	{ 0x1e32, KEY_REWIND },		/* backward << */
-	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },		/* recording */
-	{ 0x1e38, KEY_YELLOW },		/* yellow key */
-	{ 0x1e3b, KEY_SELECT },		/* top right button */
-	{ 0x1e3c, KEY_ZOOM },		/* full */
-	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
-
-	/* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */
-	{ 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_PREVIOUS },        /* Prev.Ch .. ??? */
-	{ 0x1d14, KEY_UP },
-	{ 0x1d15, KEY_DOWN },
-	{ 0x1d16, KEY_LEFT },
-	{ 0x1d17, KEY_RIGHT },
-	{ 0x1d1c, KEY_TV },
-	{ 0x1d1e, KEY_NEXT },           /* >|             */
-	{ 0x1d1f, KEY_EXIT },
-	{ 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 },
-	{ 0x1d3f, KEY_HOME },
-};
-
-static struct rc_map_list rc5_hauppauge_new_map = {
-	.map = {
-		.scan    = rc5_hauppauge_new,
-		.size    = ARRAY_SIZE(rc5_hauppauge_new),
-		.rc_type = RC_TYPE_RC5,
-		.name    = RC_MAP_RC5_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_rc5_hauppauge_new(void)
-{
-	return rc_map_register(&rc5_hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_rc5_hauppauge_new(void)
-{
-	rc_map_unregister(&rc5_hauppauge_new_map);
-}
-
-module_init(init_rc_map_rc5_hauppauge_new)
-module_exit(exit_rc_map_rc5_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-rc5-tv.c b/drivers/media/rc/keymaps/rc-rc5-tv.c
deleted file mode 100644
index 4fcef9f..0000000
--- a/drivers/media/rc/keymaps/rc-rc5-tv.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/* rc5-tv.h - Keytable for rc5_tv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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>
-
-/* generic RC5 keytable                                          */
-/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
-/* used by old (black) Hauppauge remotes                         */
-
-static struct rc_map_table rc5_tv[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0b, KEY_CHANNEL },		/* channel / program (japan: 11) */
-	{ 0x0c, KEY_POWER },		/* standby */
-	{ 0x0d, KEY_MUTE },		/* mute / demute */
-	{ 0x0f, KEY_TV },		/* display */
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_BRIGHTNESSUP },
-	{ 0x13, KEY_BRIGHTNESSDOWN },
-	{ 0x1e, KEY_SEARCH },		/* search + */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* alt / channel */
-	{ 0x23, KEY_LANGUAGE },		/* 1st / 2nd language */
-	{ 0x26, KEY_SLEEP },		/* sleeptimer */
-	{ 0x2e, KEY_MENU },		/* 2nd controls (USA: menu) */
-	{ 0x30, KEY_PAUSE },
-	{ 0x32, KEY_REWIND },
-	{ 0x33, KEY_GOTO },
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x3c, KEY_TEXT },		/* teletext submode (Japan: 12) */
-	{ 0x3d, KEY_SUSPEND },		/* system standby */
-
-};
-
-static struct rc_map_list rc5_tv_map = {
-	.map = {
-		.scan    = rc5_tv,
-		.size    = ARRAY_SIZE(rc5_tv),
-		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_RC5_TV,
-	}
-};
-
-static int __init init_rc_map_rc5_tv(void)
-{
-	return rc_map_register(&rc5_tv_map);
-}
-
-static void __exit exit_rc_map_rc5_tv(void)
-{
-	rc_map_unregister(&rc5_tv_map);
-}
-
-module_init(init_rc_map_rc5_tv)
-module_exit(exit_rc_map_rc5_tv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff --git a/drivers/media/rc/keymaps/rc-rc6-mce.c b/drivers/media/rc/keymaps/rc-rc6-mce.c
index 2f5dc06..8dd519e 100644
--- a/drivers/media/rc/keymaps/rc-rc6-mce.c
+++ b/drivers/media/rc/keymaps/rc-rc6-mce.c
@@ -30,7 +30,7 @@ static struct rc_map_table rc6_mce[] = {
 	{ 0x800f040a, KEY_DELETE },
 	{ 0x800f040b, KEY_ENTER },
 	{ 0x800f040c, KEY_POWER },		/* PC Power */
-	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */
+	{ 0x800f040d, KEY_LEFTMETA },		/* Windows MCE button */
 	{ 0x800f040e, KEY_MUTE },
 	{ 0x800f040f, KEY_INFO },
 
diff --git a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
index 2d14598..6813d11 100644
--- a/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
+++ b/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
@@ -35,7 +35,7 @@ static struct rc_map_table real_audio_220_32_keys[] = {
 	{ 0x15, KEY_CHANNELDOWN},
 	{ 0x16, KEY_ENTER},
 
-	{ 0x11, KEY_LIST},		/* Source */
+	{ 0x11, KEY_VIDEO},		/* Source */
 	{ 0x0d, KEY_AUDIO},		/* stereo */
 
 	{ 0x0f, KEY_PREVIOUS},		/* Prev */
diff --git a/drivers/media/rc/keymaps/rc-winfast.c b/drivers/media/rc/keymaps/rc-winfast.c
index 2747db4..0062ca2 100644
--- a/drivers/media/rc/keymaps/rc-winfast.c
+++ b/drivers/media/rc/keymaps/rc-winfast.c
@@ -27,15 +27,15 @@ static struct rc_map_table winfast[] = {
 	{ 0x0e, KEY_8 },
 	{ 0x0f, KEY_9 },
 
-	{ 0x00, KEY_POWER },
+	{ 0x00, KEY_POWER2 },
 	{ 0x1b, KEY_AUDIO },		/* Audio Source */
 	{ 0x02, KEY_TUNER },		/* TV/FM, not on Y0400052 */
 	{ 0x1e, KEY_VIDEO },		/* Video Source */
 	{ 0x16, KEY_INFO },		/* Display information */
-	{ 0x04, KEY_VOLUMEUP },
-	{ 0x08, KEY_VOLUMEDOWN },
-	{ 0x0c, KEY_CHANNELUP },
-	{ 0x10, KEY_CHANNELDOWN },
+	{ 0x04, KEY_LEFT },
+	{ 0x08, KEY_RIGHT },
+	{ 0x0c, KEY_UP },
+	{ 0x10, KEY_DOWN },
 	{ 0x03, KEY_ZOOM },		/* fullscreen */
 	{ 0x1f, KEY_TEXT },		/* closed caption/teletext */
 	{ 0x20, KEY_SLEEP },
@@ -47,7 +47,7 @@ static struct rc_map_table winfast[] = {
 	{ 0x2e, KEY_BLUE },
 	{ 0x18, KEY_KPPLUS },		/* fine tune + , not on Y040052 */
 	{ 0x19, KEY_KPMINUS },		/* fine tune - , not on Y040052 */
-	{ 0x2a, KEY_MEDIA },		/* PIP (Picture in picture */
+	{ 0x2a, KEY_TV2 },		/* PIP (Picture in picture */
 	{ 0x21, KEY_DOT },
 	{ 0x13, KEY_ENTER },
 	{ 0x11, KEY_LAST },		/* Recall (last channel */
@@ -57,7 +57,7 @@ static struct rc_map_table winfast[] = {
 	{ 0x25, KEY_TIME },		/* Time Shifting */
 	{ 0x26, KEY_STOP },
 	{ 0x27, KEY_RECORD },
-	{ 0x28, KEY_SAVE },		/* Screenshot */
+	{ 0x28, KEY_CAMERA },		/* Screenshot */
 	{ 0x2f, KEY_MENU },
 	{ 0x30, KEY_CANCEL },
 	{ 0x31, KEY_CHANNEL },		/* Channel Surf */
@@ -70,10 +70,10 @@ static struct rc_map_table winfast[] = {
 	{ 0x38, KEY_DVD },
 
 	{ 0x1a, KEY_MODE},		/* change to MCE mode on Y04G0051 */
-	{ 0x3e, KEY_F21 },		/* MCE +VOL, on Y04G0033 */
-	{ 0x3a, KEY_F22 },		/* MCE -VOL, on Y04G0033 */
-	{ 0x3b, KEY_F23 },		/* MCE +CH,  on Y04G0033 */
-	{ 0x3f, KEY_F24 }		/* MCE -CH,  on Y04G0033 */
+	{ 0x3e, KEY_VOLUMEUP },		/* MCE +VOL, on Y04G0033 */
+	{ 0x3a, KEY_VOLUMEDOWN },	/* MCE -VOL, on Y04G0033 */
+	{ 0x3b, KEY_CHANNELUP },	/* MCE +CH,  on Y04G0033 */
+	{ 0x3f, KEY_CHANNELDOWN }	/* MCE -CH,  on Y04G0033 */
 };
 
 static struct rc_map_list winfast_map = {
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index e4f8eac..044fb7a 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -186,7 +186,7 @@ static const struct mceusb_model mceusb_model[] = {
 		 * remotes, but we should have something handy,
 		 * to allow testing it
 		 */
-		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.rc_map = RC_MAP_HAUPPAUGE,
 		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
 	},
 	[CX_HYBRID_TV] = {
@@ -261,7 +261,7 @@ static struct usb_device_id mceusb_dev_table[] = {
 	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
-	  .driver_info = MCE_GEN2_TX_INV },
+	  .driver_info = MCE_GEN3 },
 	/* Ricavision internal Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 	/* Itron ione Libra Q-11 */
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c
index c330fb9..040aaa8 100644
--- a/drivers/media/video/cx18/cx18-i2c.c
+++ b/drivers/media/video/cx18/cx18-i2c.c
@@ -96,7 +96,7 @@ static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
 	/* Our default information for ir-kbd-i2c.c to use */
 	switch (hw) {
 	case CX18_HW_Z8F0811_IR_RX_HAUP:
-		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = cx->card_name;
diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c
index 199b996..e97cafd 100644
--- a/drivers/media/video/cx23885/cx23885-input.c
+++ b/drivers/media/video/cx23885/cx23885-input.c
@@ -264,7 +264,7 @@ int cx23885_input_init(struct cx23885_dev *dev)
 		driver_type = RC_DRIVER_IR_RAW;
 		allowed_protos = RC_TYPE_ALL;
 		/* The grey Hauppauge RC-5 remote */
-		rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
+		rc_map = RC_MAP_HAUPPAUGE;
 		break;
 	case CX23885_BOARD_TEVII_S470:
 		/* Integrated CX23885 IR controller */
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index fbfbba5..c820e2f 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -283,7 +283,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
 	case CX88_BOARD_PCHDTV_HD3000:
 	case CX88_BOARD_PCHDTV_HD5500:
 	case CX88_BOARD_HAUPPAUGE_IRONLY:
-		ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		ir_codes = RC_MAP_HAUPPAUGE;
 		ir->sampling = 1;
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
@@ -604,7 +604,7 @@ void cx88_i2c_init_ir(struct cx88_core *core)
 		if (*addrp == 0x71) {
 			/* Hauppauge XVR */
 			core->init_data.name = "cx88 Hauppauge XVR remote";
-			core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
+			core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 			core->init_data.type = RC_TYPE_RC5;
 			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 87f77a3..69fcea8 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -834,7 +834,7 @@ struct em28xx_board em28xx_boards[] = {
 		.mts_firmware = 1,
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900_digital,
-		.ir_codes     = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes     = RC_MAP_HAUPPAUGE,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -859,7 +859,7 @@ struct em28xx_board em28xx_boards[] = {
 		.tuner_type   = TUNER_XC2028,
 		.tuner_gpio   = default_tuner_gpio,
 		.mts_firmware = 1,
-		.ir_codes     = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes     = RC_MAP_HAUPPAUGE,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -885,7 +885,7 @@ struct em28xx_board em28xx_boards[] = {
 		.mts_firmware   = 1,
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-		.ir_codes       = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes       = RC_MAP_HAUPPAUGE,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -911,7 +911,7 @@ struct em28xx_board em28xx_boards[] = {
 		.mts_firmware   = 1,
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-		.ir_codes       = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.ir_codes       = RC_MAP_HAUPPAUGE,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -2430,7 +2430,7 @@ void em28xx_register_i2c_ir(struct em28xx *dev)
 		dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
 		break;
 	case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-		dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW;
+		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 		dev->init_data.get_key = em28xx_get_key_em_haup;
 		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
 		break;
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
index e53fa55..2a1ac28 100644
--- a/drivers/media/video/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/video/hdpvr/hdpvr-i2c.c
@@ -52,25 +52,36 @@ struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
 	};
 
 	/* Our default information for ir-kbd-i2c.c to use */
-	init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+	init_data->ir_codes = RC_MAP_HAUPPAUGE;
 	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 	init_data->type = RC_TYPE_RC5;
 	init_data->name = "HD-PVR";
+	init_data->polling_interval = 405; /* ms, duplicated from Windows */
 	hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
 
 	return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
 }
 
 static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
-			  unsigned char addr, char *data, int len)
+			  unsigned char addr, char *wdata, int wlen,
+			  char *data, int len)
 {
 	int ret;
 
-	if (len > sizeof(dev->i2c_buf))
+	if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
 		return -EINVAL;
 
-	ret = usb_control_msg(dev->udev,
-			      usb_rcvctrlpipe(dev->udev, 0),
+	if (wlen) {
+		memcpy(&dev->i2c_buf, wdata, wlen);
+		ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+				      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+				      (bus << 8) | addr, 0, &dev->i2c_buf,
+				      wlen, 1000);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
 			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
@@ -92,16 +103,14 @@ static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
 		return -EINVAL;
 
 	memcpy(&dev->i2c_buf, data, len);
-	ret = usb_control_msg(dev->udev,
-			      usb_sndctrlpipe(dev->udev, 0),
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
 			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
 	if (ret < 0)
 		return ret;
 
-	ret = usb_control_msg(dev->udev,
-			      usb_rcvctrlpipe(dev->udev, 0),
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
 			      0, 0, &dev->i2c_buf, 2, 1000);
 
@@ -117,24 +126,49 @@ static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
 			  int num)
 {
 	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
-	int retval = 0, i, addr;
+	int retval = 0, addr;
 
 	if (num <= 0)
 		return 0;
 
 	mutex_lock(&dev->i2c_mutex);
 
-	for (i = 0; i < num && !retval; i++) {
-		addr = msgs[i].addr << 1;
+	addr = msgs[0].addr << 1;
 
-		if (msgs[i].flags & I2C_M_RD)
-			retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
-						msgs[i].len);
+	if (num == 1) {
+		if (msgs[0].flags & I2C_M_RD)
+			retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
+						msgs[0].buf, msgs[0].len);
 		else
-			retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
-						 msgs[i].len);
+			retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
+						 msgs[0].len);
+	} else if (num == 2) {
+		if (msgs[0].addr != msgs[1].addr) {
+			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
+				  "with conflicting target addresses\n");
+			retval = -EINVAL;
+			goto out;
+		}
+
+		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
+			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
+				  "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
+				  msgs[1].flags & I2C_M_RD);
+			retval = -EINVAL;
+			goto out;
+		}
+
+		/*
+		 * Write followed by atomic read is the only complex xfer that
+		 * we actually support here.
+		 */
+		retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
+					msgs[1].buf, msgs[1].len);
+	} else {
+		v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
 	}
 
+out:
 	mutex_unlock(&dev->i2c_mutex);
 
 	return retval ? retval : num;
@@ -158,11 +192,11 @@ static struct i2c_adapter hdpvr_i2c_adapter_template = {
 
 static int hdpvr_activate_ir(struct hdpvr_device *dev)
 {
-	char buffer[8];
+	char buffer[2];
 
 	mutex_lock(&dev->i2c_mutex);
 
-	hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
+	hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
 
 	buffer[0] = 0;
 	buffer[1] = 0x8;
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index a221ad6..3ab875d 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -55,10 +55,6 @@
 static int debug;
 module_param(debug, int, 0644);    /* debug level (0,1,2) */
 
-static int hauppauge;
-module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
-MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
-
 
 #define MODULE_NAME "ir-kbd-i2c"
 #define dprintk(level, fmt, arg...)	if (debug >= level) \
@@ -105,10 +101,6 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
 		/* invalid key press */
 		return 0;
 
-	if (dev!=0x1e && dev!=0x1f)
-		/* not a hauppauge remote */
-		return 0;
-
 	if (!range)
 		code += 64;
 
@@ -116,7 +108,7 @@ static int get_key_haup_common(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
 		start, range, toggle, dev, code);
 
 	/* return key */
-	*ir_key = code;
+	*ir_key = (dev << 8) | code;
 	*ir_raw = ircode;
 	return 1;
 }
@@ -312,11 +304,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		name        = "Hauppauge";
 		ir->get_key = get_key_haup;
 		rc_type     = RC_TYPE_RC5;
-		if (hauppauge == 1) {
-			ir_codes    = RC_MAP_HAUPPAUGE_NEW;
-		} else {
-			ir_codes    = RC_MAP_RC5_TV;
-		}
+		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	case 0x30:
 		name        = "KNC One";
@@ -340,7 +328,7 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
 		rc_type     = RC_TYPE_RC5;
-		ir_codes    = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV;
+		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	}
 
diff --git a/drivers/media/video/ivtv/ivtv-i2c.c b/drivers/media/video/ivtv/ivtv-i2c.c
index 9fb86a0..d47f41a 100644
--- a/drivers/media/video/ivtv/ivtv-i2c.c
+++ b/drivers/media/video/ivtv/ivtv-i2c.c
@@ -205,15 +205,14 @@ static int ivtv_i2c_new_ir(struct ivtv *itv, u32 hw, const char *type, u8 addr)
 		break;
 	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
 	case IVTV_HW_I2C_IR_RX_HAUP_INT:
-		/* Default to old black remote */
-		init_data->ir_codes = RC_MAP_RC5_TV;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_Z8F0811_IR_RX_HAUP:
 		/* Default to grey remote */
-		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = itv->card_name;
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
index 451ecd4..e72d510 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -578,7 +578,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 	switch (hdw->ir_scheme_active) {
 	case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */
 	case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
-		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
 		init_data->type                  = RC_TYPE_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
@@ -593,7 +593,7 @@ static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
 		break;
 	case PVR2_IR_SCHEME_ZILOG:     /* HVR-1950 style */
 	case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
-		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type                  = RC_TYPE_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 790d667..be1c2a2 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -893,7 +893,7 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
 		dev->init_data.name = "HVR 1110";
 		dev->init_data.get_key = get_key_hvr1110;
-		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 		info.addr = 0x71;
 		break;
 	case SAA7134_BOARD_BEHOLD_607FM_MK3:
diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig
index cdaff59..526ec0f 100644
--- a/drivers/staging/lirc/Kconfig
+++ b/drivers/staging/lirc/Kconfig
@@ -32,18 +32,6 @@ config LIRC_IMON
 
 	  Current generation iMON devices use the input layer imon driver.
 
-config LIRC_IT87
-	tristate "ITE IT87XX CIR Port Receiver"
-	depends on LIRC && PNP
-	help
-	  Driver for the ITE IT87xx IR Receiver
-
-config LIRC_ITE8709
-	tristate "ITE8709 CIR Port Receiver"
-	depends on LIRC && PNP
-	help
-	  Driver for the ITE8709 IR Receiver
-
 config LIRC_PARALLEL
 	tristate "Homebrew Parallel Port Receiver"
 	depends on LIRC && PARPORT
diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile
index 94af218..d76b0fa 100644
--- a/drivers/staging/lirc/Makefile
+++ b/drivers/staging/lirc/Makefile
@@ -6,8 +6,6 @@
 obj-$(CONFIG_LIRC_BT829)	+= lirc_bt829.o
 obj-$(CONFIG_LIRC_IGORPLUGUSB)	+= lirc_igorplugusb.o
 obj-$(CONFIG_LIRC_IMON)		+= lirc_imon.o
-obj-$(CONFIG_LIRC_IT87)		+= lirc_it87.o
-obj-$(CONFIG_LIRC_ITE8709)	+= lirc_ite8709.o
 obj-$(CONFIG_LIRC_PARALLEL)	+= lirc_parallel.o
 obj-$(CONFIG_LIRC_SASEM)	+= lirc_sasem.o
 obj-$(CONFIG_LIRC_SERIAL)	+= lirc_serial.o
diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog
index 2d0263f..a97800a 100644
--- a/drivers/staging/lirc/TODO.lirc_zilog
+++ b/drivers/staging/lirc/TODO.lirc_zilog
@@ -1,34 +1,33 @@
-1. Both ir-kbd-i2c and lirc_zilog provide support for RX events.
-The 'tx_only' lirc_zilog module parameter will allow ir-kbd-i2c
-and lirc_zilog to coexist in the kernel, if the user requires such a set-up.
-However the IR unit will not work well without coordination between the
-two modules.  A shared mutex, for transceiver access locking, needs to be
-supplied by bridge drivers, in struct IR_i2_init_data, to both ir-kbd-i2c
-and lirc_zilog, before they will coexist usefully.  This should be fixed
-before moving out of staging.
-
-2. References and locking need careful examination.  For cx18 and ivtv PCI
-cards, which are not easily "hot unplugged", the imperfect state of reference
-counting and locking is acceptable if not correct.  For USB connected units
-like HD PVR, PVR USB2, HVR-1900, and HVR1950, the likelyhood of an Ooops on
-unplug is probably great.  Proper reference counting and locking needs to be
-implemented before this module is moved out of staging.
-
-3. The binding between hdpvr and lirc_zilog is currently disabled,
-due to an OOPS reported a few years ago when both the hdpvr and cx18
-drivers were loaded in his system. More details can be seen at:
-	http://www.mail-archive.com/linux-media@vger.kernel.org/msg09163.html
-More tests need to be done, in order to fix the reported issue.
-
-4. In addition to providing a shared mutex for transceiver access
-locking, bridge drivers, if able, should provide a chip reset() callback
+1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for
+the chips supported by lirc_zilog.  Before moving lirc_zilog out of staging:
+
+a. ir-kbd-i2c needs a module parameter added to allow the user to tell
+   ir-kbd-i2c to ignore Z8 IR units.
+
+b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c
+   does.
+
+
+2. lirc_zilog module ref-counting need examination.  It has not been
+verified that cdev and lirc_dev will take the proper module references on
+lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node
+is open.
+
+(The good news is ref-counting of lirc_zilog internal structures appears to be
+complete.  Testing has shown the cx18 module can be unloaded out from under
+irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse
+effects.  The cx18 module could then be reloaded and irw properly began
+receiving button presses again and ir_send worked without error.)
+
+
+3. Bridge drivers, if able, should provide a chip reset() callback
 to lirc_zilog via struct IR_i2c_init_data.  cx18 and ivtv already have routines
-to perform Z8 chip resets via GPIO manipulations.  This will allow lirc_zilog
+to perform Z8 chip resets via GPIO manipulations.  This would allow lirc_zilog
 to bring the chip back to normal when it hangs, in the same places the
 original lirc_pvr150 driver code does.  This is not strictly needed, so it
 is not required to move lirc_zilog out of staging.
 
-5. Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed
+Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed
 and installed on Hauppauge products.  When working on either module, developers
 must consider at least the following bridge drivers which mention an IR Rx unit
 at address 0x71 (indicative of a Z8):
diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c
index 235cab0..4039eda 100644
--- a/drivers/staging/lirc/lirc_imon.c
+++ b/drivers/staging/lirc/lirc_imon.c
@@ -379,7 +379,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
 	struct imon_context *context;
 	const unsigned char vfd_packet6[] = {
 		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
-	int *data_buf;
+	int *data_buf = NULL;
 
 	context = file->private_data;
 	if (!context) {
diff --git a/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c
deleted file mode 100644
index 5938616..0000000
--- a/drivers/staging/lirc/lirc_it87.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- * LIRC driver for ITE IT8712/IT8705 CIR port
- *
- * Copyright (C) 2001 Hans-Gunter Lutke Uphues <hg_lu@web.de>
- *
- * 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
- *
- * ITE IT8705 and IT8712(not tested) and IT8720 CIR-port support for lirc based
- * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula
- *
- * Attention: Sendmode only tested with debugging logs
- *
- * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> :
- *   reimplemented read function
- * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix,
- *   based on work of the following member of the Outertrack Digimatrix
- *   Forum: Art103 <r_tay@hotmail.com>
- * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support
- *   for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the
- *   chip identifies as 18.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/poll.h>
-#include <asm/system.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/fcntl.h>
-
-#include <linux/timer.h>
-#include <linux/pnp.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#include "lirc_it87.h"
-
-#ifdef LIRC_IT87_DIGIMATRIX
-static int digimatrix = 1;
-static int it87_freq = 36; /* kHz */
-static int irq = 9;
-#else
-static int digimatrix;
-static int it87_freq = 38; /* kHz */
-static int irq = IT87_CIR_DEFAULT_IRQ;
-#endif
-
-static unsigned long it87_bits_in_byte_out;
-static unsigned long it87_send_counter;
-static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN;
-
-#define RBUF_LEN 1024
-
-#define LIRC_DRIVER_NAME "lirc_it87"
-
-/* timeout for sequences in jiffies (=5/100s) */
-/* must be longer than TIME_CONST */
-#define IT87_TIMEOUT	(HZ*5/100)
-
-/* module parameters */
-static int debug;
-#define dprintk(fmt, args...)					\
-	do {							\
-		if (debug)					\
-			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
-			       fmt, ## args);			\
-	} while (0)
-
-static int io = IT87_CIR_DEFAULT_IOBASE;
-/* receiver demodulator default: off */
-static int it87_enable_demodulator;
-
-static int timer_enabled;
-static DEFINE_SPINLOCK(timer_lock);
-static struct timer_list timerlist;
-/* time of last signal change detected */
-static struct timeval last_tv = {0, 0};
-/* time of last UART data ready interrupt */
-static struct timeval last_intr_tv = {0, 0};
-static int last_value;
-
-static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue);
-
-static DEFINE_SPINLOCK(hardware_lock);
-static DEFINE_SPINLOCK(dev_lock);
-static bool device_open;
-
-static int rx_buf[RBUF_LEN];
-unsigned int rx_tail, rx_head;
-
-static struct pnp_driver it87_pnp_driver;
-
-/* SECTION: Prototypes */
-
-/* Communication with user-space */
-static int lirc_open(struct inode *inode, struct file *file);
-static int lirc_close(struct inode *inode, struct file *file);
-static unsigned int lirc_poll(struct file *file, poll_table *wait);
-static ssize_t lirc_read(struct file *file, char *buf,
-			 size_t count, loff_t *ppos);
-static ssize_t lirc_write(struct file *file, const char *buf,
-			  size_t n, loff_t *pos);
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
-static void add_read_queue(int flag, unsigned long val);
-static int init_chrdev(void);
-static void drop_chrdev(void);
-/* Hardware */
-static irqreturn_t it87_interrupt(int irq, void *dev_id);
-static void send_space(unsigned long len);
-static void send_pulse(unsigned long len);
-static void init_send(void);
-static void terminate_send(unsigned long len);
-static int init_hardware(void);
-static void drop_hardware(void);
-/* Initialisation */
-static int init_port(void);
-static void drop_port(void);
-
-
-/* SECTION: Communication with user-space */
-
-static int lirc_open(struct inode *inode, struct file *file)
-{
-	spin_lock(&dev_lock);
-	if (device_open) {
-		spin_unlock(&dev_lock);
-		return -EBUSY;
-	}
-	device_open = true;
-	spin_unlock(&dev_lock);
-	return 0;
-}
-
-
-static int lirc_close(struct inode *inode, struct file *file)
-{
-	spin_lock(&dev_lock);
-	device_open = false;
-	spin_unlock(&dev_lock);
-	return 0;
-}
-
-
-static unsigned int lirc_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &lirc_read_queue, wait);
-	if (rx_head != rx_tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-
-static ssize_t lirc_read(struct file *file, char *buf,
-			 size_t count, loff_t *ppos)
-{
-	int n = 0;
-	int retval = 0;
-
-	while (n < count) {
-		if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) {
-			retval = -EAGAIN;
-			break;
-		}
-		retval = wait_event_interruptible(lirc_read_queue,
-						  rx_head != rx_tail);
-		if (retval)
-			break;
-
-		if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head),
-				 sizeof(int))) {
-			retval = -EFAULT;
-			break;
-		}
-		rx_head = (rx_head + 1) & (RBUF_LEN - 1);
-		n += sizeof(int);
-	}
-	if (n)
-		return n;
-	return retval;
-}
-
-
-static ssize_t lirc_write(struct file *file, const char *buf,
-			  size_t n, loff_t *pos)
-{
-	int i = 0;
-	int *tx_buf;
-
-	if (n % sizeof(int))
-		return -EINVAL;
-	tx_buf = memdup_user(buf, n);
-	if (IS_ERR(tx_buf))
-		return PTR_ERR(tx_buf);
-	n /= sizeof(int);
-	init_send();
-	while (1) {
-		if (i >= n)
-			break;
-		if (tx_buf[i])
-			send_pulse(tx_buf[i]);
-		i++;
-		if (i >= n)
-			break;
-		if (tx_buf[i])
-			send_space(tx_buf[i]);
-		i++;
-	}
-	terminate_send(tx_buf[i - 1]);
-	kfree(tx_buf);
-	return n;
-}
-
-
-static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
-	int retval = 0;
-	__u32 value = 0;
-	unsigned long hw_flags;
-
-	if (cmd == LIRC_GET_FEATURES)
-		value = LIRC_CAN_SEND_PULSE |
-			LIRC_CAN_SET_SEND_CARRIER |
-			LIRC_CAN_REC_MODE2;
-	else if (cmd == LIRC_GET_SEND_MODE)
-		value = LIRC_MODE_PULSE;
-	else if (cmd == LIRC_GET_REC_MODE)
-		value = LIRC_MODE_MODE2;
-
-	switch (cmd) {
-	case LIRC_GET_FEATURES:
-	case LIRC_GET_SEND_MODE:
-	case LIRC_GET_REC_MODE:
-		retval = put_user(value, (__u32 *) arg);
-		break;
-
-	case LIRC_SET_SEND_MODE:
-	case LIRC_SET_REC_MODE:
-		retval = get_user(value, (__u32 *) arg);
-		break;
-
-	case LIRC_SET_SEND_CARRIER:
-		retval = get_user(value, (__u32 *) arg);
-		if (retval)
-			return retval;
-		value /= 1000;
-		if (value > IT87_CIR_FREQ_MAX ||
-		    value < IT87_CIR_FREQ_MIN)
-			return -EINVAL;
-
-		it87_freq = value;
-
-		spin_lock_irqsave(&hardware_lock, hw_flags);
-		outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |
-		      (it87_freq - IT87_CIR_FREQ_MIN) << 3),
-		      io + IT87_CIR_TCR2);
-		spin_unlock_irqrestore(&hardware_lock, hw_flags);
-		dprintk("demodulation frequency: %d kHz\n", it87_freq);
-
-		break;
-
-	default:
-		retval = -EINVAL;
-	}
-
-	if (retval)
-		return retval;
-
-	if (cmd == LIRC_SET_REC_MODE) {
-		if (value != LIRC_MODE_MODE2)
-			retval = -ENOSYS;
-	} else if (cmd == LIRC_SET_SEND_MODE) {
-		if (value != LIRC_MODE_PULSE)
-			retval = -ENOSYS;
-	}
-	return retval;
-}
-
-static void add_read_queue(int flag, unsigned long val)
-{
-	unsigned int new_rx_tail;
-	int newval;
-
-	dprintk("add flag %d with val %lu\n", flag, val);
-
-	newval = val & PULSE_MASK;
-
-	/*
-	 * statistically, pulses are ~TIME_CONST/2 too long. we could
-	 * maybe make this more exact, but this is good enough
-	 */
-	if (flag) {
-		/* pulse */
-		if (newval > TIME_CONST / 2)
-			newval -= TIME_CONST / 2;
-		else /* should not ever happen */
-			newval = 1;
-		newval |= PULSE_BIT;
-	} else
-		newval += TIME_CONST / 2;
-	new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1);
-	if (new_rx_tail == rx_head) {
-		dprintk("Buffer overrun.\n");
-		return;
-	}
-	rx_buf[rx_tail] = newval;
-	rx_tail = new_rx_tail;
-	wake_up_interruptible(&lirc_read_queue);
-}
-
-
-static const struct file_operations lirc_fops = {
-	.owner		= THIS_MODULE,
-	.read		= lirc_read,
-	.write		= lirc_write,
-	.poll		= lirc_poll,
-	.unlocked_ioctl	= lirc_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= lirc_ioctl,
-#endif
-	.open		= lirc_open,
-	.release	= lirc_close,
-	.llseek		= noop_llseek,
-};
-
-static int set_use_inc(void *data)
-{
-       return 0;
-}
-
-static void set_use_dec(void *data)
-{
-}
-
-static struct lirc_driver driver = {
-       .name		= LIRC_DRIVER_NAME,
-       .minor		= -1,
-       .code_length	= 1,
-       .sample_rate	= 0,
-       .data		= NULL,
-       .add_to_buf	= NULL,
-       .set_use_inc	= set_use_inc,
-       .set_use_dec	= set_use_dec,
-       .fops		= &lirc_fops,
-       .dev		= NULL,
-       .owner		= THIS_MODULE,
-};
-
-
-static int init_chrdev(void)
-{
-	driver.minor = lirc_register_driver(&driver);
-
-	if (driver.minor < 0) {
-		printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-
-static void drop_chrdev(void)
-{
-	lirc_unregister_driver(driver.minor);
-}
-
-
-/* SECTION: Hardware */
-static long delta(struct timeval *tv1, struct timeval *tv2)
-{
-	unsigned long deltv;
-
-	deltv = tv2->tv_sec - tv1->tv_sec;
-	if (deltv > 15)
-		deltv = 0xFFFFFF;
-	else
-		deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec;
-	return deltv;
-}
-
-static void it87_timeout(unsigned long data)
-{
-	unsigned long flags;
-
-	/* avoid interference with interrupt */
-	spin_lock_irqsave(&timer_lock, flags);
-
-	if (digimatrix) {
-		/* We have timed out. Disable the RX mechanism. */
-
-		outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) |
-		     IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR);
-		if (it87_RXEN_mask)
-			outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
-			     io + IT87_CIR_RCR);
-		dprintk(" TIMEOUT\n");
-		timer_enabled = 0;
-
-		/* fifo clear */
-		outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR,
-		     io+IT87_CIR_TCR1);
-
-	} else {
-		/*
-		 * if last received signal was a pulse, but receiving stopped
-		 * within the 9 bit frame, we need to finish this pulse and
-		 * simulate a signal change to from pulse to space. Otherwise
-		 * upper layers will receive two sequences next time.
-		 */
-
-		if (last_value) {
-			unsigned long pulse_end;
-
-			/* determine 'virtual' pulse end: */
-			pulse_end = delta(&last_tv, &last_intr_tv);
-			dprintk("timeout add %d for %lu usec\n",
-				last_value, pulse_end);
-			add_read_queue(last_value, pulse_end);
-			last_value = 0;
-			last_tv = last_intr_tv;
-		}
-	}
-	spin_unlock_irqrestore(&timer_lock, flags);
-}
-
-static irqreturn_t it87_interrupt(int irq, void *dev_id)
-{
-	unsigned char data;
-	struct timeval curr_tv;
-	static unsigned long deltv;
-	unsigned long deltintrtv;
-	unsigned long flags, hw_flags;
-	int iir, lsr;
-	int fifo = 0;
-	static char lastbit;
-	char bit;
-
-	/* Bit duration in microseconds */
-	const unsigned long bit_duration = 1000000ul /
-		(115200 / IT87_CIR_BAUDRATE_DIVISOR);
-
-
-	iir = inb(io + IT87_CIR_IIR);
-
-	switch (iir & IT87_CIR_IIR_IID) {
-	case 0x4:
-	case 0x6:
-		lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO |
-						IT87_CIR_RSR_RXFBC);
-		fifo = lsr & IT87_CIR_RSR_RXFBC;
-		dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr);
-
-		/* avoid interference with timer */
-		spin_lock_irqsave(&timer_lock, flags);
-		spin_lock_irqsave(&hardware_lock, hw_flags);
-		if (digimatrix) {
-			static unsigned long acc_pulse;
-			static unsigned long acc_space;
-
-			do {
-				data = inb(io + IT87_CIR_DR);
-				data = ~data;
-				fifo--;
-				if (data != 0x00) {
-					if (timer_enabled)
-						del_timer(&timerlist);
-					/*
-					 * start timer for end of
-					 * sequence detection
-					 */
-					timerlist.expires = jiffies +
-							    IT87_TIMEOUT;
-					add_timer(&timerlist);
-					timer_enabled = 1;
-				}
-				/* Loop through */
-				for (bit = 0; bit < 8; ++bit) {
-					if ((data >> bit) & 1) {
-						++acc_pulse;
-						if (lastbit == 0) {
-							add_read_queue(0,
-								acc_space *
-								 bit_duration);
-							acc_space = 0;
-						}
-					} else {
-						++acc_space;
-						if (lastbit == 1) {
-							add_read_queue(1,
-								acc_pulse *
-								 bit_duration);
-							acc_pulse = 0;
-						}
-					}
-					lastbit = (data >> bit) & 1;
-				}
-
-			} while (fifo != 0);
-		} else { /* Normal Operation */
-			do {
-				del_timer(&timerlist);
-				data = inb(io + IT87_CIR_DR);
-
-				dprintk("data=%02x\n", data);
-				do_gettimeofday(&curr_tv);
-				deltv = delta(&last_tv, &curr_tv);
-				deltintrtv = delta(&last_intr_tv, &curr_tv);
-
-				dprintk("t %lu , d %d\n",
-					deltintrtv, (int)data);
-
-				/*
-				 * if nothing came in last 2 cycles,
-				 * it was gap
-				 */
-				if (deltintrtv > TIME_CONST * 2) {
-					if (last_value) {
-						dprintk("GAP\n");
-
-						/* simulate signal change */
-						add_read_queue(last_value,
-							       deltv -
-							       deltintrtv);
-						last_value = 0;
-						last_tv.tv_sec =
-							last_intr_tv.tv_sec;
-						last_tv.tv_usec =
-							last_intr_tv.tv_usec;
-						deltv = deltintrtv;
-					}
-				}
-				data = 1;
-				if (data ^ last_value) {
-					/*
-					 * deltintrtv > 2*TIME_CONST,
-					 * remember ? the other case is
-					 * timeout
-					 */
-					add_read_queue(last_value,
-						       deltv-TIME_CONST);
-					last_value = data;
-					last_tv = curr_tv;
-					if (last_tv.tv_usec >= TIME_CONST)
-						last_tv.tv_usec -= TIME_CONST;
-					else {
-						last_tv.tv_sec--;
-						last_tv.tv_usec += 1000000 -
-							TIME_CONST;
-					}
-				}
-				last_intr_tv = curr_tv;
-				if (data) {
-					/*
-					 * start timer for end of
-					 * sequence detection
-					 */
-					timerlist.expires =
-						jiffies + IT87_TIMEOUT;
-					add_timer(&timerlist);
-				}
-				outb((inb(io + IT87_CIR_RCR) &
-				     ~IT87_CIR_RCR_RXEN) |
-				     IT87_CIR_RCR_RXACT,
-				     io + IT87_CIR_RCR);
-				if (it87_RXEN_mask)
-					outb(inb(io + IT87_CIR_RCR) |
-					     IT87_CIR_RCR_RXEN,
-					     io + IT87_CIR_RCR);
-				fifo--;
-			} while (fifo != 0);
-		}
-		spin_unlock_irqrestore(&hardware_lock, hw_flags);
-		spin_unlock_irqrestore(&timer_lock, flags);
-
-		return IRQ_RETVAL(IRQ_HANDLED);
-
-	default:
-		/* not our irq */
-		dprintk("unknown IRQ (shouldn't happen) !!\n");
-		return IRQ_RETVAL(IRQ_NONE);
-	}
-}
-
-
-static void send_it87(unsigned long len, unsigned long stime,
-		      unsigned char send_byte, unsigned int count_bits)
-{
-	long count = len / stime;
-	long time_left = 0;
-	static unsigned char byte_out;
-	unsigned long hw_flags;
-
-	dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte);
-
-	time_left = (long)len - (long)count * (long)stime;
-	count += ((2 * time_left) / stime);
-	while (count) {
-		long i = 0;
-		for (i = 0; i < count_bits; i++) {
-			byte_out = (byte_out << 1) | (send_byte & 1);
-			it87_bits_in_byte_out++;
-		}
-		if (it87_bits_in_byte_out == 8) {
-			dprintk("out=0x%x, tsr_txfbc: 0x%x\n",
-				byte_out,
-				inb(io + IT87_CIR_TSR) &
-				IT87_CIR_TSR_TXFBC);
-
-			while ((inb(io + IT87_CIR_TSR) &
-				IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE)
-				;
-
-			spin_lock_irqsave(&hardware_lock, hw_flags);
-			outb(byte_out, io + IT87_CIR_DR);
-			spin_unlock_irqrestore(&hardware_lock, hw_flags);
-
-			it87_bits_in_byte_out = 0;
-			it87_send_counter++;
-			byte_out = 0;
-		}
-		count--;
-	}
-}
-
-
-/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */
-
-static void send_space(unsigned long len)
-{
-	send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR);
-}
-
-static void send_pulse(unsigned long len)
-{
-	send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR);
-}
-
-
-static void init_send()
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hardware_lock, flags);
-	/* RXEN=0: receiver disable */
-	it87_RXEN_mask = 0;
-	outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN,
-	     io + IT87_CIR_RCR);
-	spin_unlock_irqrestore(&hardware_lock, flags);
-	it87_bits_in_byte_out = 0;
-	it87_send_counter = 0;
-}
-
-
-static void terminate_send(unsigned long len)
-{
-	unsigned long flags;
-	unsigned long last = 0;
-
-	last = it87_send_counter;
-	/* make sure all necessary data has been sent */
-	while (last == it87_send_counter)
-		send_space(len);
-	/* wait until all data sent */
-	while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0)
-		;
-	/* then re-enable receiver */
-	spin_lock_irqsave(&hardware_lock, flags);
-	it87_RXEN_mask = IT87_CIR_RCR_RXEN;
-	outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN,
-	     io + IT87_CIR_RCR);
-	spin_unlock_irqrestore(&hardware_lock, flags);
-}
-
-
-static int init_hardware(void)
-{
-	unsigned long flags;
-	unsigned char it87_rcr = 0;
-
-	spin_lock_irqsave(&hardware_lock, flags);
-	/* init cir-port */
-	/* enable r/w-access to Baudrate-Register */
-	outb(IT87_CIR_IER_BR, io + IT87_CIR_IER);
-	outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR);
-	outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR);
-	/* Baudrate Register off, define IRQs: Input only */
-	if (digimatrix) {
-		outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER);
-		/* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */
-	} else {
-		outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER);
-		/* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */
-	}
-	it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1;
-	if (it87_enable_demodulator)
-		it87_rcr |= IT87_CIR_RCR_RXEND;
-	outb(it87_rcr, io + IT87_CIR_RCR);
-	if (digimatrix) {
-		/* Set FIFO depth to 1 byte, and disable TX */
-		outb(inb(io + IT87_CIR_TCR1) |  0x00,
-		     io + IT87_CIR_TCR1);
-
-		/*
-		 * TX: it87_freq (36kHz), 'reserved' sensitivity
-		 * setting (0x00)
-		 */
-		outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00,
-		     io + IT87_CIR_TCR2);
-	} else {
-		/* TX: 38kHz, 13,3us (pulse-width) */
-		outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06,
-		     io + IT87_CIR_TCR2);
-	}
-	spin_unlock_irqrestore(&hardware_lock, flags);
-	return 0;
-}
-
-
-static void drop_hardware(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hardware_lock, flags);
-	disable_irq(irq);
-	/* receiver disable */
-	it87_RXEN_mask = 0;
-	outb(0x1, io + IT87_CIR_RCR);
-	/* turn off irqs */
-	outb(0, io + IT87_CIR_IER);
-	/* fifo clear */
-	outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1);
-	/* reset */
-	outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
-	enable_irq(irq);
-	spin_unlock_irqrestore(&hardware_lock, flags);
-}
-
-
-static unsigned char it87_read(unsigned char port)
-{
-	outb(port, IT87_ADRPORT);
-	return inb(IT87_DATAPORT);
-}
-
-
-static void it87_write(unsigned char port, unsigned char data)
-{
-	outb(port, IT87_ADRPORT);
-	outb(data, IT87_DATAPORT);
-}
-
-
-/* SECTION: Initialisation */
-
-static int init_port(void)
-{
-	unsigned long hw_flags;
-	int retval = 0;
-
-	unsigned char init_bytes[4] = IT87_INIT;
-	unsigned char it87_chipid = 0;
-	unsigned char ldn = 0;
-	unsigned int  it87_io = 0;
-	unsigned int  it87_irq = 0;
-
-	/* Enter MB PnP Mode */
-	outb(init_bytes[0], IT87_ADRPORT);
-	outb(init_bytes[1], IT87_ADRPORT);
-	outb(init_bytes[2], IT87_ADRPORT);
-	outb(init_bytes[3], IT87_ADRPORT);
-
-	/* 8712 or 8705 ? */
-	it87_chipid = it87_read(IT87_CHIP_ID1);
-	if (it87_chipid != 0x87) {
-		retval = -ENXIO;
-		return retval;
-	}
-	it87_chipid = it87_read(IT87_CHIP_ID2);
-	if ((it87_chipid != 0x05) &&
-		(it87_chipid != 0x12) &&
-		(it87_chipid != 0x18) &&
-		(it87_chipid != 0x20)) {
-		printk(KERN_INFO LIRC_DRIVER_NAME
-		       ": no IT8704/05/12/18/20 found (claimed IT87%02x), "
-		       "exiting..\n", it87_chipid);
-		retval = -ENXIO;
-		return retval;
-	}
-	printk(KERN_INFO LIRC_DRIVER_NAME
-	       ": found IT87%02x.\n",
-	       it87_chipid);
-
-	/* get I/O-Port and IRQ */
-	if (it87_chipid == 0x12 || it87_chipid == 0x18)
-		ldn = IT8712_CIR_LDN;
-	else
-		ldn = IT8705_CIR_LDN;
-	it87_write(IT87_LDN, ldn);
-
-	it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 +
-		  it87_read(IT87_CIR_BASE_LSB);
-	if (it87_io == 0) {
-		if (io == 0)
-			io = IT87_CIR_DEFAULT_IOBASE;
-		printk(KERN_INFO LIRC_DRIVER_NAME
-		       ": set default io 0x%x\n",
-		       io);
-		it87_write(IT87_CIR_BASE_MSB, io / 0x100);
-		it87_write(IT87_CIR_BASE_LSB, io % 0x100);
-	} else
-		io = it87_io;
-
-	it87_irq = it87_read(IT87_CIR_IRQ);
-	if (digimatrix || it87_irq == 0) {
-		if (irq == 0)
-			irq = IT87_CIR_DEFAULT_IRQ;
-		printk(KERN_INFO LIRC_DRIVER_NAME
-		       ": set default irq 0x%x\n",
-		       irq);
-		it87_write(IT87_CIR_IRQ, irq);
-	} else
-		irq = it87_irq;
-
-	spin_lock_irqsave(&hardware_lock, hw_flags);
-	/* reset */
-	outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER);
-	/* fifo clear */
-	outb(IT87_CIR_TCR1_FIFOCLR |
-	     /*	     IT87_CIR_TCR1_ILE | */
-	     IT87_CIR_TCR1_TXRLE |
-	     IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1);
-	spin_unlock_irqrestore(&hardware_lock, hw_flags);
-
-	/* get I/O port access and IRQ line */
-	if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) {
-		printk(KERN_ERR LIRC_DRIVER_NAME
-		       ": i/o port 0x%.4x already in use.\n", io);
-		/* Leaving MB PnP Mode */
-		it87_write(IT87_CFGCTRL, 0x2);
-		return -EBUSY;
-	}
-
-	/* activate CIR-Device */
-	it87_write(IT87_CIR_ACT, 0x1);
-
-	/* Leaving MB PnP Mode */
-	it87_write(IT87_CFGCTRL, 0x2);
-
-	retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/,
-			     LIRC_DRIVER_NAME, NULL);
-	if (retval < 0) {
-		printk(KERN_ERR LIRC_DRIVER_NAME
-		       ": IRQ %d already in use.\n",
-		       irq);
-		release_region(io, 8);
-		return retval;
-	}
-
-	printk(KERN_INFO LIRC_DRIVER_NAME
-	       ": I/O port 0x%.4x, IRQ %d.\n", io, irq);
-
-	init_timer(&timerlist);
-	timerlist.function = it87_timeout;
-	timerlist.data = 0xabadcafe;
-
-	return 0;
-}
-
-
-static void drop_port(void)
-{
-#if 0
-	unsigned char init_bytes[4] = IT87_INIT;
-
-	/* Enter MB PnP Mode */
-	outb(init_bytes[0], IT87_ADRPORT);
-	outb(init_bytes[1], IT87_ADRPORT);
-	outb(init_bytes[2], IT87_ADRPORT);
-	outb(init_bytes[3], IT87_ADRPORT);
-
-	/* deactivate CIR-Device */
-	it87_write(IT87_CIR_ACT, 0x0);
-
-	/* Leaving MB PnP Mode */
-	it87_write(IT87_CFGCTRL, 0x2);
-#endif
-
-	del_timer_sync(&timerlist);
-	free_irq(irq, NULL);
-	release_region(io, 8);
-}
-
-
-static int init_lirc_it87(void)
-{
-	int retval;
-
-	init_waitqueue_head(&lirc_read_queue);
-	retval = init_port();
-	if (retval < 0)
-		return retval;
-	init_hardware();
-	printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n");
-	return 0;
-}
-
-static int it87_probe(struct pnp_dev *pnp_dev,
-		      const struct pnp_device_id *dev_id)
-{
-	int retval;
-
-	driver.dev = &pnp_dev->dev;
-
-	retval = init_chrdev();
-	if (retval < 0)
-		return retval;
-
-	retval = init_lirc_it87();
-	if (retval)
-		goto init_lirc_it87_failed;
-
-	return 0;
-
-init_lirc_it87_failed:
-	drop_chrdev();
-
-	return retval;
-}
-
-static int __init lirc_it87_init(void)
-{
-	return pnp_register_driver(&it87_pnp_driver);
-}
-
-
-static void __exit lirc_it87_exit(void)
-{
-	drop_hardware();
-	drop_chrdev();
-	drop_port();
-	pnp_unregister_driver(&it87_pnp_driver);
-	printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
-}
-
-/* SECTION: PNP for ITE8704/13/18 */
-
-static const struct pnp_device_id pnp_dev_table[] = {
-	{"ITE8704", 0},
-	{"ITE8713", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static struct pnp_driver it87_pnp_driver = {
-	.name           = LIRC_DRIVER_NAME,
-	.id_table       = pnp_dev_table,
-	.probe		= it87_probe,
-};
-
-module_init(lirc_it87_init);
-module_exit(lirc_it87_exit);
-
-MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port");
-MODULE_AUTHOR("Hans-Gunter Lutke Uphues");
-MODULE_LICENSE("GPL");
-
-module_param(io, int, S_IRUGO);
-MODULE_PARM_DESC(io, "I/O base address (default: 0x310)");
-
-module_param(irq, int, S_IRUGO);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)");
-#else
-MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)");
-#endif
-
-module_param(it87_enable_demodulator, bool, S_IRUGO);
-MODULE_PARM_DESC(it87_enable_demodulator,
-		 "Receiver demodulator enable/disable (1/0), default: 0");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
-
-module_param(digimatrix, bool, S_IRUGO | S_IWUSR);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(digimatrix,
-	"Asus Digimatrix it87 compat. enable/disable (1/0), default: 1");
-#else
-MODULE_PARM_DESC(digimatrix,
-	"Asus Digimatrix it87 compat. enable/disable (1/0), default: 0");
-#endif
-
-
-module_param(it87_freq, int, S_IRUGO);
-#ifdef LIRC_IT87_DIGIMATRIX
-MODULE_PARM_DESC(it87_freq,
-    "Carrier demodulator frequency (kHz), (default: 36)");
-#else
-MODULE_PARM_DESC(it87_freq,
-    "Carrier demodulator frequency (kHz), (default: 38)");
-#endif
diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h
deleted file mode 100644
index cf021c8..0000000
--- a/drivers/staging/lirc/lirc_it87.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* lirc_it87.h */
-/* SECTION: Definitions */
-
-/********************************* ITE IT87xx ************************/
-
-/* based on the following documentation from ITE:
-   a) IT8712F Preliminary CIR Programming Guide V0.1
-   b) IT8705F Simple LPC I/O Preliminary Specification V0.3
-   c) IT8712F EC-LPC I/O Preliminary Specification V0.5
-*/
-
-/* IT8712/05 Ports: */
-#define IT87_ADRPORT      0x2e
-#define IT87_DATAPORT     0x2f
-#define IT87_INIT         {0x87, 0x01, 0x55, 0x55}
-
-/* alternate Ports: */
-/*
-#define IT87_ADRPORT      0x4e
-#define IT87_DATAPORT     0x4f
-#define IT87_INIT         {0x87, 0x01, 0x55, 0xaa}
- */
-
-/* IT8712/05 Registers */
-#define IT87_CFGCTRL      0x2
-#define IT87_LDN          0x7
-#define IT87_CHIP_ID1     0x20
-#define IT87_CHIP_ID2     0x21
-#define IT87_CFG_VERSION  0x22
-#define IT87_SWSUSPEND    0x23
-
-#define IT8712_CIR_LDN    0xa
-#define IT8705_CIR_LDN    0x7
-
-/* CIR Configuration Registers: */
-#define IT87_CIR_ACT      0x30
-#define IT87_CIR_BASE_MSB 0x60
-#define IT87_CIR_BASE_LSB 0x61
-#define IT87_CIR_IRQ      0x70
-#define IT87_CIR_CONFIG   0xf0
-
-/* List of IT87_CIR registers: offset to BaseAddr */
-#define IT87_CIR_DR   0
-#define IT87_CIR_IER  1
-#define IT87_CIR_RCR  2
-#define IT87_CIR_TCR1 3
-#define IT87_CIR_TCR2 4
-#define IT87_CIR_TSR  5
-#define IT87_CIR_RSR  6
-#define IT87_CIR_BDLR 5
-#define IT87_CIR_BDHR 6
-#define IT87_CIR_IIR  7
-
-/* Bit Definition */
-/* IER: */
-#define IT87_CIR_IER_TM_EN   0x80
-#define IT87_CIR_IER_RESEVED 0x40
-#define IT87_CIR_IER_RESET   0x20
-#define IT87_CIR_IER_BR      0x10
-#define IT87_CIR_IER_IEC     0x8
-#define IT87_CIR_IER_RFOIE   0x4
-#define IT87_CIR_IER_RDAIE   0x2
-#define IT87_CIR_IER_TLDLIE  0x1
-
-/* RCR: */
-#define IT87_CIR_RCR_RDWOS  0x80
-#define IT87_CIR_RCR_HCFS   0x40
-#define IT87_CIR_RCR_RXEN   0x20
-#define IT87_CIR_RCR_RXEND  0x10
-#define IT87_CIR_RCR_RXACT  0x8
-#define IT87_CIR_RCR_RXDCR  0x7
-
-/* TCR1: */
-#define IT87_CIR_TCR1_FIFOCLR 0x80
-#define IT87_CIR_TCR1_ILE     0x40
-#define IT87_CIR_TCR1_FIFOTL  0x30
-#define IT87_CIR_TCR1_TXRLE   0x8
-#define IT87_CIR_TCR1_TXENDF  0x4
-#define IT87_CIR_TCR1_TXMPM   0x3
-
-/* TCR2: */
-#define IT87_CIR_TCR2_CFQ   0xf8
-#define IT87_CIR_TCR2_TXMPW 0x7
-
-/* TSR: */
-#define IT87_CIR_TSR_RESERVED 0xc0
-#define IT87_CIR_TSR_TXFBC    0x3f
-
-/* RSR: */
-#define IT87_CIR_RSR_RXFTO    0x80
-#define IT87_CIR_RSR_RESERVED 0x40
-#define IT87_CIR_RSR_RXFBC    0x3f
-
-/* IIR: */
-#define IT87_CIR_IIR_RESERVED 0xf8
-#define IT87_CIR_IIR_IID      0x6
-#define IT87_CIR_IIR_IIP      0x1
-
-/* TM: */
-#define IT87_CIR_TM_IL_SEL    0x80
-#define IT87_CIR_TM_RESERVED  0x40
-#define IT87_CIR_TM_TM_REG    0x3f
-
-#define IT87_CIR_FIFO_SIZE 32
-
-/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */
-#define IT87_CIR_BAUDRATE_DIVISOR 0x1
-#define IT87_CIR_DEFAULT_IOBASE 0x310
-#define IT87_CIR_DEFAULT_IRQ    0x7
-#define IT87_CIR_SPACE 0x00
-#define IT87_CIR_PULSE 0xff
-#define IT87_CIR_FREQ_MIN 27
-#define IT87_CIR_FREQ_MAX 58
-#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul)
-
-/********************************* ITE IT87xx ************************/
diff --git a/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c
deleted file mode 100644
index cb20cfd..0000000
--- a/drivers/staging/lirc/lirc_ite8709.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * LIRC driver for ITE8709 CIR port
- *
- * Copyright (C) 2008 Grégory Lardière <spmf2004-lirc@yahoo.fr>
- *
- * 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/interrupt.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/pnp.h>
-#include <linux/io.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-#define LIRC_DRIVER_NAME "lirc_ite8709"
-
-#define BUF_CHUNK_SIZE	sizeof(int)
-#define BUF_SIZE	(128*BUF_CHUNK_SIZE)
-
-/*
- * The ITE8709 device seems to be the combination of IT8512 superIO chip and
- * a specific firmware running on the IT8512's embedded micro-controller.
- * In addition of the embedded micro-controller, the IT8512 chip contains a
- * CIR module and several other modules. A few modules are directly accessible
- * by the host CPU, but most of them are only accessible by the
- * micro-controller. The CIR module is only accessible by the micro-controller.
- * The battery-backed SRAM module is accessible by the host CPU and the
- * micro-controller. So one of the MC's firmware role is to act as a bridge
- * between the host CPU and the CIR module. The firmware implements a kind of
- * communication protocol using the SRAM module as a shared memory. The IT8512
- * specification is publicly available on ITE's web site, but the communication
- * protocol is not, so it was reverse-engineered.
- */
-
-/* ITE8709 Registers addresses and values (reverse-engineered) */
-#define ITE8709_MODE		0x1a
-#define ITE8709_REG_ADR		0x1b
-#define ITE8709_REG_VAL		0x1c
-#define ITE8709_IIR		0x1e  /* Interrupt identification register */
-#define ITE8709_RFSR		0x1f  /* Receiver FIFO status register */
-#define ITE8709_FIFO_START	0x20
-
-#define ITE8709_MODE_READY	0X00
-#define ITE8709_MODE_WRITE	0X01
-#define ITE8709_MODE_READ	0X02
-#define ITE8709_IIR_RDAI	0x02  /* Receiver data available interrupt */
-#define ITE8709_IIR_RFOI	0x04  /* Receiver FIFO overrun interrupt */
-#define ITE8709_RFSR_MASK	0x3f  /* FIFO byte count mask */
-
-/*
- * IT8512 CIR-module registers addresses and values
- * (from IT8512 E/F specification v0.4.1)
- */
-#define IT8512_REG_MSTCR	0x01  /* Master control register */
-#define IT8512_REG_IER		0x02  /* Interrupt enable register */
-#define IT8512_REG_CFR		0x04  /* Carrier frequency register */
-#define IT8512_REG_RCR		0x05  /* Receive control register */
-#define IT8512_REG_BDLR		0x08  /* Baud rate divisor low byte register */
-#define IT8512_REG_BDHR		0x09  /* Baud rate divisor high byte register */
-
-#define IT8512_MSTCR_RESET	0x01  /* Reset registers to default value */
-#define IT8512_MSTCR_FIFOCLR	0x02  /* Clear FIFO */
-#define IT8512_MSTCR_FIFOTL_7	0x04  /* FIFO threshold level : 7 */
-#define IT8512_MSTCR_FIFOTL_25	0x0c  /* FIFO threshold level : 25 */
-#define IT8512_IER_RDAIE	0x02  /* Enable data interrupt request */
-#define IT8512_IER_RFOIE	0x04  /* Enable FIFO overrun interrupt req */
-#define IT8512_IER_IEC		0x80  /* Enable interrupt request */
-#define IT8512_CFR_CF_36KHZ	0x09  /* Carrier freq : low speed, 36kHz */
-#define IT8512_RCR_RXDCR_1	0x01  /* Demodulation carrier range : 1 */
-#define IT8512_RCR_RXACT	0x08  /* Receiver active */
-#define IT8512_RCR_RXEN		0x80  /* Receiver enable */
-#define IT8512_BDR_6		6     /* Baud rate divisor : 6 */
-
-/* Actual values used by this driver */
-#define CFG_FIFOTL	IT8512_MSTCR_FIFOTL_25
-#define CFG_CR_FREQ	IT8512_CFR_CF_36KHZ
-#define CFG_DCR		IT8512_RCR_RXDCR_1
-#define CFG_BDR		IT8512_BDR_6
-#define CFG_TIMEOUT	100000 /* Rearm interrupt when a space is > 100 ms */
-
-static int debug;
-
-struct ite8709_device {
-	int use_count;
-	int io;
-	int irq;
-	spinlock_t hardware_lock;
-	__u64 acc_pulse;
-	__u64 acc_space;
-	char lastbit;
-	struct timeval last_tv;
-	struct lirc_driver driver;
-	struct tasklet_struct tasklet;
-	char force_rearm;
-	char rearmed;
-	char device_busy;
-};
-
-#define dprintk(fmt, args...)					\
-	do {							\
-		if (debug)					\
-			printk(KERN_DEBUG LIRC_DRIVER_NAME ": "	\
-				fmt, ## args);			\
-	} while (0)
-
-
-static unsigned char ite8709_read(struct ite8709_device *dev,
-					unsigned char port)
-{
-	outb(port, dev->io);
-	return inb(dev->io+1);
-}
-
-static void ite8709_write(struct ite8709_device *dev, unsigned char port,
-				unsigned char data)
-{
-	outb(port, dev->io);
-	outb(data, dev->io+1);
-}
-
-static void ite8709_wait_device(struct ite8709_device *dev)
-{
-	int i = 0;
-	/*
-	 * loop until device tells it's ready to continue
-	 * iterations count is usually ~750 but can sometimes achieve 13000
-	 */
-	for (i = 0; i < 15000; i++) {
-		udelay(2);
-		if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY)
-			break;
-	}
-}
-
-static void ite8709_write_register(struct ite8709_device *dev,
-				unsigned char reg_adr, unsigned char reg_value)
-{
-	ite8709_wait_device(dev);
-
-	ite8709_write(dev, ITE8709_REG_VAL, reg_value);
-	ite8709_write(dev, ITE8709_REG_ADR, reg_adr);
-	ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE);
-}
-
-static void ite8709_init_hardware(struct ite8709_device *dev)
-{
-	spin_lock_irq(&dev->hardware_lock);
-	dev->device_busy = 1;
-	spin_unlock_irq(&dev->hardware_lock);
-
-	ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff);
-	ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff);
-	ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ);
-	ite8709_write_register(dev, IT8512_REG_IER,
-			IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE);
-	ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR);
-	ite8709_write_register(dev, IT8512_REG_MSTCR,
-					CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
-	ite8709_write_register(dev, IT8512_REG_RCR,
-				IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
-
-	spin_lock_irq(&dev->hardware_lock);
-	dev->device_busy = 0;
-	spin_unlock_irq(&dev->hardware_lock);
-
-	tasklet_enable(&dev->tasklet);
-}
-
-static void ite8709_drop_hardware(struct ite8709_device *dev)
-{
-	tasklet_disable(&dev->tasklet);
-
-	spin_lock_irq(&dev->hardware_lock);
-	dev->device_busy = 1;
-	spin_unlock_irq(&dev->hardware_lock);
-
-	ite8709_write_register(dev, IT8512_REG_RCR, 0);
-	ite8709_write_register(dev, IT8512_REG_MSTCR,
-				IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR);
-
-	spin_lock_irq(&dev->hardware_lock);
-	dev->device_busy = 0;
-	spin_unlock_irq(&dev->hardware_lock);
-}
-
-static int ite8709_set_use_inc(void *data)
-{
-	struct ite8709_device *dev;
-	dev = data;
-	if (dev->use_count == 0)
-		ite8709_init_hardware(dev);
-	dev->use_count++;
-	return 0;
-}
-
-static void ite8709_set_use_dec(void *data)
-{
-	struct ite8709_device *dev;
-	dev = data;
-	dev->use_count--;
-	if (dev->use_count == 0)
-		ite8709_drop_hardware(dev);
-}
-
-static void ite8709_add_read_queue(struct ite8709_device *dev, int flag,
-				   __u64 val)
-{
-	int value;
-
-	dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space");
-
-	value = (val > PULSE_MASK) ? PULSE_MASK : val;
-	if (flag)
-		value |= PULSE_BIT;
-
-	if (!lirc_buffer_full(dev->driver.rbuf)) {
-		lirc_buffer_write(dev->driver.rbuf, (void *) &value);
-		wake_up(&dev->driver.rbuf->wait_poll);
-	}
-}
-
-static irqreturn_t ite8709_interrupt(int irq, void *dev_id)
-{
-	unsigned char data;
-	int iir, rfsr, i;
-	int fifo = 0;
-	char bit;
-	struct timeval curr_tv;
-
-	/* Bit duration in microseconds */
-	const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR);
-
-	struct ite8709_device *dev;
-	dev = dev_id;
-
-	/*
-	 * If device is busy, we simply discard data because we are in one of
-	 * these two cases : shutting down or rearming the device, so this
-	 * doesn't really matter and this avoids waiting too long in IRQ ctx
-	 */
-	spin_lock(&dev->hardware_lock);
-	if (dev->device_busy) {
-		spin_unlock(&dev->hardware_lock);
-		return IRQ_RETVAL(IRQ_HANDLED);
-	}
-
-	iir = ite8709_read(dev, ITE8709_IIR);
-
-	switch (iir) {
-	case ITE8709_IIR_RFOI:
-		dprintk("fifo overrun, scheduling forced rearm just in case\n");
-		dev->force_rearm = 1;
-		tasklet_schedule(&dev->tasklet);
-		spin_unlock(&dev->hardware_lock);
-		return IRQ_RETVAL(IRQ_HANDLED);
-
-	case ITE8709_IIR_RDAI:
-		rfsr = ite8709_read(dev, ITE8709_RFSR);
-		fifo = rfsr & ITE8709_RFSR_MASK;
-		if (fifo > 32)
-			fifo = 32;
-		dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo);
-
-		if (dev->rearmed) {
-			do_gettimeofday(&curr_tv);
-			dev->acc_space += 1000000ull
-				* (curr_tv.tv_sec - dev->last_tv.tv_sec)
-				+ (curr_tv.tv_usec - dev->last_tv.tv_usec);
-			dev->rearmed = 0;
-		}
-		for (i = 0; i < fifo; i++) {
-			data = ite8709_read(dev, i+ITE8709_FIFO_START);
-			data = ~data;
-			/* Loop through */
-			for (bit = 0; bit < 8; ++bit) {
-				if ((data >> bit) & 1) {
-					dev->acc_pulse += bit_duration;
-					if (dev->lastbit == 0) {
-						ite8709_add_read_queue(dev, 0,
-							dev->acc_space);
-						dev->acc_space = 0;
-					}
-				} else {
-					dev->acc_space += bit_duration;
-					if (dev->lastbit == 1) {
-						ite8709_add_read_queue(dev, 1,
-							dev->acc_pulse);
-						dev->acc_pulse = 0;
-					}
-				}
-				dev->lastbit = (data >> bit) & 1;
-			}
-		}
-		ite8709_write(dev, ITE8709_RFSR, 0);
-
-		if (dev->acc_space > CFG_TIMEOUT) {
-			dprintk("scheduling rearm IRQ\n");
-			do_gettimeofday(&dev->last_tv);
-			dev->force_rearm = 0;
-			tasklet_schedule(&dev->tasklet);
-		}
-
-		spin_unlock(&dev->hardware_lock);
-		return IRQ_RETVAL(IRQ_HANDLED);
-
-	default:
-		/* not our irq */
-		dprintk("unknown IRQ (shouldn't happen) !!\n");
-		spin_unlock(&dev->hardware_lock);
-		return IRQ_RETVAL(IRQ_NONE);
-	}
-}
-
-static void ite8709_rearm_irq(unsigned long data)
-{
-	struct ite8709_device *dev;
-	unsigned long flags;
-	dev = (struct ite8709_device *) data;
-
-	spin_lock_irqsave(&dev->hardware_lock, flags);
-	dev->device_busy = 1;
-	spin_unlock_irqrestore(&dev->hardware_lock, flags);
-
-	if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) {
-		dprintk("rearming IRQ\n");
-		ite8709_write_register(dev, IT8512_REG_RCR,
-						IT8512_RCR_RXACT | CFG_DCR);
-		ite8709_write_register(dev, IT8512_REG_MSTCR,
-					CFG_FIFOTL | IT8512_MSTCR_FIFOCLR);
-		ite8709_write_register(dev, IT8512_REG_RCR,
-				IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR);
-		if (!dev->force_rearm)
-			dev->rearmed = 1;
-		dev->force_rearm = 0;
-	}
-
-	spin_lock_irqsave(&dev->hardware_lock, flags);
-	dev->device_busy = 0;
-	spin_unlock_irqrestore(&dev->hardware_lock, flags);
-}
-
-static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno,
-				char *msg)
-{
-	if (msg != NULL)
-		printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg);
-
-	switch (stage) {
-	case 6:
-		if (dev->use_count > 0)
-			ite8709_drop_hardware(dev);
-	case 5:
-		free_irq(dev->irq, dev);
-	case 4:
-		release_region(dev->io, 2);
-	case 3:
-		lirc_unregister_driver(dev->driver.minor);
-	case 2:
-		lirc_buffer_free(dev->driver.rbuf);
-		kfree(dev->driver.rbuf);
-	case 1:
-		kfree(dev);
-	case 0:
-		;
-	}
-
-	return errno;
-}
-
-static int __devinit ite8709_pnp_probe(struct pnp_dev *dev,
-					const struct pnp_device_id *dev_id)
-{
-	struct lirc_driver *driver;
-	struct ite8709_device *ite8709_dev;
-	int ret;
-
-	/* Check resources validity */
-	if (!pnp_irq_valid(dev, 0))
-		return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ");
-	if (!pnp_port_valid(dev, 2))
-		return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port");
-
-	/* Allocate memory for device struct */
-	ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL);
-	if (ite8709_dev == NULL)
-		return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed");
-	pnp_set_drvdata(dev, ite8709_dev);
-
-	/* Initialize device struct */
-	ite8709_dev->use_count = 0;
-	ite8709_dev->irq = pnp_irq(dev, 0);
-	ite8709_dev->io = pnp_port_start(dev, 2);
-	ite8709_dev->hardware_lock =
-		__SPIN_LOCK_UNLOCKED(ite8709_dev->hardware_lock);
-	ite8709_dev->acc_pulse = 0;
-	ite8709_dev->acc_space = 0;
-	ite8709_dev->lastbit = 0;
-	do_gettimeofday(&ite8709_dev->last_tv);
-	tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq,
-							(long) ite8709_dev);
-	ite8709_dev->force_rearm = 0;
-	ite8709_dev->rearmed = 0;
-	ite8709_dev->device_busy = 0;
-
-	/* Initialize driver struct */
-	driver = &ite8709_dev->driver;
-	strcpy(driver->name, LIRC_DRIVER_NAME);
-	driver->minor = -1;
-	driver->code_length = sizeof(int) * 8;
-	driver->sample_rate = 0;
-	driver->features = LIRC_CAN_REC_MODE2;
-	driver->data = ite8709_dev;
-	driver->add_to_buf = NULL;
-	driver->set_use_inc = ite8709_set_use_inc;
-	driver->set_use_dec = ite8709_set_use_dec;
-	driver->dev = &dev->dev;
-	driver->owner = THIS_MODULE;
-
-	/* Initialize LIRC buffer */
-	driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-	if (!driver->rbuf)
-		return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
-				       "can't allocate lirc_buffer");
-	if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE))
-		return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
-				       "lirc_buffer_init() failed");
-
-	/* Register LIRC driver */
-	ret = lirc_register_driver(driver);
-	if (ret < 0)
-		return ite8709_cleanup(ite8709_dev, 2, ret,
-					"lirc_register_driver() failed");
-
-	/* Reserve I/O port access */
-	if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME))
-		return ite8709_cleanup(ite8709_dev, 3, -EBUSY,
-						"i/o port already in use");
-
-	/* Reserve IRQ line */
-	ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0,
-					LIRC_DRIVER_NAME, ite8709_dev);
-	if (ret < 0)
-		return ite8709_cleanup(ite8709_dev, 4, ret,
-						"IRQ already in use");
-
-	/* Initialize hardware */
-	ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */
-
-	printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n",
-					ite8709_dev->irq, ite8709_dev->io);
-
-	return 0;
-}
-
-static void __devexit ite8709_pnp_remove(struct pnp_dev *dev)
-{
-	struct ite8709_device *ite8709_dev;
-	ite8709_dev = pnp_get_drvdata(dev);
-
-	ite8709_cleanup(ite8709_dev, 6, 0, NULL);
-
-	printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n");
-}
-
-#ifdef CONFIG_PM
-static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state)
-{
-	struct ite8709_device *ite8709_dev;
-	ite8709_dev = pnp_get_drvdata(dev);
-
-	if (ite8709_dev->use_count > 0)
-		ite8709_drop_hardware(ite8709_dev);
-
-	return 0;
-}
-
-static int ite8709_pnp_resume(struct pnp_dev *dev)
-{
-	struct ite8709_device *ite8709_dev;
-	ite8709_dev = pnp_get_drvdata(dev);
-
-	if (ite8709_dev->use_count > 0)
-		ite8709_init_hardware(ite8709_dev);
-
-	return 0;
-}
-#else
-#define ite8709_pnp_suspend NULL
-#define ite8709_pnp_resume NULL
-#endif
-
-static const struct pnp_device_id pnp_dev_table[] = {
-	{"ITE8709", 0},
-	{}
-};
-
-MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-
-static struct pnp_driver ite8709_pnp_driver = {
-	.name           = LIRC_DRIVER_NAME,
-	.probe          = ite8709_pnp_probe,
-	.remove         = __devexit_p(ite8709_pnp_remove),
-	.suspend        = ite8709_pnp_suspend,
-	.resume         = ite8709_pnp_resume,
-	.id_table       = pnp_dev_table,
-};
-
-static int __init ite8709_init_module(void)
-{
-	return pnp_register_driver(&ite8709_pnp_driver);
-}
-module_init(ite8709_init_module);
-
-static void __exit ite8709_cleanup_module(void)
-{
-	pnp_unregister_driver(&ite8709_pnp_driver);
-}
-module_exit(ite8709_cleanup_module);
-
-MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port");
-MODULE_AUTHOR("Grégory Lardière");
-MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c
index 925eabe..63a438d 100644
--- a/drivers/staging/lirc/lirc_sasem.c
+++ b/drivers/staging/lirc/lirc_sasem.c
@@ -364,7 +364,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
 	int i;
 	int retval = 0;
 	struct sasem_context *context;
-	int *data_buf;
+	int *data_buf = NULL;
 
 	context = (struct sasem_context *) file->private_data;
 	if (!context) {
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
index 0aad0d7..dd6a57c 100644
--- a/drivers/staging/lirc/lirc_zilog.c
+++ b/drivers/staging/lirc/lirc_zilog.c
@@ -63,14 +63,16 @@
 #include <media/lirc_dev.h>
 #include <media/lirc.h>
 
+struct IR;
+
 struct IR_rx {
+	struct kref ref;
+	struct IR *ir;
+
 	/* RX device */
+	struct mutex client_lock;
 	struct i2c_client *c;
 
-	/* RX device buffer & lock */
-	struct lirc_buffer buf;
-	struct mutex buf_lock;
-
 	/* RX polling thread data */
 	struct task_struct *task;
 
@@ -80,7 +82,11 @@ struct IR_rx {
 };
 
 struct IR_tx {
+	struct kref ref;
+	struct IR *ir;
+
 	/* TX device */
+	struct mutex client_lock;
 	struct i2c_client *c;
 
 	/* TX additional actions needed */
@@ -89,19 +95,34 @@ struct IR_tx {
 };
 
 struct IR {
+	struct kref ref;
+	struct list_head list;
+
+	/* FIXME spinlock access to l.features */
 	struct lirc_driver l;
+	struct lirc_buffer rbuf;
 
 	struct mutex ir_lock;
-	int open;
+	atomic_t open_count;
 
 	struct i2c_adapter *adapter;
+
+	spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */
 	struct IR_rx *rx;
+
+	spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */
 	struct IR_tx *tx;
 };
 
-/* Minor -> data mapping */
-static struct mutex ir_devices_lock;
-static struct IR *ir_devices[MAX_IRCTL_DEVICES];
+/* IR transceiver instance object list */
+/*
+ * This lock is used for the following:
+ * a. ir_devices_list access, insertions, deletions
+ * b. struct IR kref get()s and put()s
+ * c. serialization of ir_probe() for the two i2c_clients for a Z8
+ */
+static DEFINE_MUTEX(ir_devices_lock);
+static LIST_HEAD(ir_devices_list);
 
 /* Block size for IR transmitter */
 #define TX_BLOCK_SIZE	99
@@ -147,6 +168,157 @@ static int minor = -1;	/* minor number */
 				 ## args);				\
 	} while (0)
 
+
+/* struct IR reference counting */
+static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held)
+{
+	if (ir_devices_lock_held) {
+		kref_get(&ir->ref);
+	} else {
+		mutex_lock(&ir_devices_lock);
+		kref_get(&ir->ref);
+		mutex_unlock(&ir_devices_lock);
+	}
+	return ir;
+}
+
+static void release_ir_device(struct kref *ref)
+{
+	struct IR *ir = container_of(ref, struct IR, ref);
+
+	/*
+	 * Things should be in this state by now:
+	 * ir->rx set to NULL and deallocated - happens before ir->rx->ir put()
+	 * ir->rx->task kthread stopped - happens before ir->rx->ir put()
+	 * ir->tx set to NULL and deallocated - happens before ir->tx->ir put()
+	 * ir->open_count ==  0 - happens on final close()
+	 * ir_lock, tx_ref_lock, rx_ref_lock, all released
+	 */
+	if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) {
+		lirc_unregister_driver(ir->l.minor);
+		ir->l.minor = MAX_IRCTL_DEVICES;
+	}
+	if (ir->rbuf.fifo_initialized)
+		lirc_buffer_free(&ir->rbuf);
+	list_del(&ir->list);
+	kfree(ir);
+}
+
+static int put_ir_device(struct IR *ir, bool ir_devices_lock_held)
+{
+	int released;
+
+	if (ir_devices_lock_held)
+		return kref_put(&ir->ref, release_ir_device);
+
+	mutex_lock(&ir_devices_lock);
+	released = kref_put(&ir->ref, release_ir_device);
+	mutex_unlock(&ir_devices_lock);
+
+	return released;
+}
+
+/* struct IR_rx reference counting */
+static struct IR_rx *get_ir_rx(struct IR *ir)
+{
+	struct IR_rx *rx;
+
+	spin_lock(&ir->rx_ref_lock);
+	rx = ir->rx;
+	if (rx != NULL)
+		kref_get(&rx->ref);
+	spin_unlock(&ir->rx_ref_lock);
+	return rx;
+}
+
+static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held)
+{
+	/* end up polling thread */
+	if (!IS_ERR_OR_NULL(rx->task)) {
+		kthread_stop(rx->task);
+		rx->task = NULL;
+		/* Put the ir ptr that ir_probe() gave to the rx poll thread */
+		put_ir_device(rx->ir, ir_devices_lock_held);
+	}
+}
+
+static void release_ir_rx(struct kref *ref)
+{
+	struct IR_rx *rx = container_of(ref, struct IR_rx, ref);
+	struct IR *ir = rx->ir;
+
+	/*
+	 * This release function can't do all the work, as we want
+	 * to keep the rx_ref_lock a spinlock, and killing the poll thread
+	 * and releasing the ir reference can cause a sleep.  That work is
+	 * performed by put_ir_rx()
+	 */
+	ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
+	/* Don't put_ir_device(rx->ir) here; lock can't be freed yet */
+	ir->rx = NULL;
+	/* Don't do the kfree(rx) here; we still need to kill the poll thread */
+	return;
+}
+
+static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held)
+{
+	int released;
+	struct IR *ir = rx->ir;
+
+	spin_lock(&ir->rx_ref_lock);
+	released = kref_put(&rx->ref, release_ir_rx);
+	spin_unlock(&ir->rx_ref_lock);
+	/* Destroy the rx kthread while not holding the spinlock */
+	if (released) {
+		destroy_rx_kthread(rx, ir_devices_lock_held);
+		kfree(rx);
+		/* Make sure we're not still in a poll_table somewhere */
+		wake_up_interruptible(&ir->rbuf.wait_poll);
+	}
+	/* Do a reference put() for the rx->ir reference, if we released rx */
+	if (released)
+		put_ir_device(ir, ir_devices_lock_held);
+	return released;
+}
+
+/* struct IR_tx reference counting */
+static struct IR_tx *get_ir_tx(struct IR *ir)
+{
+	struct IR_tx *tx;
+
+	spin_lock(&ir->tx_ref_lock);
+	tx = ir->tx;
+	if (tx != NULL)
+		kref_get(&tx->ref);
+	spin_unlock(&ir->tx_ref_lock);
+	return tx;
+}
+
+static void release_ir_tx(struct kref *ref)
+{
+	struct IR_tx *tx = container_of(ref, struct IR_tx, ref);
+	struct IR *ir = tx->ir;
+
+	ir->l.features &= ~LIRC_CAN_SEND_PULSE;
+	/* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */
+	ir->tx = NULL;
+	kfree(tx);
+}
+
+static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held)
+{
+	int released;
+	struct IR *ir = tx->ir;
+
+	spin_lock(&ir->tx_ref_lock);
+	released = kref_put(&tx->ref, release_ir_tx);
+	spin_unlock(&ir->tx_ref_lock);
+	/* Do a reference put() for the tx->ir reference, if we released tx */
+	if (released)
+		put_ir_device(ir, ir_devices_lock_held);
+	return released;
+}
+
 static int add_to_buf(struct IR *ir)
 {
 	__u16 code;
@@ -156,23 +328,38 @@ static int add_to_buf(struct IR *ir)
 	int ret;
 	int failures = 0;
 	unsigned char sendbuf[1] = { 0 };
-	struct IR_rx *rx = ir->rx;
+	struct lirc_buffer *rbuf = ir->l.rbuf;
+	struct IR_rx *rx;
+	struct IR_tx *tx;
 
+	if (lirc_buffer_full(rbuf)) {
+		dprintk("buffer overflow\n");
+		return -EOVERFLOW;
+	}
+
+	rx = get_ir_rx(ir);
 	if (rx == NULL)
 		return -ENXIO;
 
-	if (lirc_buffer_full(&rx->buf)) {
-		dprintk("buffer overflow\n");
-		return -EOVERFLOW;
+	/* Ensure our rx->c i2c_client remains valid for the duration */
+	mutex_lock(&rx->client_lock);
+	if (rx->c == NULL) {
+		mutex_unlock(&rx->client_lock);
+		put_ir_rx(rx, false);
+		return -ENXIO;
 	}
 
+	tx = get_ir_tx(ir);
+
 	/*
 	 * service the device as long as it is returning
 	 * data and we have space
 	 */
 	do {
-		if (kthread_should_stop())
-			return -ENODATA;
+		if (kthread_should_stop()) {
+			ret = -ENODATA;
+			break;
+		}
 
 		/*
 		 * Lock i2c bus for the duration.  RX/TX chips interfere so
@@ -182,7 +369,8 @@ static int add_to_buf(struct IR *ir)
 
 		if (kthread_should_stop()) {
 			mutex_unlock(&ir->ir_lock);
-			return -ENODATA;
+			ret = -ENODATA;
+			break;
 		}
 
 		/*
@@ -196,7 +384,7 @@ static int add_to_buf(struct IR *ir)
 				mutex_unlock(&ir->ir_lock);
 				zilog_error("unable to read from the IR chip "
 					    "after 3 resets, giving up\n");
-				return ret;
+				break;
 			}
 
 			/* Looks like the chip crashed, reset it */
@@ -206,19 +394,23 @@ static int add_to_buf(struct IR *ir)
 			set_current_state(TASK_UNINTERRUPTIBLE);
 			if (kthread_should_stop()) {
 				mutex_unlock(&ir->ir_lock);
-				return -ENODATA;
+				ret = -ENODATA;
+				break;
 			}
 			schedule_timeout((100 * HZ + 999) / 1000);
-			ir->tx->need_boot = 1;
+			if (tx != NULL)
+				tx->need_boot = 1;
 
 			++failures;
 			mutex_unlock(&ir->ir_lock);
+			ret = 0;
 			continue;
 		}
 
 		if (kthread_should_stop()) {
 			mutex_unlock(&ir->ir_lock);
-			return -ENODATA;
+			ret = -ENODATA;
+			break;
 		}
 		ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf));
 		mutex_unlock(&ir->ir_lock);
@@ -234,12 +426,17 @@ static int add_to_buf(struct IR *ir)
 
 		/* key pressed ? */
 		if (rx->hdpvr_data_fmt) {
-			if (got_data && (keybuf[0] == 0x80))
-				return 0;
-			else if (got_data && (keybuf[0] == 0x00))
-				return -ENODATA;
-		} else if ((rx->b[0] & 0x80) == 0)
-			return got_data ? 0 : -ENODATA;
+			if (got_data && (keybuf[0] == 0x80)) {
+				ret = 0;
+				break;
+			} else if (got_data && (keybuf[0] == 0x00)) {
+				ret = -ENODATA;
+				break;
+			}
+		} else if ((rx->b[0] & 0x80) == 0) {
+			ret = got_data ? 0 : -ENODATA;
+			break;
+		}
 
 		/* look what we have */
 		code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2);
@@ -248,11 +445,16 @@ static int add_to_buf(struct IR *ir)
 		codes[1] = code & 0xff;
 
 		/* return it */
-		lirc_buffer_write(&rx->buf, codes);
+		lirc_buffer_write(rbuf, codes);
 		++got_data;
-	} while (!lirc_buffer_full(&rx->buf));
+		ret = 0;
+	} while (!lirc_buffer_full(rbuf));
 
-	return 0;
+	mutex_unlock(&rx->client_lock);
+	if (tx != NULL)
+		put_ir_tx(tx, false);
+	put_ir_rx(rx, false);
+	return ret;
 }
 
 /*
@@ -268,19 +470,19 @@ static int add_to_buf(struct IR *ir)
 static int lirc_thread(void *arg)
 {
 	struct IR *ir = arg;
-	struct IR_rx *rx = ir->rx;
+	struct lirc_buffer *rbuf = ir->l.rbuf;
 
 	dprintk("poll thread started\n");
 
 	while (!kthread_should_stop()) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
 		/* if device not opened, we can sleep half a second */
-		if (!ir->open) {
+		if (atomic_read(&ir->open_count) == 0) {
 			schedule_timeout(HZ/2);
 			continue;
 		}
 
+		set_current_state(TASK_INTERRUPTIBLE);
+
 		/*
 		 * This is ~113*2 + 24 + jitter (2*repeat gap + code length).
 		 * We use this interval as the chip resets every time you poll
@@ -295,7 +497,7 @@ static int lirc_thread(void *arg)
 		if (kthread_should_stop())
 			break;
 		if (!add_to_buf(ir))
-			wake_up_interruptible(&rx->buf.wait_poll);
+			wake_up_interruptible(&rbuf->wait_poll);
 	}
 
 	dprintk("poll thread ended\n");
@@ -304,34 +506,12 @@ static int lirc_thread(void *arg)
 
 static int set_use_inc(void *data)
 {
-	struct IR *ir = data;
-
-	if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0)
-		return -ENODEV;
-
-	/* lock bttv in memory while /dev/lirc is in use  */
-	/*
-	 * this is completely broken code. lirc_unregister_driver()
-	 * must be possible even when the device is open
-	 */
-	if (ir->rx != NULL)
-		i2c_use_client(ir->rx->c);
-	if (ir->tx != NULL)
-		i2c_use_client(ir->tx->c);
-
 	return 0;
 }
 
 static void set_use_dec(void *data)
 {
-	struct IR *ir = data;
-
-	if (ir->rx)
-		i2c_release_client(ir->rx->c);
-	if (ir->tx)
-		i2c_release_client(ir->tx->c);
-	if (ir->l.owner != NULL)
-		module_put(ir->l.owner);
+	return;
 }
 
 /* safe read of a uint32 (always network byte order) */
@@ -585,7 +765,7 @@ static int fw_load(struct IR_tx *tx)
 	}
 
 	/* Request codeset data file */
-	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &tx->c->dev);
+	ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev);
 	if (ret != 0) {
 		zilog_error("firmware haup-ir-blaster.bin not available "
 			    "(%d)\n", ret);
@@ -711,59 +891,32 @@ out:
 	return ret;
 }
 
-/* initialise the IR TX device */
-static int tx_init(struct IR_tx *tx)
-{
-	int ret;
-
-	/* Load 'firmware' */
-	ret = fw_load(tx);
-	if (ret != 0)
-		return ret;
-
-	/* Send boot block */
-	ret = send_boot_data(tx);
-	if (ret != 0)
-		return ret;
-	tx->need_boot = 0;
-
-	/* Looks good */
-	return 0;
-}
-
-/* do nothing stub to make LIRC happy */
-static loff_t lseek(struct file *filep, loff_t offset, int orig)
-{
-	return -ESPIPE;
-}
-
 /* copied from lirc_dev */
 static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos)
 {
 	struct IR *ir = filep->private_data;
-	struct IR_rx *rx = ir->rx;
-	int ret = 0, written = 0;
+	struct IR_rx *rx;
+	struct lirc_buffer *rbuf = ir->l.rbuf;
+	int ret = 0, written = 0, retries = 0;
+	unsigned int m;
 	DECLARE_WAITQUEUE(wait, current);
 
 	dprintk("read called\n");
-	if (rx == NULL)
-		return -ENODEV;
-
-	if (mutex_lock_interruptible(&rx->buf_lock))
-		return -ERESTARTSYS;
-
-	if (n % rx->buf.chunk_size) {
+	if (n % rbuf->chunk_size) {
 		dprintk("read result = -EINVAL\n");
-		mutex_unlock(&rx->buf_lock);
 		return -EINVAL;
 	}
 
+	rx = get_ir_rx(ir);
+	if (rx == NULL)
+		return -ENXIO;
+
 	/*
 	 * 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(&rx->buf.wait_poll, &wait);
+	add_wait_queue(&rbuf->wait_poll, &wait);
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	/*
@@ -771,7 +924,7 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos)
 	 * mode and 'copy_to_user' is happy, wait for data.
 	 */
 	while (written < n && ret == 0) {
-		if (lirc_buffer_empty(&rx->buf)) {
+		if (lirc_buffer_empty(rbuf)) {
 			/*
 			 * According to the read(2) man page, 'written' can be
 			 * returned as less than 'n', instead of blocking
@@ -791,20 +944,27 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos)
 			schedule();
 			set_current_state(TASK_INTERRUPTIBLE);
 		} else {
-			unsigned char buf[rx->buf.chunk_size];
-			lirc_buffer_read(&rx->buf, buf);
-			ret = copy_to_user((void *)outbuf+written, buf,
-					   rx->buf.chunk_size);
-			written += rx->buf.chunk_size;
+			unsigned char buf[rbuf->chunk_size];
+			m = lirc_buffer_read(rbuf, buf);
+			if (m == rbuf->chunk_size) {
+				ret = copy_to_user((void *)outbuf+written, buf,
+						   rbuf->chunk_size);
+				written += rbuf->chunk_size;
+			} else {
+				retries++;
+			}
+			if (retries >= 5) {
+				zilog_error("Buffer read failed!\n");
+				ret = -EIO;
+			}
 		}
 	}
 
-	remove_wait_queue(&rx->buf.wait_poll, &wait);
+	remove_wait_queue(&rbuf->wait_poll, &wait);
+	put_ir_rx(rx, false);
 	set_current_state(TASK_RUNNING);
-	mutex_unlock(&rx->buf_lock);
 
-	dprintk("read result = %s (%d)\n",
-		ret ? "-EFAULT" : "OK", ret);
+	dprintk("read result = %d (%s)\n", ret, ret ? "Error" : "OK");
 
 	return ret ? ret : written;
 }
@@ -931,17 +1091,27 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 			  loff_t *ppos)
 {
 	struct IR *ir = filep->private_data;
-	struct IR_tx *tx = ir->tx;
+	struct IR_tx *tx;
 	size_t i;
 	int failures = 0;
 
-	if (tx == NULL)
-		return -ENODEV;
-
 	/* Validate user parameters */
 	if (n % sizeof(int))
 		return -EINVAL;
 
+	/* Get a struct IR_tx reference */
+	tx = get_ir_tx(ir);
+	if (tx == NULL)
+		return -ENXIO;
+
+	/* Ensure our tx->c i2c_client remains valid for the duration */
+	mutex_lock(&tx->client_lock);
+	if (tx->c == NULL) {
+		mutex_unlock(&tx->client_lock);
+		put_ir_tx(tx, false);
+		return -ENXIO;
+	}
+
 	/* Lock i2c bus for the duration */
 	mutex_lock(&ir->ir_lock);
 
@@ -952,11 +1122,24 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 
 		if (copy_from_user(&command, buf + i, sizeof(command))) {
 			mutex_unlock(&ir->ir_lock);
+			mutex_unlock(&tx->client_lock);
+			put_ir_tx(tx, false);
 			return -EFAULT;
 		}
 
 		/* Send boot data first if required */
 		if (tx->need_boot == 1) {
+			/* Make sure we have the 'firmware' loaded, first */
+			ret = fw_load(tx);
+			if (ret != 0) {
+				mutex_unlock(&ir->ir_lock);
+				mutex_unlock(&tx->client_lock);
+				put_ir_tx(tx, false);
+				if (ret != -ENOMEM)
+					ret = -EIO;
+				return ret;
+			}
+			/* Prep the chip for transmitting codes */
 			ret = send_boot_data(tx);
 			if (ret == 0)
 				tx->need_boot = 0;
@@ -968,6 +1151,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 					    (unsigned)command & 0xFFFF);
 			if (ret == -EPROTO) {
 				mutex_unlock(&ir->ir_lock);
+				mutex_unlock(&tx->client_lock);
+				put_ir_tx(tx, false);
 				return ret;
 			}
 		}
@@ -985,6 +1170,8 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 				zilog_error("unable to send to the IR chip "
 					    "after 3 resets, giving up\n");
 				mutex_unlock(&ir->ir_lock);
+				mutex_unlock(&tx->client_lock);
+				put_ir_tx(tx, false);
 				return ret;
 			}
 			set_current_state(TASK_UNINTERRUPTIBLE);
@@ -998,6 +1185,11 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 	/* Release i2c bus */
 	mutex_unlock(&ir->ir_lock);
 
+	mutex_unlock(&tx->client_lock);
+
+	/* Give back our struct IR_tx reference */
+	put_ir_tx(tx, false);
+
 	/* All looks good */
 	return n;
 }
@@ -1006,23 +1198,32 @@ static ssize_t write(struct file *filep, const char *buf, size_t n,
 static unsigned int poll(struct file *filep, poll_table *wait)
 {
 	struct IR *ir = filep->private_data;
-	struct IR_rx *rx = ir->rx;
+	struct IR_rx *rx;
+	struct lirc_buffer *rbuf = ir->l.rbuf;
 	unsigned int ret;
 
 	dprintk("poll called\n");
-	if (rx == NULL)
-		return -ENODEV;
-
-	mutex_lock(&rx->buf_lock);
 
-	poll_wait(filep, &rx->buf.wait_poll, wait);
+	rx = get_ir_rx(ir);
+	if (rx == NULL) {
+		/*
+		 * Revisit this, if our poll function ever reports writeable
+		 * status for Tx
+		 */
+		dprintk("poll result = POLLERR\n");
+		return POLLERR;
+	}
 
-	dprintk("poll result = %s\n",
-		lirc_buffer_empty(&rx->buf) ? "0" : "POLLIN|POLLRDNORM");
+	/*
+	 * Add our lirc_buffer's wait_queue to the poll_table. A wake up on
+	 * that buffer's wait queue indicates we may have a new poll status.
+	 */
+	poll_wait(filep, &rbuf->wait_poll, wait);
 
-	ret = lirc_buffer_empty(&rx->buf) ? 0 : (POLLIN|POLLRDNORM);
+	/* Indicate what ops could happen immediately without blocking */
+	ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM);
 
-	mutex_unlock(&rx->buf_lock);
+	dprintk("poll result = %s\n", ret ? "POLLIN|POLLRDNORM" : "none");
 	return ret;
 }
 
@@ -1030,11 +1231,9 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
 	struct IR *ir = filep->private_data;
 	int result;
-	unsigned long mode, features = 0;
+	unsigned long mode, features;
 
-	features |= LIRC_CAN_SEND_PULSE;
-	if (ir->rx != NULL)
-		features |= LIRC_CAN_REC_LIRCCODE;
+	features = ir->l.features;
 
 	switch (cmd) {
 	case LIRC_GET_LENGTH:
@@ -1061,9 +1260,15 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 			result = -EINVAL;
 		break;
 	case LIRC_GET_SEND_MODE:
+		if (!(features&LIRC_CAN_SEND_MASK))
+			return -ENOSYS;
+
 		result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg);
 		break;
 	case LIRC_SET_SEND_MODE:
+		if (!(features&LIRC_CAN_SEND_MASK))
+			return -ENOSYS;
+
 		result = get_user(mode, (unsigned long *) arg);
 		if (!result && mode != LIRC_MODE_PULSE)
 			return -EINVAL;
@@ -1074,13 +1279,24 @@ static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 	return result;
 }
 
-/* ir_devices_lock must be held */
-static struct IR *find_ir_device_by_minor(unsigned int minor)
+static struct IR *get_ir_device_by_minor(unsigned int minor)
 {
-	if (minor >= MAX_IRCTL_DEVICES)
-		return NULL;
+	struct IR *ir;
+	struct IR *ret = NULL;
+
+	mutex_lock(&ir_devices_lock);
+
+	if (!list_empty(&ir_devices_list)) {
+		list_for_each_entry(ir, &ir_devices_list, list) {
+			if (ir->l.minor == minor) {
+				ret = get_ir_device(ir, true);
+				break;
+			}
+		}
+	}
 
-	return ir_devices[minor];
+	mutex_unlock(&ir_devices_lock);
+	return ret;
 }
 
 /*
@@ -1090,31 +1306,20 @@ static struct IR *find_ir_device_by_minor(unsigned int minor)
 static int open(struct inode *node, struct file *filep)
 {
 	struct IR *ir;
-	int ret;
 	unsigned int minor = MINOR(node->i_rdev);
 
 	/* find our IR struct */
-	mutex_lock(&ir_devices_lock);
-	ir = find_ir_device_by_minor(minor);
-	mutex_unlock(&ir_devices_lock);
+	ir = get_ir_device_by_minor(minor);
 
 	if (ir == NULL)
 		return -ENODEV;
 
-	/* increment in use count */
-	mutex_lock(&ir->ir_lock);
-	++ir->open;
-	ret = set_use_inc(ir);
-	if (ret != 0) {
-		--ir->open;
-		mutex_unlock(&ir->ir_lock);
-		return ret;
-	}
-	mutex_unlock(&ir->ir_lock);
+	atomic_inc(&ir->open_count);
 
 	/* stash our IR struct */
 	filep->private_data = ir;
 
+	nonseekable_open(node, filep);
 	return 0;
 }
 
@@ -1128,22 +1333,12 @@ static int close(struct inode *node, struct file *filep)
 		return -ENODEV;
 	}
 
-	/* decrement in use count */
-	mutex_lock(&ir->ir_lock);
-	--ir->open;
-	set_use_dec(ir);
-	mutex_unlock(&ir->ir_lock);
+	atomic_dec(&ir->open_count);
 
+	put_ir_device(ir, false);
 	return 0;
 }
 
-static struct lirc_driver lirc_template = {
-	.name		= "lirc_zilog",
-	.set_use_inc	= set_use_inc,
-	.set_use_dec	= set_use_dec,
-	.owner		= THIS_MODULE
-};
-
 static int ir_remove(struct i2c_client *client);
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
 
@@ -1170,7 +1365,7 @@ static struct i2c_driver driver = {
 
 static const struct file_operations lirc_fops = {
 	.owner		= THIS_MODULE,
-	.llseek		= lseek,
+	.llseek		= no_llseek,
 	.read		= read,
 	.write		= write,
 	.poll		= poll,
@@ -1182,97 +1377,64 @@ static const struct file_operations lirc_fops = {
 	.release	= close
 };
 
-static void destroy_rx_kthread(struct IR_rx *rx)
-{
-	/* end up polling thread */
-	if (rx != NULL && !IS_ERR_OR_NULL(rx->task)) {
-		kthread_stop(rx->task);
-		rx->task = NULL;
-	}
-}
+static struct lirc_driver lirc_template = {
+	.name		= "lirc_zilog",
+	.minor		= -1,
+	.code_length	= 13,
+	.buffer_size	= BUFLEN / 2,
+	.sample_rate	= 0, /* tell lirc_dev to not start its own kthread */
+	.chunk_size	= 2,
+	.set_use_inc	= set_use_inc,
+	.set_use_dec	= set_use_dec,
+	.fops		= &lirc_fops,
+	.owner		= THIS_MODULE,
+};
 
-/* ir_devices_lock must be held */
-static int add_ir_device(struct IR *ir)
+static int ir_remove(struct i2c_client *client)
 {
-	int i;
-
-	for (i = 0; i < MAX_IRCTL_DEVICES; i++)
-		if (ir_devices[i] == NULL) {
-			ir_devices[i] = ir;
-			break;
+	if (strncmp("ir_tx_z8", client->name, 8) == 0) {
+		struct IR_tx *tx = i2c_get_clientdata(client);
+		if (tx != NULL) {
+			mutex_lock(&tx->client_lock);
+			tx->c = NULL;
+			mutex_unlock(&tx->client_lock);
+			put_ir_tx(tx, false);
 		}
-
-	return i == MAX_IRCTL_DEVICES ? -ENOMEM : i;
-}
-
-/* ir_devices_lock must be held */
-static void del_ir_device(struct IR *ir)
-{
-	int i;
-
-	for (i = 0; i < MAX_IRCTL_DEVICES; i++)
-		if (ir_devices[i] == ir) {
-			ir_devices[i] = NULL;
-			break;
+	} else if (strncmp("ir_rx_z8", client->name, 8) == 0) {
+		struct IR_rx *rx = i2c_get_clientdata(client);
+		if (rx != NULL) {
+			mutex_lock(&rx->client_lock);
+			rx->c = NULL;
+			mutex_unlock(&rx->client_lock);
+			put_ir_rx(rx, false);
 		}
-}
-
-static int ir_remove(struct i2c_client *client)
-{
-	struct IR *ir = i2c_get_clientdata(client);
-
-	mutex_lock(&ir_devices_lock);
-
-	if (ir == NULL) {
-		/* We destroyed everything when the first client came through */
-		mutex_unlock(&ir_devices_lock);
-		return 0;
 	}
-
-	/* Good-bye LIRC */
-	lirc_unregister_driver(ir->l.minor);
-
-	/* Good-bye Rx */
-	destroy_rx_kthread(ir->rx);
-	if (ir->rx != NULL) {
-		if (ir->rx->buf.fifo_initialized)
-			lirc_buffer_free(&ir->rx->buf);
-		i2c_set_clientdata(ir->rx->c, NULL);
-		kfree(ir->rx);
-	}
-
-	/* Good-bye Tx */
-	i2c_set_clientdata(ir->tx->c, NULL);
-	kfree(ir->tx);
-
-	/* Good-bye IR */
-	del_ir_device(ir);
-	kfree(ir);
-
-	mutex_unlock(&ir_devices_lock);
 	return 0;
 }
 
 
 /* ir_devices_lock must be held */
-static struct IR *find_ir_device_by_adapter(struct i2c_adapter *adapter)
+static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter)
 {
-	int i;
-	struct IR *ir = NULL;
+	struct IR *ir;
 
-	for (i = 0; i < MAX_IRCTL_DEVICES; i++)
-		if (ir_devices[i] != NULL &&
-		    ir_devices[i]->adapter == adapter) {
-			ir = ir_devices[i];
-			break;
+	if (list_empty(&ir_devices_list))
+		return NULL;
+
+	list_for_each_entry(ir, &ir_devices_list, list)
+		if (ir->adapter == adapter) {
+			get_ir_device(ir, true);
+			return ir;
 		}
 
-	return ir;
+	return NULL;
 }
 
 static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct IR *ir;
+	struct IR_tx *tx;
+	struct IR_rx *rx;
 	struct i2c_adapter *adap = client->adapter;
 	int ret;
 	bool tx_probe = false;
@@ -1296,133 +1458,170 @@ static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	mutex_lock(&ir_devices_lock);
 
 	/* Use a single struct IR instance for both the Rx and Tx functions */
-	ir = find_ir_device_by_adapter(adap);
+	ir = get_ir_device_by_adapter(adap);
 	if (ir == NULL) {
 		ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
 		if (ir == NULL) {
 			ret = -ENOMEM;
 			goto out_no_ir;
 		}
+		kref_init(&ir->ref);
+
 		/* store for use in ir_probe() again, and open() later on */
-		ret = add_ir_device(ir);
-		if (ret)
-			goto out_free_ir;
+		INIT_LIST_HEAD(&ir->list);
+		list_add_tail(&ir->list, &ir_devices_list);
 
 		ir->adapter = adap;
 		mutex_init(&ir->ir_lock);
+		atomic_set(&ir->open_count, 0);
+		spin_lock_init(&ir->tx_ref_lock);
+		spin_lock_init(&ir->rx_ref_lock);
 
 		/* set lirc_dev stuff */
 		memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
-		ir->l.minor       = minor; /* module option */
-		ir->l.code_length = 13;
-		ir->l.rbuf	  = NULL;
-		ir->l.fops	  = &lirc_fops;
-		ir->l.data	  = ir;
-		ir->l.dev         = &adap->dev;
-		ir->l.sample_rate = 0;
+		/*
+		 * FIXME this is a pointer reference to us, but no refcount.
+		 *
+		 * This OK for now, since lirc_dev currently won't touch this
+		 * buffer as we provide our own lirc_fops.
+		 *
+		 * Currently our own lirc_fops rely on this ir->l.rbuf pointer
+		 */
+		ir->l.rbuf = &ir->rbuf;
+		ir->l.dev  = &adap->dev;
+		ret = lirc_buffer_init(ir->l.rbuf,
+				       ir->l.chunk_size, ir->l.buffer_size);
+		if (ret)
+			goto out_put_ir;
 	}
 
 	if (tx_probe) {
+		/* Get the IR_rx instance for later, if already allocated */
+		rx = get_ir_rx(ir);
+
 		/* Set up a struct IR_tx instance */
-		ir->tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL);
-		if (ir->tx == NULL) {
+		tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL);
+		if (tx == NULL) {
 			ret = -ENOMEM;
-			goto out_free_xx;
+			goto out_put_xx;
 		}
-
-		ir->tx->c = client;
-		ir->tx->need_boot = 1;
-		ir->tx->post_tx_ready_poll =
+		kref_init(&tx->ref);
+		ir->tx = tx;
+
+		ir->l.features |= LIRC_CAN_SEND_PULSE;
+		mutex_init(&tx->client_lock);
+		tx->c = client;
+		tx->need_boot = 1;
+		tx->post_tx_ready_poll =
 			       (id->driver_data & ID_FLAG_HDPVR) ? false : true;
+
+		/* An ir ref goes to the struct IR_tx instance */
+		tx->ir = get_ir_device(ir, true);
+
+		/* A tx ref goes to the i2c_client */
+		i2c_set_clientdata(client, get_ir_tx(ir));
+
+		/*
+		 * Load the 'firmware'.  We do this before registering with
+		 * lirc_dev, so the first firmware load attempt does not happen
+		 * after a open() or write() call on the device.
+		 *
+		 * Failure here is not deemed catastrophic, so the receiver will
+		 * still be usable.  Firmware load will be retried in write(),
+		 * if it is needed.
+		 */
+		fw_load(tx);
+
+		/* Proceed only if the Rx client is also ready or not needed */
+		if (rx == NULL && !tx_only) {
+			zilog_info("probe of IR Tx on %s (i2c-%d) done. Waiting"
+				   " on IR Rx.\n", adap->name, adap->nr);
+			goto out_ok;
+		}
 	} else {
+		/* Get the IR_tx instance for later, if already allocated */
+		tx = get_ir_tx(ir);
+
 		/* Set up a struct IR_rx instance */
-		ir->rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL);
-		if (ir->rx == NULL) {
+		rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL);
+		if (rx == NULL) {
 			ret = -ENOMEM;
-			goto out_free_xx;
+			goto out_put_xx;
 		}
+		kref_init(&rx->ref);
+		ir->rx = rx;
 
-		ret = lirc_buffer_init(&ir->rx->buf, 2, BUFLEN / 2);
-		if (ret)
-			goto out_free_xx;
-
-		mutex_init(&ir->rx->buf_lock);
-		ir->rx->c = client;
-		ir->rx->hdpvr_data_fmt =
+		ir->l.features |= LIRC_CAN_REC_LIRCCODE;
+		mutex_init(&rx->client_lock);
+		rx->c = client;
+		rx->hdpvr_data_fmt =
 			       (id->driver_data & ID_FLAG_HDPVR) ? true : false;
 
-		/* set lirc_dev stuff */
-		ir->l.rbuf = &ir->rx->buf;
-	}
-
-	i2c_set_clientdata(client, ir);
+		/* An ir ref goes to the struct IR_rx instance */
+		rx->ir = get_ir_device(ir, true);
 
-	/* Proceed only if we have the required Tx and Rx clients ready to go */
-	if (ir->tx == NULL ||
-	    (ir->rx == NULL && !tx_only)) {
-		zilog_info("probe of IR %s on %s (i2c-%d) done. Waiting on "
-			   "IR %s.\n", tx_probe ? "Tx" : "Rx", adap->name,
-			   adap->nr, tx_probe ? "Rx" : "Tx");
-		goto out_ok;
-	}
+		/* An rx ref goes to the i2c_client */
+		i2c_set_clientdata(client, get_ir_rx(ir));
 
-	/* initialise RX device */
-	if (ir->rx != NULL) {
-		/* try to fire up polling thread */
-		ir->rx->task = kthread_run(lirc_thread, ir,
-					   "zilog-rx-i2c-%d", adap->nr);
-		if (IS_ERR(ir->rx->task)) {
-			ret = PTR_ERR(ir->rx->task);
+		/*
+		 * Start the polling thread.
+		 * It will only perform an empty loop around schedule_timeout()
+		 * until we register with lirc_dev and the first user open()
+		 */
+		/* An ir ref goes to the new rx polling kthread */
+		rx->task = kthread_run(lirc_thread, get_ir_device(ir, true),
+				       "zilog-rx-i2c-%d", adap->nr);
+		if (IS_ERR(rx->task)) {
+			ret = PTR_ERR(rx->task);
 			zilog_error("%s: could not start IR Rx polling thread"
 				    "\n", __func__);
-			goto out_free_xx;
+			/* Failed kthread, so put back the ir ref */
+			put_ir_device(ir, true);
+			/* Failure exit, so put back rx ref from i2c_client */
+			i2c_set_clientdata(client, NULL);
+			put_ir_rx(rx, true);
+			ir->l.features &= ~LIRC_CAN_REC_LIRCCODE;
+			goto out_put_xx;
+		}
+
+		/* Proceed only if the Tx client is also ready */
+		if (tx == NULL) {
+			zilog_info("probe of IR Rx on %s (i2c-%d) done. Waiting"
+				   " on IR Tx.\n", adap->name, adap->nr);
+			goto out_ok;
 		}
 	}
 
 	/* register with lirc */
+	ir->l.minor = minor; /* module option: user requested minor number */
 	ir->l.minor = lirc_register_driver(&ir->l);
 	if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
 		zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n",
 			    __func__, MAX_IRCTL_DEVICES-1, ir->l.minor);
 		ret = -EBADRQC;
-		goto out_free_thread;
+		goto out_put_xx;
 	}
+	zilog_info("IR unit on %s (i2c-%d) registered as lirc%d and ready\n",
+		   adap->name, adap->nr, ir->l.minor);
 
-	/*
-	 * if we have the tx device, load the 'firmware'.  We do this
-	 * after registering with lirc as otherwise hotplug seems to take
-	 * 10s to create the lirc device.
-	 */
-	ret = tx_init(ir->tx);
-	if (ret != 0)
-		goto out_unregister;
-
-	zilog_info("probe of IR %s on %s (i2c-%d) done. IR unit ready.\n",
-		   tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
 out_ok:
+	if (rx != NULL)
+		put_ir_rx(rx, true);
+	if (tx != NULL)
+		put_ir_tx(tx, true);
+	put_ir_device(ir, true);
+	zilog_info("probe of IR %s on %s (i2c-%d) done\n",
+		   tx_probe ? "Tx" : "Rx", adap->name, adap->nr);
 	mutex_unlock(&ir_devices_lock);
 	return 0;
 
-out_unregister:
-	lirc_unregister_driver(ir->l.minor);
-out_free_thread:
-	destroy_rx_kthread(ir->rx);
-out_free_xx:
-	if (ir->rx != NULL) {
-		if (ir->rx->buf.fifo_initialized)
-			lirc_buffer_free(&ir->rx->buf);
-		if (ir->rx->c != NULL)
-			i2c_set_clientdata(ir->rx->c, NULL);
-		kfree(ir->rx);
-	}
-	if (ir->tx != NULL) {
-		if (ir->tx->c != NULL)
-			i2c_set_clientdata(ir->tx->c, NULL);
-		kfree(ir->tx);
-	}
-out_free_ir:
-	del_ir_device(ir);
-	kfree(ir);
+out_put_xx:
+	if (rx != NULL)
+		put_ir_rx(rx, true);
+	if (tx != NULL)
+		put_ir_tx(tx, true);
+out_put_ir:
+	put_ir_device(ir, true);
 out_no_ir:
 	zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n",
 		    __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr,
@@ -1438,7 +1637,6 @@ static int __init zilog_init(void)
 	zilog_notify("Zilog/Hauppauge IR driver initializing\n");
 
 	mutex_init(&tx_data_lock);
-	mutex_init(&ir_devices_lock);
 
 	request_module("firmware_class");
 
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index d843afc..9184751 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -94,7 +94,7 @@ void rc_map_init(void);
 #define RC_MAP_GADMEI_RM008Z             "rc-gadmei-rm008z"
 #define RC_MAP_GENIUS_TVGO_A11MCE        "rc-genius-tvgo-a11mce"
 #define RC_MAP_GOTVIEW7135               "rc-gotview7135"
-#define RC_MAP_HAUPPAUGE_NEW             "rc-hauppauge-new"
+#define RC_MAP_HAUPPAUGE_NEW             "rc-hauppauge"
 #define RC_MAP_IMON_MCE                  "rc-imon-mce"
 #define RC_MAP_IMON_PAD                  "rc-imon-pad"
 #define RC_MAP_IODATA_BCTV7E             "rc-iodata-bctv7e"
@@ -125,7 +125,7 @@ void rc_map_init(void);
 #define RC_MAP_PROTEUS_2309              "rc-proteus-2309"
 #define RC_MAP_PURPLETV                  "rc-purpletv"
 #define RC_MAP_PV951                     "rc-pv951"
-#define RC_MAP_RC5_HAUPPAUGE_NEW         "rc-rc5-hauppauge-new"
+#define RC_MAP_HAUPPAUGE                 "rc-hauppauge"
 #define RC_MAP_RC5_TV                    "rc-rc5-tv"
 #define RC_MAP_RC6_MCE                   "rc-rc6-mce"
 #define RC_MAP_REAL_AUDIO_220_32_KEYS    "rc-real-audio-220-32-keys"
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 6e96b26..f80b537 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -30,6 +30,8 @@ struct soc_camera_device {
 	struct device *pdev;		/* Platform device */
 	s32 user_width;
 	s32 user_height;
+	u32 bytesperline;		/* for padding, zero if unused */
+	u32 sizeimage;
 	enum v4l2_colorspace colorspace;
 	unsigned char iface;		/* Host number */
 	unsigned char devnum;		/* Device number per host */