]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 16:35:11 +0000 (09:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 28 Oct 2010 16:35:11 +0000 (09:35 -0700)
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (505 commits)
  [media] af9015: Fix max I2C message size when used with tda18271
  [media] IR: initialize ir_raw_event in few more drivers
  [media] Guard a divide in v4l1 compat layer
  [media] imon: fix nomouse modprobe option
  [media] imon: remove redundant change_protocol call
  [media] imon: fix my egregious brown paper bag w/rdev/idev split
  [media] cafe_ccic: Configure ov7670 correctly
  [media] ov7670: allow configuration of image size, clock speed, and I/O method
  [media] af9015: support for DigitalNow TinyTwin v3 [1f4d:9016]
  [media] af9015: map DigitalNow TinyTwin v2 remote
  [media] DigitalNow TinyTwin remote controller
  [media] af9015: RC fixes and improvements
  videodev2.h.xml: Update to reflect the latest changes at videodev2.h
  [media] v4l: document new Bayer and monochrome pixel formats
  [media] DocBook/v4l: Add missing formats used on gspca cpia1 and sn9c2028
  [media] firedtv: add parameter to fake ca_system_ids in CA_INFO
  [media] tm6000: fix a macro coding style issue
  tm6000: Remove some ugly debug code
  [media] Nova-S-Plus audio line input
  [media] [RFC,1/1] V4L2: Use new CAP bits in existing RDS capable drivers
  ...

32 files changed:
1  2 
Documentation/devices.txt
Documentation/feature-removal-schedule.txt
arch/arm/mach-mx3/mach-pcm037.c
arch/arm/mach-pxa/em-x270.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-pxa/mioa701.c
arch/sh/boards/mach-ecovec24/setup.c
drivers/media/IR/imon.c
drivers/media/IR/ir-keytable.c
drivers/media/IR/ir-lirc-codec.c
drivers/media/IR/lirc_dev.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/dvb/ttpci/av7110_av.c
drivers/media/dvb/ttpci/budget-core.c
drivers/media/video/Kconfig
drivers/media/video/cafe_ccic.c
drivers/media/video/cx23885/cx23885-417.c
drivers/media/video/cx88/cx88-blackbird.c
drivers/media/video/mxb.c
drivers/media/video/zoran/zoran_driver.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/cx25821/Kconfig
drivers/staging/go7007/Kconfig
drivers/staging/lirc/lirc_it87.c
drivers/staging/lirc/lirc_serial.c
drivers/staging/lirc/lirc_sir.c
drivers/video/via/accel.c
drivers/video/via/via-core.c
include/linux/Kbuild
include/media/rc-map.h

index 170cc1e7e135d083d52595bda54cb35d09aff1a8,76b1d2f22b6aef97b142e4828c4db92357309f12..eccffe715229433e912067440e85492e10d4ffa3
@@@ -239,7 -239,6 +239,7 @@@ Your cooperation is appreciated
                  0 = /dev/tty          Current TTY device
                  1 = /dev/console      System console
                  2 = /dev/ptmx         PTY master multiplex
 +                3 = /dev/ttyprintk    User messages via printk TTY device
                 64 = /dev/cua0         Callout device for ttyS0
                    ...
                255 = /dev/cua191       Callout device for ttyS191
                 64 = /dev/radio0       Radio device
                    ...
                127 = /dev/radio63      Radio device
-               192 = /dev/vtx0         Teletext device
-                   ...
-               223 = /dev/vtx31        Teletext device
                224 = /dev/vbi0         Vertical blank interrupt
                    ...
                255 = /dev/vbi31        Vertical blank interrupt
                  8 = /dev/mmcblk1      Second SD/MMC card
                    ...
  
 +              The start of next SD/MMC card can be configured with
 +              CONFIG_MMC_BLOCK_MINORS, or overridden at boot/modprobe
 +              time using the mmcblk.perdev_minors option. That would
 +              bump the offset between each card to be the configured
 +              value instead of the default 8.
 +
  179 char      CCube DVXChip-based PCI products
                  0 = /dev/dvxirq0      First DVX device
                  1 = /dev/dvxirq1      Second DVX device
                175 = /dev/usb/legousbtower15   16th USB Legotower device
                176 = /dev/usb/usbtmc1  First USB TMC device
                   ...
 -              192 = /dev/usb/usbtmc16 16th USB TMC device
 +              191 = /dev/usb/usbtmc16 16th USB TMC device
 +              192 = /dev/usb/yurex1   First USB Yurex device
 +                 ...
 +              209 = /dev/usb/yurex16  16th USB Yurex device
                240 = /dev/usb/dabusb0  First daubusb device
                    ...
                243 = /dev/usb/dabusb3  Fourth dabusb device
index f3da8c0a3af21ca7b2d958e415f9e83ceae01f7f,d87ee1760e3aaf83294d0dd316904189f57e607e..d8f36f984faa517c84883f625a93ee45a3f91dcc
@@@ -98,7 -98,7 +98,7 @@@ Who:  Pavel Machek <pavel@ucw.cz
  ---------------------------
  
  What: Video4Linux API 1 ioctls and from Video devices.
- When: July 2009
+ When: kernel 2.6.38
  Files:        include/linux/videodev.h
  Check:        include/linux/videodev.h
  Why:  V4L1 AP1 was replaced by V4L2 API during migration from 2.4 to 2.6
@@@ -116,6 -116,21 +116,21 @@@ Who:     Mauro Carvalho Chehab <mchehab@inf
  
  ---------------------------
  
+ What: Video4Linux obsolete drivers using V4L1 API
+ When: kernel 2.6.38
+ Files:        drivers/staging/cpia/* drivers/staging/stradis/*
+ Check:        drivers/staging/cpia/cpia.c drivers/staging/stradis/stradis.c
+ Why:  There are some drivers still using V4L1 API, despite all efforts we've done
+       to migrate. Those drivers are for obsolete hardware that the old maintainer
+       didn't care (or not have the hardware anymore), and that no other developer
+       could find any hardware to buy. They probably have no practical usage today,
+       and people with such old hardware could probably keep using an older version
+       of the kernel. Those drivers will be moved to staging on 2.6.37 and, if nobody
+       care enough to port and test them with V4L2 API, they'll be removed on 2.6.38.
+ Who:  Mauro Carvalho Chehab <mchehab@infradead.org>
+ ---------------------------
  What: sys_sysctl
  When: September 2010
  Option: CONFIG_SYSCTL_SYSCALL
@@@ -386,6 -401,34 +401,6 @@@ Who:      Tejun Heo <tj@kernel.org
  
  ----------------------------
  
 -What: Support for VMware's guest paravirtuliazation technique [VMI] will be
 -      dropped.
 -When: 2.6.37 or earlier.
 -Why:  With the recent innovations in CPU hardware acceleration technologies
 -      from Intel and AMD, VMware ran a few experiments to compare these
 -      techniques to guest paravirtualization technique on VMware's platform.
 -      These hardware assisted virtualization techniques have outperformed the
 -      performance benefits provided by VMI in most of the workloads. VMware
 -      expects that these hardware features will be ubiquitous in a couple of
 -      years, as a result, VMware has started a phased retirement of this
 -      feature from the hypervisor. We will be removing this feature from the
 -      Kernel too. Right now we are targeting 2.6.37 but can retire earlier if
 -      technical reasons (read opportunity to remove major chunk of pvops)
 -      arise.
 -
 -      Please note that VMI has always been an optimization and non-VMI kernels
 -      still work fine on VMware's platform.
 -      Latest versions of VMware's product which support VMI are,
 -      Workstation 7.0 and VSphere 4.0 on ESX side, future maintainence
 -      releases for these products will continue supporting VMI.
 -
 -      For more details about VMI retirement take a look at this,
 -      http://blogs.vmware.com/guestosguide/2009/09/vmi-retirement.html
 -
 -Who:  Alok N Kataria <akataria@vmware.com>
 -
 -----------------------------
 -
  What: Support for lcd_switch and display_get in asus-laptop driver
  When: March 2010
  Why:  These two features use non-standard interfaces. There are the
@@@ -470,29 -513,6 +485,6 @@@ When:     April 201
  Why:  Superseded by xt_CT
  Who:  Netfilter developer team <netfilter-devel@vger.kernel.org>
  
- ---------------------------
- What: video4linux /dev/vtx teletext API support
- When: 2.6.35
- Files:        drivers/media/video/saa5246a.c drivers/media/video/saa5249.c
-       include/linux/videotext.h
- Why:  The vtx device nodes have been superseded by vbi device nodes
-       for many years. No applications exist that use the vtx support.
-       Of the two i2c drivers that actually support this API the saa5249
-       has been impossible to use for a year now and no known hardware
-       that supports this device exists. The saa5246a is theoretically
-       supported by the old mxb boards, but it never actually worked.
-       In summary: there is no hardware that can use this API and there
-       are no applications actually implementing this API.
-       The vtx support still reserves minors 192-223 and we would really
-       like to reuse those for upcoming new functionality. In the unlikely
-       event that new hardware appears that wants to use the functionality
-       provided by the vtx API, then that functionality should be build
-       around the sliced VBI API instead.
- Who:  Hans Verkuil <hverkuil@xs4all.nl>
  ----------------------------
  
  What: IRQF_DISABLED
@@@ -502,6 -522,16 +494,6 @@@ Who:      Thomas Gleixner <tglx@linutronix.d
  
  ----------------------------
  
 -What: old ieee1394 subsystem (CONFIG_IEEE1394)
 -When: 2.6.37
 -Files:        drivers/ieee1394/ except init_ohci1394_dma.c
 -Why:  superseded by drivers/firewire/ (CONFIG_FIREWIRE) which offers more
 -      features, better performance, and better security, all with smaller
 -      and more modern code base
 -Who:  Stefan Richter <stefanr@s5r6.in-berlin.de>
 -
 -----------------------------
 -
  What: The acpi_sleep=s4_nonvs command line option
  When: 2.6.37
  Files:        arch/x86/kernel/acpi/sleep.c
@@@ -526,39 -556,3 +518,39 @@@ Who:     FUJITA Tomonori <fujita.tomonori@l
  
  ----------------------------
  
 +What:   namespace cgroup (ns_cgroup)
 +When:   2.6.38
 +Why:    The ns_cgroup leads to some problems:
 +      * cgroup creation is out-of-control
 +      * cgroup name can conflict when pids are looping
 +      * it is not possible to have a single process handling
 +      a lot of namespaces without falling in a exponential creation time
 +      * we may want to create a namespace without creating a cgroup
 +
 +      The ns_cgroup is replaced by a compatibility flag 'clone_children',
 +      where a newly created cgroup will copy the parent cgroup values.
 +      The userspace has to manually create a cgroup and add a task to
 +      the 'tasks' file.
 +Who:    Daniel Lezcano <daniel.lezcano@free.fr>
 +
 +----------------------------
 +
 +What: iwlwifi disable_hw_scan module parameters
 +When: 2.6.40
 +Why:  Hareware scan is the prefer method for iwlwifi devices for
 +      scanning operation. Remove software scan support for all the
 +      iwlwifi devices.
 +
 +Who:  Wey-Yi Guy <wey-yi.w.guy@intel.com>
 +
 +----------------------------
 +
 +What:   access to nfsd auth cache through sys_nfsservctl or '.' files
 +        in the 'nfsd' filesystem.
 +When:   2.6.40
 +Why:    This is a legacy interface which have been replaced by a more
 +        dynamic cache.  Continuing to maintain this interface is an
 +        unnecessary burden.
 +Who:    NeilBrown <neilb@suse.de>
 +
 +----------------------------
index 86e86c1300d5525352ed8d2b3dee50162eef89d9,b32889798337270b7bd02d3e4430a52b6b3f5bc8..2ff3f661a48e1dd02c6c608d57f87a473ea2bf5e
@@@ -311,7 -311,6 +311,6 @@@ static struct soc_camera_link iclink_mt
        .bus_id         = 0,            /* Must match with the camera ID */
        .board_info     = &pcm037_i2c_camera[1],
        .i2c_adapter_id = 2,
-       .module_name    = "mt9v022",
  };
  
  static struct soc_camera_link iclink_mt9t031 = {
        .power          = pcm037_camera_power,
        .board_info     = &pcm037_i2c_camera[0],
        .i2c_adapter_id = 2,
-       .module_name    = "mt9t031",
  };
  
  static struct i2c_board_info pcm037_i2c_devices[] = {
@@@ -680,6 -678,8 +678,6 @@@ struct sys_timer pcm037_timer = 
  
  MACHINE_START(PCM037, "Phytec Phycore pcm037")
        /* Maintainer: Pengutronix */
 -      .phys_io        = MX31_AIPS1_BASE_ADDR,
 -      .io_pg_offst    = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
        .boot_params    = MX3x_PHYS_OFFSET + 0x100,
        .map_io         = mx31_map_io,
        .init_irq       = mx31_init_irq,
index ab48bb81b570d518f8a84f419ed2e85a857e3c13,0c95476c791d9711b832ca60c212e36054e903bf..ed0dbfdb22ed8c0bba1fe048c46151dddcf4482e
@@@ -43,7 -43,7 +43,7 @@@
  #include <mach/pxafb.h>
  #include <mach/ohci.h>
  #include <mach/mmc.h>
 -#include <mach/pxa27x_keypad.h>
 +#include <plat/pxa27x_keypad.h>
  #include <plat/i2c.h>
  #include <mach/camera.h>
  #include <mach/pxa2xx_spi.h>
@@@ -1015,7 -1015,6 +1015,6 @@@ static struct soc_camera_link iclink = 
        .power          = em_x270_sensor_power,
        .board_info     = &em_x270_i2c_cam_info[0],
        .i2c_adapter_id = 0,
-       .module_name    = "mt9m111",
  };
  
  static struct platform_device em_x270_camera = {
@@@ -1301,6 -1300,8 +1300,6 @@@ static void __init em_x270_init(void
  
  MACHINE_START(EM_X270, "Compulab EM-X270")
        .boot_params    = 0xa0000100,
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
@@@ -1309,6 -1310,8 +1308,6 @@@ MACHINE_EN
  
  MACHINE_START(EXEDA, "Compulab eXeda")
        .boot_params    = 0xa0000100,
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .map_io         = pxa_map_io,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
diff --combined arch/arm/mach-pxa/ezx.c
index 80a9352d43f31017c26a079d29849bb0840beff7,70dfe0867ef2836b51d45f276fac53cc595d2612..142c711f4cda0118e4c4aaed5099c7ff6e26ae7d
  #include <mach/ohci.h>
  #include <plat/i2c.h>
  #include <mach/hardware.h>
 -#include <mach/pxa27x_keypad.h>
 +#include <plat/pxa27x_keypad.h>
  #include <mach/camera.h>
  
  #include "devices.h"
  #include "generic.h"
  
 +#define EZX_NR_IRQS                   (IRQ_BOARD_START + 24)
 +
  #define GPIO12_A780_FLIP_LID          12
  #define GPIO15_A1200_FLIP_LID                 15
  #define GPIO15_A910_FLIP_LID          15
@@@ -755,7 -753,6 +755,6 @@@ static struct soc_camera_link a780_icli
        .flags          = SOCAM_SENSOR_INVERT_PCLK,
        .i2c_adapter_id = 0,
        .board_info     = &a780_camera_i2c_board_info,
-       .module_name    = "mt9m111",
        .power          = a780_camera_power,
        .reset          = a780_camera_reset,
  };
@@@ -798,9 -795,10 +797,9 @@@ static void __init a780_init(void
  }
  
  MACHINE_START(EZX_A780, "Motorola EZX A780")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a780_init,
@@@ -863,9 -861,10 +862,9 @@@ static void __init e680_init(void
  }
  
  MACHINE_START(EZX_E680, "Motorola EZX E680")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e680_init,
@@@ -928,9 -927,10 +927,9 @@@ static void __init a1200_init(void
  }
  
  MACHINE_START(EZX_A1200, "Motorola EZX A1200")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a1200_init,
@@@ -1024,7 -1024,6 +1023,6 @@@ static struct soc_camera_link a910_icli
        .bus_id         = 0,
        .i2c_adapter_id = 0,
        .board_info     = &a910_camera_i2c_board_info,
-       .module_name    = "mt9m111",
        .power          = a910_camera_power,
        .reset          = a910_camera_reset,
  };
@@@ -1119,9 -1118,10 +1117,9 @@@ static void __init a910_init(void
  }
  
  MACHINE_START(EZX_A910, "Motorola EZX A910")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = a910_init,
@@@ -1184,9 -1184,10 +1182,9 @@@ static void __init e6_init(void
  }
  
  MACHINE_START(EZX_E6, "Motorola EZX E6")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e6_init,
@@@ -1223,9 -1224,10 +1221,9 @@@ static void __init e2_init(void
  }
  
  MACHINE_START(EZX_E2, "Motorola EZX E2")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = pxa_map_io,
 +      .nr_irqs        = EZX_NR_IRQS,
        .init_irq       = pxa27x_init_irq,
        .timer          = &pxa_timer,
        .init_machine   = e2_init,
index 0c31fabfc7fdd46ee793252bf62fe9be2541cc47,83734c8b4b5223ddd78a725b4479da9b0ffe7573..f5fb915e1315e202e1a95528720dc3e445825b2b
@@@ -45,7 -45,7 +45,7 @@@
  
  #include <mach/pxa27x.h>
  #include <mach/regs-rtc.h>
 -#include <mach/pxa27x_keypad.h>
 +#include <plat/pxa27x_keypad.h>
  #include <mach/pxafb.h>
  #include <mach/mmc.h>
  #include <mach/udc.h>
@@@ -711,7 -711,6 +711,6 @@@ static struct soc_camera_link iclink = 
        .bus_id         = 0, /* Match id in pxa27x_device_camera in device.c */
        .board_info     = &mioa701_i2c_devices[0],
        .i2c_adapter_id = 0,
-       .module_name    = "mt9m111",
  };
  
  struct i2c_pxa_platform_data i2c_pdata = {
@@@ -819,6 -818,8 +818,6 @@@ static void mioa701_machine_exit(void
  }
  
  MACHINE_START(MIOA701, "MIO A701")
 -      .phys_io        = 0x40000000,
 -      .io_pg_offst    = (io_p2v(0x40000000) >> 18) & 0xfffc,
        .boot_params    = 0xa0000100,
        .map_io         = &pxa_map_io,
        .init_irq       = &pxa27x_init_irq,
index 71a3368ab1fc00837ab9161298637f999fb8bed5,ae0b13822849255f54be03c85398fd730cb329e8..ddc7e4e4d2a0431ca0ca64a6300a5ab4288f7d03
@@@ -620,7 -620,6 +620,6 @@@ static struct soc_camera_link tw9910_li
        .bus_id         = 1,
        .power          = tw9910_power,
        .board_info     = &i2c_camera[0],
-       .module_name    = "tw9910",
        .priv           = &tw9910_info,
  };
  
@@@ -644,7 -643,6 +643,6 @@@ static struct soc_camera_link mt9t112_l
        .power          = mt9t112_power1,
        .bus_id         = 0,
        .board_info     = &i2c_camera[1],
-       .module_name    = "mt9t112",
        .priv           = &mt9t112_info1,
  };
  
@@@ -667,7 -665,6 +665,6 @@@ static struct soc_camera_link mt9t112_l
        .power          = mt9t112_power2,
        .bus_id         = 1,
        .board_info     = &i2c_camera[2],
-       .module_name    = "mt9t112",
        .priv           = &mt9t112_info2,
  };
  
@@@ -793,7 -790,6 +790,6 @@@ static struct sh_vou_pdata sh_vou_pdat
        .flags          = SH_VOU_HSYNC_LOW | SH_VOU_VSYNC_LOW,
        .board_info     = &ak8813,
        .i2c_adap       = 0,
-       .module_name    = "ak881x",
  };
  
  static struct resource sh_vou_resources[] = {
@@@ -1248,14 -1244,14 +1244,14 @@@ static int __init arch_setup(void
  
        /* set SPU2 clock to 83.4 MHz */
        clk = clk_get(NULL, "spu_clk");
 -      if (clk) {
 +      if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 83333333));
                clk_put(clk);
        }
  
        /* change parent of FSI B */
        clk = clk_get(NULL, "fsib_clk");
 -      if (clk) {
 +      if (!IS_ERR(clk)) {
                clk_register(&fsimckb_clk);
                clk_set_parent(clk, &fsimckb_clk);
                clk_set_rate(clk, 11000);
  
        /* set VPU clock to 166 MHz */
        clk = clk_get(NULL, "vpu_clk");
 -      if (clk) {
 +      if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 166000000));
                clk_put(clk);
        }
diff --combined drivers/media/IR/imon.c
index faed5a332c718f0720bd87b44dbb8f09f0d5b5fb,f782a9d72ce6510b3d13c85ca8aaa2db193d0a66..bc118066bc38ba2fd4a0c74c7e7c061de42bed3d
@@@ -1,7 -1,7 +1,7 @@@
  /*
   *   imon.c:  input and display driver for SoundGraph iMON IR/VFD/LCD
   *
-  *   Copyright(C) 2009  Jarod Wilson <jarod@wilsonet.com>
+  *   Copyright(C) 2010  Jarod Wilson <jarod@wilsonet.com>
   *   Portions based on the original lirc_imon driver,
   *    Copyright(C) 2004  Venky Raju(dev@venky.ws)
   *
@@@ -26,6 -26,8 +26,8 @@@
   *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   */
  
+ #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
  #include <linux/errno.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
@@@ -44,7 -46,7 +46,7 @@@
  #define MOD_AUTHOR    "Jarod Wilson <jarod@wilsonet.com>"
  #define MOD_DESC      "Driver for SoundGraph iMON MultiMedia IR/Display"
  #define MOD_NAME      "imon"
- #define MOD_VERSION   "0.9.1"
+ #define MOD_VERSION   "0.9.2"
  
  #define DISPLAY_MINOR_BASE    144
  #define DEVICE_NAME   "lcd%d"
@@@ -121,21 -123,26 +123,26 @@@ struct imon_context 
        u16 vendor;                     /* usb vendor ID */
        u16 product;                    /* usb product ID */
  
-       struct input_dev *idev;         /* input device for remote */
+       struct input_dev *rdev;         /* input device for remote */
+       struct input_dev *idev;         /* input device for panel & IR mouse */
        struct input_dev *touch;        /* input device for touchscreen */
  
+       spinlock_t kc_lock;             /* make sure we get keycodes right */
        u32 kc;                         /* current input keycode */
        u32 last_keycode;               /* last reported input keycode */
+       u32 rc_scancode;                /* the computed remote scancode */
+       u8 rc_toggle;                   /* the computed remote toggle bit */
        u64 ir_type;                    /* iMON or MCE (RC6) IR protocol? */
-       u8 mce_toggle_bit;              /* last mce toggle bit */
        bool release_code;              /* some keys send a release code */
  
        u8 display_type;                /* store the display type */
        bool pad_mouse;                 /* toggle kbd(0)/mouse(1) mode */
  
+       char name_rdev[128];            /* rc input device name */
+       char phys_rdev[64];             /* rc input device phys path */
        char name_idev[128];            /* input device name */
        char phys_idev[64];             /* input device phys path */
-       struct timer_list itimer;       /* input device timer, need for rc6 */
  
        char name_touch[128];           /* touch screen name */
        char phys_touch[64];            /* touch screen phys path */
@@@ -151,8 -158,7 +158,8 @@@ static const struct file_operations vfd
        .owner          = THIS_MODULE,
        .open           = &display_open,
        .write          = &vfd_write,
 -      .release        = &display_close
 +      .release        = &display_close,
 +      .llseek         = noop_llseek,
  };
  
  /* lcd character device file operations */
@@@ -160,8 -166,7 +167,8 @@@ static const struct file_operations lcd
        .owner          = THIS_MODULE,
        .open           = &display_open,
        .write          = &lcd_write,
 -      .release        = &display_close
 +      .release        = &display_close,
 +      .llseek         = noop_llseek,
  };
  
  enum {
@@@ -289,6 -294,9 +296,9 @@@ static const struct 
        { 0x000100000000ffeell, KEY_VOLUMEUP },
        { 0x010000000000ffeell, KEY_VOLUMEDOWN },
        { 0x000000000100ffeell, KEY_MUTE },
+       /* 0xffdc iMON MCE VFD */
+       { 0x00010000ffffffeell, KEY_VOLUMEUP },
+       { 0x01000000ffffffeell, KEY_VOLUMEDOWN },
        /* iMON Knob values */
        { 0x000100ffffffffeell, KEY_VOLUMEUP },
        { 0x010000ffffffffeell, KEY_VOLUMEDOWN },
@@@ -307,7 -315,7 +317,7 @@@ MODULE_DEVICE_TABLE(usb, imon_usb_id_ta
  
  static bool debug;
  module_param(debug, bool, S_IRUGO | S_IWUSR);
- MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)");
+ MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)");
  
  /* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */
  static int display_type;
@@@ -365,15 -373,14 +375,14 @@@ static int display_open(struct inode *i
        subminor = iminor(inode);
        interface = usb_find_interface(&imon_driver, subminor);
        if (!interface) {
-               err("%s: could not find interface for minor %d",
-                   __func__, subminor);
+               pr_err("could not find interface for minor %d\n", subminor);
                retval = -ENODEV;
                goto exit;
        }
        ictx = usb_get_intfdata(interface);
  
        if (!ictx) {
-               err("%s: no context found for minor %d", __func__, subminor);
+               pr_err("no context found for minor %d\n", subminor);
                retval = -ENODEV;
                goto exit;
        }
        mutex_lock(&ictx->lock);
  
        if (!ictx->display_supported) {
-               err("%s: display not supported by device", __func__);
+               pr_err("display not supported by device\n");
                retval = -ENODEV;
        } else if (ictx->display_isopen) {
-               err("%s: display port is already open", __func__);
+               pr_err("display port is already open\n");
                retval = -EBUSY;
        } else {
                ictx->display_isopen = true;
@@@ -411,17 -418,17 +420,17 @@@ static int display_close(struct inode *
        ictx = file->private_data;
  
        if (!ictx) {
-               err("%s: no context for device", __func__);
+               pr_err("no context for device\n");
                return -ENODEV;
        }
  
        mutex_lock(&ictx->lock);
  
        if (!ictx->display_supported) {
-               err("%s: display not supported by device", __func__);
+               pr_err("display not supported by device\n");
                retval = -ENODEV;
        } else if (!ictx->display_isopen) {
-               err("%s: display is not open", __func__);
+               pr_err("display is not open\n");
                retval = -EIO;
        } else {
                ictx->display_isopen = false;
@@@ -500,19 -507,19 +509,19 @@@ static int send_packet(struct imon_cont
        if (retval) {
                ictx->tx.busy = false;
                smp_rmb(); /* ensure later readers know we're not busy */
-               err("%s: error submitting urb(%d)", __func__, retval);
+               pr_err("error submitting urb(%d)\n", retval);
        } else {
                /* Wait for transmission to complete (or abort) */
                mutex_unlock(&ictx->lock);
                retval = wait_for_completion_interruptible(
                                &ictx->tx.finished);
                if (retval)
-                       err("%s: task interrupted", __func__);
+                       pr_err("task interrupted\n");
                mutex_lock(&ictx->lock);
  
                retval = ictx->tx.status;
                if (retval)
-                       err("%s: packet tx failed (%d)", __func__, retval);
+                       pr_err("packet tx failed (%d)\n", retval);
        }
  
        kfree(control_req);
@@@ -544,12 -551,12 +553,12 @@@ static int send_associate_24g(struct im
                                          0x00, 0x00, 0x00, 0x20 };
  
        if (!ictx) {
-               err("%s: no context for device", __func__);
+               pr_err("no context for device\n");
                return -ENODEV;
        }
  
        if (!ictx->dev_present_intf0) {
-               err("%s: no iMON device present", __func__);
+               pr_err("no iMON device present\n");
                return -ENODEV;
        }
  
@@@ -577,7 -584,7 +586,7 @@@ static int send_set_imon_clock(struct i
        int i;
  
        if (!ictx) {
-               err("%s: no context for device", __func__);
+               pr_err("no context for device\n");
                return -ENODEV;
        }
  
                memcpy(ictx->usb_tx_buf, clock_enable_pkt[i], 8);
                retval = send_packet(ictx);
                if (retval) {
-                       err("%s: send_packet failed for packet %d",
-                           __func__, i);
+                       pr_err("send_packet failed for packet %d\n", i);
                        break;
                }
        }
@@@ -778,7 -784,7 +786,7 @@@ static struct attribute *imon_display_s
        NULL
  };
  
- static struct attribute_group imon_display_attribute_group = {
+ static struct attribute_group imon_display_attr_group = {
        .attrs = imon_display_sysfs_entries
  };
  
@@@ -787,7 -793,7 +795,7 @@@ static struct attribute *imon_rf_sysfs_
        NULL
  };
  
- static struct attribute_group imon_rf_attribute_group = {
+ static struct attribute_group imon_rf_attr_group = {
        .attrs = imon_rf_sysfs_entries
  };
  
@@@ -815,20 -821,20 +823,20 @@@ static ssize_t vfd_write(struct file *f
  
        ictx = file->private_data;
        if (!ictx) {
-               err("%s: no context for device", __func__);
+               pr_err("no context for device\n");
                return -ENODEV;
        }
  
        mutex_lock(&ictx->lock);
  
        if (!ictx->dev_present_intf0) {
-               err("%s: no iMON device present", __func__);
+               pr_err("no iMON device present\n");
                retval = -ENODEV;
                goto exit;
        }
  
        if (n_bytes <= 0 || n_bytes > 32) {
-               err("%s: invalid payload size", __func__);
+               pr_err("invalid payload size\n");
                retval = -EINVAL;
                goto exit;
        }
  
                retval = send_packet(ictx);
                if (retval) {
-                       err("%s: send packet failed for packet #%d",
-                                       __func__, seq/2);
+                       pr_err("send packet failed for packet #%d\n", seq / 2);
                        goto exit;
                } else {
                        seq += 2;
        ictx->usb_tx_buf[7] = (unsigned char) seq;
        retval = send_packet(ictx);
        if (retval)
-               err("%s: send packet failed for packet #%d",
-                   __func__, seq / 2);
+               pr_err("send packet failed for packet #%d\n", seq / 2);
  
  exit:
        mutex_unlock(&ictx->lock);
@@@ -899,21 -903,20 +905,20 @@@ static ssize_t lcd_write(struct file *f
  
        ictx = file->private_data;
        if (!ictx) {
-               err("%s: no context for device", __func__);
+               pr_err("no context for device\n");
                return -ENODEV;
        }
  
        mutex_lock(&ictx->lock);
  
        if (!ictx->display_supported) {
-               err("%s: no iMON display present", __func__);
+               pr_err("no iMON display present\n");
                retval = -ENODEV;
                goto exit;
        }
  
        if (n_bytes != 8) {
-               err("%s: invalid payload size: %d (expecting 8)",
-                   __func__, (int) n_bytes);
+               pr_err("invalid payload size: %d (expected 8)\n", (int)n_bytes);
                retval = -EINVAL;
                goto exit;
        }
  
        retval = send_packet(ictx);
        if (retval) {
-               err("%s: send packet failed!", __func__);
+               pr_err("send packet failed!\n");
                goto exit;
        } else {
                dev_dbg(ictx->dev, "%s: write %d bytes to LCD\n",
@@@ -957,17 -960,6 +962,6 @@@ static void usb_tx_callback(struct urb 
        complete(&ictx->tx.finished);
  }
  
- /**
-  * mce/rc6 keypresses have no distinct release code, use timer
-  */
- static void imon_mce_timeout(unsigned long data)
- {
-       struct imon_context *ictx = (struct imon_context *)data;
-       input_report_key(ictx->idev, ictx->last_keycode, 0);
-       input_sync(ictx->idev);
- }
  /**
   * report touchscreen input
   */
@@@ -1008,14 -1000,11 +1002,11 @@@ int imon_ir_change_protocol(void *priv
                dev_dbg(dev, "Configuring IR receiver for MCE protocol\n");
                ir_proto_packet[0] = 0x01;
                pad_mouse = false;
-               init_timer(&ictx->itimer);
-               ictx->itimer.data = (unsigned long)ictx;
-               ictx->itimer.function = imon_mce_timeout;
                break;
        case IR_TYPE_UNKNOWN:
        case IR_TYPE_OTHER:
                dev_dbg(dev, "Configuring IR receiver for iMON protocol\n");
-               if (pad_stabilize)
+               if (pad_stabilize && !nomouse)
                        pad_mouse = true;
                else {
                        dev_dbg(dev, "PAD stabilize functionality disabled\n");
        default:
                dev_warn(dev, "Unsupported IR protocol specified, overriding "
                         "to iMON IR protocol\n");
-               if (pad_stabilize)
+               if (pad_stabilize && !nomouse)
                        pad_mouse = true;
                else {
                        dev_dbg(dev, "PAD stabilize functionality disabled\n");
@@@ -1149,20 -1138,21 +1140,21 @@@ static int stabilize(int a, int b, u16 
        return result;
  }
  
- static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 hw_code)
+ static u32 imon_remote_key_lookup(struct imon_context *ictx, u32 scancode)
  {
-       u32 scancode = be32_to_cpu(hw_code);
        u32 keycode;
        u32 release;
        bool is_release_code = false;
  
        /* Look for the initial press of a button */
-       keycode = ir_g_keycode_from_table(ictx->idev, scancode);
+       keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
+       ictx->rc_toggle = 0x0;
+       ictx->rc_scancode = scancode;
  
        /* Look for the release of a button */
        if (keycode == KEY_RESERVED) {
                release = scancode & ~0x4000;
-               keycode = ir_g_keycode_from_table(ictx->idev, release);
+               keycode = ir_g_keycode_from_table(ictx->rdev, release);
                if (keycode != KEY_RESERVED)
                        is_release_code = true;
        }
        return keycode;
  }
  
- static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 hw_code)
+ static u32 imon_mce_key_lookup(struct imon_context *ictx, u32 scancode)
  {
-       u32 scancode = be32_to_cpu(hw_code);
        u32 keycode;
  
  #define MCE_KEY_MASK 0x7000
         * but we can't or them into all codes, as some keys are decoded in
         * a different way w/o the same use of the toggle bit...
         */
-       if ((scancode >> 24) & 0x80)
+       if (scancode & 0x80000000)
                scancode = scancode | MCE_KEY_MASK | MCE_TOGGLE_BIT;
  
-       keycode = ir_g_keycode_from_table(ictx->idev, scancode);
+       ictx->rc_scancode = scancode;
+       keycode = ir_g_keycode_from_table(ictx->rdev, scancode);
+       /* not used in mce mode, but make sure we know its false */
+       ictx->release_code = false;
  
        return keycode;
  }
  
- static u32 imon_panel_key_lookup(u64 hw_code)
+ static u32 imon_panel_key_lookup(u64 code)
  {
        int i;
-       u64 code = be64_to_cpu(hw_code);
        u32 keycode = KEY_RESERVED;
  
        for (i = 0; i < ARRAY_SIZE(imon_panel_key_table); i++) {
@@@ -1219,6 -1211,9 +1213,9 @@@ static bool imon_mouse_event(struct imo
        u8 right_shift = 1;
        bool mouse_input = true;
        int dir = 0;
+       unsigned long flags;
+       spin_lock_irqsave(&ictx->kc_lock, flags);
  
        /* newer iMON device PAD or mouse button */
        if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) {
        } else
                mouse_input = false;
  
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
        if (mouse_input) {
                dev_dbg(ictx->dev, "sending mouse data via input subsystem\n");
  
                                         buf[1] >> right_shift & 0x1);
                }
                input_sync(ictx->idev);
+               spin_lock_irqsave(&ictx->kc_lock, flags);
                ictx->last_keycode = ictx->kc;
+               spin_unlock_irqrestore(&ictx->kc_lock, flags);
        }
  
        return mouse_input;
@@@ -1286,8 -1285,8 +1287,8 @@@ static void imon_pad_to_keys(struct imo
        int dir = 0;
        char rel_x = 0x00, rel_y = 0x00;
        u16 timeout, threshold;
-       u64 temp_key;
-       u32 remote_key;
+       u32 scancode = KEY_RESERVED;
+       unsigned long flags;
  
        /*
         * The imon directional pad functions more like a touchpad. Bytes 3 & 4
                                dir = stabilize((int)rel_x, (int)rel_y,
                                                timeout, threshold);
                                if (!dir) {
+                                       spin_lock_irqsave(&ictx->kc_lock,
+                                                         flags);
                                        ictx->kc = KEY_UNKNOWN;
+                                       spin_unlock_irqrestore(&ictx->kc_lock,
+                                                              flags);
                                        return;
                                }
                                buf[2] = dir & 0xFF;
                                buf[3] = (dir >> 8) & 0xFF;
-                               memcpy(&temp_key, buf, sizeof(temp_key));
-                               remote_key = (u32) (le64_to_cpu(temp_key)
-                                                   & 0xffffffff);
-                               ictx->kc = imon_remote_key_lookup(ictx,
-                                                                 remote_key);
+                               scancode = be32_to_cpu(*((u32 *)buf));
                        }
                } else {
+                       /*
+                        * Hack alert: instead of using keycodes, we have
+                        * to use hard-coded scancodes here...
+                        */
                        if (abs(rel_y) > abs(rel_x)) {
                                buf[2] = (rel_y > 0) ? 0x7F : 0x80;
                                buf[3] = 0;
-                               ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+                               if (rel_y > 0)
+                                       scancode = 0x01007f00; /* KEY_DOWN */
+                               else
+                                       scancode = 0x01008000; /* KEY_UP */
                        } else {
                                buf[2] = 0;
                                buf[3] = (rel_x > 0) ? 0x7F : 0x80;
-                               ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+                               if (rel_x > 0)
+                                       scancode = 0x0100007f; /* KEY_RIGHT */
+                               else
+                                       scancode = 0x01000080; /* KEY_LEFT */
                        }
                }
  
                        dir = stabilize((int)rel_x, (int)rel_y,
                                        timeout, threshold);
                        if (!dir) {
+                               spin_lock_irqsave(&ictx->kc_lock, flags);
                                ictx->kc = KEY_UNKNOWN;
+                               spin_unlock_irqrestore(&ictx->kc_lock, flags);
                                return;
                        }
                        buf[2] = dir & 0xFF;
                        buf[3] = (dir >> 8) & 0xFF;
-                       memcpy(&temp_key, buf, sizeof(temp_key));
-                       remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
-                       ictx->kc = imon_remote_key_lookup(ictx, remote_key);
+                       scancode = be32_to_cpu(*((u32 *)buf));
                } else {
+                       /*
+                        * Hack alert: instead of using keycodes, we have
+                        * to use hard-coded scancodes here...
+                        */
                        if (abs(rel_y) > abs(rel_x)) {
                                buf[2] = (rel_y > 0) ? 0x7F : 0x80;
                                buf[3] = 0;
-                               ictx->kc = (rel_y > 0) ? KEY_DOWN : KEY_UP;
+                               if (rel_y > 0)
+                                       scancode = 0x01007f00; /* KEY_DOWN */
+                               else
+                                       scancode = 0x01008000; /* KEY_UP */
                        } else {
                                buf[2] = 0;
                                buf[3] = (rel_x > 0) ? 0x7F : 0x80;
-                               ictx->kc = (rel_x > 0) ? KEY_RIGHT : KEY_LEFT;
+                               if (rel_x > 0)
+                                       scancode = 0x0100007f; /* KEY_RIGHT */
+                               else
+                                       scancode = 0x01000080; /* KEY_LEFT */
                        }
                }
        }
+       if (scancode) {
+               spin_lock_irqsave(&ictx->kc_lock, flags);
+               ictx->kc = imon_remote_key_lookup(ictx, scancode);
+               spin_unlock_irqrestore(&ictx->kc_lock, flags);
+       }
  }
  
+ /**
+  * figure out if these is a press or a release. We don't actually
+  * care about repeats, as those will be auto-generated within the IR
+  * subsystem for repeating scancodes.
+  */
  static int imon_parse_press_type(struct imon_context *ictx,
                                 unsigned char *buf, u8 ktype)
  {
        int press_type = 0;
-       int rep_delay = ictx->idev->rep[REP_DELAY];
-       int rep_period = ictx->idev->rep[REP_PERIOD];
+       unsigned long flags;
+       spin_lock_irqsave(&ictx->kc_lock, flags);
  
        /* key release of 0x02XXXXXX key */
        if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00)
                 buf[2] == 0x81 && buf[3] == 0xb7)
                ictx->kc = ictx->last_keycode;
  
-       /* mce-specific button handling */
+       /* mce-specific button handling, no keyup events */
        else if (ktype == IMON_KEY_MCE) {
-               /* initial press */
-               if (ictx->kc != ictx->last_keycode
-                   || buf[2] != ictx->mce_toggle_bit) {
-                       ictx->last_keycode = ictx->kc;
-                       ictx->mce_toggle_bit = buf[2];
-                       press_type = 1;
-                       mod_timer(&ictx->itimer,
-                                 jiffies + msecs_to_jiffies(rep_delay));
-               /* repeat */
-               } else {
-                       press_type = 2;
-                       mod_timer(&ictx->itimer,
-                                 jiffies + msecs_to_jiffies(rep_period));
-               }
+               ictx->rc_toggle = buf[2];
+               press_type = 1;
  
        /* incoherent or irrelevant data */
        } else if (ictx->kc == KEY_RESERVED)
        else
                press_type = 1;
  
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
        return press_type;
  }
  
@@@ -1451,41 -1472,45 +1474,45 @@@ static void imon_incoming_packet(struc
        int len = urb->actual_length;
        unsigned char *buf = urb->transfer_buffer;
        struct device *dev = ictx->dev;
+       unsigned long flags;
        u32 kc;
        bool norelease = false;
        int i;
-       u64 temp_key;
-       u64 panel_key = 0;
-       u32 remote_key = 0;
-       struct input_dev *idev = NULL;
+       u64 scancode;
+       struct input_dev *rdev = NULL;
+       struct ir_input_dev *irdev = NULL;
        int press_type = 0;
        int msec;
        struct timeval t;
        static struct timeval prev_time = { 0, 0 };
-       u8 ktype = IMON_KEY_IMON;
+       u8 ktype;
  
-       idev = ictx->idev;
+       rdev = ictx->rdev;
+       irdev = input_get_drvdata(rdev);
  
        /* filter out junk data on the older 0xffdc imon devices */
        if ((buf[0] == 0xff) && (buf[1] == 0xff) && (buf[2] == 0xff))
                return;
  
        /* Figure out what key was pressed */
-       memcpy(&temp_key, buf, sizeof(temp_key));
        if (len == 8 && buf[7] == 0xee) {
+               scancode = be64_to_cpu(*((u64 *)buf));
                ktype = IMON_KEY_PANEL;
-               panel_key = le64_to_cpu(temp_key);
-               kc = imon_panel_key_lookup(panel_key);
+               kc = imon_panel_key_lookup(scancode);
        } else {
-               remote_key = (u32) (le64_to_cpu(temp_key) & 0xffffffff);
+               scancode = be32_to_cpu(*((u32 *)buf));
                if (ictx->ir_type == IR_TYPE_RC6) {
+                       ktype = IMON_KEY_IMON;
                        if (buf[0] == 0x80)
                                ktype = IMON_KEY_MCE;
-                       kc = imon_mce_key_lookup(ictx, remote_key);
-               } else
-                       kc = imon_remote_key_lookup(ictx, remote_key);
+                       kc = imon_mce_key_lookup(ictx, scancode);
+               } else {
+                       ktype = IMON_KEY_IMON;
+                       kc = imon_remote_key_lookup(ictx, scancode);
+               }
        }
  
+       spin_lock_irqsave(&ictx->kc_lock, flags);
        /* keyboard/mouse mode toggle button */
        if (kc == KEY_KEYBOARD && !ictx->release_code) {
                ictx->last_keycode = kc;
                        ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
                        dev_dbg(dev, "toggling to %s mode\n",
                                ictx->pad_mouse ? "mouse" : "keyboard");
+                       spin_unlock_irqrestore(&ictx->kc_lock, flags);
                        return;
                } else {
                        ictx->pad_mouse = 0;
        }
  
        ictx->kc = kc;
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
  
        /* send touchscreen events through input subsystem if touchpad data */
        if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
            buf[7] == 0x86) {
                imon_touch_event(ictx, buf);
+               return;
  
        /* look for mouse events with pad in mouse mode */
        } else if (ictx->pad_mouse) {
        if (press_type < 0)
                goto not_input_data;
  
+       spin_lock_irqsave(&ictx->kc_lock, flags);
        if (ictx->kc == KEY_UNKNOWN)
                goto unknown_key;
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
+       if (ktype != IMON_KEY_PANEL) {
+               if (press_type == 0)
+                       ir_keyup(irdev);
+               else {
+                       ir_keydown(rdev, ictx->rc_scancode, ictx->rc_toggle);
+                       spin_lock_irqsave(&ictx->kc_lock, flags);
+                       ictx->last_keycode = ictx->kc;
+                       spin_unlock_irqrestore(&ictx->kc_lock, flags);
+               }
+               return;
+       }
  
-       /* KEY_MUTE repeats from MCE and knob need to be suppressed */
-       if ((ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode)
-           && (buf[7] == 0xee || ktype == IMON_KEY_MCE)) {
+       /* Only panel type events left to process now */
+       spin_lock_irqsave(&ictx->kc_lock, flags);
+       /* KEY_MUTE repeats from knob need to be suppressed */
+       if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
                do_gettimeofday(&t);
                msec = tv2int(&t, &prev_time);
                prev_time = t;
-               if (msec < idev->rep[REP_DELAY])
+               if (msec < ictx->idev->rep[REP_DELAY]) {
+                       spin_unlock_irqrestore(&ictx->kc_lock, flags);
                        return;
+               }
        }
+       kc = ictx->kc;
  
-       input_report_key(idev, ictx->kc, press_type);
-       input_sync(idev);
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
  
-       /* panel keys and some remote keys don't generate a release */
-       if (panel_key || norelease) {
-               input_report_key(idev, ictx->kc, 0);
-               input_sync(idev);
-       }
+       input_report_key(ictx->idev, kc, press_type);
+       input_sync(ictx->idev);
  
-       ictx->last_keycode = ictx->kc;
+       /* panel keys don't generate a release */
+       input_report_key(ictx->idev, kc, 0);
+       input_sync(ictx->idev);
+       ictx->last_keycode = kc;
  
        return;
  
  unknown_key:
+       spin_unlock_irqrestore(&ictx->kc_lock, flags);
        dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__,
-                (panel_key ? be64_to_cpu(panel_key) :
-                             be32_to_cpu(remote_key)));
+                (long long)scancode);
        return;
  
  not_input_data:
@@@ -1653,31 -1700,205 +1702,205 @@@ static void usb_rx_callback_intf1(struc
        usb_submit_urb(ictx->rx_urb_intf1, GFP_ATOMIC);
  }
  
+ /*
+  * The 0x15c2:0xffdc device ID was used for umpteen different imon
+  * devices, and all of them constantly spew interrupts, even when there
+  * is no actual data to report. However, byte 6 of this buffer looks like
+  * its unique across device variants, so we're trying to key off that to
+  * figure out which display type (if any) and what IR protocol the device
+  * actually supports. These devices have their IR protocol hard-coded into
+  * their firmware, they can't be changed on the fly like the newer hardware.
+  */
+ static void imon_get_ffdc_type(struct imon_context *ictx)
+ {
+       u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
+       u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
+       u64 allowed_protos = IR_TYPE_OTHER;
+       switch (ffdc_cfg_byte) {
+       /* iMON Knob, no display, iMON IR + vol knob */
+       case 0x21:
+               dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
+               ictx->display_supported = false;
+               break;
+       /* iMON 2.4G LT (usb stick), no display, iMON RF */
+       case 0x4e:
+               dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
+               ictx->display_supported = false;
+               ictx->rf_device = true;
+               break;
+       /* iMON VFD, no IR (does have vol knob tho) */
+       case 0x35:
+               dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
+               detected_display_type = IMON_DISPLAY_TYPE_VFD;
+               break;
+       /* iMON VFD, iMON IR */
+       case 0x24:
+       case 0x85:
+               dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
+               detected_display_type = IMON_DISPLAY_TYPE_VFD;
+               break;
+       /* iMON VFD, MCE IR */
+       case 0x9e:
+               dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
+               detected_display_type = IMON_DISPLAY_TYPE_VFD;
+               allowed_protos = IR_TYPE_RC6;
+               break;
+       /* iMON LCD, MCE IR */
+       case 0x9f:
+               dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
+               detected_display_type = IMON_DISPLAY_TYPE_LCD;
+               allowed_protos = IR_TYPE_RC6;
+               break;
+       default:
+               dev_info(ictx->dev, "Unknown 0xffdc device, "
+                        "defaulting to VFD and iMON IR");
+               detected_display_type = IMON_DISPLAY_TYPE_VFD;
+               break;
+       }
+       printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
+       ictx->display_type = detected_display_type;
+       ictx->props->allowed_protos = allowed_protos;
+       ictx->ir_type = allowed_protos;
+ }
+ static void imon_set_display_type(struct imon_context *ictx)
+ {
+       u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
+       /*
+        * Try to auto-detect the type of display if the user hasn't set
+        * it by hand via the display_type modparam. Default is VFD.
+        */
+       if (display_type == IMON_DISPLAY_TYPE_AUTO) {
+               switch (ictx->product) {
+               case 0xffdc:
+                       /* set in imon_get_ffdc_type() */
+                       configured_display_type = ictx->display_type;
+                       break;
+               case 0x0034:
+               case 0x0035:
+                       configured_display_type = IMON_DISPLAY_TYPE_VGA;
+                       break;
+               case 0x0038:
+               case 0x0039:
+               case 0x0045:
+                       configured_display_type = IMON_DISPLAY_TYPE_LCD;
+                       break;
+               case 0x003c:
+               case 0x0041:
+               case 0x0042:
+               case 0x0043:
+                       configured_display_type = IMON_DISPLAY_TYPE_NONE;
+                       ictx->display_supported = false;
+                       break;
+               case 0x0036:
+               case 0x0044:
+               default:
+                       configured_display_type = IMON_DISPLAY_TYPE_VFD;
+                       break;
+               }
+       } else {
+               configured_display_type = display_type;
+               if (display_type == IMON_DISPLAY_TYPE_NONE)
+                       ictx->display_supported = false;
+               else
+                       ictx->display_supported = true;
+               dev_info(ictx->dev, "%s: overriding display type to %d via "
+                        "modparam\n", __func__, display_type);
+       }
+       ictx->display_type = configured_display_type;
+ }
+ static struct input_dev *imon_init_rdev(struct imon_context *ictx)
+ {
+       struct input_dev *rdev;
+       struct ir_dev_props *props;
+       int ret;
+       char *ir_codes = NULL;
+       const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
+                                           0x00, 0x00, 0x00, 0x88 };
+       rdev = input_allocate_device();
+       props = kzalloc(sizeof(*props), GFP_KERNEL);
+       if (!rdev || !props) {
+               dev_err(ictx->dev, "remote control dev allocation failed\n");
+               goto out;
+       }
+       snprintf(ictx->name_rdev, sizeof(ictx->name_rdev),
+                "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
+       usb_make_path(ictx->usbdev_intf0, ictx->phys_rdev,
+                     sizeof(ictx->phys_rdev));
+       strlcat(ictx->phys_rdev, "/input0", sizeof(ictx->phys_rdev));
+       rdev->name = ictx->name_rdev;
+       rdev->phys = ictx->phys_rdev;
+       usb_to_input_id(ictx->usbdev_intf0, &rdev->id);
+       rdev->dev.parent = ictx->dev;
+       rdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+       input_set_drvdata(rdev, ictx);
+       props->priv = ictx;
+       props->driver_type = RC_DRIVER_SCANCODE;
+       props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6; /* iMON PAD or MCE */
+       props->change_protocol = imon_ir_change_protocol;
+       ictx->props = props;
+       /* Enable front-panel buttons and/or knobs */
+       memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
+       ret = send_packet(ictx);
+       /* Not fatal, but warn about it */
+       if (ret)
+               dev_info(ictx->dev, "panel buttons/knobs setup failed\n");
+       if (ictx->product == 0xffdc)
+               imon_get_ffdc_type(ictx);
+       imon_set_display_type(ictx);
+       if (ictx->ir_type == IR_TYPE_RC6)
+               ir_codes = RC_MAP_IMON_MCE;
+       else
+               ir_codes = RC_MAP_IMON_PAD;
+       ret = ir_input_register(rdev, ir_codes, props, MOD_NAME);
+       if (ret < 0) {
+               dev_err(ictx->dev, "remote input dev register failed\n");
+               goto out;
+       }
+       return rdev;
+ out:
+       kfree(props);
+       input_free_device(rdev);
+       return NULL;
+ }
  static struct input_dev *imon_init_idev(struct imon_context *ictx)
  {
        struct input_dev *idev;
-       struct ir_dev_props *props;
        int ret, i;
  
        idev = input_allocate_device();
        if (!idev) {
-               dev_err(ictx->dev, "remote input dev allocation failed\n");
-               goto idev_alloc_failed;
-       }
-       props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
-       if (!props) {
-               dev_err(ictx->dev, "remote ir dev props allocation failed\n");
-               goto props_alloc_failed;
+               dev_err(ictx->dev, "input dev allocation failed\n");
+               goto out;
        }
  
        snprintf(ictx->name_idev, sizeof(ictx->name_idev),
-                "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
+                "iMON Panel, Knob and Mouse(%04x:%04x)",
+                ictx->vendor, ictx->product);
        idev->name = ictx->name_idev;
  
        usb_make_path(ictx->usbdev_intf0, ictx->phys_idev,
                      sizeof(ictx->phys_idev));
-       strlcat(ictx->phys_idev, "/input0", sizeof(ictx->phys_idev));
+       strlcat(ictx->phys_idev, "/input1", sizeof(ictx->phys_idev));
        idev->phys = ictx->phys_idev;
  
        idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | BIT_MASK(EV_REL);
                __set_bit(kc, idev->keybit);
        }
  
-       props->priv = ictx;
-       props->driver_type = RC_DRIVER_SCANCODE;
-       /* IR_TYPE_OTHER maps to iMON PAD remote, IR_TYPE_RC6 to MCE remote */
-       props->allowed_protos = IR_TYPE_OTHER | IR_TYPE_RC6;
-       props->change_protocol = imon_ir_change_protocol;
-       ictx->props = props;
        usb_to_input_id(ictx->usbdev_intf0, &idev->id);
        idev->dev.parent = ictx->dev;
+       input_set_drvdata(idev, ictx);
  
-       ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
+       ret = input_register_device(idev);
        if (ret < 0) {
-               dev_err(ictx->dev, "remote input dev register failed\n");
-               goto idev_register_failed;
+               dev_err(ictx->dev, "input dev register failed\n");
+               goto out;
        }
  
        return idev;
  
- idev_register_failed:
-       kfree(props);
- props_alloc_failed:
+ out:
        input_free_device(idev);
- idev_alloc_failed:
        return NULL;
  }
  
@@@ -1738,7 -1949,7 +1951,7 @@@ static struct input_dev *imon_init_touc
  
        usb_make_path(ictx->usbdev_intf1, ictx->phys_touch,
                      sizeof(ictx->phys_touch));
-       strlcat(ictx->phys_touch, "/input1", sizeof(ictx->phys_touch));
+       strlcat(ictx->phys_touch, "/input2", sizeof(ictx->phys_touch));
        touch->phys = ictx->phys_touch;
  
        touch->evbit[0] =
@@@ -1850,7 -2061,7 +2063,7 @@@ static bool imon_find_endpoints(struct 
  
        /* Input endpoint is mandatory */
        if (!ir_ep_found)
-               err("%s: no valid input (IR) endpoint found.", __func__);
+               pr_err("no valid input (IR) endpoint found\n");
  
        ictx->tx_control = tx_control;
  
@@@ -1888,6 -2099,7 +2101,7 @@@ static struct imon_context *imon_init_i
        }
  
        mutex_init(&ictx->lock);
+       spin_lock_init(&ictx->kc_lock);
  
        mutex_lock(&ictx->lock);
  
                goto idev_setup_failed;
        }
  
+       ictx->rdev = imon_init_rdev(ictx);
+       if (!ictx->rdev) {
+               dev_err(dev, "%s: rc device setup failed\n", __func__);
+               goto rdev_setup_failed;
+       }
        usb_fill_int_urb(ictx->rx_urb_intf0, ictx->usbdev_intf0,
                usb_rcvintpipe(ictx->usbdev_intf0,
                        ictx->rx_endpoint_intf0->bEndpointAddress),
  
        ret = usb_submit_urb(ictx->rx_urb_intf0, GFP_KERNEL);
        if (ret) {
-               err("%s: usb_submit_urb failed for intf0 (%d)",
-                   __func__, ret);
+               pr_err("usb_submit_urb failed for intf0 (%d)\n", ret);
                goto urb_submit_failed;
        }
  
        return ictx;
  
  urb_submit_failed:
-       ir_input_unregister(ictx->idev);
+       ir_input_unregister(ictx->rdev);
+ rdev_setup_failed:
+       input_unregister_device(ictx->idev);
  idev_setup_failed:
  find_endpoint_failed:
        mutex_unlock(&ictx->lock);
@@@ -1954,7 -2173,7 +2175,7 @@@ static struct imon_context *imon_init_i
  
        rx_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!rx_urb) {
-               err("%s: usb_alloc_urb failed for IR urb", __func__);
+               pr_err("usb_alloc_urb failed for IR urb\n");
                goto rx_urb_alloc_failed;
        }
  
        ret = usb_submit_urb(ictx->rx_urb_intf1, GFP_KERNEL);
  
        if (ret) {
-               err("%s: usb_submit_urb failed for intf1 (%d)",
-                   __func__, ret);
+               pr_err("usb_submit_urb failed for intf1 (%d)\n", ret);
                goto urb_submit_failed;
        }
  
@@@ -2012,116 -2230,6 +2232,6 @@@ rx_urb_alloc_failed
        return NULL;
  }
  
- /*
-  * The 0x15c2:0xffdc device ID was used for umpteen different imon
-  * devices, and all of them constantly spew interrupts, even when there
-  * is no actual data to report. However, byte 6 of this buffer looks like
-  * its unique across device variants, so we're trying to key off that to
-  * figure out which display type (if any) and what IR protocol the device
-  * actually supports. These devices have their IR protocol hard-coded into
-  * their firmware, they can't be changed on the fly like the newer hardware.
-  */
- static void imon_get_ffdc_type(struct imon_context *ictx)
- {
-       u8 ffdc_cfg_byte = ictx->usb_rx_buf[6];
-       u8 detected_display_type = IMON_DISPLAY_TYPE_NONE;
-       u64 allowed_protos = IR_TYPE_OTHER;
-       switch (ffdc_cfg_byte) {
-       /* iMON Knob, no display, iMON IR + vol knob */
-       case 0x21:
-               dev_info(ictx->dev, "0xffdc iMON Knob, iMON IR");
-               ictx->display_supported = false;
-               break;
-       /* iMON 2.4G LT (usb stick), no display, iMON RF */
-       case 0x4e:
-               dev_info(ictx->dev, "0xffdc iMON 2.4G LT, iMON RF");
-               ictx->display_supported = false;
-               ictx->rf_device = true;
-               break;
-       /* iMON VFD, no IR (does have vol knob tho) */
-       case 0x35:
-               dev_info(ictx->dev, "0xffdc iMON VFD + knob, no IR");
-               detected_display_type = IMON_DISPLAY_TYPE_VFD;
-               break;
-       /* iMON VFD, iMON IR */
-       case 0x24:
-       case 0x85:
-               dev_info(ictx->dev, "0xffdc iMON VFD, iMON IR");
-               detected_display_type = IMON_DISPLAY_TYPE_VFD;
-               break;
-       /* iMON LCD, MCE IR */
-       case 0x9e:
-       case 0x9f:
-               dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
-               detected_display_type = IMON_DISPLAY_TYPE_LCD;
-               allowed_protos = IR_TYPE_RC6;
-               break;
-       default:
-               dev_info(ictx->dev, "Unknown 0xffdc device, "
-                        "defaulting to VFD and iMON IR");
-               detected_display_type = IMON_DISPLAY_TYPE_VFD;
-               break;
-       }
-       printk(KERN_CONT " (id 0x%02x)\n", ffdc_cfg_byte);
-       ictx->display_type = detected_display_type;
-       ictx->props->allowed_protos = allowed_protos;
-       ictx->ir_type = allowed_protos;
- }
- static void imon_set_display_type(struct imon_context *ictx,
-                                 struct usb_interface *intf)
- {
-       u8 configured_display_type = IMON_DISPLAY_TYPE_VFD;
-       /*
-        * Try to auto-detect the type of display if the user hasn't set
-        * it by hand via the display_type modparam. Default is VFD.
-        */
-       if (display_type == IMON_DISPLAY_TYPE_AUTO) {
-               switch (ictx->product) {
-               case 0xffdc:
-                       /* set in imon_get_ffdc_type() */
-                       configured_display_type = ictx->display_type;
-                       break;
-               case 0x0034:
-               case 0x0035:
-                       configured_display_type = IMON_DISPLAY_TYPE_VGA;
-                       break;
-               case 0x0038:
-               case 0x0039:
-               case 0x0045:
-                       configured_display_type = IMON_DISPLAY_TYPE_LCD;
-                       break;
-               case 0x003c:
-               case 0x0041:
-               case 0x0042:
-               case 0x0043:
-                       configured_display_type = IMON_DISPLAY_TYPE_NONE;
-                       ictx->display_supported = false;
-                       break;
-               case 0x0036:
-               case 0x0044:
-               default:
-                       configured_display_type = IMON_DISPLAY_TYPE_VFD;
-                       break;
-               }
-       } else {
-               configured_display_type = display_type;
-               if (display_type == IMON_DISPLAY_TYPE_NONE)
-                       ictx->display_supported = false;
-               else
-                       ictx->display_supported = true;
-               dev_info(ictx->dev, "%s: overriding display type to %d via "
-                        "modparam\n", __func__, display_type);
-       }
-       ictx->display_type = configured_display_type;
- }
  static void imon_init_display(struct imon_context *ictx,
                              struct usb_interface *intf)
  {
        dev_dbg(ictx->dev, "Registering iMON display with sysfs\n");
  
        /* set up sysfs entry for built-in clock */
-       ret = sysfs_create_group(&intf->dev.kobj,
-                                &imon_display_attribute_group);
+       ret = sysfs_create_group(&intf->dev.kobj, &imon_display_attr_group);
        if (ret)
                dev_err(ictx->dev, "Could not create display sysfs "
                        "entries(%d)", ret);
@@@ -2162,8 -2269,6 +2271,6 @@@ static int __devinit imon_probe(struct 
        struct imon_context *ictx = NULL;
        struct imon_context *first_if_ctx = NULL;
        u16 vendor, product;
-       const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00,
-                                           0x00, 0x00, 0x00, 0x88 };
  
        code_length = BUF_CHUNK_SIZE * 8;
  
        if (ifnum == 0) {
                ictx = imon_init_intf0(interface);
                if (!ictx) {
-                       err("%s: failed to initialize context!\n", __func__);
+                       pr_err("failed to initialize context!\n");
                        ret = -ENODEV;
                        goto fail;
                }
        /* this is the secondary interface on the device */
                ictx = imon_init_intf1(interface, first_if_ctx);
                if (!ictx) {
-                       err("%s: failed to attach to context!\n", __func__);
+                       pr_err("failed to attach to context!\n");
                        ret = -ENODEV;
                        goto fail;
                }
        usb_set_intfdata(interface, ictx);
  
        if (ifnum == 0) {
-               /* Enable front-panel buttons and/or knobs */
-               memcpy(ictx->usb_tx_buf, &fp_packet, sizeof(fp_packet));
-               ret = send_packet(ictx);
-               /* Not fatal, but warn about it */
-               if (ret)
-                       dev_info(dev, "failed to enable panel buttons "
-                                "and/or knobs\n");
-               if (product == 0xffdc)
-                       imon_get_ffdc_type(ictx);
-               imon_set_display_type(ictx, interface);
                if (product == 0xffdc && ictx->rf_device) {
                        sysfs_err = sysfs_create_group(&interface->dev.kobj,
-                                                      &imon_rf_attribute_group);
+                                                      &imon_rf_attr_group);
                        if (sysfs_err)
-                               err("%s: Could not create RF sysfs entries(%d)",
-                                   __func__, sysfs_err);
+                               pr_err("Could not create RF sysfs entries(%d)\n",
+                                      sysfs_err);
                }
  
                if (ictx->display_supported)
                        imon_init_display(ictx, interface);
        }
  
-       /* set IR protocol/remote type */
-       ret = imon_ir_change_protocol(ictx, ictx->ir_type);
-       if (ret) {
-               dev_warn(dev, "%s: failed to set IR protocol, falling back "
-                        "to standard iMON protocol mode\n", __func__);
-               ictx->ir_type = IR_TYPE_OTHER;
-       }
        dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
                 "usb<%d:%d> initialized\n", vendor, product, ifnum,
                 usbdev->bus->busnum, usbdev->devnum);
@@@ -2275,10 -2359,8 +2361,8 @@@ static void __devexit imon_disconnect(s
         * sysfs_remove_group is safe to call even if sysfs_create_group
         * hasn't been called
         */
-       sysfs_remove_group(&interface->dev.kobj,
-                          &imon_display_attribute_group);
-       sysfs_remove_group(&interface->dev.kobj,
-                          &imon_rf_attribute_group);
+       sysfs_remove_group(&interface->dev.kobj, &imon_display_attr_group);
+       sysfs_remove_group(&interface->dev.kobj, &imon_rf_attr_group);
  
        usb_set_intfdata(interface, NULL);
  
        if (ifnum == 0) {
                ictx->dev_present_intf0 = false;
                usb_kill_urb(ictx->rx_urb_intf0);
-               ir_input_unregister(ictx->idev);
+               input_unregister_device(ictx->idev);
+               ir_input_unregister(ictx->rdev);
                if (ictx->display_supported) {
                        if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
                                usb_deregister_dev(interface, &imon_lcd_class);
                mutex_unlock(&ictx->lock);
                if (!ictx->display_isopen)
                        free_imon_context(ictx);
-       } else {
-               if (ictx->ir_type == IR_TYPE_RC6)
-                       del_timer_sync(&ictx->itimer);
+       } else
                mutex_unlock(&ictx->lock);
-       }
  
        mutex_unlock(&driver_lock);
  
@@@ -2372,7 -2452,7 +2454,7 @@@ static int __init imon_init(void
  
        rc = usb_register(&imon_driver);
        if (rc) {
-               err("%s: usb register failed(%d)", __func__, rc);
+               pr_err("usb register failed(%d)\n", rc);
                rc = -ENODEV;
        }
  
index c06b4d50a3dca84e28021b8cd02b05886ea87f81,5f24cd6ed990ae0017422b32e603221f343aa880..9186b45132ed8d14d9274b6d32315a460a8ba471
  /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
  #define IR_KEYPRESS_TIMEOUT 250
  
 +/**
 + * ir_create_table() - initializes a scancode table
 + * @rc_tab:   the ir_scancode_table to initialize
 + * @name:     name to assign to the table
 + * @ir_type:  ir type to assign to the new table
 + * @size:     initial size of the table
 + * @return:   zero on success or a negative error code
 + *
 + * This routine will initialize the ir_scancode_table and will allocate
 + * memory to hold at least the specified number elements.
 + */
 +static int ir_create_table(struct ir_scancode_table *rc_tab,
 +                         const char *name, u64 ir_type, size_t size)
 +{
 +      rc_tab->name = name;
 +      rc_tab->ir_type = ir_type;
 +      rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
 +      rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
 +      rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
 +      if (!rc_tab->scan)
 +              return -ENOMEM;
 +
 +      IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
 +                 rc_tab->size, rc_tab->alloc);
 +      return 0;
 +}
 +
 +/**
 + * ir_free_table() - frees memory allocated by a scancode table
 + * @rc_tab:   the table whose mappings need to be freed
 + *
 + * This routine will free memory alloctaed for key mappings used by given
 + * scancode table.
 + */
 +static void ir_free_table(struct ir_scancode_table *rc_tab)
 +{
 +      rc_tab->size = 0;
 +      kfree(rc_tab->scan);
 +      rc_tab->scan = NULL;
 +}
 +
  /**
   * ir_resize_table() - resizes a scancode table if necessary
   * @rc_tab:   the ir_scancode_table to resize
 + * @gfp_flags:        gfp flags to use when allocating memory
   * @return:   zero on success or a negative error code
   *
   * This routine will shrink the ir_scancode_table if it has lots of
   * unused entries and grow it if it is full.
   */
 -static int ir_resize_table(struct ir_scancode_table *rc_tab)
 +static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
  {
        unsigned int oldalloc = rc_tab->alloc;
        unsigned int newalloc = oldalloc;
@@@ -99,7 -57,7 +99,7 @@@
        if (newalloc == oldalloc)
                return 0;
  
 -      newscan = kmalloc(newalloc, GFP_ATOMIC);
 +      newscan = kmalloc(newalloc, gfp_flags);
        if (!newscan) {
                IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
                return -ENOMEM;
  }
  
  /**
 - * ir_do_setkeycode() - internal function to set a keycode in the
 - *                    scancode->keycode table
 + * ir_update_mapping() - set a keycode in the scancode->keycode table
   * @dev:      the struct input_dev device descriptor
 - * @rc_tab:   the struct ir_scancode_table to set the keycode in
 - * @scancode: the scancode for the ir command
 - * @keycode:  the keycode for the ir command
 - * @resize:   whether the keytable may be shrunk
 - * @return:   -EINVAL if the keycode could not be inserted, otherwise zero.
 + * @rc_tab:   scancode table to be adjusted
 + * @index:    index of the mapping that needs to be updated
 + * @keycode:  the desired keycode
 + * @return:   previous keycode assigned to the mapping
 + *
 + * This routine is used to update scancode->keycopde mapping at given
 + * position.
 + */
 +static unsigned int ir_update_mapping(struct input_dev *dev,
 +                                    struct ir_scancode_table *rc_tab,
 +                                    unsigned int index,
 +                                    unsigned int new_keycode)
 +{
 +      int old_keycode = rc_tab->scan[index].keycode;
 +      int i;
 +
 +      /* Did the user wish to remove the mapping? */
 +      if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
 +              IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
 +                         index, rc_tab->scan[index].scancode);
 +              rc_tab->len--;
 +              memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
 +                      (rc_tab->len - index) * sizeof(struct ir_scancode));
 +      } else {
 +              IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
 +                         index,
 +                         old_keycode == KEY_RESERVED ? "New" : "Replacing",
 +                         rc_tab->scan[index].scancode, new_keycode);
 +              rc_tab->scan[index].keycode = new_keycode;
 +              __set_bit(new_keycode, dev->keybit);
 +      }
 +
 +      if (old_keycode != KEY_RESERVED) {
 +              /* A previous mapping was updated... */
 +              __clear_bit(old_keycode, dev->keybit);
 +              /* ... but another scancode might use the same keycode */
 +              for (i = 0; i < rc_tab->len; i++) {
 +                      if (rc_tab->scan[i].keycode == old_keycode) {
 +                              __set_bit(old_keycode, dev->keybit);
 +                              break;
 +                      }
 +              }
 +
 +              /* Possibly shrink the keytable, failure is not a problem */
 +              ir_resize_table(rc_tab, GFP_ATOMIC);
 +      }
 +
 +      return old_keycode;
 +}
 +
 +/**
 + * ir_locate_scancode() - set a keycode in the scancode->keycode table
 + * @ir_dev:   the struct ir_input_dev device descriptor
 + * @rc_tab:   scancode table to be searched
 + * @scancode: the desired scancode
 + * @resize:   controls whether we allowed to resize the table to
 + *            accomodate not yet present scancodes
 + * @return:   index of the mapping containing scancode in question
 + *            or -1U in case of failure.
   *
 - * This routine is used internally to manipulate the scancode->keycode table.
 - * The caller has to hold @rc_tab->lock.
 + * This routine is used to locate given scancode in ir_scancode_table.
 + * If scancode is not yet present the routine will allocate a new slot
 + * for it.
   */
 -static int ir_do_setkeycode(struct input_dev *dev,
 -                          struct ir_scancode_table *rc_tab,
 -                          unsigned scancode, unsigned keycode,
 -                          bool resize)
 +static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
 +                                        struct ir_scancode_table *rc_tab,
 +                                        unsigned int scancode,
 +                                        bool resize)
  {
        unsigned int i;
 -      int old_keycode = KEY_RESERVED;
 -      struct ir_input_dev *ir_dev = input_get_drvdata(dev);
  
        /*
         * Unfortunately, some hardware-based IR decoders don't provide
         * the provided IR with another one, it is needed to allow loading
         * IR tables from other remotes. So,
         */
 -      if (ir_dev->props && ir_dev->props->scanmask) {
 +      if (ir_dev->props && ir_dev->props->scanmask)
                scancode &= ir_dev->props->scanmask;
 -      }
  
        /* First check if we already have a mapping for this ir command */
        for (i = 0; i < rc_tab->len; i++) {
 +              if (rc_tab->scan[i].scancode == scancode)
 +                      return i;
 +
                /* Keytable is sorted from lowest to highest scancode */
 -              if (rc_tab->scan[i].scancode > scancode)
 +              if (rc_tab->scan[i].scancode >= scancode)
                        break;
 -              else if (rc_tab->scan[i].scancode < scancode)
 -                      continue;
 -
 -              old_keycode = rc_tab->scan[i].keycode;
 -              rc_tab->scan[i].keycode = keycode;
 -
 -              /* Did the user wish to remove the mapping? */
 -              if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) {
 -                      IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
 -                                 i, scancode);
 -                      rc_tab->len--;
 -                      memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1],
 -                              (rc_tab->len - i) * sizeof(struct ir_scancode));
 -              }
 -
 -              /* Possibly shrink the keytable, failure is not a problem */
 -              ir_resize_table(rc_tab);
 -              break;
        }
  
 -      if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) {
 -              /* No previous mapping found, we might need to grow the table */
 -              if (resize && ir_resize_table(rc_tab))
 -                      return -ENOMEM;
 -
 -              IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
 -                         i, scancode, keycode);
 +      /* No previous mapping found, we might need to grow the table */
 +      if (rc_tab->size == rc_tab->len) {
 +              if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
 +                      return -1U;
 +      }
  
 -              /* i is the proper index to insert our new keycode */
 +      /* i is the proper index to insert our new keycode */
 +      if (i < rc_tab->len)
                memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
                        (rc_tab->len - i) * sizeof(struct ir_scancode));
 -              rc_tab->scan[i].scancode = scancode;
 -              rc_tab->scan[i].keycode = keycode;
 -              rc_tab->len++;
 -              set_bit(keycode, dev->keybit);
 -      } else {
 -              IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
 -                         i, scancode, keycode);
 -              /* A previous mapping was updated... */
 -              clear_bit(old_keycode, dev->keybit);
 -              /* ...but another scancode might use the same keycode */
 -              for (i = 0; i < rc_tab->len; i++) {
 -                      if (rc_tab->scan[i].keycode == old_keycode) {
 -                              set_bit(old_keycode, dev->keybit);
 -                              break;
 -                      }
 -              }
 -      }
 +      rc_tab->scan[i].scancode = scancode;
 +      rc_tab->scan[i].keycode = KEY_RESERVED;
 +      rc_tab->len++;
  
 -      return 0;
 +      return i;
  }
  
  /**
   * This routine is used to handle evdev EVIOCSKEY ioctl.
   */
  static int ir_setkeycode(struct input_dev *dev,
 -                       unsigned int scancode, unsigned int keycode)
 +                       const struct input_keymap_entry *ke,
 +                       unsigned int *old_keycode)
  {
 -      int rc;
 -      unsigned long flags;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 +      unsigned int index;
 +      unsigned int scancode;
 +      int retval;
 +      unsigned long flags;
  
        spin_lock_irqsave(&rc_tab->lock, flags);
 -      rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
 +
 +      if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
 +              index = ke->index;
 +              if (index >= rc_tab->len) {
 +                      retval = -EINVAL;
 +                      goto out;
 +              }
 +      } else {
 +              retval = input_scancode_to_scalar(ke, &scancode);
 +              if (retval)
 +                      goto out;
 +
 +              index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
 +              if (index >= rc_tab->len) {
 +                      retval = -ENOMEM;
 +                      goto out;
 +              }
 +      }
 +
 +      *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
 +
 +out:
        spin_unlock_irqrestore(&rc_tab->lock, flags);
 -      return rc;
 +      return retval;
  }
  
  /**
   * @dev:      the struct input_dev device descriptor
   * @to:               the struct ir_scancode_table to copy entries to
   * @from:     the struct ir_scancode_table to copy entries from
 - * @return:   -EINVAL if all keycodes could not be inserted, otherwise zero.
 + * @return:   -ENOMEM if all keycodes could not be inserted, otherwise zero.
   *
   * This routine is used to handle table initialization.
   */
 -static int ir_setkeytable(struct input_dev *dev,
 -                        struct ir_scancode_table *to,
 +static int ir_setkeytable(struct ir_input_dev *ir_dev,
                          const struct ir_scancode_table *from)
  {
 -      struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 -      unsigned long flags;
 -      unsigned int i;
 -      int rc = 0;
 +      unsigned int i, index;
 +      int rc;
 +
 +      rc = ir_create_table(&ir_dev->rc_tab,
 +                           from->name, from->ir_type, from->size);
 +      if (rc)
 +              return rc;
 +
 +      IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
 +                 rc_tab->size, rc_tab->alloc);
  
 -      spin_lock_irqsave(&rc_tab->lock, flags);
        for (i = 0; i < from->size; i++) {
 -              rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
 -                                    from->scan[i].keycode, false);
 -              if (rc)
 +              index = ir_establish_scancode(ir_dev, rc_tab,
 +                                            from->scan[i].scancode, false);
 +              if (index >= rc_tab->len) {
 +                      rc = -ENOMEM;
                        break;
 +              }
 +
 +              ir_update_mapping(ir_dev->input_dev, rc_tab, index,
 +                                from->scan[i].keycode);
        }
 -      spin_unlock_irqrestore(&rc_tab->lock, flags);
 +
 +      if (rc)
 +              ir_free_table(rc_tab);
 +
        return rc;
  }
  
 +/**
 + * ir_lookup_by_scancode() - locate mapping by scancode
 + * @rc_tab:   the &struct ir_scancode_table to search
 + * @scancode: scancode to look for in the table
 + * @return:   index in the table, -1U if not found
 + *
 + * This routine performs binary search in RC keykeymap table for
 + * given scancode.
 + */
 +static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
 +                                        unsigned int scancode)
 +{
 +      unsigned int start = 0;
 +      unsigned int end = rc_tab->len - 1;
 +      unsigned int mid;
 +
 +      while (start <= end) {
 +              mid = (start + end) / 2;
 +              if (rc_tab->scan[mid].scancode < scancode)
 +                      start = mid + 1;
 +              else if (rc_tab->scan[mid].scancode > scancode)
 +                      end = mid - 1;
 +              else
 +                      return mid;
 +      }
 +
 +      return -1U;
 +}
 +
  /**
   * ir_getkeycode() - get a keycode from the scancode->keycode table
   * @dev:      the struct input_dev device descriptor
   * This routine is used to handle evdev EVIOCGKEY ioctl.
   */
  static int ir_getkeycode(struct input_dev *dev,
 -                       unsigned int scancode, unsigned int *keycode)
 +                       struct input_keymap_entry *ke)
  {
 -      int start, end, mid;
 -      unsigned long flags;
 -      int key = KEY_RESERVED;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 +      struct ir_scancode *entry;
 +      unsigned long flags;
 +      unsigned int index;
 +      unsigned int scancode;
 +      int retval;
  
        spin_lock_irqsave(&rc_tab->lock, flags);
 -      start = 0;
 -      end = rc_tab->len - 1;
 -      while (start <= end) {
 -              mid = (start + end) / 2;
 -              if (rc_tab->scan[mid].scancode < scancode)
 -                      start = mid + 1;
 -              else if (rc_tab->scan[mid].scancode > scancode)
 -                      end = mid - 1;
 -              else {
 -                      key = rc_tab->scan[mid].keycode;
 -                      break;
 -              }
 +
 +      if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
 +              index = ke->index;
 +      } else {
 +              retval = input_scancode_to_scalar(ke, &scancode);
 +              if (retval)
 +                      goto out;
 +
 +              index = ir_lookup_by_scancode(rc_tab, scancode);
 +      }
 +
 +      if (index >= rc_tab->len) {
 +              if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
 +                      IR_dprintk(1, "unknown key for scancode 0x%04x\n",
 +                                 scancode);
 +              retval = -EINVAL;
 +              goto out;
        }
 -      spin_unlock_irqrestore(&rc_tab->lock, flags);
  
 -      if (key == KEY_RESERVED)
 -              IR_dprintk(1, "unknown key for scancode 0x%04x\n",
 -                         scancode);
 +      entry = &rc_tab->scan[index];
  
 -      *keycode = key;
 -      return 0;
 +      ke->index = index;
 +      ke->keycode = entry->keycode;
 +      ke->len = sizeof(entry->scancode);
 +      memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
 +
 +out:
 +      spin_unlock_irqrestore(&rc_tab->lock, flags);
 +      return retval;
  }
  
  /**
   */
  u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
  {
 -      int keycode;
 +      struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 +      struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
 +      unsigned int keycode;
 +      unsigned int index;
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&rc_tab->lock, flags);
 +
 +      index = ir_lookup_by_scancode(rc_tab, scancode);
 +      keycode = index < rc_tab->len ?
 +                      rc_tab->scan[index].keycode : KEY_RESERVED;
 +
 +      spin_unlock_irqrestore(&rc_tab->lock, flags);
  
 -      ir_getkeycode(dev, scancode, &keycode);
        if (keycode != KEY_RESERVED)
                IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
                           dev->name, scancode, keycode);
 +
        return keycode;
  }
  EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
   * This routine is used to signal that a key has been released on the
   * remote control. It reports a keyup input event via input_report_key().
   */
static void ir_keyup(struct ir_input_dev *ir)
+ void ir_keyup(struct ir_input_dev *ir)
  {
        if (!ir->keypressed)
                return;
        input_sync(ir->input_dev);
        ir->keypressed = false;
  }
+ EXPORT_SYMBOL_GPL(ir_keyup);
  
  /**
   * ir_timer_keyup() - generates a keyup event after a timeout
@@@ -603,8 -454,8 +604,8 @@@ int __ir_input_register(struct input_de
                goto out_dev;
        }
  
 -      input_dev->getkeycode = ir_getkeycode;
 -      input_dev->setkeycode = ir_setkeycode;
 +      input_dev->getkeycode_new = ir_getkeycode;
 +      input_dev->setkeycode_new = ir_setkeycode;
        input_set_drvdata(input_dev, ir_dev);
        ir_dev->input_dev = input_dev;
  
        spin_lock_init(&ir_dev->keylock);
        setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
  
 -      ir_dev->rc_tab.name = rc_tab->name;
 -      ir_dev->rc_tab.ir_type = rc_tab->ir_type;
 -      ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size *
 -                                                sizeof(struct ir_scancode));
 -      ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
 -      ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
        if (props) {
                ir_dev->props = props;
                if (props->open)
                        input_dev->close = ir_close;
        }
  
 -      if (!ir_dev->rc_tab.scan) {
 -              rc = -ENOMEM;
 -              goto out_name;
 -      }
 -
 -      IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
 -                 ir_dev->rc_tab.size, ir_dev->rc_tab.alloc);
 -
        set_bit(EV_KEY, input_dev->evbit);
        set_bit(EV_REP, input_dev->evbit);
        set_bit(EV_MSC, input_dev->evbit);
        set_bit(MSC_SCAN, input_dev->mscbit);
  
 -      if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
 -              rc = -ENOMEM;
 -              goto out_table;
 -      }
 +      rc = ir_setkeytable(ir_dev, rc_tab);
 +      if (rc)
 +              goto out_name;
  
        rc = ir_register_class(input_dev);
        if (rc < 0)
                                goto out_event;
                }
  
+       rc = ir_register_input(input_dev);
+       if (rc < 0)
+               goto out_event;
        IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
                   driver_name, rc_tab->name,
                   (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
  out_event:
        ir_unregister_class(input_dev);
  out_table:
 -      kfree(ir_dev->rc_tab.scan);
 +      ir_free_table(&ir_dev->rc_tab);
  out_name:
        kfree(ir_dev->driver_name);
  out_dev:
@@@ -675,6 -545,7 +680,6 @@@ EXPORT_SYMBOL_GPL(__ir_input_register)
  void ir_input_unregister(struct input_dev *input_dev)
  {
        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
 -      struct ir_scancode_table *rc_tab;
  
        if (!ir_dev)
                return;
                if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
                        ir_raw_event_unregister(input_dev);
  
 -      rc_tab = &ir_dev->rc_tab;
 -      rc_tab->size = 0;
 -      kfree(rc_tab->scan);
 -      rc_tab->scan = NULL;
 +      ir_free_table(&ir_dev->rc_tab);
  
        ir_unregister_class(input_dev);
  
index 1983cd3f39945cbbdae6ef3a6b8b6f3618ad1b47,1d9c6b0fd0eaa1434d8c449ca9ff34d93871d568..9fc0db9d344d6458f6297cc4e015bc12d9486332
@@@ -32,6 -32,7 +32,7 @@@
  static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
  {
        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+       struct lirc_codec *lirc = &ir_dev->raw->lirc;
        int sample;
  
        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
        if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
                return -EINVAL;
  
-       if (IS_RESET(ev))
+       /* Packet start */
+       if (ev.reset)
                return 0;
  
-       IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
-                  TO_US(ev.duration), TO_STR(ev.pulse));
+       /* Carrier reports */
+       if (ev.carrier_report) {
+               sample = LIRC_FREQUENCY(ev.carrier);
  
-       sample = ev.duration / 1000;
-       if (ev.pulse)
-               sample |= PULSE_BIT;
+       /* Packet end */
+       } else if (ev.timeout) {
+               if (lirc->gap)
+                       return 0;
+               lirc->gap_start = ktime_get();
+               lirc->gap = true;
+               lirc->gap_duration = ev.duration;
+               if (!lirc->send_timeout_reports)
+                       return 0;
+               sample = LIRC_TIMEOUT(ev.duration / 1000);
+       /* Normal sample */
+       } else {
+               if (lirc->gap) {
+                       int gap_sample;
+                       lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
+                               lirc->gap_start));
+                       /* Convert to ms and cap by LIRC_VALUE_MASK */
+                       do_div(lirc->gap_duration, 1000);
+                       lirc->gap_duration = min(lirc->gap_duration,
+                                                       (u64)LIRC_VALUE_MASK);
+                       gap_sample = LIRC_SPACE(lirc->gap_duration);
+                       lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
+                                               (unsigned char *) &gap_sample);
+                       lirc->gap = false;
+               }
+               sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
+                                       LIRC_SPACE(ev.duration / 1000);
+       }
  
        lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
                          (unsigned char *) &sample);
        wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
  
        return 0;
  }
  
@@@ -102,7 -139,7 +139,7 @@@ static long ir_lirc_ioctl(struct file *
        struct ir_input_dev *ir_dev;
        int ret = 0;
        void *drv_data;
-       unsigned long val = 0;
+       __u32 val = 0, tmp;
  
        lirc = lirc_get_pdata(filep);
        if (!lirc)
        drv_data = ir_dev->props->priv;
  
        if (_IOC_DIR(cmd) & _IOC_WRITE) {
-               ret = get_user(val, (unsigned long *)arg);
+               ret = get_user(val, (__u32 *)arg);
                if (ret)
                        return ret;
        }
        case LIRC_SET_SEND_MODE:
                if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
                        return -EINVAL;
-               break;
+               return 0;
  
        /* TX settings */
        case LIRC_SET_TRANSMITTER_MASK:
-               if (ir_dev->props->s_tx_mask)
-                       ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
-               else
+               if (!ir_dev->props->s_tx_mask)
                        return -EINVAL;
-               break;
+               return ir_dev->props->s_tx_mask(drv_data, val);
  
        case LIRC_SET_SEND_CARRIER:
-               if (ir_dev->props->s_tx_carrier)
-                       ir_dev->props->s_tx_carrier(drv_data, (u32)val);
-               else
+               if (!ir_dev->props->s_tx_carrier)
                        return -EINVAL;
-               break;
+               return ir_dev->props->s_tx_carrier(drv_data, val);
  
        case LIRC_SET_SEND_DUTY_CYCLE:
                if (!ir_dev->props->s_tx_duty_cycle)
                if (val <= 0 || val >= 100)
                        return -EINVAL;
  
-               ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
-               break;
+               return ir_dev->props->s_tx_duty_cycle(drv_data, val);
  
        /* RX settings */
        case LIRC_SET_REC_CARRIER:
-               if (ir_dev->props->s_rx_carrier_range)
-                       ret = ir_dev->props->s_rx_carrier_range(
-                               ir_dev->props->priv,
-                               ir_dev->raw->lirc.carrier_low, val);
-               else
+               if (!ir_dev->props->s_rx_carrier_range)
                        return -ENOSYS;
  
-               if (!ret)
-                       ir_dev->raw->lirc.carrier_low = 0;
-               break;
+               if (val <= 0)
+                       return -EINVAL;
+               return ir_dev->props->s_rx_carrier_range(drv_data,
+                       ir_dev->raw->lirc.carrier_low, val);
  
        case LIRC_SET_REC_CARRIER_RANGE:
-               if (val >= 0)
-                       ir_dev->raw->lirc.carrier_low = val;
-               break;
+               if (val <= 0)
+                       return -EINVAL;
  
+               ir_dev->raw->lirc.carrier_low = val;
+               return 0;
  
        case LIRC_GET_REC_RESOLUTION:
                val = ir_dev->props->rx_resolution;
                break;
  
        case LIRC_SET_WIDEBAND_RECEIVER:
-               if (ir_dev->props->s_learning_mode)
-                       return ir_dev->props->s_learning_mode(
-                               ir_dev->props->priv, !!val);
-               else
+               if (!ir_dev->props->s_learning_mode)
                        return -ENOSYS;
  
+               return ir_dev->props->s_learning_mode(drv_data, !!val);
+       case LIRC_SET_MEASURE_CARRIER_MODE:
+               if (!ir_dev->props->s_carrier_report)
+                       return -ENOSYS;
+               return ir_dev->props->s_carrier_report(drv_data, !!val);
        /* Generic timeout support */
        case LIRC_GET_MIN_TIMEOUT:
                if (!ir_dev->props->max_timeout)
                break;
  
        case LIRC_SET_REC_TIMEOUT:
-               if (val < ir_dev->props->min_timeout ||
-                   val > ir_dev->props->max_timeout)
-                       return -EINVAL;
-               ir_dev->props->timeout = val * 1000;
+               if (!ir_dev->props->max_timeout)
+                       return -ENOSYS;
+               tmp = val * 1000;
+               if (tmp < ir_dev->props->min_timeout ||
+                       tmp > ir_dev->props->max_timeout)
+                               return -EINVAL;
+               ir_dev->props->timeout = tmp;
+               break;
+       case LIRC_SET_REC_TIMEOUT_REPORTS:
+               lirc->send_timeout_reports = !!val;
                break;
  
        default:
        }
  
        if (_IOC_DIR(cmd) & _IOC_READ)
-               ret = put_user(val, (unsigned long *)arg);
+               ret = put_user(val, (__u32 *)arg);
  
        return ret;
  }
@@@ -231,11 -279,13 +279,14 @@@ static struct file_operations lirc_fop
        .owner          = THIS_MODULE,
        .write          = ir_lirc_transmit_ir,
        .unlocked_ioctl = ir_lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl   = ir_lirc_ioctl,
+ #endif
        .read           = lirc_dev_fop_read,
        .poll           = lirc_dev_fop_poll,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
 +      .llseek         = no_llseek,
  };
  
  static int ir_lirc_register(struct input_dev *input_dev)
        if (ir_dev->props->s_learning_mode)
                features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
  
+       if (ir_dev->props->s_carrier_report)
+               features |= LIRC_CAN_MEASURE_CARRIER;
        if (ir_dev->props->max_timeout)
                features |= LIRC_CAN_SET_REC_TIMEOUT;
  
index 202581808bdc63087567e49c1323c08123f80d79,3ef15625fa8423972bf488a6e63e2abf15bf623f..8418b14ee4d2244ee3b6528549d0d22f35c85159
@@@ -27,6 -27,7 +27,6 @@@
  #include <linux/fs.h>
  #include <linux/poll.h>
  #include <linux/completion.h>
 -#include <linux/errno.h>
  #include <linux/mutex.h>
  #include <linux/wait.h>
  #include <linux/unistd.h>
@@@ -57,13 -58,12 +57,12 @@@ struct irctl 
  
        struct task_struct *task;
        long jiffies_to_wait;
-       struct cdev cdev;
  };
  
  static DEFINE_MUTEX(lirc_dev_lock);
  
  static struct irctl *irctls[MAX_IRCTL_DEVICES];
+ static struct cdev cdevs[MAX_IRCTL_DEVICES];
  
  /* Only used for sysfs but defined to void otherwise */
  static struct class *lirc_class;
  /*  helper function
   *  initializes the irctl structure
   */
- static void init_irctl(struct irctl *ir)
+ static void lirc_irctl_init(struct irctl *ir)
  {
-       dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
-               ir->d.name, ir->d.minor);
        mutex_init(&ir->irctl_lock);
        ir->d.minor = NOPLUG;
  }
  
- static void cleanup(struct irctl *ir)
+ static void lirc_irctl_cleanup(struct irctl *ir)
  {
        dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
  
@@@ -96,7 -94,7 +93,7 @@@
   *  reads key codes from driver and puts them into buffer
   *  returns 0 on success
   */
- static int add_to_buf(struct irctl *ir)
+ static int lirc_add_to_buf(struct irctl *ir)
  {
        if (ir->d.add_to_buf) {
                int res = -ENODATA;
@@@ -139,7 -137,7 +136,7 @@@ static int lirc_thread(void *irctl
                        }
                        if (kthread_should_stop())
                                break;
-                       if (!add_to_buf(ir))
+                       if (!lirc_add_to_buf(ir))
                                wake_up_interruptible(&ir->buf->wait_poll);
                } else {
                        set_current_state(TASK_INTERRUPTIBLE);
  }
  
  
- static struct file_operations fops = {
+ static struct file_operations lirc_dev_fops = {
        .owner          = THIS_MODULE,
        .read           = lirc_dev_fop_read,
        .write          = lirc_dev_fop_write,
        .poll           = lirc_dev_fop_poll,
        .unlocked_ioctl = lirc_dev_fop_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl   = lirc_dev_fop_ioctl,
+ #endif
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
 +      .llseek         = noop_llseek,
  };
  
  static int lirc_cdev_add(struct irctl *ir)
  {
        int retval;
        struct lirc_driver *d = &ir->d;
+       struct cdev *cdev = &cdevs[d->minor];
  
        if (d->fops) {
-               cdev_init(&ir->cdev, d->fops);
-               ir->cdev.owner = d->owner;
+               cdev_init(cdev, d->fops);
+               cdev->owner = d->owner;
        } else {
-               cdev_init(&ir->cdev, &fops);
-               ir->cdev.owner = THIS_MODULE;
+               cdev_init(cdev, &lirc_dev_fops);
+               cdev->owner = THIS_MODULE;
        }
-       kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
+       kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
  
-       retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
+       retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
        if (retval)
-               kobject_put(&ir->cdev.kobj);
+               kobject_put(&cdev->kobj);
  
        return retval;
  }
@@@ -202,6 -203,12 +203,12 @@@ int lirc_register_driver(struct lirc_dr
                goto out;
        }
  
+       if (!d->dev) {
+               printk(KERN_ERR "%s: dev pointer not filled in!\n", __func__);
+               err = -EINVAL;
+               goto out;
+       }
        if (MAX_IRCTL_DEVICES <= d->minor) {
                dev_err(d->dev, "lirc_dev: lirc_register_driver: "
                        "\"minor\" must be between 0 and %d (%d)!\n",
                err = -ENOMEM;
                goto out_lock;
        }
-       init_irctl(ir);
+       lirc_irctl_init(ir);
        irctls[minor] = ir;
        d->minor = minor;
  
                d->features = LIRC_CAN_REC_LIRCCODE;
  
        ir->d = *d;
-       ir->d.minor = minor;
  
        device_create(lirc_class, ir->d.dev,
                      MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
@@@ -357,21 -363,28 +363,28 @@@ EXPORT_SYMBOL(lirc_register_driver)
  int lirc_unregister_driver(int minor)
  {
        struct irctl *ir;
+       struct cdev *cdev;
  
        if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
-               printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
-                      "\"minor (%d)\" must be between 0 and %d!\n",
-                      minor, MAX_IRCTL_DEVICES-1);
+               printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
+                      "0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
                return -EBADRQC;
        }
  
        ir = irctls[minor];
+       if (!ir) {
+               printk(KERN_ERR "lirc_dev: %s: failed to get irctl struct "
+                      "for minor %d!\n", __func__, minor);
+               return -ENOENT;
+       }
+       cdev = &cdevs[minor];
  
        mutex_lock(&lirc_dev_lock);
  
        if (ir->d.minor != minor) {
-               printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
-                      "minor (%d) device not registered!", minor);
+               printk(KERN_ERR "lirc_dev: %s: minor (%d) device not "
+                      "registered!\n", __func__, minor);
                mutex_unlock(&lirc_dev_lock);
                return -ENOENT;
        }
                wake_up_interruptible(&ir->buf->wait_poll);
                mutex_lock(&ir->irctl_lock);
                ir->d.set_use_dec(ir->d.data);
-               module_put(ir->d.owner);
+               module_put(cdev->owner);
                mutex_unlock(&ir->irctl_lock);
-               cdev_del(&ir->cdev);
        } else {
-               cleanup(ir);
-               cdev_del(&ir->cdev);
+               lirc_irctl_cleanup(ir);
+               cdev_del(cdev);
                kfree(ir);
                irctls[minor] = NULL;
        }
@@@ -409,6 -421,7 +421,7 @@@ EXPORT_SYMBOL(lirc_unregister_driver)
  int lirc_dev_fop_open(struct inode *inode, struct file *file)
  {
        struct irctl *ir;
+       struct cdev *cdev;
        int retval = 0;
  
        if (iminor(inode) >= MAX_IRCTL_DEVICES) {
                retval = -ENODEV;
                goto error;
        }
-       file->private_data = ir;
  
        dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
  
                goto error;
        }
  
-       if (try_module_get(ir->d.owner)) {
-               ++ir->open;
+       cdev = &cdevs[iminor(inode)];
+       if (try_module_get(cdev->owner)) {
+               ir->open++;
                retval = ir->d.set_use_inc(ir->d.data);
  
                if (retval) {
-                       module_put(ir->d.owner);
-                       --ir->open;
+                       module_put(cdev->owner);
+                       ir->open--;
                } else {
                        lirc_buffer_clear(ir->buf);
                }
@@@ -460,8 -473,6 +473,8 @@@ error
  
        mutex_unlock(&lirc_dev_lock);
  
 +      nonseekable_open(inode, file);
 +
        return retval;
  }
  EXPORT_SYMBOL(lirc_dev_fop_open);
  int lirc_dev_fop_close(struct inode *inode, struct file *file)
  {
        struct irctl *ir = irctls[iminor(inode)];
+       struct cdev *cdev = &cdevs[iminor(inode)];
+       if (!ir) {
+               printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+               return -EINVAL;
+       }
  
        dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
  
        WARN_ON(mutex_lock_killable(&lirc_dev_lock));
  
-       --ir->open;
+       ir->open--;
        if (ir->attached) {
                ir->d.set_use_dec(ir->d.data);
-               module_put(ir->d.owner);
+               module_put(cdev->owner);
        } else {
-               cleanup(ir);
+               lirc_irctl_cleanup(ir);
+               cdev_del(cdev);
                irctls[ir->d.minor] = NULL;
                kfree(ir);
        }
@@@ -495,6 -513,11 +515,11 @@@ unsigned int lirc_dev_fop_poll(struct f
        struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
        unsigned int ret;
  
+       if (!ir) {
+               printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+               return POLLERR;
+       }
        dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
  
        if (!ir->attached) {
@@@ -521,9 -544,14 +546,14 @@@ EXPORT_SYMBOL(lirc_dev_fop_poll)
  
  long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
-       unsigned long mode;
+       __u32 mode;
        int result = 0;
-       struct irctl *ir = file->private_data;
+       struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
+       if (!ir) {
+               printk(KERN_ERR "lirc_dev: %s: no irctl found!\n", __func__);
+               return -ENODEV;
+       }
  
        dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
                ir->d.name, ir->d.minor, cmd);
  
        switch (cmd) {
        case LIRC_GET_FEATURES:
-               result = put_user(ir->d.features, (unsigned long *)arg);
+               result = put_user(ir->d.features, (__u32 *)arg);
                break;
        case LIRC_GET_REC_MODE:
                if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
  
                result = put_user(LIRC_REC2MODE
                                  (ir->d.features & LIRC_CAN_REC_MASK),
-                                 (unsigned long *)arg);
+                                 (__u32 *)arg);
                break;
        case LIRC_SET_REC_MODE:
                if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
                        break;
                }
  
-               result = get_user(mode, (unsigned long *)arg);
+               result = get_user(mode, (__u32 *)arg);
                if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
                        result = -EINVAL;
                /*
                 */
                break;
        case LIRC_GET_LENGTH:
-               result = put_user(ir->d.code_length, (unsigned long *)arg);
+               result = put_user(ir->d.code_length, (__u32 *)arg);
                break;
        case LIRC_GET_MIN_TIMEOUT:
                if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
                        break;
                }
  
-               result = put_user(ir->d.min_timeout, (unsigned long *)arg);
+               result = put_user(ir->d.min_timeout, (__u32 *)arg);
                break;
        case LIRC_GET_MAX_TIMEOUT:
                if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
                        break;
                }
  
-               result = put_user(ir->d.max_timeout, (unsigned long *)arg);
+               result = put_user(ir->d.max_timeout, (__u32 *)arg);
                break;
        default:
                result = -EINVAL;
@@@ -604,12 -632,21 +634,21 @@@ ssize_t lirc_dev_fop_read(struct file *
                          loff_t *ppos)
  {
        struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
-       unsigned char buf[ir->chunk_size];
+       unsigned char *buf;
        int ret = 0, written = 0;
        DECLARE_WAITQUEUE(wait, current);
  
+       if (!ir) {
+               printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+               return -ENODEV;
+       }
        dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
  
+       buf = kzalloc(ir->chunk_size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
        if (mutex_lock_interruptible(&ir->irctl_lock))
                return -ERESTARTSYS;
        if (!ir->attached) {
        mutex_unlock(&ir->irctl_lock);
  
  out_unlocked:
+       kfree(buf);
        dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
                ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
  
@@@ -709,6 -747,11 +749,11 @@@ ssize_t lirc_dev_fop_write(struct file 
  {
        struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
  
+       if (!ir) {
+               printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
+               return -ENODEV;
+       }
        dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
  
        if (!ir->attached)
index 970c9b8882d4445eecbc42961255d45c31486341,083ed151e9c9a288f34f28875f1dbd3d4ea8a6bd..1589d5a5cb4696ab2114019780866aab93622135
@@@ -702,7 -702,7 +702,7 @@@ static void dvb_frontend_stop(struct dv
  
        kthread_stop(fepriv->thread);
  
-       init_MUTEX (&fepriv->sem);
+       sema_init(&fepriv->sem, 1);
        fepriv->state = FESTATE_IDLE;
  
        /* paranoia check in case a signal arrived */
@@@ -2034,8 -2034,7 +2034,8 @@@ static const struct file_operations dvb
        .unlocked_ioctl = dvb_generic_ioctl,
        .poll           = dvb_frontend_poll,
        .open           = dvb_frontend_open,
 -      .release        = dvb_frontend_release
 +      .release        = dvb_frontend_release,
 +      .llseek         = noop_llseek,
  };
  
  int dvb_register_frontend(struct dvb_adapter* dvb,
        }
        fepriv = fe->frontend_priv;
  
-       init_MUTEX (&fepriv->sem);
+       sema_init(&fepriv->sem, 1);
        init_waitqueue_head (&fepriv->wait_queue);
        init_waitqueue_head (&fepriv->events.wait_queue);
        mutex_init(&fepriv->events.mtx);
index a12b88f53ed9dbc590e8d38707cbfbcbf5655adc,c453cd0a745ed764c0214acffe906cbd3f7b79a5..fc0a60f8a1e14b8e2fe9d200604f681b86b20389
@@@ -26,7 -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/dvb/
 + * the project's page is at http://www.linuxtv.org/ 
   */
  
  
@@@ -730,7 -730,6 +730,7 @@@ static const struct file_operations dvb
        .unlocked_ioctl = dvb_generic_ioctl,
        .open           = dvb_generic_open,
        .release        = dvb_generic_release,
 +      .llseek         = noop_llseek,
  };
  
  static struct dvb_device dvbdev_osd = {
@@@ -2291,7 -2290,12 +2291,7 @@@ static int frontend_init(struct av7110 
  /* Budgetpatch note:
   * Original hardware design by Roberto Deza:
   * There is a DVB_Wiki at
 - * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page
 - * where is described this 'DVB TT Budget Patch', on Card Modding:
 - * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch
 - * On the short description there is also a link to a external file,
 - * with more details:
 - * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip
 + * http://www.linuxtv.org/
   *
   * New software triggering design by Emard that works on
   * original Roberto Deza's hardware:
@@@ -2472,7 -2476,6 +2472,6 @@@ static int __devinit av7110_attach(stru
           get recognized before the main driver is fully loaded */
        saa7146_write(dev, GPIO_CTRL, 0x500000);
  
-       av7110->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
        strlcpy(av7110->i2c_adap.name, pci_ext->ext_priv, sizeof(av7110->i2c_adap.name));
  
        saa7146_i2c_adapter_prepare(dev, &av7110->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */
@@@ -2886,7 -2889,7 +2885,7 @@@ MODULE_DEVICE_TABLE(pci, pci_tbl)
  
  
  static struct saa7146_extension av7110_extension_driver = {
-       .name           = "dvb",
+       .name           = "av7110",
        .flags          = SAA7146_USE_I2C_IRQ,
  
        .module         = THIS_MODULE,
index 244d5d51f5f970fc950073d931b284cbed05e18a,4a31cf6746312728a17ce107564c16cb4561eba3..952b33dbac4f33e4c2ee18496d3b26f149d60192
@@@ -25,7 -25,7 +25,7 @@@
   * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
   *
   *
 - * the project's page is at http://www.linuxtv.org/dvb/
 + * the project's page is at http://www.linuxtv.org/ 
   */
  
  #include <linux/types.h>
@@@ -245,8 -245,11 +245,11 @@@ int av7110_pes_play(void *dest, struct 
                return -1;
        }
        while (1) {
-               if ((len = dvb_ringbuffer_avail(buf)) < 6)
+               len = dvb_ringbuffer_avail(buf);
+               if (len < 6) {
+                       wake_up(&buf->queue);
                        return -1;
+               }
                sync =  DVB_RINGBUFFER_PEEK(buf, 0) << 24;
                sync |= DVB_RINGBUFFER_PEEK(buf, 1) << 16;
                sync |= DVB_RINGBUFFER_PEEK(buf, 2) << 8;
@@@ -1521,7 -1524,6 +1524,7 @@@ static const struct file_operations dvb
        .open           = dvb_video_open,
        .release        = dvb_video_release,
        .poll           = dvb_video_poll,
 +      .llseek         = noop_llseek,
  };
  
  static struct dvb_device dvbdev_video = {
@@@ -1540,7 -1542,6 +1543,7 @@@ static const struct file_operations dvb
        .open           = dvb_audio_open,
        .release        = dvb_audio_release,
        .poll           = dvb_audio_poll,
 +      .llseek         = noop_llseek,
  };
  
  static struct dvb_device dvbdev_audio = {
index 054661315311c5447f3095c46708d5a683e39de9,847f6601d84216e1bec277b4ed42a92a69887974..37666d4edab679fb9e4d8a848293c985316d564a
@@@ -31,7 -31,7 +31,7 @@@
   * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
   *
   *
 - * the project's page is at http://www.linuxtv.org/dvb/
 + * the project's page is at http://www.linuxtv.org/ 
   */
  
  
@@@ -495,8 -495,6 +495,6 @@@ int ttpci_budget_init(struct budget *bu
        if (bi->type != BUDGET_FS_ACTIVY)
                saa7146_write(dev, GPIO_CTRL, 0x500000);        /* GPIO 3 = 1 */
  
-       budget->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
        strlcpy(budget->i2c_adap.name, budget->card->name, sizeof(budget->i2c_adap.name));
  
        saa7146_i2c_adapter_prepare(dev, &budget->i2c_adap, SAA7146_I2C_BUS_BIT_RATE_120);
index d000522cb0f4b43939d3504d0a4b53321b6ae37b,0efbb29a1a08872e5cfd5b35a0e12c21665d49d3..ac16e815e2750e2e8e37295b082f6a7da988a0a1
@@@ -539,7 -539,7 +539,7 @@@ config VIDEO_VI
  config VIDEO_VIVI
        tristate "Virtual Video Driver"
        depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
-       depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS
+       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
        select FONT_8x16
        select VIDEOBUF_VMALLOC
        default n
@@@ -599,68 -599,8 +599,8 @@@ config VIDEO_W996
          Check out <file:Documentation/video4linux/w9966.txt> for more
          information.
  
- config VIDEO_CPIA
-       tristate "CPiA Video For Linux (DEPRECATED)"
-       depends on VIDEO_V4L1
-       default n
-       ---help---
-         This driver is DEPRECATED please use the gspca cpia1 module
-         instead. Note that you need atleast version 0.6.4 of libv4l for
-         the cpia1 gspca module.
-         This is the video4linux driver for cameras based on Vision's CPiA
-         (Colour Processor Interface ASIC), such as the Creative Labs Video
-         Blaster Webcam II. If you have one of these cameras, say Y here
-         and select parallel port and/or USB lowlevel support below,
-         otherwise say N. This will not work with the Creative Webcam III.
-         Please read <file:Documentation/video4linux/README.cpia> for more
-         information.
-         This driver is also available as a module (cpia).
- config VIDEO_CPIA_PP
-       tristate "CPiA Parallel Port Lowlevel Support"
-       depends on PARPORT_1284 && VIDEO_CPIA && PARPORT
-       help
-         This is the lowlevel parallel port support for cameras based on
-         Vision's CPiA (Colour Processor Interface ASIC), such as the
-         Creative Webcam II. If you have the parallel port version of one
-         of these cameras, say Y here, otherwise say N. It is also available
-         as a module (cpia_pp).
- config VIDEO_CPIA_USB
-       tristate "CPiA USB Lowlevel Support"
-       depends on VIDEO_CPIA && USB
-       help
-         This is the lowlevel USB support for cameras based on Vision's CPiA
-         (Colour Processor Interface ASIC), such as the Creative Webcam II.
-         If you have the USB version of one of these cameras, say Y here,
-         otherwise say N. This will not work with the Creative Webcam III.
-         It is also available as a module (cpia_usb).
  source "drivers/media/video/cpia2/Kconfig"
  
- config VIDEO_SAA5246A
-       tristate "SAA5246A, SAA5281 Teletext processor"
-       depends on I2C && VIDEO_V4L2
-       help
-         Support for I2C bus based teletext using the SAA5246A or SAA5281
-         chip. Useful only if you live in Europe.
-         To compile this driver as a module, choose M here: the
-         module will be called saa5246a.
- config VIDEO_SAA5249
-       tristate "SAA5249 Teletext processor"
-       depends on I2C && VIDEO_V4L2
-       help
-         Support for I2C bus based teletext using the SAA5249 chip. At the
-         moment this is only useful on some European WinTV cards.
-         To compile this driver as a module, choose M here: the
-         module will be called saa5249.
  config VIDEO_VINO
        tristate "SGI Vino Video For Linux (EXPERIMENTAL)"
        depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2
          Say Y here to build in support for the Vino video input system found
          on SGI Indy machines.
  
- config VIDEO_STRADIS
-       tristate "Stradis 4:2:2 MPEG-2 video driver  (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && VIRT_TO_BUS
-       help
-         Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video
-         driver for PCI.  There is a product page at
-         <http://www.stradis.com/>.
  source "drivers/media/video/zoran/Kconfig"
  
  config VIDEO_MEYE
@@@ -774,6 -706,22 +706,22 @@@ config VIDEO_CAFE_CCI
          CMOS camera controller.  This is the controller found on first-
          generation OLPC systems.
  
+ config VIDEO_SR030PC30
+       tristate "SR030PC30 VGA camera sensor support"
+       depends on I2C && VIDEO_V4L2
+       ---help---
+         This driver supports SR030PC30 VGA camera from Siliconfile
+ config VIDEO_VIA_CAMERA
+       tristate "VIAFB camera controller support"
+       depends on FB_VIA
+       select VIDEOBUF_DMA_SG
+       select VIDEO_OV7670
+       help
+          Driver support for the integrated camera controller in VIA
+          Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
+          with ov7670 sensors.
  config SOC_CAMERA
        tristate "SoC camera support"
        depends on VIDEO_V4L2 && HAS_DMA && I2C
          over a bus like PCI or USB. For example some i2c camera connected
          directly to the data bus of an SoC.
  
+ config SOC_CAMERA_IMX074
+       tristate "imx074 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports IMX074 cameras from Sony
  config SOC_CAMERA_MT9M001
        tristate "mt9m001 support"
        depends on SOC_CAMERA && I2C
@@@ -835,6 -789,12 +789,12 @@@ config SOC_CAMERA_PLATFOR
        help
          This is a generic SoC camera platform driver, useful for testing
  
+ config SOC_CAMERA_OV6650
+       tristate "ov6650 sensor support"
+       depends on SOC_CAMERA && I2C
+       ---help---
+         This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor
  config SOC_CAMERA_OV772X
        tristate "ov772x camera support"
        depends on SOC_CAMERA && I2C
@@@ -890,6 -850,14 +850,14 @@@ config VIDEO_SH_MOBILE_CE
        ---help---
          This is a v4l2 driver for the SuperH Mobile CEU Interface
  
+ config VIDEO_OMAP1
+       tristate "OMAP1 Camera Interface driver"
+       depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA
+       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF_DMA_SG
+       ---help---
+         This is a v4l2 driver for the TI OMAP1 camera interface
  config VIDEO_OMAP2
        tristate "OMAP2 Camera Capture Interface driver"
        depends on VIDEO_DEV && ARCH_OMAP2
@@@ -978,7 -946,7 +946,7 @@@ config USB_STKWEBCA
          Supported devices are typically found in some Asus laptops,
          with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
          may be supported by the stk11xx driver, from which this is
 -        derived, see http://stk11xx.sourceforge.net
 +        derived, see <http://sourceforge.net/projects/syntekdriver/> 
  
          To compile this driver as a module, choose M here: the
          module will be called stkwebcam.
index 9536f1a40dd2e38b3327079ad88d4d7d6098db79,7c849eaf8519075a3035683cca59f174afbf557d..2934770dacc3fee149baef4a20f7d6ed770addad
@@@ -4,7 -4,7 +4,7 @@@
   * sensor.
   *
   * The data sheet for this device can be found at:
 - *    http://www.marvell.com/products/pcconn/88ALP01.jsp
 + *    http://www.marvell.com/products/pc_connectivity/88alp01/ 
   *
   * Copyright 2006 One Laptop Per Child Association, Inc.
   * Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
@@@ -25,6 -25,7 +25,7 @@@
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/fs.h>
+ #include <linux/dmi.h>
  #include <linux/mm.h>
  #include <linux/pci.h>
  #include <linux/i2c.h>
@@@ -46,6 -47,7 +47,7 @@@
  #include <asm/uaccess.h>
  #include <asm/io.h>
  
+ #include "ov7670.h"
  #include "cafe_ccic-regs.h"
  
  #define CAFE_VERSION 0x000002
@@@ -180,6 -182,7 +182,7 @@@ struct cafe_camer
        /* Current operating parameters */
        u32 sensor_type;                /* Currently ov7670 only */
        struct v4l2_pix_format pix_format;
+       enum v4l2_mbus_pixelcode mbus_code;
  
        /* Locks */
        struct mutex s_mutex; /* Access to this structure */
@@@ -207,6 -210,49 +210,49 @@@ static inline struct cafe_camera *to_ca
        return container_of(dev, struct cafe_camera, v4l2_dev);
  }
  
+ static struct cafe_format_struct {
+       __u8 *desc;
+       __u32 pixelformat;
+       int bpp;   /* Bytes per pixel */
+       enum v4l2_mbus_pixelcode mbus_code;
+ } cafe_formats[] = {
+       {
+               .desc           = "YUYV 4:2:2",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "RGB 444",
+               .pixelformat    = V4L2_PIX_FMT_RGB444,
+               .mbus_code      = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "RGB 565",
+               .pixelformat    = V4L2_PIX_FMT_RGB565,
+               .mbus_code      = V4L2_MBUS_FMT_RGB565_2X8_LE,
+               .bpp            = 2,
+       },
+       {
+               .desc           = "Raw RGB Bayer",
+               .pixelformat    = V4L2_PIX_FMT_SBGGR8,
+               .mbus_code      = V4L2_MBUS_FMT_SBGGR8_1X8,
+               .bpp            = 1
+       },
+ };
+ #define N_CAFE_FMTS ARRAY_SIZE(cafe_formats)
+ static struct cafe_format_struct *cafe_find_format(u32 pixelformat)
+ {
+       unsigned i;
+       for (i = 0; i < N_CAFE_FMTS; i++)
+               if (cafe_formats[i].pixelformat == pixelformat)
+                       return cafe_formats + i;
+       /* Not found? Then return the first format. */
+       return cafe_formats;
+ }
  
  /*
   * Start over with DMA buffers - dev_lock needed.
@@@ -319,7 -365,6 +365,6 @@@ static int cafe_smbus_write_data(struc
  {
        unsigned int rval;
        unsigned long flags;
-       DEFINE_WAIT(the_wait);
  
        spin_lock_irqsave(&cam->dev_lock, flags);
        rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID);
        cafe_reg_write(cam, REG_TWSIC1, rval);
        spin_unlock_irqrestore(&cam->dev_lock, flags);
  
+       /* Unfortunately, reading TWSIC1 too soon after sending a command
+        * causes the device to die.
+        * Use a busy-wait because we often send a large quantity of small
+        * commands at-once; using msleep() would cause a lot of context
+        * switches which take longer than 2ms, resulting in a noticable
+        * boot-time and capture-start delays.
+        */
+       mdelay(2);
        /*
-        * Time to wait for the write to complete.  THIS IS A RACY
-        * WAY TO DO IT, but the sad fact is that reading the TWSIC1
-        * register too quickly after starting the operation sends
-        * the device into a place that may be kinder and better, but
-        * which is absolutely useless for controlling the sensor.  In
-        * practice we have plenty of time to get into our sleep state
-        * before the interrupt hits, and the worst case is that we
-        * time out and then see that things completed, so this seems
-        * the best way for now.
+        * Another sad fact is that sometimes, commands silently complete but
+        * cafe_smbus_write_done() never becomes aware of this.
+        * This happens at random and appears to possible occur with any
+        * command.
+        * We don't understand why this is. We work around this issue
+        * with the timeout in the wait below, assuming that all commands
+        * complete within the timeout.
         */
-       do {
-               prepare_to_wait(&cam->smbus_wait, &the_wait,
-                               TASK_UNINTERRUPTIBLE);
-               schedule_timeout(1); /* even 1 jiffy is too long */
-               finish_wait(&cam->smbus_wait, &the_wait);
-       } while (!cafe_smbus_write_done(cam));
- #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT
        wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam),
                        CAFE_SMBUS_TIMEOUT);
- #endif
        spin_lock_irqsave(&cam->dev_lock, flags);
        rval = cafe_reg_read(cam, REG_TWSIC1);
        spin_unlock_irqrestore(&cam->dev_lock, flags);
@@@ -812,15 -856,15 +856,15 @@@ static int cafe_cam_set_flip(struct caf
  
  static int cafe_cam_configure(struct cafe_camera *cam)
  {
-       struct v4l2_format fmt;
+       struct v4l2_mbus_framefmt mbus_fmt;
        int ret;
  
        if (cam->state != S_IDLE)
                return -EINVAL;
-       fmt.fmt.pix = cam->pix_format;
+       v4l2_fill_mbus_format(&mbus_fmt, &cam->pix_format, cam->mbus_code);
        ret = sensor_call(cam, core, init, 0);
        if (ret == 0)
-               ret = sensor_call(cam, video, s_fmt, &fmt);
+               ret = sensor_call(cam, video, s_mbus_fmt, &mbus_fmt);
        /*
         * OV7670 does weird things if flip is set *before* format...
         */
@@@ -1481,7 -1525,7 +1525,7 @@@ static int cafe_vidioc_querycap(struct 
  /*
   * The default format we use until somebody says otherwise.
   */
- static struct v4l2_pix_format cafe_def_pix_format = {
+ static const struct v4l2_pix_format cafe_def_pix_format = {
        .width          = VGA_WIDTH,
        .height         = VGA_HEIGHT,
        .pixelformat    = V4L2_PIX_FMT_YUYV,
        .sizeimage      = VGA_WIDTH*VGA_HEIGHT*2,
  };
  
+ static const enum v4l2_mbus_pixelcode cafe_def_mbus_code =
+                                       V4L2_MBUS_FMT_YUYV8_2X8;
  static int cafe_vidioc_enum_fmt_vid_cap(struct file *filp,
                void *priv, struct v4l2_fmtdesc *fmt)
  {
-       struct cafe_camera *cam = priv;
-       int ret;
-       mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, enum_fmt, fmt);
-       mutex_unlock(&cam->s_mutex);
-       return ret;
+       if (fmt->index >= N_CAFE_FMTS)
+               return -EINVAL;
+       strlcpy(fmt->description, cafe_formats[fmt->index].desc,
+                       sizeof(fmt->description));
+       fmt->pixelformat = cafe_formats[fmt->index].pixelformat;
+       return 0;
  }
  
  static int cafe_vidioc_try_fmt_vid_cap(struct file *filp, void *priv,
                struct v4l2_format *fmt)
  {
        struct cafe_camera *cam = priv;
+       struct cafe_format_struct *f;
+       struct v4l2_pix_format *pix = &fmt->fmt.pix;
+       struct v4l2_mbus_framefmt mbus_fmt;
        int ret;
  
+       f = cafe_find_format(pix->pixelformat);
+       pix->pixelformat = f->pixelformat;
+       v4l2_fill_mbus_format(&mbus_fmt, pix, f->mbus_code);
        mutex_lock(&cam->s_mutex);
-       ret = sensor_call(cam, video, try_fmt, fmt);
+       ret = sensor_call(cam, video, try_mbus_fmt, &mbus_fmt);
        mutex_unlock(&cam->s_mutex);
+       v4l2_fill_pix_format(pix, &mbus_fmt);
+       pix->bytesperline = pix->width * f->bpp;
+       pix->sizeimage = pix->height * pix->bytesperline;
        return ret;
  }
  
@@@ -1519,6 -1573,7 +1573,7 @@@ static int cafe_vidioc_s_fmt_vid_cap(st
                struct v4l2_format *fmt)
  {
        struct cafe_camera *cam = priv;
+       struct cafe_format_struct *f;
        int ret;
  
        /*
         */
        if (cam->state != S_IDLE || cam->n_sbufs > 0)
                return -EBUSY;
+       f = cafe_find_format(fmt->fmt.pix.pixelformat);
        /*
         * See if the formatting works in principle.
         */
         */
        mutex_lock(&cam->s_mutex);
        cam->pix_format = fmt->fmt.pix;
+       cam->mbus_code = f->mbus_code;
        /*
         * Make sure we have appropriate DMA buffers.
         */
@@@ -1652,6 -1712,30 +1712,30 @@@ static int cafe_vidioc_g_chip_ident(str
        return sensor_call(cam, core, g_chip_ident, chip);
  }
  
+ static int cafe_vidioc_enum_framesizes(struct file *filp, void *priv,
+               struct v4l2_frmsizeenum *sizes)
+ {
+       struct cafe_camera *cam = priv;
+       int ret;
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, enum_framesizes, sizes);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+ }
+ static int cafe_vidioc_enum_frameintervals(struct file *filp, void *priv,
+               struct v4l2_frmivalenum *interval)
+ {
+       struct cafe_camera *cam = priv;
+       int ret;
+       mutex_lock(&cam->s_mutex);
+       ret = sensor_call(cam, video, enum_frameintervals, interval);
+       mutex_unlock(&cam->s_mutex);
+       return ret;
+ }
  #ifdef CONFIG_VIDEO_ADV_DEBUG
  static int cafe_vidioc_g_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg)
@@@ -1715,6 -1799,8 +1799,8 @@@ static const struct v4l2_ioctl_ops cafe
        .vidioc_s_ctrl          = cafe_vidioc_s_ctrl,
        .vidioc_g_parm          = cafe_vidioc_g_parm,
        .vidioc_s_parm          = cafe_vidioc_s_parm,
+       .vidioc_enum_framesizes = cafe_vidioc_enum_framesizes,
+       .vidioc_enum_frameintervals = cafe_vidioc_enum_frameintervals,
        .vidioc_g_chip_ident    = cafe_vidioc_g_chip_ident,
  #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register      = cafe_vidioc_g_register,
@@@ -1890,11 -1976,33 +1976,33 @@@ static irqreturn_t cafe_irq(int irq, vo
   * PCI interface stuff.
   */
  
+ static const struct dmi_system_id olpc_xo1_dmi[] = {
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "OLPC"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1"),
+               },
+       },
+       { }
+ };
  static int cafe_pci_probe(struct pci_dev *pdev,
                const struct pci_device_id *id)
  {
        int ret;
        struct cafe_camera *cam;
+       struct ov7670_config sensor_cfg = {
+               /* This controller only does SMBUS */
+               .use_smbus = true,
+               /*
+                * Exclude QCIF mode, because it only captures a tiny portion
+                * of the sensor FOV
+                */
+               .min_width = 320,
+               .min_height = 240,
+       };
  
        /*
         * Start putting together one of our big camera structures.
        init_waitqueue_head(&cam->iowait);
        cam->pdev = pdev;
        cam->pix_format = cafe_def_pix_format;
+       cam->mbus_code = cafe_def_mbus_code;
        INIT_LIST_HEAD(&cam->dev_list);
        INIT_LIST_HEAD(&cam->sb_avail);
        INIT_LIST_HEAD(&cam->sb_full);
        if (ret)
                goto out_freeirq;
  
+       /* Apply XO-1 clock speed */
+       if (dmi_check_system(olpc_xo1_dmi))
+               sensor_cfg.clock_speed = 45;
        cam->sensor_addr = 0x42;
        cam->sensor = v4l2_i2c_new_subdev(&cam->v4l2_dev, &cam->i2c_adapter,
-                       "ov7670", "ov7670", cam->sensor_addr, NULL);
+                       NULL, "ov7670", cam->sensor_addr, NULL);
        if (cam->sensor == NULL) {
                ret = -ENODEV;
                goto out_smbus;
        }
        ret = cafe_cam_init(cam);
        if (ret)
                goto out_smbus;
index 53a67824071ba3aea5441a7a82f103bfb9d5b4bb,6628e07a809382e04b50a8daa001c00e5021c1b4..a6cc12f8736c803cc1418a0fc0b4b86e3d248f66
@@@ -7,7 -7,7 +7,7 @@@
   *    (c) 2008 Steven Toth <stoth@linuxtv.org>
   *      - CX23885/7/8 support
   *
 - *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
 + *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
   *
   *  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
@@@ -1591,7 -1591,7 +1591,7 @@@ static int mpeg_open(struct file *file
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx23885_buffer),
-                           fh);
+                           fh, NULL);
        unlock_kernel();
  
        return 0;
index 660b2a927feb3d82488711572bc01b9f8a067009,ac885f49313cd90a64afd1f3a22108183ed003a4..417d1d5c73c4fead58a7c0133454debaed8a7f73
@@@ -9,7 -9,7 +9,7 @@@
   *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
   *        - video_ioctl2 conversion
   *
 - *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
 + *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
   *
   *  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
@@@ -1057,7 -1057,7 +1057,7 @@@ static int mpeg_open(struct file *file
  
        dprintk( 1, "%s\n", __func__);
  
-       lock_kernel();
+       mutex_lock(&dev->core->lock);
  
        /* Make sure we can acquire the hardware */
        drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
                err = drv->request_acquire(drv);
                if(err != 0) {
                        dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
-                       unlock_kernel();
+                       mutex_unlock(&dev->core->lock);;
                        return err;
                }
        }
        if (!atomic_read(&dev->core->mpeg_users) && blackbird_initialize_codec(dev) < 0) {
                if (drv)
                        drv->request_release(drv);
-               unlock_kernel();
+               mutex_unlock(&dev->core->lock);
                return -EINVAL;
        }
        dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
        if (NULL == fh) {
                if (drv)
                        drv->request_release(drv);
-               unlock_kernel();
+               mutex_unlock(&dev->core->lock);
                return -ENOMEM;
        }
        file->private_data = fh;
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct cx88_buffer),
-                           fh);
+                           fh, NULL);
  
        /* FIXME: locking against other video device */
        cx88_set_scale(dev->core, dev->width, dev->height,
                        fh->mpegq.field);
-       unlock_kernel();
  
        atomic_inc(&dev->core->mpeg_users);
+       mutex_unlock(&dev->core->lock);
        return 0;
  }
  
@@@ -1120,8 -1119,11 +1119,11 @@@ static int mpeg_release(struct file *fi
        videobuf_stop(&fh->mpegq);
  
        videobuf_mmap_free(&fh->mpegq);
+       mutex_lock(&dev->core->lock);
        file->private_data = NULL;
        kfree(fh);
+       mutex_unlock(&dev->core->lock);
  
        /* Make sure we release the hardware */
        drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
index b1dbcf1d2bcb6f7214e073df9a47f76625e15d80,4c9c1bb688c6c45335beb07f002fbbd6388f1fd9..94ba698d0ad4228d3d07e6653d594773c42ab3c0
@@@ -3,7 -3,7 +3,7 @@@
  
      Copyright (C) 1998-2006 Michael Hunold <michael@mihu.de>
  
 -    Visit http://www.mihu.de/linux/saa7146/mxb/
 +    Visit http://www.themm.net/~mihu/linux/saa7146/mxb.html 
      for further details about this card.
  
      This program is free software; you can redistribute it and/or modify
@@@ -32,7 -32,6 +32,6 @@@
  #include "tea6415c.h"
  #include "tea6420.h"
  
- #define       I2C_SAA5246A  0x11
  #define I2C_SAA7111A  0x24
  #define       I2C_TDA9840   0x42
  #define       I2C_TEA6415C  0x43
@@@ -186,21 -185,17 +185,17 @@@ static int mxb_probe(struct saa7146_de
        }
  
        mxb->saa7111a = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "saa7115", "saa7111", I2C_SAA7111A, NULL);
+                       NULL, "saa7111", I2C_SAA7111A, NULL);
        mxb->tea6420_1 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "tea6420", "tea6420", I2C_TEA6420_1, NULL);
+                       NULL, "tea6420", I2C_TEA6420_1, NULL);
        mxb->tea6420_2 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "tea6420", "tea6420", I2C_TEA6420_2, NULL);
+                       NULL, "tea6420", I2C_TEA6420_2, NULL);
        mxb->tea6415c = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "tea6415c", "tea6415c", I2C_TEA6415C, NULL);
+                       NULL, "tea6415c", I2C_TEA6415C, NULL);
        mxb->tda9840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "tda9840", "tda9840", I2C_TDA9840, NULL);
+                       NULL, "tda9840", I2C_TDA9840, NULL);
        mxb->tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "tuner", "tuner", I2C_TUNER, NULL);
-       if (v4l2_i2c_new_subdev(&dev->v4l2_dev, &mxb->i2c_adapter,
-                       "saa5246a", "saa5246a", I2C_SAA5246A, NULL)) {
-               printk(KERN_INFO "mxb: found teletext decoder\n");
-       }
+                       NULL, "tuner", I2C_TUNER, NULL);
  
        /* check if all devices are present */
        if (!mxb->tea6420_1 || !mxb->tea6420_2 || !mxb->tea6415c ||
index 3c471a4e3e4ad281a8a9b7b41757b31c475a0ae8,c155ddfb1332cd30e96a3f2a584cbb76b891586c..401082b853f086bbe67046a561d810fe43e8b173
@@@ -1177,7 -1177,7 +1177,7 @@@ static int setup_window(struct zoran_f
        if (height > BUZ_MAX_HEIGHT)
                height = BUZ_MAX_HEIGHT;
  
 -      /* Check for vaild parameters */
 +      /* Check for invalid parameters */
        if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||
            width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {
                dprintk(1,
@@@ -3322,7 -3322,7 +3322,7 @@@ zoran_mmap (struct file           *file
  mmap_unlock_and_return:
        mutex_unlock(&zr->resource_lock);
  
-       return 0;
+       return res;
  }
  
  static const struct v4l2_ioctl_ops zoran_ioctl_ops = {
diff --combined drivers/staging/Kconfig
index 8e03e76002393935ee1a600eac19a7824fde4f0d,078525ca19d00d86673c420b92a03c7bbeedc043..2ea91e04925577e1e336f1f478e1672c6863e9d1
@@@ -51,6 -51,10 +51,10 @@@ source "drivers/staging/cx25821/Kconfig
  
  source "drivers/staging/tm6000/Kconfig"
  
+ source "drivers/staging/cpia/Kconfig"
+ source "drivers/staging/stradis/Kconfig"
  source "drivers/staging/usbip/Kconfig"
  
  source "drivers/staging/winbond/Kconfig"
@@@ -139,6 -143,8 +143,6 @@@ source "drivers/staging/adis16255/Kconf
  
  source "drivers/staging/xgifb/Kconfig"
  
 -source "drivers/staging/mrst-touchscreen/Kconfig"
 -
  source "drivers/staging/msm/Kconfig"
  
  source "drivers/staging/lirc/Kconfig"
diff --combined drivers/staging/Makefile
index 0e7d7559d379890c9c5e509f5745c6fa3d68b15a,057adca4d04de47f934ec91365a3fd9c5f9cecd6..c359fbb0e04a5a5b763180c67bfb5bbfad1b1bfa
@@@ -8,6 -8,8 +8,8 @@@ obj-$(CONFIG_SLICOSS)            += slicoss
  obj-$(CONFIG_VIDEO_GO7007)    += go7007/
  obj-$(CONFIG_VIDEO_CX25821)   += cx25821/
  obj-$(CONFIG_VIDEO_TM6000)    += tm6000/
+ obj-$(CONFIG_VIDEO_CPIA)      += cpia/
+ obj-$(CONFIG_VIDEO_STRADIS)   += stradis/
  obj-$(CONFIG_LIRC_STAGING)    += lirc/
  obj-$(CONFIG_USB_IP_COMMON)   += usbip/
  obj-$(CONFIG_W35UND)          += winbond/
@@@ -51,6 -53,7 +53,6 @@@ obj-$(CONFIG_CXT1E1)          += cxt1e1
  obj-$(CONFIG_TI_ST)           += ti-st/
  obj-$(CONFIG_ADIS16255)               += adis16255/
  obj-$(CONFIG_FB_XGI)          += xgifb/
 -obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)    += mrst-touchscreen/
  obj-$(CONFIG_MSM_STAGING)     += msm/
  obj-$(CONFIG_EASYCAP)         += easycap/
  obj-$(CONFIG_SOLO6X10)                += solo6x10/
index 813cb355ac01645069461b022b165f79054b3ab6,a766d0bed4fbc4c6da20a5cb1b958bd5d91bd480..1d73334d2a440fbf9782a327ca397fb346a9b68a
@@@ -1,11 -1,10 +1,11 @@@
  config VIDEO_CX25821
        tristate "Conexant cx25821 support"
        depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
 +      depends on BKL # please fix
        select I2C_ALGOBIT
        select VIDEO_BTCX
        select VIDEO_TVEEPROM
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEOBUF_DVB
        select VIDEOBUF_DMA_SG
        select VIDEO_CX25840
index 75fa46805527c94313b20a89bb9ce4b5c781be58,b816a6045d0f4f712d32c480d1068dfab83c964c..3aecd30f0d1e778fc21377c8a8167cf7e70b733a
@@@ -1,10 -1,9 +1,10 @@@
  config VIDEO_GO7007
        tristate "WIS GO7007 MPEG encoder support"
        depends on VIDEO_DEV && PCI && I2C && INPUT
 +      depends on BKL # please fix
        depends on SND
        select VIDEOBUF_DMA_SG
-       select VIDEO_IR
+       depends on VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select SND_PCM
index 543c5c3bf90715f7fa2a87afee2da18772217183,20f02bc6236b362899c115e5e1f0aeca5d1f0aef..929ae579546773c5a6f1cd34fc58f908985df1dc
@@@ -239,8 -239,7 +239,7 @@@ static ssize_t lirc_write(struct file *
  static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  {
        int retval = 0;
-       unsigned long value = 0;
-       unsigned int ivalue;
+       __u32 value = 0;
        unsigned long hw_flags;
  
        if (cmd == LIRC_GET_FEATURES)
        case LIRC_GET_FEATURES:
        case LIRC_GET_SEND_MODE:
        case LIRC_GET_REC_MODE:
-               retval = put_user(value, (unsigned long *) arg);
+               retval = put_user(value, (__u32 *) arg);
                break;
  
        case LIRC_SET_SEND_MODE:
        case LIRC_SET_REC_MODE:
-               retval = get_user(value, (unsigned long *) arg);
+               retval = get_user(value, (__u32 *) arg);
                break;
  
        case LIRC_SET_SEND_CARRIER:
-               retval = get_user(ivalue, (unsigned int *) arg);
+               retval = get_user(value, (__u32 *) arg);
                if (retval)
                        return retval;
-               ivalue /= 1000;
-               if (ivalue > IT87_CIR_FREQ_MAX ||
-                   ivalue < IT87_CIR_FREQ_MIN)
+               value /= 1000;
+               if (value > IT87_CIR_FREQ_MAX ||
+                   value < IT87_CIR_FREQ_MIN)
                        return -EINVAL;
  
-               it87_freq = ivalue;
+               it87_freq = value;
  
                spin_lock_irqsave(&hardware_lock, hw_flags);
                outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) |
@@@ -340,9 -339,11 +339,12 @@@ static const struct file_operations lir
        .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)
@@@ -964,10 -965,11 +966,11 @@@ static void __exit lirc_it87_exit(void
        printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
  }
  
- /* SECTION: PNP for ITE8704/18 */
+ /* SECTION: PNP for ITE8704/13/18 */
  
  static const struct pnp_device_id pnp_dev_table[] = {
        {"ITE8704", 0},
+       {"ITE8713", 0},
        {}
  };
  
index 8da38249261295273dc609535c069dc399157331,05a9bf3980ab329f384562f44fcc82df5fa6fa23..971844bbee284a141f36d6221a29fb793a6574a9
@@@ -372,7 -372,7 +372,7 @@@ static unsigned long conv_us_to_clocks
  static int init_timing_params(unsigned int new_duty_cycle,
                unsigned int new_freq)
  {
-       unsigned long long loops_per_sec, work;
+       __u64 loops_per_sec, work;
  
        duty_cycle = new_duty_cycle;
        freq = new_freq;
@@@ -987,8 -987,7 +987,7 @@@ static ssize_t lirc_write(struct file *
  static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  {
        int result;
-       unsigned long value;
-       unsigned int ivalue;
+       __u32 value;
  
        switch (cmd) {
        case LIRC_GET_SEND_MODE:
  
                result = put_user(LIRC_SEND2MODE
                                  (hardware[type].features&LIRC_CAN_SEND_MASK),
-                                 (unsigned long *) arg);
+                                 (__u32 *) arg);
                if (result)
                        return result;
                break;
                if (!(hardware[type].features&LIRC_CAN_SEND_MASK))
                        return -ENOIOCTLCMD;
  
-               result = get_user(value, (unsigned long *) arg);
+               result = get_user(value, (__u32 *) arg);
                if (result)
                        return result;
                /* only LIRC_MODE_PULSE supported */
                if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
                        return -ENOIOCTLCMD;
  
-               result = get_user(ivalue, (unsigned int *) arg);
+               result = get_user(value, (__u32 *) arg);
                if (result)
                        return result;
-               if (ivalue <= 0 || ivalue > 100)
+               if (value <= 0 || value > 100)
                        return -EINVAL;
-               return init_timing_params(ivalue, freq);
+               return init_timing_params(value, freq);
                break;
  
        case LIRC_SET_SEND_CARRIER:
                if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER))
                        return -ENOIOCTLCMD;
  
-               result = get_user(ivalue, (unsigned int *) arg);
+               result = get_user(value, (__u32 *) arg);
                if (result)
                        return result;
-               if (ivalue > 500000 || ivalue < 20000)
+               if (value > 500000 || value < 20000)
                        return -EINVAL;
-               return init_timing_params(duty_cycle, ivalue);
+               return init_timing_params(duty_cycle, value);
                break;
  
        default:
@@@ -1054,11 -1053,13 +1053,14 @@@ static const struct file_operations lir
        .owner          = THIS_MODULE,
        .write          = lirc_write,
        .unlocked_ioctl = lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl   = lirc_ioctl,
+ #endif
        .read           = lirc_dev_fop_read,
        .poll           = lirc_dev_fop_poll,
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
 +      .llseek         = no_llseek,
  };
  
  static struct lirc_driver driver = {
index 2478871bd95efbedd72f7e09b7f6cb451ecf0f0b,c4cb3aa842db4c2a6bbe2ec53a003f82d0ac91e0..c553ab6262386ad4b68916f928ee25c770f3fbf2
@@@ -336,9 -336,8 +336,8 @@@ static ssize_t lirc_write(struct file *
  static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  {
        int retval = 0;
-       unsigned long value = 0;
+       __u32 value = 0;
  #ifdef LIRC_ON_SA1100
-       unsigned int ivalue;
  
        if (cmd == LIRC_GET_FEATURES)
                value = LIRC_CAN_SEND_PULSE |
        case LIRC_GET_FEATURES:
        case LIRC_GET_SEND_MODE:
        case LIRC_GET_REC_MODE:
-               retval = put_user(value, (unsigned long *) arg);
+               retval = put_user(value, (__u32 *) arg);
                break;
  
        case LIRC_SET_SEND_MODE:
        case LIRC_SET_REC_MODE:
-               retval = get_user(value, (unsigned long *) arg);
+               retval = get_user(value, (__u32 *) arg);
                break;
  #ifdef LIRC_ON_SA1100
        case LIRC_SET_SEND_DUTY_CYCLE:
-               retval = get_user(ivalue, (unsigned int *) arg);
+               retval = get_user(value, (__u32 *) arg);
                if (retval)
                        return retval;
-               if (ivalue <= 0 || ivalue > 100)
+               if (value <= 0 || value > 100)
                        return -EINVAL;
-               /* (ivalue/100)*(1000000/freq) */
-               duty_cycle = ivalue;
+               /* (value/100)*(1000000/freq) */
+               duty_cycle = value;
                pulse_width = (unsigned long) duty_cycle*10000/freq;
                space_width = (unsigned long) 1000000L/freq-pulse_width;
                if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
                        space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY;
                break;
        case LIRC_SET_SEND_CARRIER:
-               retval = get_user(ivalue, (unsigned int *) arg);
+               retval = get_user(value, (__u32 *) arg);
                if (retval)
                        return retval;
-               if (ivalue > 500000 || ivalue < 20000)
+               if (value > 500000 || value < 20000)
                        return -EINVAL;
-               freq = ivalue;
+               freq = value;
                pulse_width = (unsigned long) duty_cycle*10000/freq;
                space_width = (unsigned long) 1000000L/freq-pulse_width;
                if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY)
@@@ -457,9 -456,11 +456,12 @@@ static const struct file_operations lir
        .write          = lirc_write,
        .poll           = lirc_poll,
        .unlocked_ioctl = lirc_ioctl,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl   = lirc_ioctl,
+ #endif
        .open           = lirc_dev_fop_open,
        .release        = lirc_dev_fop_close,
 +      .llseek         = no_llseek,
  };
  
  static int set_use_inc(void *data)
index 3c969cdef0af90ce8ed7f1450e5cfc9e2f6cb6d5,04bec058569ca0e29713fffff2873a1a46545f9d..4b67b8e6030a1d25338a0a4159b7a7c5986751af
@@@ -283,12 -283,11 +283,12 @@@ static int hw_bitblt_2(void __iomem *en
                writel(tmp, engine + 0x1C);
        }
  
 -      if (op != VIA_BITBLT_COLOR)
 +      if (op == VIA_BITBLT_FILL) {
 +              writel(fg_color, engine + 0x58);
 +      } else if (op == VIA_BITBLT_MONO) {
                writel(fg_color, engine + 0x4C);
 -
 -      if (op == VIA_BITBLT_MONO)
                writel(bg_color, engine + 0x50);
 +      }
  
        if (op == VIA_BITBLT_FILL)
                ge_cmd |= fill_rop << 24 | 0x00002000 | 0x00000001;
        return 0;
  }
  
 -int viafb_init_engine(struct fb_info *info)
 +int viafb_setup_engine(struct fb_info *info)
  {
        struct viafb_par *viapar = info->par;
        void __iomem *engine;
 -      int highest_reg, i;
 -      u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
 -              vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
 +      u32 chip_name = viapar->shared->chip_info.gfx_chip_name;
  
        engine = viapar->shared->vdev->engine_mmio;
        if (!engine) {
                return -ENOMEM;
        }
  
 -      /* Initialize registers to reset the 2D engine */
 -      switch (viapar->shared->chip_info.twod_engine) {
 -      case VIA_2D_ENG_M1:
 -              highest_reg = 0x5c;
 -              break;
 -      default:
 -              highest_reg = 0x40;
 -              break;
 -      }
 -      for (i = 0; i <= highest_reg; i += 4)
 -              writel(0x0, engine + i);
 -
        switch (chip_name) {
        case UNICHROME_CLE266:
        case UNICHROME_K400:
                break;
        case UNICHROME_VX800:
        case UNICHROME_VX855:
 +      case UNICHROME_VX900:
                viapar->shared->hw_bitblt = hw_bitblt_2;
                break;
        default:
        viapar->shared->vq_vram_addr = viapar->fbmem_free;
        viapar->fbmem_used += VQ_SIZE;
  
- #if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE)
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
        /*
         * Set aside a chunk of framebuffer memory for the camera
         * driver.  Someday this driver probably needs a proper allocator
        viapar->shared->vdev->camera_fbmem_offset = viapar->fbmem_free;
  #endif
  
 +      viafb_reset_engine(viapar);
 +      return 0;
 +}
 +
 +void viafb_reset_engine(struct viafb_par *viapar)
 +{
 +      void __iomem *engine = viapar->shared->vdev->engine_mmio;
 +      int highest_reg, i;
 +      u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high,
 +              vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name;
 +
 +      /* Initialize registers to reset the 2D engine */
 +      switch (viapar->shared->chip_info.twod_engine) {
 +      case VIA_2D_ENG_M1:
 +              highest_reg = 0x5c;
 +              break;
 +      default:
 +              highest_reg = 0x40;
 +              break;
 +      }
 +      for (i = 0; i <= highest_reg; i += 4)
 +              writel(0x0, engine + i);
 +
        /* Init AGP and VQ regs */
        switch (chip_name) {
        case UNICHROME_K8M890:
        case UNICHROME_P4M900:
        case UNICHROME_VX800:
        case UNICHROME_VX855:
 +      case UNICHROME_VX900:
                writel(0x00100000, engine + VIA_REG_CR_TRANSET);
                writel(0x680A0000, engine + VIA_REG_CR_TRANSPACE);
                writel(0x02000000, engine + VIA_REG_CR_TRANSPACE);
        case UNICHROME_P4M900:
        case UNICHROME_VX800:
        case UNICHROME_VX855:
 +      case UNICHROME_VX900:
                vq_start_low |= 0x20000000;
                vq_end_low |= 0x20000000;
                vq_high |= 0x20000000;
        writel(0x0, engine + VIA_REG_CURSOR_ORG);
        writel(0x0, engine + VIA_REG_CURSOR_BG);
        writel(0x0, engine + VIA_REG_CURSOR_FG);
 -      return 0;
 +      return;
  }
  
  void viafb_show_hw_cursor(struct fb_info *info, int Status)
index 31e30338e89306cf7e85387d2fcc8f969e9a0ac4,27d7260d4f50d482a5aba8da9b8da0f240636e83..a3aa917095038d4afa8515a2d79d1184520e8c6e
@@@ -20,7 -20,7 +20,7 @@@
   * The default port config.
   */
  static struct via_port_cfg adap_configs[] = {
 -      [VIA_PORT_26]   = { VIA_PORT_I2C,  VIA_MODE_OFF, VIASR, 0x26 },
 +      [VIA_PORT_26]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x26 },
        [VIA_PORT_31]   = { VIA_PORT_I2C,  VIA_MODE_I2C, VIASR, 0x31 },
        [VIA_PORT_25]   = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
        [VIA_PORT_2C]   = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
@@@ -94,6 -94,13 +94,13 @@@ void viafb_irq_disable(u32 mask
  EXPORT_SYMBOL_GPL(viafb_irq_disable);
  
  /* ---------------------------------------------------------------------- */
+ /*
+  * Currently, the camera driver is the only user of the DMA code, so we
+  * only compile it in if the camera driver is being built.  Chances are,
+  * most viafb systems will not need to have this extra code for a while.
+  * As soon as another user comes long, the ifdef can be removed.
+  */
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
  /*
   * Access to the DMA engine.  This currently provides what the camera
   * driver needs (i.e. outgoing only) but is easily expandable if need
@@@ -322,7 -329,7 +329,7 @@@ int viafb_dma_copy_out_sg(unsigned int 
        return 0;
  }
  EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
+ #endif /* CONFIG_VIDEO_VIA_CAMERA */
  
  /* ---------------------------------------------------------------------- */
  /*
  static u16 via_function3[] = {
        CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
        CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
 -      P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3,
 +      P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
  };
  
  /* Get the BIOS-configured framebuffer size from PCI configuration space
@@@ -370,7 -377,6 +377,7 @@@ static int viafb_get_fb_size_from_pci(i
                case P4M900_FUNCTION3:
                case VX800_FUNCTION3:
                case VX855_FUNCTION3:
 +              case VX900_FUNCTION3:
                /*case CN750_FUNCTION3: */
                        offset = 0xA0;
                        break;
@@@ -475,10 -481,7 +482,10 @@@ static int __devinit via_pci_setup_mmio
         * Eventually we want to move away from mapping this
         * entire region.
         */
 -      vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
 +      if (vdev->chip_type == UNICHROME_VX900)
 +              vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
 +      else
 +              vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
        ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
        if (ret < 0)
                goto out_unmap;
@@@ -511,7 -514,12 +518,12 @@@ static struct viafb_subdev_info 
        },
        {
                .name = "viafb-i2c",
-       }
+       },
+ #if defined(CONFIG_VIDEO_VIA_CAMERA) || defined(CONFIG_VIDEO_VIA_CAMERA_MODULE)
+       {
+               .name = "viafb-camera",
+       },
+ #endif
  };
  #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
  
@@@ -639,8 -647,6 +651,8 @@@ static struct pci_device_id via_pci_tab
          .driver_data = UNICHROME_VX800 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
          .driver_data = UNICHROME_VX855 },
 +      { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
 +        .driver_data = UNICHROME_VX900 },
        { }
  };
  MODULE_DEVICE_TABLE(pci, via_pci_table);
@@@ -650,10 -656,6 +662,10 @@@ static struct pci_driver via_driver = 
        .id_table       = via_pci_table,
        .probe          = via_pci_probe,
        .remove         = __devexit_p(via_pci_remove),
 +#ifdef CONFIG_PM
 +      .suspend        = viafb_suspend,
 +      .resume         = viafb_resume,
 +#endif
  };
  
  static int __init via_core_init(void)
diff --combined include/linux/Kbuild
index 831c4634162c6eb8db5dd72fe830a57c3c9a95fb,38a9f502baef7bd670a9a7852013a318ae3ee3ae..05a59f0ce37a50c78c740f120eb327eeb6d988bb
@@@ -301,7 -301,6 +301,7 @@@ header-y += quota.
  header-y += radeonfb.h
  header-y += random.h
  header-y += raw.h
 +header-y += rds.h
  header-y += reboot.h
  header-y += reiserfs_fs.h
  header-y += reiserfs_xattr.h
@@@ -372,7 -371,6 +372,6 @@@ header-y += veth.
  header-y += vhost.h
  header-y += videodev.h
  header-y += videodev2.h
- header-y += videotext.h
  header-y += virtio_9p.h
  header-y += virtio_balloon.h
  header-y += virtio_blk.h
diff --combined include/media/rc-map.h
index 9b201ec8dc7f1e2abb79b7b5205292c8755e4f0f,25883cfc311815dae1b99bbf91104af350647669..e0f17edf38ed58a6d9bb1289b286ba220289b82a
  #define IR_TYPE_RC6   (1  << 2)       /* Philips RC6 protocol */
  #define IR_TYPE_JVC   (1  << 3)       /* JVC protocol */
  #define IR_TYPE_SONY  (1  << 4)       /* Sony12/15/20 protocol */
+ #define IR_TYPE_RC5_SZ        (1  << 5)       /* RC5 variant used by Streamzap */
  #define IR_TYPE_LIRC  (1  << 30)      /* Pass raw IR to lirc userspace */
  #define IR_TYPE_OTHER (1u << 31)
  
  #define IR_TYPE_ALL (IR_TYPE_RC5 | IR_TYPE_NEC  | IR_TYPE_RC6  | \
                     IR_TYPE_JVC | IR_TYPE_SONY | IR_TYPE_LIRC | \
-                    IR_TYPE_OTHER)
+                    IR_TYPE_RC5_SZ | IR_TYPE_OTHER)
  
  struct ir_scancode {
        u32     scancode;
@@@ -35,7 -36,7 +36,7 @@@ struct ir_scancode_table 
        unsigned int            len;    /* Used number of entries */
        unsigned int            alloc;  /* Size of *scan in bytes */
        u64                     ir_type;
 -      char                    *name;
 +      const char              *name;
        spinlock_t              lock;
  };
  
@@@ -54,6 -55,8 +55,8 @@@ void rc_map_init(void)
  /* Names of the several keytables defined in-kernel */
  
  #define RC_MAP_ADSTECH_DVB_T_PCI         "rc-adstech-dvb-t-pci"
+ #define RC_MAP_ALINK_DTU_M               "rc-alink-dtu-m"
+ #define RC_MAP_ANYSEE                    "rc-anysee"
  #define RC_MAP_APAC_VIEWCOMP             "rc-apac-viewcomp"
  #define RC_MAP_ASUS_PC39                 "rc-asus-pc39"
  #define RC_MAP_ATI_TV_WONDER_HD_600      "rc-ati-tv-wonder-hd-600"
  #define RC_MAP_AVERMEDIA_DVBT            "rc-avermedia-dvbt"
  #define RC_MAP_AVERMEDIA_M135A           "rc-avermedia-m135a"
  #define RC_MAP_AVERMEDIA_M733A_RM_K6     "rc-avermedia-m733a-rm-k6"
+ #define RC_MAP_AVERMEDIA_RM_KS           "rc-avermedia-rm-ks"
  #define RC_MAP_AVERMEDIA                 "rc-avermedia"
  #define RC_MAP_AVERTV_303                "rc-avertv-303"
+ #define RC_MAP_AZUREWAVE_AD_TU700        "rc-azurewave-ad-tu700"
  #define RC_MAP_BEHOLD_COLUMBUS           "rc-behold-columbus"
  #define RC_MAP_BEHOLD                    "rc-behold"
  #define RC_MAP_BUDGET_CI_OLD             "rc-budget-ci-old"
@@@ -71,6 -76,8 +76,8 @@@
  #define RC_MAP_CINERGY                   "rc-cinergy"
  #define RC_MAP_DIB0700_NEC_TABLE         "rc-dib0700-nec"
  #define RC_MAP_DIB0700_RC5_TABLE         "rc-dib0700-rc5"
+ #define RC_MAP_DIGITALNOW_TINYTWIN       "rc-digitalnow-tinytwin"
+ #define RC_MAP_DIGITTRADE                "rc-digittrade"
  #define RC_MAP_DM1105_NEC                "rc-dm1105-nec"
  #define RC_MAP_DNTV_LIVE_DVBT_PRO        "rc-dntv-live-dvbt-pro"
  #define RC_MAP_DNTV_LIVE_DVB_T           "rc-dntv-live-dvb-t"
  #define RC_MAP_KAIOMY                    "rc-kaiomy"
  #define RC_MAP_KWORLD_315U               "rc-kworld-315u"
  #define RC_MAP_KWORLD_PLUS_TV_ANALOG     "rc-kworld-plus-tv-analog"
+ #define RC_MAP_LEADTEK_Y04G0051          "rc-leadtek-y04g0051"
  #define RC_MAP_LIRC                      "rc-lirc"
+ #define RC_MAP_LME2510                   "rc-lme2510"
  #define RC_MAP_MANLI                     "rc-manli"
+ #define RC_MAP_MSI_DIGIVOX_II            "rc-msi-digivox-ii"
+ #define RC_MAP_MSI_DIGIVOX_III           "rc-msi-digivox-iii"
  #define RC_MAP_MSI_TVANYWHERE_PLUS       "rc-msi-tvanywhere-plus"
  #define RC_MAP_MSI_TVANYWHERE            "rc-msi-tvanywhere"
  #define RC_MAP_NEBULA                    "rc-nebula"
  #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_RC5_STREAMZAP             "rc-rc5-streamzap"
  #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"
+ #define RC_MAP_STREAMZAP                 "rc-streamzap"
  #define RC_MAP_TBS_NEC                   "rc-tbs-nec"
  #define RC_MAP_TERRATEC_CINERGY_XS       "rc-terratec-cinergy-xs"
+ #define RC_MAP_TERRATEC_SLIM             "rc-terratec-slim"
  #define RC_MAP_TEVII_NEC                 "rc-tevii-nec"
+ #define RC_MAP_TOTAL_MEDIA_IN_HAND       "rc-total-media-in-hand"
+ #define RC_MAP_TREKSTOR                  "rc-trekstor"
  #define RC_MAP_TT_1500                   "rc-tt-1500"
+ #define RC_MAP_TWINHAN_VP1027_DVBS       "rc-twinhan1027"
  #define RC_MAP_VIDEOMATE_S350            "rc-videomate-s350"
  #define RC_MAP_VIDEOMATE_TV_PVR          "rc-videomate-tv-pvr"
  #define RC_MAP_WINFAST                   "rc-winfast"