diff options
Diffstat (limited to 'drivers/input')
97 files changed, 1003 insertions, 150 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9f9816baeb9..2ee6c7a68bd 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -515,7 +515,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct input_absinfo abs; struct ff_effect effect; int __user *ip = (int __user *)p; - int i, t, u, v; + unsigned int i, t, u, v; int error; switch (cmd) { diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index b2f07aa1604..03078c08309 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/sched.h> +#include <linux/slab.h> /* * Check that the effect_id is a valid effect and whether the user diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index f967008f332..1d881c96ba8 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -25,6 +25,7 @@ #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) +#include <linux/slab.h> #include <linux/input.h> #include <linux/module.h> #include <linux/mutex.h> diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c index 06ad36ed348..85d6ee09f11 100644 --- a/drivers/input/gameport/lightning.c +++ b/drivers/input/gameport/lightning.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/gameport.h> -#include <linux/slab.h> #define L4_PORT 0x201 #define L4_SELECT_ANALOG 0xa4 diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 291d9393d35..10c9b0a845f 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -9,6 +9,7 @@ */ #include <linux/jiffies.h> +#include <linux/slab.h> #include <linux/mutex.h> #include <linux/input-polldev.h> diff --git a/drivers/input/input.c b/drivers/input/input.c index 41168d5f8c1..9c79bd56b51 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -14,6 +14,7 @@ #include <linux/types.h> #include <linux/input.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/random.h> #include <linux/major.h> #include <linux/proc_fs.h> @@ -582,7 +583,8 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) } static int input_default_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { if (!dev->keycodesize) return -EINVAL; @@ -596,7 +598,8 @@ static int input_default_getkeycode(struct input_dev *dev, } static int input_default_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int old_keycode; int i; @@ -654,12 +657,17 @@ static int input_default_setkeycode(struct input_dev *dev, * This function should be called by anyone interested in retrieving current * keymap. Presently keyboard and evdev handlers use it. */ -int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) +int input_get_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { - if (scancode < 0) - return -EINVAL; + unsigned long flags; + int retval; + + spin_lock_irqsave(&dev->event_lock, flags); + retval = dev->getkeycode(dev, scancode, keycode); + spin_unlock_irqrestore(&dev->event_lock, flags); - return dev->getkeycode(dev, scancode, keycode); + return retval; } EXPORT_SYMBOL(input_get_keycode); @@ -672,16 +680,14 @@ EXPORT_SYMBOL(input_get_keycode); * This function should be called by anyone needing to update current * keymap. Presently keyboard and evdev handlers use it. */ -int input_set_keycode(struct input_dev *dev, int scancode, int keycode) +int input_set_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { unsigned long flags; int old_keycode; int retval; - if (scancode < 0) - return -EINVAL; - - if (keycode < 0 || keycode > KEY_MAX) + if (keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); @@ -1881,35 +1887,37 @@ static int input_open_file(struct inode *inode, struct file *file) const struct file_operations *old_fops, *new_fops = NULL; int err; - lock_kernel(); + err = mutex_lock_interruptible(&input_mutex); + if (err) + return err; + /* No load-on-demand here? */ handler = input_table[iminor(inode) >> 5]; - if (!handler || !(new_fops = fops_get(handler->fops))) { - err = -ENODEV; - goto out; - } + if (handler) + new_fops = fops_get(handler->fops); + + mutex_unlock(&input_mutex); /* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */ - if (!new_fops->open) { + if (!new_fops || !new_fops->open) { fops_put(new_fops); err = -ENODEV; goto out; } + old_fops = file->f_op; file->f_op = new_fops; err = new_fops->open(inode, file); - if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } fops_put(old_fops); out: - unlock_kernel(); return err; } diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 52395948475..8e7de5c7754 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -36,6 +36,7 @@ #include <linux/parport.h> #include <linux/input.h> #include <linux/mutex.h> +#include <linux/slab.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index ae998d99a5a..fbd62abb66f 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -39,6 +39,7 @@ #include <linux/parport.h> #include <linux/input.h> #include <linux/mutex.h> +#include <linux/slab.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); @@ -819,7 +820,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) int i; int err; - if (pad_type < 1 || pad_type > GC_MAX) { + if (pad_type < 1 || pad_type >= GC_MAX) { pr_err("Pad type %d unknown\n", pad_type); return -EINVAL; } diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index b6f85986954..d53b9e90023 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -35,6 +35,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/mutex.h> +#include <linux/slab.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index a7ba27fb410..3db8006dac3 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -12,6 +12,7 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/mfd/adp5520.h> +#include <linux/slab.h> struct adp5520_keys { struct input_dev *input; diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index b5142d2d511..4771ab172b5 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/i2c.h> +#include <linux/slab.h> #include <linux/i2c/adp5588.h> diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fe376a27fe5..7d989603f87 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -34,6 +34,7 @@ #include <linux/fs.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/slab.h> #include <linux/sched.h> #include <linux/pm.h> #include <linux/sysctl.h> @@ -162,7 +163,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) input_sync(input); if (bfin_kpad_get_keypressed(bf54x_kpad)) { - disable_irq(bf54x_kpad->irq); + disable_irq_nosync(bf54x_kpad->irq); bf54x_kpad->lastkey = key; mod_timer(&bf54x_kpad->timer, jiffies + bf54x_kpad->keyup_test_jiffies); diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index d410d7a52f1..a91ee941b5c 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -30,6 +30,7 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/errno.h> +#include <linux/slab.h> #include <asm/irq.h> diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index bd25a3af166..c8242dd190d 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -25,6 +25,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/input/matrix_keypad.h> +#include <linux/slab.h> #include <mach/hardware.h> #include <mach/ep93xx_keypad.h> diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2b708aa8555..b8213fd13c3 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -16,6 +16,7 @@ #include <linux/irq.h> #include <linux/sched.h> #include <linux/pm.h> +#include <linux/slab.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/delay.h> diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 2ee5b798024..d92c15c39e6 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -21,6 +21,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <linux/timer.h> /* diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 781fc610286..5fc976dbce0 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <asm/delay.h> #include <asm/io.h> diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 4e016d82306..2cd3e1d56ea 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <mach/jornada720.h> #include <mach/hardware.h> diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 574eda2a495..60ac4684f87 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -31,6 +31,7 @@ #include <linux/input.h> #include <linux/leds.h> #include <linux/i2c/lm8323.h> +#include <linux/slab.h> /* Commands to send to the chip. */ #define LM8323_CMD_READ_ID 0x80 /* Read chip ID. */ diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 9caed30f3bb..b1ab29861e1 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -192,11 +192,18 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd) static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) { struct locomokbd *locomokbd = dev_id; + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC); + if ((r & 0x0001) == 0) + return IRQ_HANDLED; + + locomo_writel(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */ + /** wait chattering delay **/ udelay(100); locomokbd_scankeyboard(locomokbd); - return IRQ_HANDLED; } @@ -210,6 +217,25 @@ static void locomokbd_timer_callback(unsigned long data) locomokbd_scankeyboard(locomokbd); } +static int locomokbd_open(struct input_dev *dev) +{ + struct locomokbd *locomokbd = input_get_drvdata(dev); + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC) | 0x0010; + locomo_writel(r, locomokbd->base + LOCOMO_KIC); + return 0; +} + +static void locomokbd_close(struct input_dev *dev) +{ + struct locomokbd *locomokbd = input_get_drvdata(dev); + u16 r; + + r = locomo_readl(locomokbd->base + LOCOMO_KIC) & ~0x0010; + locomo_writel(r, locomokbd->base + LOCOMO_KIC); +} + static int __devinit locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; @@ -253,6 +279,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; input_dev->id.version = 0x0100; + input_dev->open = locomokbd_open; + input_dev->close = locomokbd_close; input_dev->dev.parent = &dev->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | @@ -261,6 +289,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) input_dev->keycodesize = sizeof(locomokbd_keycode[0]); input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode); + input_set_drvdata(input_dev, locomokbd); + memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode)); for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) set_bit(locomokbd->keycode[i], input_dev->keybit); diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index d3c8b61a941..b443e088fd3 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -22,6 +22,7 @@ #include <linux/module.h> #include <linux/gpio.h> #include <linux/input/matrix_keypad.h> +#include <linux/slab.h> struct matrix_keypad { const struct matrix_keypad_platform_data *pdata; @@ -373,7 +374,9 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); + input_dev->evbit[0] = BIT_MASK(EV_KEY); + if (!pdata->no_autorepeat) + input_dev->evbit[0] |= BIT_MASK(EV_REP); input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 3b5b948eba3..7fc8185e5c1 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/i2c.h> +#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/input/matrix_keypad.h> diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 1a494d50543..a72e61ddca9 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -34,6 +34,7 @@ #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/errno.h> +#include <linux/slab.h> #include <mach/gpio.h> #include <plat/keypad.h> #include <plat/menelaus.h> diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 78cccddbf55..1f1a5563f60 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> struct opencores_kbd { struct input_dev *input; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 79cd3e9fdf2..0e53b3bc39a 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -26,6 +26,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/input/matrix_keypad.h> +#include <linux/slab.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 95fbba470e6..b7123a44b6e 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -13,6 +13,7 @@ #include <linux/input.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> #include <mach/pxa930_rotary.h> diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 854e2035cd6..d7dafd9425b 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -22,6 +22,7 @@ #include <linux/bitmap.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/slab.h> static const struct { unsigned char kymd, keyout, keyin; diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 42cb3faf733..3910f269cfc 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c @@ -18,6 +18,7 @@ #include <linux/input.h> #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <mach/gpio.h> #include <mach/tosa.h> diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 21d6184efa9..7aa59e07b68 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -32,6 +32,7 @@ #include <linux/input.h> #include <linux/platform_device.h> #include <linux/i2c/twl.h> +#include <linux/slab.h> /* diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 6032def0370..4ef764cc493 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -19,6 +19,7 @@ #include <linux/clk.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/slab.h> #include <mach/w90p910_keypad.h> diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c new file mode 100644 index 00000000000..40dabd8487b --- /dev/null +++ b/drivers/input/misc/88pm860x_onkey.c @@ -0,0 +1,156 @@ +/* + * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver + * + * Copyright (C) 2009-2010 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/mfd/88pm860x.h> +#include <linux/slab.h> + +#define PM8607_WAKEUP 0x0b + +#define LONG_ONKEY_EN (1 << 1) +#define ONKEY_STATUS (1 << 0) + +struct pm860x_onkey_info { + struct input_dev *idev; + struct pm860x_chip *chip; + struct i2c_client *i2c; + struct device *dev; + int irq; +}; + +/* 88PM860x gives us an interrupt when ONKEY is held */ +static irqreturn_t pm860x_onkey_handler(int irq, void *data) +{ + struct pm860x_onkey_info *info = data; + int ret; + + ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); + ret &= ONKEY_STATUS; + input_report_key(info->idev, KEY_POWER, ret); + input_sync(info->idev); + + /* Enable 8-second long onkey detection */ + pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN); + return IRQ_HANDLED; +} + +static int __devinit pm860x_onkey_probe(struct platform_device *pdev) +{ + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm860x_onkey_info *info; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "No IRQ resource!\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->chip = chip; + info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; + info->dev = &pdev->dev; + info->irq = irq + chip->irq_base; + + info->idev = input_allocate_device(); + if (!info->idev) { + dev_err(chip->dev, "Failed to allocate input dev\n"); + ret = -ENOMEM; + goto out; + } + + info->idev->name = "88pm860x_on"; + info->idev->phys = "88pm860x_on/input0"; + info->idev->id.bustype = BUS_I2C; + info->idev->dev.parent = &pdev->dev; + info->irq = irq; + info->idev->evbit[0] = BIT_MASK(EV_KEY); + info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); + + ret = input_register_device(info->idev); + if (ret) { + dev_err(chip->dev, "Can't register input device: %d\n", ret); + goto out_reg; + } + + ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler, + IRQF_ONESHOT, "onkey", info); + if (ret < 0) { + dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", + info->irq, ret); + goto out_irq; + } + + platform_set_drvdata(pdev, info); + return 0; + +out_irq: + input_unregister_device(info->idev); + kfree(info); + return ret; + +out_reg: + input_free_device(info->idev); +out: + kfree(info); + return ret; +} + +static int __devexit pm860x_onkey_remove(struct platform_device *pdev) +{ + struct pm860x_onkey_info *info = platform_get_drvdata(pdev); + + free_irq(info->irq, info); + input_unregister_device(info->idev); + kfree(info); + return 0; +} + +static struct platform_driver pm860x_onkey_driver = { + .driver = { + .name = "88pm860x-onkey", + .owner = THIS_MODULE, + }, + .probe = pm860x_onkey_probe, + .remove = __devexit_p(pm860x_onkey_remove), +}; + +static int __init pm860x_onkey_init(void) +{ + return platform_driver_register(&pm860x_onkey_driver); +} +module_init(pm860x_onkey_init); + +static void __exit pm860x_onkey_exit(void) +{ + platform_driver_unregister(&pm860x_onkey_driver); +} +module_exit(pm860x_onkey_exit); + +MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver"); +MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 16ec5233441..23140a3bb8e 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -12,6 +12,16 @@ menuconfig INPUT_MISC if INPUT_MISC +config INPUT_88PM860X_ONKEY + tristate "88PM860x ONKEY support" + depends on MFD_88PM860X + help + Support the ONKEY of Marvell 88PM860x PMICs as an input device + reporting power button status. + + To compile this driver as a module, choose M here: the module + will be called 88pm860x_onkey. + config INPUT_PCSPKR tristate "PC Speaker support" depends on PCSPKR_PLATFORM @@ -204,6 +214,17 @@ config INPUT_TWL4030_PWRBUTTON To compile this driver as a module, choose M here. The module will be called twl4030_pwrbutton. +config INPUT_TWL4030_VIBRA + tristate "Support for TWL4030 Vibrator" + depends on TWL4030_CORE + select TWL4030_CODEC + select INPUT_FF_MEMLESS + help + This option enables support for TWL4030 Vibrator Driver. + + To compile this driver as a module, choose M here. The module will + be called twl4030_vibra. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index a8b84854fb7..7e95a5d474d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -4,6 +4,7 @@ # Each configuration option enables a list of files. +obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o obj-$(CONFIG_INPUT_APANEL) += apanel.o obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o @@ -25,6 +26,7 @@ obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o +obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0501f0e6515..2124b99378b 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -10,6 +10,7 @@ */ #include <linux/usb/input.h> +#include <linux/slab.h> #define DRIVER_DESC "ATI/Philips USB RF remote driver" #define DRIVER_VERSION "0.3" @@ -474,10 +475,11 @@ static void ati_remote2_complete_key(struct urb *urb) } static int ati_remote2_getkeycode(struct input_dev *idev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode; + unsigned int mode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -491,10 +493,12 @@ static int ati_remote2_getkeycode(struct input_dev *idev, return 0; } -static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) +static int ati_remote2_setkeycode(struct input_dev *idev, + unsigned int scancode, unsigned int keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode, old_keycode; + unsigned int mode, old_keycode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -504,9 +508,6 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc if (index < 0) return -EINVAL; - if (keycode < KEY_RESERVED || keycode > KEY_MAX) - return -EINVAL; - old_keycode = ar2->keycode[mode][index]; ar2->keycode[mode][index] = keycode; __set_bit(keycode, idev->keybit); diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index 61d10177fa8..4f72bdd6941 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -13,6 +13,7 @@ #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/input.h> +#include <linux/slab.h> #include <asm/portmux.h> #include <asm/bfin_rotary.h> diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index ee73d7219c9..fd8407a2963 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -22,6 +22,7 @@ #include <linux/ioport.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #define BUTTONS_POLL_INTERVAL 30 /* msec */ #define BUTTONS_COUNT_THRESHOLD 3 diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index 766c06911f4..19af682c24f 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/input.h> #include <linux/input/sparse-keymap.h> #include <linux/platform_device.h> diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 7ea969347ca..99335c28625 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/input.h> #include <linux/mfd/ezx-pcap.h> +#include <linux/slab.h> struct pcap_keys { struct pcap_chip *pcap; diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 008de0c5834..95562735728 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -20,6 +20,7 @@ #include <linux/device.h> #include <linux/platform_device.h> #include <linux/input.h> +#include <linux/slab.h> #include <linux/mfd/pcf50633/core.h> diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 4ae07935985..1f8e0108962 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/rotary_encoder.h> +#include <linux/slab.h> #define DRV_NAME "rotary-encoder" diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index be3a15f5b25..1a80c0dab83 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -22,6 +22,7 @@ #include <linux/ioport.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/slab.h> #ifdef CONFIG_SGI_IP22 #include <asm/sgi/ioc.h> diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index b064419b90a..0d45422f809 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -9,6 +9,7 @@ #include <linux/init.h> #include <linux/input.h> #include <linux/of_device.h> +#include <linux/slab.h> #include <asm/io.h> diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c new file mode 100644 index 00000000000..fee9eac8e04 --- /dev/null +++ b/drivers/input/misc/twl4030-vibra.c @@ -0,0 +1,298 @@ +/* + * twl4030-vibra.c - TWL4030 Vibrator driver + * + * Copyright (C) 2008-2010 Nokia Corporation + * + * Written by Henrik Saari <henrik.saari@nokia.com> + * Updates by Felipe Balbi <felipe.balbi@nokia.com> + * Input by Jari Vanhala <ext-jari.vanhala@nokia.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/i2c/twl.h> +#include <linux/mfd/twl4030-codec.h> +#include <linux/input.h> +#include <linux/slab.h> + +/* MODULE ID2 */ +#define LEDEN 0x00 + +/* ForceFeedback */ +#define EFFECT_DIR_180_DEG 0x8000 /* range is 0 - 0xFFFF */ + +struct vibra_info { + struct device *dev; + struct input_dev *input_dev; + + struct workqueue_struct *workqueue; + struct work_struct play_work; + + bool enabled; + int speed; + int direction; + + bool coexist; +}; + +static void vibra_disable_leds(void) +{ + u8 reg; + + /* Disable LEDA & LEDB, cannot be used with vibra (PWM) */ + twl_i2c_read_u8(TWL4030_MODULE_LED, ®, LEDEN); + reg &= ~0x03; + twl_i2c_write_u8(TWL4030_MODULE_LED, LEDEN, reg); +} + +/* Powers H-Bridge and enables audio clk */ +static void vibra_enable(struct vibra_info *info) +{ + u8 reg; + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); + + /* turn H-Bridge on */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = true; +} + +static void vibra_disable(struct vibra_info *info) +{ + u8 reg; + + /* Power down H-Bridge */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); + twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = false; +} + +static void vibra_play_work(struct work_struct *work) +{ + struct vibra_info *info = container_of(work, + struct vibra_info, play_work); + int dir; + int pwm; + u8 reg; + + dir = info->direction; + pwm = info->speed; + + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { + + if (!info->enabled) + vibra_enable(info); + + /* set vibra rotation direction */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : + (reg & ~TWL4030_VIBRA_DIR); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg, TWL4030_REG_VIBRA_CTL); + + /* set PWM, 1 = max, 255 = min */ + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + 256 - pwm, TWL4030_REG_VIBRA_SET); + } else { + if (info->enabled) + vibra_disable(info); + } +} + +/*** Input/ForceFeedback ***/ + +static int vibra_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->speed = effect->u.rumble.strong_magnitude >> 8; + if (!info->speed) + info->speed = effect->u.rumble.weak_magnitude >> 9; + info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; + queue_work(info->workqueue, &info->play_work); + return 0; +} + +static int twl4030_vibra_open(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->workqueue = create_singlethread_workqueue("vibra"); + if (info->workqueue == NULL) { + dev_err(&input->dev, "couldn't create workqueue\n"); + return -ENOMEM; + } + return 0; +} + +static void twl4030_vibra_close(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + cancel_work_sync(&info->play_work); + INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ + destroy_workqueue(info->workqueue); + info->workqueue = NULL; + + if (info->enabled) + vibra_disable(info); +} + +/*** Module ***/ +#if CONFIG_PM +static int twl4030_vibra_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vibra_info *info = platform_get_drvdata(pdev); + + if (info->enabled) + vibra_disable(info); + + return 0; +} + +static int twl4030_vibra_resume(struct device *dev) +{ + vibra_disable_leds(); + return 0; +} + +static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, + twl4030_vibra_suspend, twl4030_vibra_resume); +#endif + +static int __devinit twl4030_vibra_probe(struct platform_device *pdev) +{ + struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; + struct vibra_info *info; + int ret; + + if (!pdata) { + dev_dbg(&pdev->dev, "platform_data not available\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = &pdev->dev; + info->coexist = pdata->coexist; + INIT_WORK(&info->play_work, vibra_play_work); + + info->input_dev = input_allocate_device(); + if (info->input_dev == NULL) { + dev_err(&pdev->dev, "couldn't allocate input device\n"); + ret = -ENOMEM; + goto err_kzalloc; + } + + input_set_drvdata(info->input_dev, info); + + info->input_dev->name = "twl4030:vibrator"; + info->input_dev->id.version = 1; + info->input_dev->dev.parent = pdev->dev.parent; + info->input_dev->open = twl4030_vibra_open; + info->input_dev->close = twl4030_vibra_close; + __set_bit(FF_RUMBLE, info->input_dev->ffbit); + + ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); + goto err_ialloc; + } + + ret = input_register_device(info->input_dev); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register input device\n"); + goto err_iff; + } + + vibra_disable_leds(); + + platform_set_drvdata(pdev, info); + return 0; + +err_iff: + input_ff_destroy(info->input_dev); +err_ialloc: + input_free_device(info->input_dev); +err_kzalloc: + kfree(info); + return ret; +} + +static int __devexit twl4030_vibra_remove(struct platform_device *pdev) +{ + struct vibra_info *info = platform_get_drvdata(pdev); + + /* this also free ff-memless and calls close if needed */ + input_unregister_device(info->input_dev); + kfree(info); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver twl4030_vibra_driver = { + .probe = twl4030_vibra_probe, + .remove = __devexit_p(twl4030_vibra_remove), + .driver = { + .name = "twl4030_codec_vibra", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &twl4030_vibra_pm_ops, +#endif + }, +}; + +static int __init twl4030_vibra_init(void) +{ + return platform_driver_register(&twl4030_vibra_driver); +} +module_init(twl4030_vibra_init); + +static void __exit twl4030_vibra_exit(void) +{ + platform_driver_unregister(&twl4030_vibra_driver); +} +module_exit(twl4030_vibra_exit); + +MODULE_ALIAS("platform:twl4030_codec_vibra"); + +MODULE_DESCRIPTION("TWL4030 Vibra driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nokia Corporation"); diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index cbec3dfdd42..64f1de7960c 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -56,6 +56,7 @@ #include <linux/io.h> #include <linux/bitrev.h> #include <linux/bitops.h> +#include <linux/slab.h> #define DRVNAME "winbond-cir" @@ -385,26 +386,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) } static int -wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) +wbcir_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct wbcir_data *data = input_get_drvdata(dev); - *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); + *keycode = wbcir_do_getkeycode(data, scancode); return 0; } static int -wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) +wbcir_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct wbcir_data *data = input_get_drvdata(dev); struct wbcir_keyentry *keyentry; struct wbcir_keyentry *new_keyentry; unsigned long flags; unsigned int old_keycode = KEY_RESERVED; - u32 scancode = (u32)sscancode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); if (!new_keyentry) diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index c0afb71a3a6..04d5a4a3181 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -29,6 +29,7 @@ #include <linux/module.h> #include <linux/preempt.h> #include <linux/string.h> +#include <linux/slab.h> #include <linux/types.h> #include <linux/platform_device.h> #include <linux/leds.h> diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index ba4f5dd7c60..c3d7ba5f5b4 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -19,6 +19,7 @@ #include <linux/module.h> #include <linux/init.h> +#include <linux/slab.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/input.h> @@ -97,8 +98,9 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->phys = "wm831x_on/input0"; wm831x_on->dev->dev.parent = &pdev->dev; - ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq, - IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on); + ret = request_threaded_irq(irq, NULL, wm831x_on_irq, + IRQF_TRIGGER_RISING, "wm831x_on", + wm831x_on); if (ret < 0) { dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); goto err_input_dev; @@ -114,7 +116,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) return 0; err_irq: - wm831x_free_irq(wm831x, irq, NULL); + free_irq(irq, wm831x_on); err_input_dev: input_free_device(wm831x_on->dev); err: @@ -127,7 +129,7 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev) struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); - wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on); + free_irq(irq, wm831x_on); cancel_delayed_work_sync(&wm831x_on->work); input_unregister_device(wm831x_on->dev); kfree(wm831x_on); diff --git a/drivers/input/misc/yealink.h b/drivers/input/misc/yealink.h index 48af0be9cbd..1e0f5239701 100644 --- a/drivers/input/misc/yealink.h +++ b/drivers/input/misc/yealink.h @@ -127,7 +127,7 @@ struct yld_ctl_packet { * yld_status struct. */ -/* LCD, each segment must be driven seperately. +/* LCD, each segment must be driven separately. * * Layout: * diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f93c2c0daf1..0d22cb9ce42 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -15,6 +15,7 @@ * the Free Software Foundation. */ +#include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/libps2.h> @@ -63,6 +64,9 @@ static const struct alps_model_info alps_model_data[] = { { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */ + { { 0x52, 0x01, 0x14 }, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ }; /* @@ -118,40 +122,27 @@ static void alps_report_buttons(struct psmouse *psmouse, struct input_dev *dev1, struct input_dev *dev2, int left, int right, int middle) { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if (model->flags & ALPS_PS2_INTERLEAVED) { - struct input_dev *dev; + struct input_dev *dev; - /* - * If shared button has already been reported on the - * other device (dev2) then this event should be also - * sent through that device. - */ - dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_LEFT, left); + /* + * If shared button has already been reported on the + * other device (dev2) then this event should be also + * sent through that device. + */ + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_LEFT, left); - dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_RIGHT, right); + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_RIGHT, right); - dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_MIDDLE, middle); + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_MIDDLE, middle); - /* - * Sync the _other_ device now, we'll do the first - * device later once we report the rest of the events. - */ - input_sync(dev2); - } else { - /* - * For devices with non-interleaved packets we know what - * device buttons belong to so we can simply report them. - */ - input_report_key(dev1, BTN_LEFT, left); - input_report_key(dev1, BTN_RIGHT, right); - input_report_key(dev1, BTN_MIDDLE, middle); - } + /* + * Sync the _other_ device now, we'll do the first + * device later once we report the rest of the events. + */ + input_sync(dev2); } static void alps_process_packet(struct psmouse *psmouse) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 908b5b44052..53ec7ddd182 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -205,8 +205,8 @@ struct atp { bool overflow_warned; int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ - signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int idlecount; /* number of empty packets */ struct work_struct work; @@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; + int change = dev->xy_old[i] - dev->xy_cur[i]; dev->xy_acc[i] -= change; /* prevent down drifting */ diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 4f8fe0886b2..b89879bd860 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -803,7 +803,6 @@ static struct usb_driver bcm5974_driver = { .disconnect = bcm5974_disconnect, .suspend = bcm5974_suspend, .resume = bcm5974_resume, - .reset_resume = bcm5974_resume, .id_table = bcm5974_table, .supports_autosuspend = 1, }; diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index b27684f267b..a138b5da79f 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -11,6 +11,7 @@ */ #include <linux/delay.h> +#include <linux/slab.h> #include <linux/module.h> #include <linux/input.h> #include <linux/serio.h> diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 9169d1591c1..08d66d820d2 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -30,6 +30,7 @@ */ #define DEBUG +#include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> #include <linux/libps2.h> diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 7c1d7d420ae..c31ad11df6b 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -16,6 +16,7 @@ #include <linux/serio.h> #include <linux/libps2.h> #include <linux/dmi.h> +#include <linux/slab.h> #include "psmouse.h" #include "lifebook.h" diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 1e827ad0afb..943cfec1566 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -18,6 +18,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/slab.h> #include <mach/hardware.h> #include <mach/pxa930_trkball.h> diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 81a6b81cb2f..1242775fee1 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -26,6 +26,7 @@ #include <linux/libps2.h> #include <linux/serio.h> #include <linux/jiffies.h> +#include <linux/slab.h> #include "psmouse.h" #include "sentelic.h" diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index d3f5243fa09..026df601016 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -28,6 +28,7 @@ #include <linux/input.h> #include <linux/serio.h> #include <linux/libps2.h> +#include <linux/slab.h> #include "psmouse.h" #include "synaptics.h" diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 9867dfe2a63..8291e7399ff 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -17,6 +17,7 @@ #include <linux/input.h> #include <linux/delay.h> #include <linux/workqueue.h> +#include <linux/slab.h> #define DRIVER_NAME "synaptics_i2c" /* maximum product id is 15 characters */ diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 909431c31ab..88121c59c3c 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c @@ -26,7 +26,6 @@ */ #include <linux/kernel.h> -#include <linux/slab.h> #include <linux/input.h> #include <linux/serio.h> diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 63d4a67830f..0643e49ca60 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c @@ -8,6 +8,7 @@ * Trademarks are the property of their respective owners. */ +#include <linux/slab.h> #include <linux/delay.h> #include <linux/serio.h> #include <linux/module.h> diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a13d80f7da1..f34b22bce4f 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -15,7 +15,6 @@ #include <linux/sched.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/poll.h> #include <linux/module.h> #include <linux/init.h> @@ -542,10 +541,8 @@ static int mousedev_open(struct inode *inode, struct file *file) if (i >= MOUSEDEV_MINORS) return -ENODEV; - lock_kernel(); error = mutex_lock_interruptible(&mousedev_table_mutex); if (error) { - unlock_kernel(); return error; } mousedev = mousedev_table[i]; @@ -554,7 +551,6 @@ static int mousedev_open(struct inode *inode, struct file *file) mutex_unlock(&mousedev_table_mutex); if (!mousedev) { - unlock_kernel(); return -ENODEV; } @@ -575,7 +571,6 @@ static int mousedev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; - unlock_kernel(); return 0; err_free_client: @@ -583,7 +578,6 @@ static int mousedev_open(struct inode *inode, struct file *file) kfree(client); err_put_mousedev: put_device(&mousedev->dev); - unlock_kernel(); return error; } diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index 320b7ca48bf..7998560a190 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -18,6 +18,7 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> #define DRV_NAME "altera_ps2" diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index b54452a8c77..6ee8f0ddad5 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c @@ -18,6 +18,7 @@ #include <linux/io.h> #include <linux/clk.h> #include <linux/platform_device.h> +#include <linux/slab.h> /* PSIF register offsets */ #define PSIF_CR 0x00 diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index d1380fc72cc..4a3084695c0 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -35,6 +35,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <asm/io.h> diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 06addfa7cc4..3c287dd879d 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -24,6 +24,7 @@ #include <linux/init.h> #include <linux/module.h> +#include <linux/slab.h> #include <linux/serio.h> #include <linux/input.h> #include <linux/interrupt.h> diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 6cd03ebaf5f..c92f4edfee7 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -58,6 +58,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <linux/timer.h> #include <linux/list.h> diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2a5982e532f..ead0494721d 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -442,6 +442,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { }, }, { + /* Medion Akoya E1222 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E122X"), + }, + }, + { /* Mivvy M310 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), @@ -624,6 +631,9 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); } + /* Keyboard ports are always supposed to be wakeup-enabled */ + device_set_wakeup_enable(&dev->dev, true); + i8042_pnp_kbd_devices++; return 0; } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index b54aee7cd9e..6440a8f5568 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -21,6 +21,7 @@ #include <linux/rcupdate.h> #include <linux/platform_device.h> #include <linux/i8042.h> +#include <linux/slab.h> #include <asm/io.h> @@ -38,7 +39,7 @@ MODULE_PARM_DESC(noaux, "Do not probe or use AUX (mouse) port."); static bool i8042_nomux; module_param_named(nomux, i8042_nomux, bool, 0); -MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing conrtoller is present."); +MODULE_PARM_DESC(nomux, "Do not check whether an active multiplexing controller is present."); static bool i8042_unlock; module_param_named(unlock, i8042_unlock, bool, 0); @@ -430,7 +431,7 @@ static bool i8042_filter(unsigned char data, unsigned char str, } if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { - dbg("Filtered out by platfrom filter\n"); + dbg("Filtered out by platform filter\n"); return true; } @@ -1386,6 +1387,8 @@ static int __init i8042_probe(struct platform_device *dev) { int error; + i8042_platform_device = dev; + error = i8042_controller_selftest(); if (error) return error; @@ -1421,6 +1424,7 @@ static int __init i8042_probe(struct platform_device *dev) i8042_free_aux_ports(); /* in case KBD failed but AUX not */ i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return error; } @@ -1430,6 +1434,7 @@ static int __devexit i8042_remove(struct platform_device *dev) i8042_unregister_ports(); i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return 0; } @@ -1448,6 +1453,7 @@ static struct platform_driver i8042_driver = { static int __init i8042_init(void) { + struct platform_device *pdev; int err; dbg_init(); @@ -1460,31 +1466,18 @@ static int __init i8042_init(void) if (err) goto err_platform_exit; - i8042_platform_device = platform_device_alloc("i8042", -1); - if (!i8042_platform_device) { - err = -ENOMEM; + pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); + if (IS_ERR(pdev)) { + err = PTR_ERR(pdev); goto err_platform_exit; } - err = platform_device_add(i8042_platform_device); - if (err) - goto err_free_device; - - err = platform_driver_probe(&i8042_driver, i8042_probe); - if (err) - goto err_del_device; - panic_blink = i8042_panic_blink; return 0; - err_del_device: - platform_device_del(i8042_platform_device); - err_free_device: - platform_device_put(i8042_platform_device); err_platform_exit: i8042_platform_exit(); - return err; } diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index f3876acc3e8..980af94ba9c 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -14,7 +14,6 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/sched.h> -#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/input.h> #include <linux/serio.h> diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index b089977e0ef..26b45936f9f 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -46,6 +46,7 @@ #include <linux/module.h> #include <linux/parport.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/serio.h> diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 797314be7af..43494742541 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -15,6 +15,7 @@ #include <linux/ioport.h> #include <linux/input.h> #include <linux/pci.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index e36a0901646..5eb84b3b67f 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -36,6 +36,7 @@ #include <linux/err.h> #include <linux/bitops.h> #include <linux/platform_device.h> +#include <linux/slab.h> #include <asm/io.h> #include <asm/uaccess.h> diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index ed045c99f84..9da6fbcaaa7 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -34,6 +34,7 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/io.h> +#include <linux/slab.h> #include <asm/irq.h> #include <mach/hardware.h> diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 27fdaaffbb4..99866485444 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -81,12 +81,12 @@ static int serio_raw_open(struct inode *inode, struct file *file) struct serio_raw_list *list; int retval = 0; - lock_kernel(); retval = mutex_lock_interruptible(&serio_raw_mutex); if (retval) - goto out_bkl; + return retval; - if (!(serio_raw = serio_raw_locate(iminor(inode)))) { + serio_raw = serio_raw_locate(iminor(inode)); + if (!serio_raw) { retval = -ENODEV; goto out; } @@ -96,7 +96,8 @@ static int serio_raw_open(struct inode *inode, struct file *file) goto out; } - if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { + list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); + if (!list) { retval = -ENOMEM; goto out; } @@ -109,8 +110,6 @@ static int serio_raw_open(struct inode *inode, struct file *file) out: mutex_unlock(&serio_raw_mutex); -out_bkl: - unlock_kernel(); return retval; } diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 8298e1f6823..f84f8e32e3f 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -19,6 +19,7 @@ #include <linux/serio.h> #include <linux/interrupt.h> #include <linux/errno.h> +#include <linux/slab.h> #include <linux/init.h> #include <linux/list.h> #include <linux/io.h> diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index fbd3987af57..01424834476 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -15,6 +15,7 @@ #include <linux/input.h> #include <linux/input/sparse-keymap.h> +#include <linux/slab.h> MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); MODULE_DESCRIPTION("Generic support for sparse keymaps"); @@ -64,36 +65,39 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); static int sparse_keymap_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { - const struct key_entry *key = - sparse_keymap_entry_from_scancode(dev, scancode); + const struct key_entry *key; - if (key && key->type == KE_KEY) { - *keycode = key->keycode; - return 0; + if (dev->keycode) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } } return -EINVAL; } static int sparse_keymap_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { struct key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = sparse_keymap_entry_from_scancode(dev, scancode); - if (key && key->type == KE_KEY) { - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; + if (dev->keycode) { + key = sparse_keymap_entry_from_scancode(dev, scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } } return -EINVAL; @@ -161,7 +165,7 @@ int sparse_keymap_setup(struct input_dev *dev, return 0; err_out: - kfree(keymap); + kfree(map); return error; } @@ -173,14 +177,27 @@ EXPORT_SYMBOL(sparse_keymap_setup); * * This function is used to free memory allocated by sparse keymap * in an input device that was set up by sparse_keymap_setup(). + * NOTE: It is safe to cal this function while input device is + * still registered (however the drivers should care not to try to + * use freed keymap and thus have to shut off interrups/polling + * before freeing the keymap). */ void sparse_keymap_free(struct input_dev *dev) { + unsigned long flags; + + /* + * Take event lock to prevent racing with input_get_keycode() + * and input_set_keycode() if we are called while input device + * is still registered. + */ + spin_lock_irqsave(&dev->event_lock, flags); + kfree(dev->keycode); dev->keycode = NULL; dev->keycodemax = 0; - dev->getkeycode = NULL; - dev->setkeycode = NULL; + + spin_unlock_irqrestore(&dev->event_lock, flags); } EXPORT_SYMBOL(sparse_keymap_free); diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 7d005a3616d..4be039d7dca 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -362,7 +362,7 @@ static const int macroKeyEvents[] = { }; /*********************************************************************** - * Map values to strings and back. Every map shoudl have the following + * Map values to strings and back. Every map should have the following * as its last element: { NULL, AIPTEK_INVALID_VALUE }. */ #define AIPTEK_INVALID_VALUE -1 diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a1770e6feee..f46502589e4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -371,7 +371,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = wacom_le16_to_cpu(&report[i + 3]); @@ -410,7 +410,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = wacom_le16_to_cpu(&report[i + 3]); @@ -673,13 +673,15 @@ static int wacom_resume(struct usb_interface *intf) int rv; mutex_lock(&wacom->lock); - if (wacom->open) { + + /* switch to wacom mode first */ + wacom_query_tablet_data(intf, features); + + if (wacom->open) rv = usb_submit_urb(wacom->irq, GFP_NOIO); - /* switch to wacom mode if needed */ - if (!wacom_retrieve_hid_descriptor(intf, features)) - wacom_query_tablet_data(intf, features); - } else + else rv = 0; + mutex_unlock(&wacom->lock); return rv; diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 3d81443e683..4a852d815c6 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1028,7 +1028,7 @@ static const struct wacom_features wacom_features_0x93 = static const struct wacom_features wacom_features_0x9A = { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0x9F = - { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0xE2 = { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; static const struct wacom_features wacom_features_0xE3 = diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 8590b1e8ec3..b50cf04e61a 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -17,7 +17,6 @@ #define WACOM_PKGLEN_GRAPHIRE 8 #define WACOM_PKGLEN_BBFUN 9 #define WACOM_PKGLEN_INTUOS 10 -#define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC2FG 14 diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c new file mode 100644 index 00000000000..b3aebc2166b --- /dev/null +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -0,0 +1,237 @@ +/* + * Touchscreen driver for Marvell 88PM860x + * + * Copyright (C) 2009 Marvell International Ltd. + * Haojian Zhuang <haojian.zhuang@marvell.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/mfd/88pm860x.h> +#include <linux/slab.h> + +#define MEAS_LEN (8) +#define ACCURATE_BIT (12) + +/* touch register */ +#define MEAS_EN3 (0x52) + +#define MEAS_TSIX_1 (0x8D) +#define MEAS_TSIX_2 (0x8E) +#define MEAS_TSIY_1 (0x8F) +#define MEAS_TSIY_2 (0x90) +#define MEAS_TSIZ1_1 (0x91) +#define MEAS_TSIZ1_2 (0x92) +#define MEAS_TSIZ2_1 (0x93) +#define MEAS_TSIZ2_2 (0x94) + +/* bit definitions of touch */ +#define MEAS_PD_EN (1 << 3) +#define MEAS_TSIX_EN (1 << 4) +#define MEAS_TSIY_EN (1 << 5) +#define MEAS_TSIZ1_EN (1 << 6) +#define MEAS_TSIZ2_EN (1 << 7) + +struct pm860x_touch { + struct input_dev *idev; + struct i2c_client *i2c; + struct pm860x_chip *chip; + int irq; + int res_x; /* resistor of Xplate */ +}; + +static irqreturn_t pm860x_touch_handler(int irq, void *data) +{ + struct pm860x_touch *touch = data; + struct pm860x_chip *chip = touch->chip; + unsigned char buf[MEAS_LEN]; + int x, y, pen_down; + int z1, z2, rt = 0; + int ret; + + ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf); + if (ret < 0) + goto out; + + pen_down = buf[1] & (1 << 6); + x = ((buf[0] & 0xFF) << 4) | (buf[1] & 0x0F); + y = ((buf[2] & 0xFF) << 4) | (buf[3] & 0x0F); + z1 = ((buf[4] & 0xFF) << 4) | (buf[5] & 0x0F); + z2 = ((buf[6] & 0xFF) << 4) | (buf[7] & 0x0F); + + if (pen_down) { + if ((x != 0) && (z1 != 0) && (touch->res_x != 0)) { + rt = z2 / z1 - 1; + rt = (rt * touch->res_x * x) >> ACCURATE_BIT; + dev_dbg(chip->dev, "z1:%d, z2:%d, rt:%d\n", + z1, z2, rt); + } + input_report_abs(touch->idev, ABS_X, x); + input_report_abs(touch->idev, ABS_Y, y); + input_report_abs(touch->idev, ABS_PRESSURE, rt); + input_report_key(touch->idev, BTN_TOUCH, 1); + dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y); + } else { + input_report_abs(touch->idev, ABS_PRESSURE, 0); + input_report_key(touch->idev, BTN_TOUCH, 0); + dev_dbg(chip->dev, "pen release\n"); + } + input_sync(touch->idev); + +out: + return IRQ_HANDLED; +} + +static int pm860x_touch_open(struct input_dev *dev) +{ + struct pm860x_touch *touch = input_get_drvdata(dev); + int data, ret; + + data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN + | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN; + ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data); + if (ret < 0) + goto out; + return 0; +out: + return ret; +} + +static void pm860x_touch_close(struct input_dev *dev) +{ + struct pm860x_touch *touch = input_get_drvdata(dev); + int data; + + data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN + | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN; + pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); +} + +static int __devinit pm860x_touch_probe(struct platform_device *pdev) +{ + struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct pm860x_platform_data *pm860x_pdata = \ + pdev->dev.parent->platform_data; + struct pm860x_touch_pdata *pdata = NULL; + struct pm860x_touch *touch; + int irq, ret; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "No IRQ resource!\n"); + return -EINVAL; + } + + if (!pm860x_pdata) { + dev_err(&pdev->dev, "platform data is missing\n"); + return -EINVAL; + } + + pdata = pm860x_pdata->touch; + if (!pdata) { + dev_err(&pdev->dev, "touchscreen data is missing\n"); + return -EINVAL; + } + + touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); + if (touch == NULL) + return -ENOMEM; + dev_set_drvdata(&pdev->dev, touch); + + touch->idev = input_allocate_device(); + if (touch->idev == NULL) { + dev_err(&pdev->dev, "Failed to allocate input device!\n"); + ret = -ENOMEM; + goto out; + } + + touch->idev->name = "88pm860x-touch"; + touch->idev->phys = "88pm860x/input0"; + touch->idev->id.bustype = BUS_I2C; + touch->idev->dev.parent = &pdev->dev; + touch->idev->open = pm860x_touch_open; + touch->idev->close = pm860x_touch_close; + touch->chip = chip; + touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; + touch->irq = irq + chip->irq_base; + touch->res_x = pdata->res_x; + input_set_drvdata(touch->idev, touch); + + ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, + IRQF_ONESHOT, "touch", touch); + if (ret < 0) + goto out_irq; + + __set_bit(EV_ABS, touch->idev->evbit); + __set_bit(ABS_X, touch->idev->absbit); + __set_bit(ABS_Y, touch->idev->absbit); + __set_bit(ABS_PRESSURE, touch->idev->absbit); + __set_bit(EV_SYN, touch->idev->evbit); + __set_bit(EV_KEY, touch->idev->evbit); + __set_bit(BTN_TOUCH, touch->idev->keybit); + + input_set_abs_params(touch->idev, ABS_X, 0, 1 << ACCURATE_BIT, 0, 0); + input_set_abs_params(touch->idev, ABS_Y, 0, 1 << ACCURATE_BIT, 0, 0); + input_set_abs_params(touch->idev, ABS_PRESSURE, 0, 1 << ACCURATE_BIT, + 0, 0); + + ret = input_register_device(touch->idev); + if (ret < 0) { + dev_err(chip->dev, "Failed to register touch!\n"); + goto out_rg; + } + + platform_set_drvdata(pdev, touch); + return 0; +out_rg: + free_irq(touch->irq, touch); +out_irq: + input_free_device(touch->idev); +out: + kfree(touch); + return ret; +} + +static int __devexit pm860x_touch_remove(struct platform_device *pdev) +{ + struct pm860x_touch *touch = platform_get_drvdata(pdev); + + input_unregister_device(touch->idev); + free_irq(touch->irq, touch); + platform_set_drvdata(pdev, NULL); + kfree(touch); + return 0; +} + +static struct platform_driver pm860x_touch_driver = { + .driver = { + .name = "88pm860x-touch", + .owner = THIS_MODULE, + }, + .probe = pm860x_touch_probe, + .remove = __devexit_p(pm860x_touch_remove), +}; + +static int __init pm860x_touch_init(void) +{ + return platform_driver_register(&pm860x_touch_driver); +} +module_init(pm860x_touch_init); + +static void __exit pm860x_touch_exit(void) +{ + platform_driver_unregister(&pm860x_touch_driver); +} +module_exit(pm860x_touch_exit); + +MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x"); +MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:88pm860x-touch"); + diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 6457e060ae4..8a8fa4d2d6a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -11,18 +11,31 @@ menuconfig INPUT_TOUCHSCREEN if INPUT_TOUCHSCREEN +config TOUCHSCREEN_88PM860X + tristate "Marvell 88PM860x touchscreen" + depends on MFD_88PM860X + help + Say Y here if you have a 88PM860x PMIC and want to enable + support for the built-in touchscreen. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called 88pm860x-ts. + config TOUCHSCREEN_ADS7846 - tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" + tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens" depends on SPI_MASTER depends on HWMON = n || HWMON help Say Y here if you have a touchscreen interface using the - ADS7846/TSC2046 or ADS7843 controller, and your board-specific - setup code includes that in its table of SPI devices. + ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller, + and your board-specific setup code includes that in its + table of SPI devices. If HWMON is selected, and the driver is told the reference voltage on your board, you will also get hwmon interfaces for the voltage - (and on ads7846/tsc2046, temperature) sensors of this chip. + (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip. If unsure, say N (but it's safe to say "Y"). diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index d61a3b4def9..7fef7d5cca2 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -6,6 +6,7 @@ wm97xx-ts-y := wm97xx-core.o +obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index eb83939c705..e019d53d1ab 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -46,7 +46,7 @@ #include <linux/spi/ad7877.h> #include <asm/irq.h> -#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) +#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) #define MAX_SPI_FREQ_HZ 20000000 #define MAX_12BIT ((1<<12)-1) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8b05d8e9754..532279cda0e 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -36,6 +36,7 @@ * TSC2046 is just newer ads7846 silicon. * Support for ads7843 tested on Atmel at91sam926x-EK. * Support for ads7845 has only been stubbed in. + * Support for Analog Devices AD7873 and AD7843 tested. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -821,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) spin_unlock_irq(&ts->lock); + if (device_may_wakeup(&ts->spi->dev)) + enable_irq_wake(ts->spi->irq); + return 0; } @@ -829,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (device_may_wakeup(&ts->spi->dev)) + disable_irq_wake(ts->spi->irq); + spin_lock_irq(&ts->lock); ts->is_suspended = 0; @@ -984,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) vref = pdata->keep_vref_on; + if (ts->model == 7873) { + /* The AD7873 is almost identical to the ADS7846 + * keep VREF off during differential/ratiometric + * conversion modes + */ + ts->model = 7846; + vref = 0; + } + /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ @@ -1191,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (err) goto err_remove_attr_group; + device_init_wakeup(&spi->dev, pdata->wakeup); + return 0; err_remove_attr_group: @@ -1220,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + device_init_wakeup(&spi->dev, false); + ads784x_hwmon_unregister(spi, ts); input_unregister_device(ts->input); diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index a12242f77e2..fa8e56bd909 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c @@ -19,6 +19,7 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/io.h> +#include <linux/slab.h> #define AC97C_ICA 0x10 #define AC97C_CBRHR 0x30 diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 3ffd4c4b170..2b72a5923c1 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c @@ -19,6 +19,7 @@ #include <linux/input.h> #include <linux/workqueue.h> #include <linux/mfd/da903x.h> +#include <linux/slab.h> #define DA9034_MANUAL_CTRL 0x50 #define DA9034_LDO_ADC_EN (1 << 4) diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 9029bd3f34e..204b8a1a601 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -33,6 +33,7 @@ #include <linux/timer.h> #include <linux/gpio.h> #include <linux/input/eeti_ts.h> +#include <linux/slab.h> static int flip_x; module_param(flip_x, bool, 0644); diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index c8b7e8a45c4..4b0a061811f 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -18,6 +18,7 @@ #include <linux/input.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/slab.h> #include <mach/hardware.h> #include <mach/jornada720.h> diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index be115b3b65e..c5bc62d85bb 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c @@ -17,6 +17,7 @@ #include <linux/module.h> #include <linux/input.h> #include <linux/sched.h> +#include <linux/slab.h> #include <linux/init.h> #define MC13783_TS_NAME "mc13783-ts" @@ -44,7 +45,7 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data) { struct mc13783_ts_priv *priv = data; - mc13783_ackirq(priv->mc13783, irq); + mc13783_irq_ack(priv->mc13783, irq); /* * Kick off reading coordinates. Note that if work happens already @@ -135,7 +136,7 @@ static int mc13783_ts_open(struct input_dev *dev) mc13783_lock(priv->mc13783); - mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS); + mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS); ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, mc13783_ts_handler, MC13783_TS_NAME, priv); diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 4c28b89757f..ce8ab0269f6 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -20,6 +20,7 @@ #include <linux/interrupt.h> #include <linux/input.h> #include <linux/irq.h> +#include <linux/slab.h> /* Registers */ #define MCS5000_TS_STATUS 0x00 diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 141dd584330..defe5dd3627 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -23,6 +23,7 @@ #include <linux/kernel.h> #include <linux/input.h> #include <linux/interrupt.h> +#include <linux/slab.h> #include <asm/io.h> #include <linux/i2c.h> #include <linux/timer.h> diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index b79097e3028..ea6ef16e59b 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/fs.h> #include <linux/string.h> +#include <linux/slab.h> #include <linux/pm.h> #include <linux/timer.h> #include <linux/interrupt.h> diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 3755a47d053..98a7d127948 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -26,7 +26,6 @@ #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/gpio.h> #include <linux/input.h> #include <linux/init.h> diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 89dcbe7b4b0..028a5363eea 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -26,7 +26,6 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/suspend.h> -#include <linux/slab.h> #include <linux/kthread.h> #include <linux/freezer.h> #include <linux/ucb1400.h> diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6ccbdbbf33f..cc18265be1a 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c @@ -16,6 +16,7 @@ #include <linux/clk.h> #include <linux/input.h> #include <linux/interrupt.h> +#include <linux/slab.h> /* ADC controller bit defines */ #define ADC_DELAY 0xf00 diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index f944918466e..5109bf3dd85 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -48,6 +48,7 @@ #include <linux/wm97xx.h> #include <linux/uaccess.h> #include <linux/io.h> +#include <linux/slab.h> #define TS_NAME "wm97xx" #define WM_CORE_VERSION "1.00" diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index d30436fee47..e14081675bb 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c @@ -21,6 +21,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/input.h> +#include <linux/slab.h> #include <asm/xen/hypervisor.h> |