diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 07:59:01 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-25 07:59:01 -0700 |
commit | 3a99c6319064af3f2e18eb929f638d555dbf7a62 (patch) | |
tree | e611927f41142123dc8efed7e07a3a91151edb01 /drivers/input | |
parent | 1dfd166e93f98892aa4427069a23ed73259983c8 (diff) | |
parent | 49327ad2bbbaf1945d5ba431522201574219d150 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (75 commits)
Input: wacom - specify Cinitq supported tools
Input: ab8500-ponkey - fix IRQ freeing in error path
Input: adp5588-keys - use more obvious i2c_device_id name string
Input: ad7877 - switch to using threaded IRQ
Input: ad7877 - use attribute group to control visibility of attributes
Input: serio - add support for PS2Mult multiplexer protocol
Input: wacom - properly enable runtime PM
Input: ad7877 - filter events where pressure is beyond the maximum
Input: ad7877 - implement EV_KEY:BTN_TOUCH reporting
Input: ad7877 - implement specified chip select behavior
Input: hp680_ts_input - use cancel_delayed_work_sync()
Input: mousedev - correct lockdep annotation
Input: ads7846 - switch to using threaded IRQ
Input: serio - support multiple child devices per single parent
Input: synaptics - simplify pass-through port handling
Input: add ROHM BU21013 touch panel controller support
Input: omap4-keypad - wake-up on events & long presses
Input: omap4-keypad - fix interrupt line configuration
Input: omap4-keypad - SYSCONFIG register configuration
Input: omap4-keypad - use platform device helpers
...
Diffstat (limited to 'drivers/input')
50 files changed, 5051 insertions, 756 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 535fea4fe67..e3f7fc6f956 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev, } #undef OLD_KEY_MAX +static int evdev_handle_get_keycode(struct input_dev *dev, + void __user *p, size_t size) +{ + struct input_keymap_entry ke; + int error; + + memset(&ke, 0, sizeof(ke)); + + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; + + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; + + ke.len = sizeof(unsigned int); + ke.flags = 0; + + error = input_get_keycode(dev, &ke); + if (error) + return error; + + if (put_user(ke.keycode, ip + 1)) + return -EFAULT; + + } else { + size = min(size, sizeof(ke)); + + if (copy_from_user(&ke, p, size)) + return -EFAULT; + + error = input_get_keycode(dev, &ke); + if (error) + return error; + + if (copy_to_user(p, &ke, size)) + return -EFAULT; + } + return 0; +} + +static int evdev_handle_set_keycode(struct input_dev *dev, + void __user *p, size_t size) +{ + struct input_keymap_entry ke; + + memset(&ke, 0, sizeof(ke)); + + if (size == sizeof(unsigned int[2])) { + /* legacy case */ + int __user *ip = (int __user *)p; + + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) + return -EFAULT; + + if (get_user(ke.keycode, ip + 1)) + return -EFAULT; + + ke.len = sizeof(unsigned int); + ke.flags = 0; + + } else { + size = min(size, sizeof(ke)); + + if (copy_from_user(&ke, p, size)) + return -EFAULT; + + if (ke.len > sizeof(ke.scancode)) + return -EINVAL; + } + + return input_set_keycode(dev, &ke); +} + static long evdev_do_ioctl(struct file *file, unsigned int cmd, void __user *p, int compat_mode) { @@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return 0; - case EVIOCGKEYCODE: - if (get_user(t, ip)) - return -EFAULT; - - error = input_get_keycode(dev, t, &v); - if (error) - return error; - - if (put_user(v, ip + 1)) - return -EFAULT; - - return 0; - - case EVIOCSKEYCODE: - if (get_user(t, ip) || get_user(v, ip + 1)) - return -EFAULT; - - return input_set_keycode(dev, t, v); - case EVIOCRMFF: return input_ff_erase(dev, (int)(unsigned long) p, file); @@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, /* Now check variable-length commands */ #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) - switch (EVIOC_MASK_SIZE(cmd)) { case EVIOCGKEY(0): @@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, return -EFAULT; return error; + + case EVIOC_MASK_SIZE(EVIOCGKEYCODE): + return evdev_handle_get_keycode(dev, p, size); + + case EVIOC_MASK_SIZE(EVIOCSKEYCODE): + return evdev_handle_set_keycode(dev, p, size); } /* Multi-number variable-length handlers */ diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index 7392992da42..422aa0a6b77 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -59,44 +59,52 @@ MODULE_DEVICE_TABLE(pci, emu_tbl); static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - int ioport, iolen; struct emu *emu; struct gameport *port; - - if (pci_enable_device(pdev)) - return -EBUSY; - - ioport = pci_resource_start(pdev, 0); - iolen = pci_resource_len(pdev, 0); - - if (!request_region(ioport, iolen, "emu10k1-gp")) - return -EBUSY; + int error; emu = kzalloc(sizeof(struct emu), GFP_KERNEL); port = gameport_allocate_port(); if (!emu || !port) { printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); - release_region(ioport, iolen); - kfree(emu); - gameport_free_port(port); - return -ENOMEM; + error = -ENOMEM; + goto err_out_free; } - emu->io = ioport; - emu->size = iolen; + error = pci_enable_device(pdev); + if (error) + goto err_out_free; + + emu->io = pci_resource_start(pdev, 0); + emu->size = pci_resource_len(pdev, 0); + emu->dev = pdev; emu->gameport = port; gameport_set_name(port, "EMU10K1"); gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); port->dev.parent = &pdev->dev; - port->io = ioport; + port->io = emu->io; + + if (!request_region(emu->io, emu->size, "emu10k1-gp")) { + printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n", + emu->io, emu->io + emu->size - 1); + error = -EBUSY; + goto err_out_disable_dev; + } pci_set_drvdata(pdev, emu); gameport_register_port(port); return 0; + + err_out_disable_dev: + pci_disable_device(pdev); + err_out_free: + gameport_free_port(port); + kfree(emu); + return error; } static void __devexit emu_remove(struct pci_dev *pdev) @@ -106,6 +114,8 @@ static void __devexit emu_remove(struct pci_dev *pdev) gameport_unregister_port(emu->gameport); release_region(emu->io, emu->size); kfree(emu); + + pci_disable_device(pdev); } static struct pci_driver emu_driver = { diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 14d3f3e208a..a3b70ff2101 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -133,11 +133,11 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci) { struct fm801_gp *gp = pci_get_drvdata(pci); - if (gp) { - gameport_unregister_port(gp->gameport); - release_resource(gp->res_port); - kfree(gp); - } + gameport_unregister_port(gp->gameport); + release_resource(gp->res_port); + kfree(gp); + + pci_disable_device(pci); } static const struct pci_device_id fm801_gp_id_table[] = { diff --git a/drivers/input/input.c b/drivers/input/input.c index 7919c253722..d092ef9291d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -171,7 +171,7 @@ static int input_handle_abs_event(struct input_dev *dev, if (code == ABS_MT_SLOT) { /* * "Stage" the event; we'll flush it later, when we - * get actiual touch data. + * get actual touch data. */ if (*pval >= 0 && *pval < dev->mtsize) dev->slot = *pval; @@ -188,7 +188,7 @@ static int input_handle_abs_event(struct input_dev *dev, pold = &mtslot->abs[code - ABS_MT_FIRST]; } else { /* - * Bypass filtering for multitouch events when + * Bypass filtering for multi-touch events when * not employing slots. */ pold = NULL; @@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev) spin_unlock_irq(&dev->event_lock); } -static int input_fetch_keycode(struct input_dev *dev, int scancode) +/** + * input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry + * @ke: keymap entry containing scancode to be converted. + * @scancode: pointer to the location where converted scancode should + * be stored. + * + * This function is used to convert scancode stored in &struct keymap_entry + * into scalar form understood by legacy keymap handling methods. These + * methods expect scancodes to be represented as 'unsigned int'. + */ +int input_scancode_to_scalar(const struct input_keymap_entry *ke, + unsigned int *scancode) +{ + switch (ke->len) { + case 1: + *scancode = *((u8 *)ke->scancode); + break; + + case 2: + *scancode = *((u16 *)ke->scancode); + break; + + case 4: + *scancode = *((u32 *)ke->scancode); + break; + + default: + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(input_scancode_to_scalar); + +/* + * Those routines handle the default case where no [gs]etkeycode() is + * defined. In this case, an array indexed by the scancode is used. + */ + +static unsigned int input_fetch_keycode(struct input_dev *dev, + unsigned int index) { switch (dev->keycodesize) { - case 1: - return ((u8 *)dev->keycode)[scancode]; + case 1: + return ((u8 *)dev->keycode)[index]; - case 2: - return ((u16 *)dev->keycode)[scancode]; + case 2: + return ((u16 *)dev->keycode)[index]; - default: - return ((u32 *)dev->keycode)[scancode]; + default: + return ((u32 *)dev->keycode)[index]; } } static int input_default_getkeycode(struct input_dev *dev, - unsigned int scancode, - unsigned int *keycode) + struct input_keymap_entry *ke) { + unsigned int index; + int error; + if (!dev->keycodesize) return -EINVAL; - if (scancode >= dev->keycodemax) + if (ke->flags & INPUT_KEYMAP_BY_INDEX) + index = ke->index; + else { + error = input_scancode_to_scalar(ke, &index); + if (error) + return error; + } + + if (index >= dev->keycodemax) return -EINVAL; - *keycode = input_fetch_keycode(dev, scancode); + ke->keycode = input_fetch_keycode(dev, index); + ke->index = index; + ke->len = sizeof(index); + memcpy(ke->scancode, &index, sizeof(index)); return 0; } static int input_default_setkeycode(struct input_dev *dev, - unsigned int scancode, - unsigned int keycode) + const struct input_keymap_entry *ke, + unsigned int *old_keycode) { - int old_keycode; + unsigned int index; + int error; int i; - if (scancode >= dev->keycodemax) + if (!dev->keycodesize) return -EINVAL; - if (!dev->keycodesize) + if (ke->flags & INPUT_KEYMAP_BY_INDEX) { + index = ke->index; + } else { + error = input_scancode_to_scalar(ke, &index); + if (error) + return error; + } + + if (index >= dev->keycodemax) return -EINVAL; - if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) + if (dev->keycodesize < sizeof(dev->keycode) && + (ke->keycode >> (dev->keycodesize * 8))) return -EINVAL; switch (dev->keycodesize) { case 1: { u8 *k = (u8 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } case 2: { u16 *k = (u16 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } default: { u32 *k = (u32 *)dev->keycode; - old_keycode = k[scancode]; - k[scancode] = keycode; + *old_keycode = k[index]; + k[index] = ke->keycode; break; } } - __clear_bit(old_keycode, dev->keybit); - __set_bit(keycode, dev->keybit); + __clear_bit(*old_keycode, dev->keybit); + __set_bit(ke->keycode, dev->keybit); for (i = 0; i < dev->keycodemax; i++) { - if (input_fetch_keycode(dev, i) == old_keycode) { - __set_bit(old_keycode, dev->keybit); + if (input_fetch_keycode(dev, i) == *old_keycode) { + __set_bit(*old_keycode, dev->keybit); break; /* Setting the bit twice is useless, so break */ } } @@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev, /** * input_get_keycode - retrieve keycode currently mapped to a given scancode * @dev: input device which keymap is being queried - * @scancode: scancode (or its equivalent for device in question) for which - * keycode is needed - * @keycode: result + * @ke: keymap entry * * This function should be called by anyone interested in retrieving current - * keymap. Presently keyboard and evdev handlers use it. + * keymap. Presently evdev handlers use it. */ -int input_get_keycode(struct input_dev *dev, - unsigned int scancode, unsigned int *keycode) +int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) { 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); + if (dev->getkeycode) { + /* + * Support for legacy drivers, that don't implement the new + * ioctls + */ + u32 scancode = ke->index; + + memcpy(ke->scancode, &scancode, sizeof(scancode)); + ke->len = sizeof(scancode); + retval = dev->getkeycode(dev, scancode, &ke->keycode); + } else { + retval = dev->getkeycode_new(dev, ke); + } + + spin_unlock_irqrestore(&dev->event_lock, flags); return retval; } EXPORT_SYMBOL(input_get_keycode); /** - * input_get_keycode - assign new keycode to a given scancode + * input_set_keycode - attribute a keycode to a given scancode * @dev: input device which keymap is being updated - * @scancode: scancode (or its equivalent for device in question) - * @keycode: new keycode to be assigned to the scancode + * @ke: new keymap entry * * 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, - unsigned int scancode, unsigned int keycode) + const struct input_keymap_entry *ke) { unsigned long flags; unsigned int old_keycode; int retval; - if (keycode > KEY_MAX) + if (ke->keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); - retval = dev->getkeycode(dev, scancode, &old_keycode); - if (retval) - goto out; + if (dev->setkeycode) { + /* + * Support for legacy drivers, that don't implement the new + * ioctls + */ + unsigned int scancode; + + retval = input_scancode_to_scalar(ke, &scancode); + if (retval) + goto out; + + /* + * We need to know the old scancode, in order to generate a + * keyup effect, if the set operation happens successfully + */ + if (!dev->getkeycode) { + retval = -EINVAL; + goto out; + } + + retval = dev->getkeycode(dev, scancode, &old_keycode); + if (retval) + goto out; + + retval = dev->setkeycode(dev, scancode, ke->keycode); + } else { + retval = dev->setkeycode_new(dev, ke, &old_keycode); + } - retval = dev->setkeycode(dev, scancode, keycode); if (retval) goto out; @@ -1601,7 +1697,7 @@ EXPORT_SYMBOL(input_free_device); * * This function allocates all necessary memory for MT slot handling in the * input device, and adds ABS_MT_SLOT to the device capabilities. All slots - * are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1. + * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1. */ int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) { @@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev) dev->rep[REP_PERIOD] = 33; } - if (!dev->getkeycode) - dev->getkeycode = input_default_getkeycode; + if (!dev->getkeycode && !dev->getkeycode_new) + dev->getkeycode_new = input_default_getkeycode; - if (!dev->setkeycode) - dev->setkeycode = input_default_setkeycode; + if (!dev->setkeycode && !dev->setkeycode_new) + dev->setkeycode_new = input_default_setkeycode; dev_set_name(&dev->dev, "input%ld", (unsigned long) atomic_inc_return(&input_no) - 1); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index aa037fec2f8..0426630f0e9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -327,6 +327,16 @@ config KEYBOARD_NEWTON To compile this driver as a module, choose M here: the module will be called newtonkbd. +config KEYBOARD_NOMADIK + tristate "ST-Ericsson Nomadik SKE keyboard" + depends on PLAT_NOMADIK + help + Say Y here if you want to use a keypad provided on the SKE controller + used on the Ux500 and Nomadik platforms + + To compile this driver as a module, choose M here: the + module will be called nmk-ske-keypad. + config KEYBOARD_OPENCORES tristate "OpenCores Keyboard Controller" help @@ -424,6 +434,15 @@ config KEYBOARD_OMAP To compile this driver as a module, choose M here: the module will be called omap-keypad. +config KEYBOARD_OMAP4 + tristate "TI OMAP4 keypad support" + depends on ARCH_OMAP4 + help + Say Y here if you want to use the OMAP4 keypad. + + To compile this driver as a module, choose M here: the + module will be called omap4-keypad. + config KEYBOARD_TWL4030 tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" depends on TWL4030_CORE diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 504b591be0c..c13809c5c3a 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -28,7 +28,9 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o +obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o +obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index d6918cb966c..b92d1cd5cba 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -660,7 +660,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = { #endif static const struct i2c_device_id adp5588_id[] = { - { KBUILD_MODNAME, 0 }, + { "adp5588-keys", 0 }, { "adp5587-keys", 0 }, { } }; diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index 19fa94af207..fed31e0947a 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -570,6 +570,8 @@ static struct serio_device_id hil_dev_ids[] = { { 0 } }; +MODULE_DEVICE_TABLE(serio, hil_dev_ids); + static struct serio_driver hil_serio_drv = { .driver = { .name = "hil_dev", diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c new file mode 100644 index 00000000000..6e0f2309136 --- /dev/null +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson + * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson + * + * License terms:GNU General Public License (GPL) version 2 + * + * Keypad controller driver for the SKE (Scroll Key Encoder) module used in + * the Nomadik 8815 and Ux500 platforms. + */ + +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/input.h> +#include <linux/slab.h> +#include <linux/clk.h> + +#include <plat/ske.h> + +/* SKE_CR bits */ +#define SKE_KPMLT (0x1 << 6) +#define SKE_KPCN (0x7 << 3) +#define SKE_KPASEN (0x1 << 2) +#define SKE_KPASON (0x1 << 7) + +/* SKE_IMSC bits */ +#define SKE_KPIMA (0x1 << 2) + +/* SKE_ICR bits */ +#define SKE_KPICS (0x1 << 3) +#define SKE_KPICA (0x1 << 2) + +/* SKE_RIS bits */ +#define SKE_KPRISA (0x1 << 2) + +#define SKE_KEYPAD_ROW_SHIFT 3 +#define SKE_KPD_KEYMAP_SIZE (8 * 8) + +/* keypad auto scan registers */ +#define SKE_ASR0 0x20 +#define SKE_ASR1 0x24 +#define SKE_ASR2 0x28 +#define SKE_ASR3 0x2C + +#define SKE_NUM_ASRX_REGISTERS |