diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 18:46:02 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 18:46:02 -0700 |
commit | f4f9b8fc73f9aa93744f0e91e18f367d7766f523 (patch) | |
tree | 90d02c6722b0ffd8252ac438370600aaf8d814e7 /drivers/input | |
parent | 9894e6d9c020b754dd962960e9f7eac18282f69f (diff) | |
parent | a292241cccb7e20e8b997a9a44177e7c98141859 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
Pull input updates from Dmitry Torokhov:
"A big update to the Atmel touchscreen driver, devm support for polled
input devices, several drivers have been converted to using managed
resources, and assorted driver fixes"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (87 commits)
Input: synaptics - fix resolution for manually provided min/max
Input: atmel_mxt_ts - fix invalid return from mxt_get_bootloader_version
Input: max8997_haptic - add error handling for regulator and pwm
Input: elantech - don't set bit 1 of reg_10 when the no_hw_res quirk is set
Input: elantech - deal with clickpads reporting right button events
Input: edt-ft5x06 - fix an i2c write for M09 support
Input: omap-keypad - remove platform data support
ARM: OMAP2+: remove unused omap4-keypad file and code
Input: ab8500-ponkey - switch to using managed resources
Input: max8925_onkey - switch to using managed resources
Input: 88pm860x-ts - switch to using managed resources
Input: 88pm860x_onkey - switch to using managed resources
Input: intel-mid-touch - switch to using managed resources
Input: wacom - process outbound for newer Cintiqs
Input: wacom - set stylus_in_proximity when pen is in range
DTS: ARM: OMAP3-N900: Add tsc2005 support
Input: tsc2005 - add DT support
Input: add common DT binding for touchscreens
Input: jornada680_kbd - switch top using managed resources
Input: adp5520-keys - switch to using managed resources
...
Diffstat (limited to 'drivers/input')
52 files changed, 2234 insertions, 1017 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index ce953d895f5..fd325ec9f06 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -629,12 +629,10 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) return copy_to_user(p, str, len) ? -EFAULT : len; } -#define OLD_KEY_MAX 0x1ff static int handle_eviocgbit(struct input_dev *dev, unsigned int type, unsigned int size, void __user *p, int compat_mode) { - static unsigned long keymax_warn_time; unsigned long *bits; int len; @@ -652,24 +650,8 @@ static int handle_eviocgbit(struct input_dev *dev, default: return -EINVAL; } - /* - * Work around bugs in userspace programs that like to do - * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' - * should be in bytes, not in bits. - */ - if (type == EV_KEY && size == OLD_KEY_MAX) { - len = OLD_KEY_MAX; - if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) - pr_warning("(EVIOCGBIT): Suspicious buffer size %u, " - "limiting output to %zu bytes. See " - "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", - OLD_KEY_MAX, - BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); - } - return bits_to_user(bits, len, size, p, compat_mode); } -#undef OLD_KEY_MAX static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) { diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 7f161d93203..3664f81655c 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c @@ -147,6 +147,11 @@ static struct attribute_group input_polldev_attribute_group = { .attrs = sysfs_attrs }; +static const struct attribute_group *input_polldev_attribute_groups[] = { + &input_polldev_attribute_group, + NULL +}; + /** * input_allocate_polled_device - allocate memory for polled device * @@ -171,6 +176,91 @@ struct input_polled_dev *input_allocate_polled_device(void) } EXPORT_SYMBOL(input_allocate_polled_device); +struct input_polled_devres { + struct input_polled_dev *polldev; +}; + +static int devm_input_polldev_match(struct device *dev, void *res, void *data) +{ + struct input_polled_devres *devres = res; + + return devres->polldev == data; +} + +static void devm_input_polldev_release(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: dropping reference/freeing %s\n", + __func__, dev_name(&polldev->input->dev)); + + input_put_device(polldev->input); + kfree(polldev); +} + +static void devm_input_polldev_unregister(struct device *dev, void *res) +{ + struct input_polled_devres *devres = res; + struct input_polled_dev *polldev = devres->polldev; + + dev_dbg(dev, "%s: unregistering device %s\n", + __func__, dev_name(&polldev->input->dev)); + input_unregister_device(polldev->input); + + /* + * Note that we are still holding extra reference to the input + * device so it will stick around until devm_input_polldev_release() + * is called. + */ +} + +/** + * devm_input_allocate_polled_device - allocate managed polled device + * @dev: device owning the polled device being created + * + * Returns prepared &struct input_polled_dev or %NULL. + * + * Managed polled input devices do not need to be explicitly unregistered + * or freed as it will be done automatically when owner device unbinds + * from * its driver (or binding fails). Once such managed polled device + * is allocated, it is ready to be set up and registered in the same + * fashion as regular polled input devices (using + * input_register_polled_device() function). + * + * If you want to manually unregister and free such managed polled devices, + * it can be still done by calling input_unregister_polled_device() and + * input_free_polled_device(), although it is rarely needed. + * + * NOTE: the owner device is set up as parent of input device and users + * should not override it. + */ +struct input_polled_dev *devm_input_allocate_polled_device(struct device *dev) +{ + struct input_polled_dev *polldev; + struct input_polled_devres *devres; + + devres = devres_alloc(devm_input_polldev_release, sizeof(*devres), + GFP_KERNEL); + if (!devres) + return NULL; + + polldev = input_allocate_polled_device(); + if (!polldev) { + devres_free(devres); + return NULL; + } + + polldev->input->dev.parent = dev; + polldev->devres_managed = true; + + devres->polldev = polldev; + devres_add(dev, devres); + + return polldev; +} +EXPORT_SYMBOL(devm_input_allocate_polled_device); + /** * input_free_polled_device - free memory allocated for polled device * @dev: device to free @@ -181,7 +271,12 @@ EXPORT_SYMBOL(input_allocate_polled_device); void input_free_polled_device(struct input_polled_dev *dev) { if (dev) { - input_free_device(dev->input); + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_release, + devm_input_polldev_match, + dev)); + input_put_device(dev->input); kfree(dev); } } @@ -199,26 +294,35 @@ EXPORT_SYMBOL(input_free_polled_device); */ int input_register_polled_device(struct input_polled_dev *dev) { + struct input_polled_devres *devres = NULL; struct input_dev *input = dev->input; int error; + if (dev->devres_managed) { + devres = devres_alloc(devm_input_polldev_unregister, + sizeof(*devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; + + devres->polldev = dev; + } + input_set_drvdata(input, dev); INIT_DELAYED_WORK(&dev->work, input_polled_device_work); + if (!dev->poll_interval) dev->poll_interval = 500; if (!dev->poll_interval_max) dev->poll_interval_max = dev->poll_interval; + input->open = input_open_polled_device; input->close = input_close_polled_device; - error = input_register_device(input); - if (error) - return error; + input->dev.groups = input_polldev_attribute_groups; - error = sysfs_create_group(&input->dev.kobj, - &input_polldev_attribute_group); + error = input_register_device(input); if (error) { - input_unregister_device(input); + devres_free(devres); return error; } @@ -231,6 +335,12 @@ int input_register_polled_device(struct input_polled_dev *dev) */ input_get_device(input); + if (dev->devres_managed) { + dev_dbg(input->dev.parent, "%s: registering %s with devres.\n", + __func__, dev_name(&input->dev)); + devres_add(input->dev.parent, devres); + } + return 0; } EXPORT_SYMBOL(input_register_polled_device); @@ -245,8 +355,11 @@ EXPORT_SYMBOL(input_register_polled_device); */ void input_unregister_polled_device(struct input_polled_dev *dev) { - sysfs_remove_group(&dev->input->dev.kobj, - &input_polldev_attribute_group); + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->input->dev.parent, + devm_input_polldev_unregister, + devm_input_polldev_match, + dev)); input_unregister_device(dev->input); } diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index ffc7ad3a2c8..f7e79b48134 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -524,6 +524,17 @@ config KEYBOARD_STOWAWAY To compile this driver as a module, choose M here: the module will be called stowaway. +config KEYBOARD_ST_KEYSCAN + tristate "STMicroelectronics keyscan support" + depends on ARCH_STI || COMPILE_TEST + select INPUT_MATRIXKMAP + help + Say Y here if you want to use a keypad attached to the keyscan block + on some STMicroelectronics SoC devices. + + To compile this driver as a module, choose M here: the + module will be called st-keyscan. + config KEYBOARD_SUNKBD tristate "Sun Type 4 and Type 5 keyboard" select SERIO @@ -578,7 +589,7 @@ config KEYBOARD_OMAP config KEYBOARD_OMAP4 tristate "TI OMAP4+ keypad support" - depends on ARCH_OMAP2PLUS + depends on OF || ARCH_OMAP2PLUS select INPUT_MATRIXKMAP help Say Y here if you want to use the OMAP4+ keypad. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 11cff7b84b4..7504ae19049 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o +obj-$(CONFIG_KEYBOARD_ST_KEYSCAN) += st-keyscan.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index 4cc14c2fa7d..7f4a8b58efc 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -12,6 +12,7 @@ #include <linux/input.h> #include <linux/mfd/adp5520.h> #include <linux/slab.h> +#include <linux/device.h> struct adp5520_keys { struct input_dev *input; @@ -81,7 +82,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) return -EINVAL; } - if (pdata == NULL) { + if (!pdata) { dev_err(&pdev->dev, "missing platform data\n"); return -EINVAL; } @@ -89,17 +90,15 @@ static int adp5520_keys_probe(struct platform_device *pdev) if (!(pdata->rows_en_mask && pdata->cols_en_mask)) return -EINVAL; - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { + dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); + if (!dev) { dev_err(&pdev->dev, "failed to alloc memory\n"); return -ENOMEM; } - input = input_allocate_device(); - if (!input) { - ret = -ENOMEM; - goto err; - } + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; dev->master = pdev->dev.parent; dev->input = input; @@ -135,7 +134,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) ret = input_register_device(input); if (ret) { dev_err(&pdev->dev, "unable to register input device\n"); - goto err; + return ret; } en_mask = pdata->rows_en_mask | pdata->cols_en_mask; @@ -157,8 +156,7 @@ static int adp5520_keys_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "failed to write\n"); - ret = -EIO; - goto err1; + return -EIO; } dev->notifier.notifier_call = adp5520_keys_notifier; @@ -166,19 +164,11 @@ static int adp5520_keys_probe(struct platform_device *pdev) ADP5520_KP_IEN | ADP5520_KR_IEN); if (ret) { dev_err(&pdev->dev, "failed to register notifier\n"); - goto err1; + return ret; } platform_set_drvdata(pdev, dev); return 0; - -err1: - input_unregister_device(input); - input = NULL; -err: - input_free_device(input); - kfree(dev); - return ret; } static int adp5520_keys_remove(struct platform_device *pdev) @@ -188,8 +178,6 @@ static int adp5520_keys_remove(struct platform_device *pdev) adp5520_unregister_notifier(dev->master, &dev->notifier, ADP5520_KP_IEN | ADP5520_KR_IEN); - input_unregister_device(dev->input); - kfree(dev); return 0; } diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c index 3955aecee44..552b65c6e6b 100644 --- a/drivers/input/keyboard/clps711x-keypad.c +++ b/drivers/input/keyboard/clps711x-keypad.c @@ -185,7 +185,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev) return 0; } -static struct of_device_id clps711x_keypad_of_match[] = { +static const struct of_device_id clps711x_keypad_of_match[] = { { .compatible = "cirrus,clps711x-keypad", }, { } }; diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 2db13246eb8..8c98e97f8e4 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -424,6 +424,16 @@ out: return IRQ_HANDLED; } +static void gpio_keys_quiesce_key(void *data) +{ + struct gpio_button_data *bdata = data; + + if (bdata->timer_debounce) + del_timer_sync(&bdata->timer); + + cancel_work_sync(&bdata->work); +} + static int gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_button_data *bdata, @@ -433,7 +443,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, struct device *dev = &pdev->dev; irq_handler_t isr; unsigned long irqflags; - int irq, error; + int irq; + int error; bdata->input = input; bdata->button = button; @@ -441,7 +452,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, if (gpio_is_valid(button->gpio)) { - error = gpio_request_one(button->gpio, GPIOF_IN, desc); + error = devm_gpio_request_one(&pdev->dev, button->gpio, + GPIOF_IN, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); @@ -463,7 +475,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); - goto fail; + return error; } bdata->irq = irq; @@ -497,26 +509,33 @@ static int gpio_keys_setup_key(struct platform_device *pdev, input_set_capability(input, button->type ?: EV_KEY, button->code); /* + * Install custom action to cancel debounce timer and + * workqueue item. + */ + error = devm_add_action(&pdev->dev, gpio_keys_quiesce_key, bdata); + if (error) { + dev_err(&pdev->dev, + "failed to register quiesce action, error: %d\n", + error); + return error; + } + + /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. */ if (!button->can_disable) irqflags |= IRQF_SHARED; - error = request_any_context_irq(bdata->irq, isr, irqflags, desc, bdata); + error = devm_request_any_context_irq(&pdev->dev, bdata->irq, + isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); - goto fail; + return error; } return 0; - -fail: - if (gpio_is_valid(button->gpio)) - gpio_free(button->gpio); - - return error; } static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) @@ -578,23 +597,18 @@ gpio_keys_get_devtree_pdata(struct device *dev) int i; node = dev->of_node; - if (!node) { - error = -ENODEV; - goto err_out; - } + if (!node) + return ERR_PTR(-ENODEV); nbuttons = of_get_child_count(node); - if (nbuttons == 0) { - error = -ENODEV; - goto err_out; - } + if (nbuttons == 0) + return ERR_PTR(-ENODEV); - pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), - GFP_KERNEL); - if (!pdata) { - error = -ENOMEM; - goto err_out; - } + pdata = devm_kzalloc(dev, + sizeof(*pdata) + nbuttons * sizeof(*button), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); pdata->buttons = (struct gpio_keys_button *)(pdata + 1); pdata->nbuttons = nbuttons; @@ -619,7 +633,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) dev_err(dev, "Failed to get gpio flags, error: %d\n", error); - goto err_free_pdata; + return ERR_PTR(error); } button = &pdata->buttons[i++]; @@ -630,8 +644,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) if (of_property_read_u32(pp, "linux,code", &button->code)) { dev_err(dev, "Button without keycode: 0x%x\n", button->gpio); - error = -EINVAL; - goto err_free_pdata; + return ERR_PTR(-EINVAL); } button->desc = of_get_property(pp, "label", NULL); @@ -646,20 +659,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) button->debounce_interval = 5; } - if (pdata->nbuttons == 0) { - error = -EINVAL; - goto err_free_pdata; - } + if (pdata->nbuttons == 0) + return ERR_PTR(-EINVAL); return pdata; - -err_free_pdata: - kfree(pdata); -err_out: - return ERR_PTR(error); } -static struct of_device_id gpio_keys_of_match[] = { +static const struct of_device_id gpio_keys_of_match[] = { { .compatible = "gpio-keys", }, { }, }; @@ -675,22 +681,13 @@ gpio_keys_get_devtree_pdata(struct device *dev) #endif -static void gpio_remove_key(struct gpio_button_data *bdata) -{ - free_irq(bdata->irq, bdata); - if (bdata->timer_debounce) - del_timer_sync(&bdata->timer); - cancel_work_sync(&bdata->work); - if (gpio_is_valid(bdata->button->gpio)) - gpio_free(bdata->button->gpio); -} - static int gpio_keys_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_drvdata *ddata; struct input_dev *input; + size_t size; int i, error; int wakeup = 0; @@ -700,14 +697,18 @@ static int gpio_keys_probe(struct platform_device *pdev) return PTR_ERR(pdata); } - ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + - pdata->nbuttons * sizeof(struct gpio_button_data), - GFP_KERNEL); - input = input_allocate_device(); - if (!ddata || !input) { + size = sizeof(struct gpio_keys_drvdata) + + pdata->nbuttons * sizeof(struct gpio_button_data); + ddata = devm_kzalloc(dev, size, GFP_KERNEL); + if (!ddata) { dev_err(dev, "failed to allocate state\n"); - error = -ENOMEM; - goto fail1; + return -ENOMEM; + } + + input = devm_input_allocate_device(dev); + if (!input) { + dev_err(dev, "failed to allocate input device\n"); + return -ENOMEM; } ddata->pdata = pdata; @@ -738,7 +739,7 @@ static int gpio_keys_probe(struct platform_device *pdev) error = gpio_keys_setup_key(pdev, input, bdata, button); if (error) - goto fail2; + return error; if (button->wakeup) wakeup = 1; @@ -748,57 +749,31 @@ static int gpio_keys_probe(struct platform_device *pdev) if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); - goto fail2; + return error; } error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", error); - goto fail3; + goto err_remove_group; } device_init_wakeup(&pdev->dev, wakeup); return 0; - fail3: +err_remove_group: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); - fail2: - while (--i >= 0) - gpio_remove_key(&ddata->data[i]); - - fail1: - input_free_device(input); - kfree(ddata); - /* If we have no platform data, we allocated pdata dynamically. */ - if (!dev_get_platdata(&pdev->dev)) - kfree(pdata); - return error; } static int gpio_keys_remove(struct platform_device *pdev) { - struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); - struct input_dev *input = ddata->input; - int i; - sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < ddata->pdata->nbuttons; i++) - gpio_remove_key(&ddata->data[i]); - - input_unregister_device(input); - - /* If we have no platform data, we allocated pdata dynamically. */ - if (!dev_get_platdata(&pdev->dev)) - kfree(ddata->pdata); - - kfree(ddata); - return 0; } diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index e571e194ff8..432d36395f3 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/ |