diff options
Diffstat (limited to 'drivers/input')
40 files changed, 1208 insertions, 796 deletions
diff --git a/drivers/input/apm-power.c b/drivers/input/apm-power.c index e90ee3d3061..650177a3c85 100644 --- a/drivers/input/apm-power.c +++ b/drivers/input/apm-power.c @@ -33,7 +33,7 @@ static void system_power_event(unsigned int keycode) } static void apmpower_event(struct input_handle *handle, unsigned int type, - unsigned int code, int value) + unsigned int code, int value) { /* only react on key down events */ if (value != 1) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 118d0300f1f..f0f8928b3c8 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -23,11 +23,11 @@ #include <linux/input/mt.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/cdev.h> #include "input-compat.h" struct evdev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct evdev_client __rcu *grab; @@ -35,6 +35,7 @@ struct evdev { spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; }; @@ -51,9 +52,6 @@ struct evdev_client { struct input_event buffer[]; }; -static struct evdev *evdev_table[EVDEV_MINORS]; -static DEFINE_MUTEX(evdev_table_mutex); - static void __pass_event(struct evdev_client *client, const struct input_event *event) { @@ -294,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file) kfree(client); evdev_close_device(evdev); - put_device(&evdev->dev); return 0; } @@ -310,35 +307,16 @@ static unsigned int evdev_compute_buffer_size(struct input_dev *dev) static int evdev_open(struct inode *inode, struct file *file) { - struct evdev *evdev; + struct evdev *evdev = container_of(inode->i_cdev, struct evdev, cdev); + unsigned int bufsize = evdev_compute_buffer_size(evdev->handle.dev); struct evdev_client *client; - int i = iminor(inode) - EVDEV_MINOR_BASE; - unsigned int bufsize; int error; - if (i >= EVDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&evdev_table_mutex); - if (error) - return error; - evdev = evdev_table[i]; - if (evdev) - get_device(&evdev->dev); - mutex_unlock(&evdev_table_mutex); - - if (!evdev) - return -ENODEV; - - bufsize = evdev_compute_buffer_size(evdev->handle.dev); - client = kzalloc(sizeof(struct evdev_client) + bufsize * sizeof(struct input_event), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_evdev; - } + if (!client) + return -ENOMEM; client->bufsize = bufsize; spin_lock_init(&client->buffer_lock); @@ -357,8 +335,6 @@ static int evdev_open(struct inode *inode, struct file *file) err_free_client: evdev_detach_client(evdev, client); kfree(client); - err_put_evdev: - put_device(&evdev->dev); return error; } @@ -942,26 +918,6 @@ static const struct file_operations evdev_fops = { .llseek = no_llseek, }; -static int evdev_install_chrdev(struct evdev *evdev) -{ - /* - * No need to do any locking here as calls to connect and - * disconnect are serialized by the input core - */ - evdev_table[evdev->minor] = evdev; - return 0; -} - -static void evdev_remove_chrdev(struct evdev *evdev) -{ - /* - * Lock evdev table to prevent race with evdev_open() - */ - mutex_lock(&evdev_table_mutex); - evdev_table[evdev->minor] = NULL; - mutex_unlock(&evdev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -980,7 +936,8 @@ static void evdev_cleanup(struct evdev *evdev) evdev_mark_dead(evdev); evdev_hangup(evdev); - evdev_remove_chrdev(evdev); + + cdev_del(&evdev->cdev); /* evdev is marked dead so no one else accesses evdev->open */ if (evdev->open) { @@ -991,43 +948,47 @@ static void evdev_cleanup(struct evdev *evdev) /* * Create new evdev device. Note that input core serializes calls - * to connect and disconnect so we don't need to lock evdev_table here. + * to connect and disconnect. */ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct evdev *evdev; int minor; + int dev_no; int error; - for (minor = 0; minor < EVDEV_MINORS; minor++) - if (!evdev_table[minor]) - break; - - if (minor == EVDEV_MINORS) { - pr_err("no more free evdev devices\n"); - return -ENFILE; + minor = input_get_new_minor(EVDEV_MINOR_BASE, EVDEV_MINORS, true); + if (minor < 0) { + error = minor; + pr_err("failed to reserve new minor: %d\n", error); + return error; } evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); - if (!evdev) - return -ENOMEM; + if (!evdev) { + error = -ENOMEM; + goto err_free_minor; + } INIT_LIST_HEAD(&evdev->client_list); spin_lock_init(&evdev->client_lock); mutex_init(&evdev->mutex); init_waitqueue_head(&evdev->wait); - - dev_set_name(&evdev->dev, "event%d", minor); evdev->exist = true; - evdev->minor = minor; + + dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < EVDEV_MINOR_BASE + EVDEV_MINORS) + dev_no -= EVDEV_MINOR_BASE; + dev_set_name(&evdev->dev, "event%d", dev_no); evdev->handle.dev = input_get_device(dev); evdev->handle.name = dev_name(&evdev->dev); evdev->handle.handler = handler; evdev->handle.private = evdev; - evdev->dev.devt = MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor); + evdev->dev.devt = MKDEV(INPUT_MAJOR, minor); evdev->dev.class = &input_class; evdev->dev.parent = &dev->dev; evdev->dev.release = evdev_free; @@ -1037,7 +998,9 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, if (error) goto err_free_evdev; - error = evdev_install_chrdev(evdev); + cdev_init(&evdev->cdev, &evdev_fops); + evdev->cdev.kobj.parent = &evdev->dev.kobj; + error = cdev_add(&evdev->cdev, evdev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -1053,6 +1016,8 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev, input_unregister_handle(&evdev->handle); err_free_evdev: put_device(&evdev->dev); + err_free_minor: + input_free_minor(minor); return error; } @@ -1062,6 +1027,7 @@ static void evdev_disconnect(struct input_handle *handle) device_del(&evdev->dev); evdev_cleanup(evdev); + input_free_minor(MINOR(evdev->dev.devt)); input_unregister_handle(handle); put_device(&evdev->dev); } @@ -1078,7 +1044,7 @@ static struct input_handler evdev_handler = { .events = evdev_events, .connect = evdev_connect, .disconnect = evdev_disconnect, - .fops = &evdev_fops, + .legacy_minors = true, .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 480eb9d9876..f50f6dd9227 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -138,8 +138,8 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, if (effect->id == -1) { for (id = 0; id < ff->max_effects; id++) - if (!ff->effect_owners[id]) - break; + if (!ff->effect_owners[id]) + break; if (id >= ff->max_effects) { ret = -ENOSPC; diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b107922514f..74c0d8c6002 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -72,12 +72,14 @@ static const struct ff_envelope *get_envelope(const struct ff_effect *effect) static const struct ff_envelope empty_envelope; switch (effect->type) { - case FF_PERIODIC: - return &effect->u.periodic.envelope; - case FF_CONSTANT: - return &effect->u.constant.envelope; - default: - return &empty_envelope; + case FF_PERIODIC: + return &effect->u.periodic.envelope; + + case FF_CONSTANT: + return &effect->u.constant.envelope; + + default: + return &empty_envelope; } } diff --git a/drivers/input/input.c b/drivers/input/input.c index 5244f3d05b1..53a0ddee787 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -14,6 +14,7 @@ #include <linux/init.h> #include <linux/types.h> +#include <linux/idr.h> #include <linux/input/mt.h> #include <linux/module.h> #include <linux/slab.h> @@ -32,7 +33,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); MODULE_DESCRIPTION("Input core"); MODULE_LICENSE("GPL"); -#define INPUT_DEVICES 256 +#define INPUT_MAX_CHAR_DEVICES 1024 +#define INPUT_FIRST_DYNAMIC_DEV 256 +static DEFINE_IDA(input_ida); static LIST_HEAD(input_dev_list); static LIST_HEAD(input_handler_list); @@ -45,8 +48,6 @@ static LIST_HEAD(input_handler_list); */ static DEFINE_MUTEX(input_mutex); -static struct input_handler *input_table[8]; - static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; static inline int is_event_supported(unsigned int code, @@ -918,18 +919,10 @@ int input_set_keycode(struct input_dev *dev, } EXPORT_SYMBOL(input_set_keycode); -#define MATCH_BIT(bit, max) \ - for (i = 0; i < BITS_TO_LONGS(max); i++) \ - if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \ - break; \ - if (i != BITS_TO_LONGS(max)) \ - continue; - static const struct input_device_id *input_match_device(struct input_handler *handler, struct input_dev *dev) { const struct input_device_id *id; - int i; for (id = handler->id_table; id->flags || id->driver_info; id++) { @@ -949,15 +942,32 @@ static const struct input_device_id *input_match_device(struct input_handler *ha if (id->version != dev->id.version) continue; - MATCH_BIT(evbit, EV_MAX); - MATCH_BIT(keybit, KEY_MAX); - MATCH_BIT(relbit, REL_MAX); - MATCH_BIT(absbit, ABS_MAX); - MATCH_BIT(mscbit, MSC_MAX); - MATCH_BIT(ledbit, LED_MAX); - MATCH_BIT(sndbit, SND_MAX); - MATCH_BIT(ffbit, FF_MAX); - MATCH_BIT(swbit, SW_MAX); + if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX)) + continue; + + if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX)) + continue; + + if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX)) + continue; + + if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX)) + continue; + + if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX)) + continue; + + if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX)) + continue; + + if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX)) + continue; + + if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX)) + continue; + + if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX)) + continue; if (!handler->match || handler->match(handler, dev)) return id; @@ -1209,7 +1219,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); if (handler->filter) seq_puts(seq, " (filter)"); - if (handler->fops) + if (handler->legacy_minors) seq_printf(seq, " Minor=%d", handler->minor); seq_putc(seq, '\n'); @@ -2007,22 +2017,14 @@ EXPORT_SYMBOL(input_unregister_device); int input_register_handler(struct input_handler *handler) { struct input_dev *dev; - int retval; + int error; - retval = mutex_lock_interruptible(&input_mutex); - if (retval) - return retval; + error = mutex_lock_interruptible(&input_mutex); + if (error) + return error; INIT_LIST_HEAD(&handler->h_list); - if (handler->fops != NULL) { - if (input_table[handler->minor >> 5]) { - retval = -EBUSY; - goto out; - } - input_table[handler->minor >> 5] = handler; - } - list_add_tail(&handler->node, &input_handler_list); list_for_each_entry(dev, &input_dev_list, node) @@ -2030,9 +2032,8 @@ int input_register_handler(struct input_handler *handler) input_wakeup_procfs_readers(); - out: mutex_unlock(&input_mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_register_handler); @@ -2055,9 +2056,6 @@ void input_unregister_handler(struct input_handler *handler) list_del_init(&handler->node); - if (handler->fops != NULL) - input_table[handler->minor >> 5] = NULL; - input_wakeup_procfs_readers(); mutex_unlock(&input_mutex); @@ -2174,51 +2172,52 @@ void input_unregister_handle(struct input_handle *handle) } EXPORT_SYMBOL(input_unregister_handle); -static int input_open_file(struct inode *inode, struct file *file) +/** + * input_get_new_minor - allocates a new input minor number + * @legacy_base: beginning or the legacy range to be searched + * @legacy_num: size of legacy range + * @allow_dynamic: whether we can also take ID from the dynamic range + * + * This function allocates a new device minor for from input major namespace. + * Caller can request legacy minor by specifying @legacy_base and @legacy_num + * parameters and whether ID can be allocated from dynamic range if there are + * no free IDs in legacy range. + */ +int input_get_new_minor(int legacy_base, unsigned int legacy_num, + bool allow_dynamic) { - struct input_handler *handler; - const struct file_operations *old_fops, *new_fops = NULL; - int err; - - 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); - - mutex_unlock(&input_mutex); - /* - * That's _really_ odd. Usually NULL ->open means "nothing special", - * not "no device". Oh, well... + * This function should be called from input handler's ->connect() + * methods, which are serialized with input_mutex, so no additional + * locking is needed here. */ - if (!new_fops || !new_fops->open) { - fops_put(new_fops); - err = -ENODEV; - goto out; + if (legacy_base >= 0) { + int minor = ida_simple_get(&input_ida, + legacy_base, + legacy_base + legacy_num, + GFP_KERNEL); + if (minor >= 0 || !allow_dynamic) + return minor; } - 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: - return err; + return ida_simple_get(&input_ida, + INPUT_FIRST_DYNAMIC_DEV, INPUT_MAX_CHAR_DEVICES, + GFP_KERNEL); } +EXPORT_SYMBOL(input_get_new_minor); -static const struct file_operations input_fops = { - .owner = THIS_MODULE, - .open = input_open_file, - .llseek = noop_llseek, -}; +/** + * input_free_minor - release previously allocated minor + * @minor: minor to be released + * + * This function releases previously allocated input minor so that it can be + * reused later. + */ +void input_free_minor(unsigned int minor) +{ + ida_simple_remove(&input_ida, minor); +} +EXPORT_SYMBOL(input_free_minor); static int __init input_init(void) { @@ -2234,7 +2233,8 @@ static int __init input_init(void) if (err) goto fail1; - err = register_chrdev(INPUT_MAJOR, "input", &input_fops); + err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0), + INPUT_MAX_CHAR_DEVICES, "input"); if (err) { pr_err("unable to register char major %d", INPUT_MAJOR); goto fail2; @@ -2250,7 +2250,8 @@ static int __init input_init(void) static void __exit input_exit(void) { input_proc_exit(); - unregister_chrdev(INPUT_MAJOR, "input"); + unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0), + INPUT_MAX_CHAR_DEVICES); class_unregister(&input_class); } diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 26043cc6a01..f362883c94e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -27,6 +27,7 @@ #include <linux/poll.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/cdev.h> MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Joystick device interfaces"); @@ -39,13 +40,13 @@ MODULE_LICENSE("GPL"); struct joydev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; struct js_corr corr[ABS_CNT]; @@ -70,9 +71,6 @@ struct joydev_client { struct list_head node; }; -static struct joydev *joydev_table[JOYDEV_MINORS]; -static DEFINE_MUTEX(joydev_table_mutex); - static int joydev_correct(int value, struct js_corr *corr) { switch (corr->type) { @@ -245,37 +243,20 @@ static int joydev_release(struct inode *inode, struct file *file) kfree(client); joydev_close_device(joydev); - put_device(&joydev->dev); return 0; } static int joydev_open(struct inode *inode, struct file *file) { + struct joydev *joydev = + container_of(inode->i_cdev, struct joydev, cdev); struct joydev_client *client; - struct joydev *joydev; - int i = iminor(inode) - JOYDEV_MINOR_BASE; int error; - if (i >= JOYDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&joydev_table_mutex); - if (error) - return error; - joydev = joydev_table[i]; - if (joydev) - get_device(&joydev->dev); - mutex_unlock(&joydev_table_mutex); - - if (!joydev) - return -ENODEV; - client = kzalloc(sizeof(struct joydev_client), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_joydev; - } + if (!client) + return -ENOMEM; spin_lock_init(&client->buffer_lock); client->joydev = joydev; @@ -293,8 +274,6 @@ static int joydev_open(struct inode *inode, struct file *file) err_free_client: joydev_detach_client(joydev, client); kfree(client); - err_put_joydev: - put_device(&joydev->dev); return error; } @@ -711,7 +690,7 @@ static long joydev_ioctl(struct file *file, case JS_SET_ALL: retval = copy_from_user(&joydev->glue, argp, - sizeof(joydev->glue)) ? -EFAULT: 0; + sizeof(joydev->glue)) ? -EFAULT : 0; break; case JS_GET_ALL: @@ -742,19 +721,6 @@ static const struct file_operations joydev_fops = { .llseek = no_llseek, }; -static int joydev_install_chrdev(struct joydev *joydev) -{ - joydev_table[joydev->minor] = joydev; - return 0; -} - -static void joydev_remove_chrdev(struct joydev *joydev) -{ - mutex_lock(&joydev_table_mutex); - joydev_table[joydev->minor] = NULL; - mutex_unlock(&joydev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -773,7 +739,8 @@ static void joydev_cleanup(struct joydev *joydev) joydev_mark_dead(joydev); joydev_hangup(joydev); - joydev_remove_chrdev(joydev); + + cdev_del(&joydev->cdev); /* joydev is marked dead so no one else accesses joydev->open */ if (joydev->open) @@ -798,30 +765,33 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct joydev *joydev; - int i, j, t, minor; + int i, j, t, minor, dev_no; int error; - for (minor = 0; minor < JOYDEV_MINORS; minor++) - if (!joydev_table[minor]) - break; - - if (minor == JOYDEV_MINORS) { - pr_err("no more free joydev devices\n"); - return -ENFILE; + minor = input_get_new_minor(JOYDEV_MINOR_BASE, JOYDEV_MINORS, true); + if (minor < 0) { + error = minor; + pr_err("failed to reserve new minor: %d\n", error); + return error; } joydev = kzalloc(sizeof(struct joydev), GFP_KERNEL); - if (!joydev) - return -ENOMEM; + if (!joydev) { + error = -ENOMEM; + goto err_free_minor; + } INIT_LIST_HEAD(&joydev->client_list); spin_lock_init(&joydev->client_lock); mutex_init(&joydev->mutex); init_waitqueue_head(&joydev->wait); - - dev_set_name(&joydev->dev, "js%d", minor); joydev->exist = true; - joydev->minor = minor; + + dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < JOYDEV_MINOR_BASE + JOYDEV_MINORS) + dev_no -= JOYDEV_MINOR_BASE; + dev_set_name(&joydev->dev, "js%d", dev_no); joydev->handle.dev = input_get_device(dev); joydev->handle.name = dev_name(&joydev->dev); @@ -875,7 +845,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, } } - joydev->dev.devt = MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor); + joydev->dev.devt = MKDEV(INPUT_MAJOR, minor); joydev->dev.class = &input_class; joydev->dev.parent = &dev->dev; joydev->dev.release = joydev_free; @@ -885,7 +855,9 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, if (error) goto err_free_joydev; - error = joydev_install_chrdev(joydev); + cdev_init(&joydev->cdev, &joydev_fops); + joydev->cdev.kobj.parent = &joydev->dev.kobj; + error = cdev_add(&joydev->cdev, joydev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -901,6 +873,8 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, input_unregister_handle(&joydev->handle); err_free_joydev: put_device(&joydev->dev); + err_free_minor: + input_free_minor(minor); return error; } @@ -910,6 +884,7 @@ static void joydev_disconnect(struct input_handle *handle) device_del(&joydev->dev); joydev_cleanup(joydev); + input_free_minor(MINOR(joydev->dev.devt)); input_unregister_handle(handle); put_device(&joydev->dev); } @@ -961,7 +936,7 @@ static struct input_handler joydev_handler = { .match = joydev_match, .connect = joydev_connect, .disconnect = joydev_disconnect, - .fops = &joydev_fops, + .legacy_minors = true, .minor = JOYDEV_MINOR_BASE, .name = "joydev", .id_table = joydev_ids, diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index c50fa75416f..b4b65af8612 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -533,7 +533,7 @@ config KEYBOARD_DAVINCI config KEYBOARD_OMAP tristate "TI OMAP keypad support" - depends on (ARCH_OMAP1 || ARCH_OMAP2) + depends on ARCH_OMAP1 select INPUT_MATRIXKMAP help Say Y here if you want to use the OMAP keypad. diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index 9d82b3aeff5..d5bacbb479b 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -36,7 +36,7 @@ #include <mach/hardware.h> #include <mach/irqs.h> -#include <mach/keyscan.h> +#include <linux/platform_data/keyscan-davinci.h> /* Key scan registers */ #define DAVINCI_KEYSCAN_KEYCTRL 0x0000 diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index c46fc818546..7363402de8d 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -29,7 +29,7 @@ #include <linux/slab.h> #include <mach/hardware.h> -#include <mach/ep93xx_keypad.h> +#include <linux/platform_data/keypad-ep93xx.h> /* * Keypad Interface Register offsets diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index cbb1add43d5..6a68041c261 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -43,11 +43,9 @@ struct gpio_button_data { }; struct gpio_keys_drvdata { + const struct gpio_keys_platform_data *pdata; struct input_dev *input; struct mutex disable_lock; - unsigned int n_buttons; - int (*enable)(struct device *dev); - void (*disable)(struct device *dev); struct gpio_button_data data[0]; }; @@ -171,7 +169,7 @@ static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, if (!bits) return -ENOMEM; - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -219,7 +217,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, goto out; /* First validate */ - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -234,7 +232,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, mutex_lock(&ddata->disable_lock); - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->type != type) @@ -346,6 +344,9 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) container_of(work, struct gpio_button_data, work); gpio_keys_gpio_report_event(bdata); + + if (bdata->button->wakeup) + pm_relax(bdata->input->dev.parent); } static void gpio_keys_gpio_timer(unsigned long _data) @@ -361,6 +362,8 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id) BUG_ON(irq != bdata->irq); + if (bdata->button->wakeup) + pm_stay_awake(bdata->input->dev.parent); if (bdata->timer_debounce) mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(bdata->timer_debounce)); @@ -397,6 +400,9 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) spin_lock_irqsave(&bdata->lock, flags); if (!bdata->key_pressed) { + if (bdata->button->wakeup) + pm_wakeup_event(bdata->input->dev.parent, 0); + input_event(input, EV_KEY, button->code, 1); input_sync(input); @@ -523,56 +529,64 @@ fail: static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + const struct gpio_keys_platform_data *pdata = ddata->pdata; - return ddata->enable ? ddata->enable(input->dev.parent) : 0; + return pdata->enable ? pdata->enable(input->dev.parent) : 0; } static void gpio_keys_close(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); + const struct gpio_keys_platform_data *pdata = ddata->pdata; - if (ddata->disable) - ddata->disable(input->dev.parent); + if (pdata->disable) + pdata->disable(input->dev.parent); } /* * Handlers for alternative sources of platform_data */ + #ifdef CONFIG_OF /* * Translate OpenFirmware node properties into platform_data */ -static int gpio_keys_get_devtree_pdata(struct device *dev, - struct gpio_keys_platform_data *pdata) +static struct gpio_keys_platform_data * __devinit +gpio_keys_get_devtree_pdata(struct device *dev) { struct device_node *node, *pp; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button *button; + int error; + int nbuttons; int i; - struct gpio_keys_button *buttons; - u32 reg; node = dev->of_node; - if (node == NULL) - return -ENODEV; - - memset(pdata, 0, sizeof *pdata); + if (!node) { + error = -ENODEV; + goto err_out; + } - pdata->rep = !!of_get_property(node, "autorepeat", NULL); + nbuttons = of_get_child_count(node); + if (nbuttons == 0) { + error = -ENODEV; + goto err_out; + } - /* First count the subnodes */ - pp = NULL; - while ((pp = of_get_next_child(node, pp))) - pdata->nbuttons++; + pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), + GFP_KERNEL); + if (!pdata) { + error = -ENOMEM; + goto err_out; + } - if (pdata->nbuttons == 0) - return -ENODEV; + pdata->buttons = (struct gpio_keys_button *)(pdata + 1); + pdata->nbuttons = nbuttons; - buttons = kzalloc(pdata->nbuttons * (sizeof *buttons), GFP_KERNEL); - if (!buttons) - return -ENOMEM; + pdata->rep = !!of_get_property(node, "autorepeat", NULL); - pp = NULL; i = 0; - while ((pp = of_get_next_child(node, pp))) { + for_each_child_of_node(node, pp) { enum of_gpio_flags flags; if (!of_find_property(pp, "gpios", NULL)) { @@ -580,39 +594,42 @@ static int gpio_keys_get_devtree_pdata(struct device *dev, dev_warn(dev, "Found button without gpios\n"); continue; } - buttons[i].gpio = of_get_gpio_flags(pp, 0, &flags); - buttons[i].active_low = flags & OF_GPIO_ACTIVE_LOW; - if (of_property_read_u32(pp, "linux,code", ®)) { - dev_err(dev, "Button without keycode: 0x%x\n", buttons[i].gpio); - goto out_fail; - } - buttons[i].code = reg; + button = &pdata->buttons[i++]; - buttons[i].desc = of_get_property(pp, "label", NULL); + button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->active_low = flags & OF_GPIO_ACTIVE_LOW; - if (of_property_read_u32(pp, "linux,input-type", ®) == 0) - buttons[i].type = reg; - else - buttons[i].type = EV_KEY; + 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; + } - buttons[i].wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + button->desc = of_get_property(pp, "label", NULL); - if (of_property_read_u32(pp, "debounce-interval", ®) == 0) - buttons[i].debounce_interval = reg; - else - buttons[i].debounce_interval = 5; + if (of_property_read_u32(pp, "linux,input-type", &button->type)) + button->type = EV_KEY; - i++; + button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + + if (of_property_read_u32(pp, "debounce-interval", + &button->debounce_interval)) + button->debounce_interval = 5; } - pdata->buttons = buttons; + if (pdata->nbuttons == 0) { + error = -EINVAL; + goto err_free_pdata; + } - return 0; + return pdata; -out_fail: - kfree(buttons); - return -ENODEV; +err_free_pdata: + kfree(pdata); +err_out: + return ERR_PTR(error); } static struct of_device_id gpio_keys_of_match[] = { @@ -623,14 +640,12 @@ MODULE_DEVICE_TABLE(of, gpio_keys_of_match); #else -static int gpio_keys_get_devtree_pdata(struct device *dev, - struct gpio_keys_platform_data *altp) +static inline struct gpio_keys_platform_data * +gpio_keys_get_devtree_pdata(struct device *dev) { - return -ENODEV; + return ERR_PTR(-ENODEV); } -#define gpio_keys_of_match NULL - #endif static void gpio_remove_key(struct gpio_button_data *bdata) @@ -645,19 +660,17 @@ static void gpio_remove_key(struct gpio_button_data *bdata) static int __devinit gpio_keys_probe(struct platform_device *pdev) { - const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; - struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; - struct gpio_keys_platform_data alt_pdata; + const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); + struct gpio_keys_drvdata *ddata; struct input_dev *input; int i, error; int wakeup = 0; if (!pdata) { - error = gpio_keys_get_devtree_pdata(dev, &alt_pdata); - if (error) - return error; - pdata = &alt_pdata; + pdata = gpio_keys_get_devtree_pdata(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); } ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + @@ -670,10 +683,8 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail1; } + ddata->pdata = pdata; ddata->input = input; - ddata->n_buttons = pdata->nbuttons; - ddata->enable = pdata->enable; - ddata->disable = pdata->disable; mutex_init(&ddata->disable_lock); platform_set_drvdata(pdev, ddata); @@ -742,9 +753,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) fail1: input_free_device(input); kfree(ddata); - /* If we have no platform_data, we allocated buttons dynamically. */ - if (!pdev->dev.platform_data) - kfree(pdata->buttons); + /* If we have no platform data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); return error; } @@ -759,18 +770,14 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); - for (i = 0; i < ddata->n_buttons; i++) + for (i = 0; i < ddata->pdata->nbuttons; i++) gpio_remove_key(&ddata->data[i]); input_unregister_device(input); - /* - * If we had no platform_data, we allocated buttons dynamically, and - * must free them here. ddata->data[0].button is the pointer to the - * beginning of the allocated array. - */ - if (!pdev->dev.platform_data) - kfree(ddata->data[0].button); + /* If we have no platform data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(ddata->pdata); kfree(ddata); @@ -784,7 +791,7 @@ static int gpio_keys_suspend(struct device *dev) int i; if (device_may_wakeup(dev)) { - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup) enable_irq_wake(bdata->irq); @@ -799,7 +806,7 @@ static int gpio_keys_resume(struct device *dev) struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); int i; - for (i = 0; i < ddata->n_buttons; i++) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; if (bdata->button->wakeup && device_may_wakeup(dev)) disable_irq_wake(bdata->irq); @@ -822,7 +829,7 @@ static struct platform_driver gpio_keys_device_driver = { .name = "gpio-keys", .owner = THIS_MODULE, .pm = &gpio_keys_pm_ops, - .of_match_table = gpio_keys_of_match, + .of_match_table = of_match_ptr(gpio_keys_of_match), } }; diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index 20c8ab17221..f2142de789e 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -25,6 +25,8 @@ #include <linux/platform_device.h> #include <linux/gpio.h> #include <linux/gpio_keys.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> #define DRV_NAME "gpio-keys-polled" @@ -38,7 +40,7 @@ struct gpio_keys_button_data { struct gpio_keys_polled_dev { struct input_polled_dev *poll_dev; struct device *dev; - struct gpio_keys_platform_data *pdata; + const struct gpio_keys_platform_data *pdata; struct gpio_keys_button_data data[0]; }; @@ -67,11 +69,11 @@ static void gpio_keys_polled_check_state(struct input_dev *input, static void gpio_keys_polled_poll(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; struct input_dev *input = dev->input; int i; - for (i = 0; i < bdev->pdata->nbuttons; i++) { + for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button_data *bdata = &bdev->data[i]; if (bdata->count < bdata->threshold) @@ -85,7 +87,7 @@ static void gpio_keys_polled_poll(struct input_polled_dev *dev) static void gpio_keys_polled_open(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->enable) pdata->enable(bdev->dev); @@ -94,31 +96,139 @@ static void gpio_keys_polled_open(struct input_polled_dev *dev) static void gpio_keys_polled_close(struct input_polled_dev *dev) { struct gpio_keys_polled_dev *bdev = dev->private; - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; if (pdata->disable) pdata->disable(bdev->dev); } +#ifdef CONFIG_OF +static struct gpio_keys_platform_data * __devinit +gpio_keys_polled_get_devtree_pdata(struct device *dev) +{ + struct device_node *node, *pp; + struct gpio_keys_platform_data *pdata; + struct gpio_keys_button *button; + int error; + int nbuttons; + int i; + + node = dev->of_node; + if (!node) + return NULL; + + nbuttons = of_get_child_count(node); + if (nbuttons == 0) + return NULL; + + pdata = kzalloc(sizeof(*pdata) + nbuttons * (sizeof *button), + GFP_KERNEL); + if (!pdata) { + error = -ENOMEM; + goto err_out; + } + + pdata->buttons = (struct gpio_keys_button *)(pdata + 1); + pdata->nbuttons = nbuttons; + + pdata->rep = !!of_get_property(node, "autorepeat", NULL); + of_property_read_u32(node, "poll-interval", &pdata->poll_interval); + + i = 0; + for_each_child_of_node(node, pp) { + enum of_gpio_flags flags; + + if (!of_find_property(pp, "gpios", NULL)) { + pdata->nbuttons--; + dev_warn(dev, "Found button without gpios\n"); + continue; + } + + button = &pdata->buttons[i++]; + + button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->active_low = flags & OF_GPIO_ACTIVE_LOW; + + 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; + } + + button->desc = of_get_property(pp, "label", NULL); + + if (of_property_read_u32(pp, "linux,input-type", &button->type)) + button->type = EV_KEY; + + button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL); + + if (of_property_read_u32(pp, "debounce-interval", + &button->debounce_interval)) + button->debounce_interval = 5; + } + + if (pdata->nbuttons == 0) { + error = -EINVAL; + goto err_free_pdata; + } + + return pdata; + +err_free_pdata: + kfree(pdata); +err_out: + return ERR_PTR(error); +} + +static struct of_device_id gpio_keys_polled_of_match[] = { + { .compatible = "gpio-keys-polled", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match); + +#else + +static inline struct gpio_keys_platform_data * +gpio_keys_polled_get_devtree_pdata(struct device *dev) +{ + return NULL; +} +#endif + static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) { - struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; + const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); struct gpio_keys_polled_dev *bdev; struct input_polled_dev *poll_dev; struct input_dev *input; int error; int i; - if (!pdata || !pdata->poll_interval) - return -EINVAL; + if (!pdata) { + pdata = gpio_keys_polled_get_devtree_pdata(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } + } + + if (!pdata->poll_interval) { + dev_err(dev, "missing poll_interval value\n"); + error = -EINVAL; + goto err_free_pdata; + } bdev = kzalloc(sizeof(struct gpio_keys_polled_dev) + pdata->nbuttons * sizeof(struct gpio_keys_button_data), GFP_KERNEL); if (!bdev) { dev_err(dev, "no memory for private data\n"); - return -ENOMEM; + error = -ENOMEM; + goto err_free_pdata; } poll_dev = input_allocate_polled_device(); @@ -197,7 +307,7 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) /* report initial state of the buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_polled_check_state(input, &pdata->buttons[i], - &bdev->data[i]); + &bdev->data[i]); return 0; @@ -209,15 +319,20 @@ err_free_gpio: err_free_bdev: kfree(bdev); - platform_set_drvdata(pdev, NULL); + +err_free_pdata: + /* If we have no platform_data, we allocated pdata dynamically. */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + return error; } static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) { struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); - struct gpio_keys_platform_data *pdata = bdev->pdata; + const struct gpio_keys_platform_data *pdata = bdev->pdata; int i; input_unregister_polled_device(bdev->poll_dev); @@ -227,6 +342,13 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) input_free_polled_device(bdev->poll_dev); + /* + * If we had no platform_data, we allocated pdata dynamically and + * must free it here. + */ + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + kfree(bdev); platform_set_drvdata(pdev, NULL); @@ -239,6 +361,7 @@ static struct platform_driver gpio_keys_polled_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpio_keys_polled_of_match), }, }; module_platform_driver(gpio_keys_polled_driver); diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index a880e741420..49f5fa64e0b 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -20,7 +20,7 @@ #include <linux/clk.h> #include <linux/module.h> -#include <plat/ske.h> +#include <linux/platform_data/keypad-nomadik-ske.h> /* SKE_CR bits */ #define SKE_KPMLT (0x1 << 6) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index a0222db4dc8..4a5fcc8026f 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -35,13 +35,9 @@ #include <linux/mutex.h> #include <linux/errno.h> #include <linux/slab.h> -#include <asm/gpio.h> -#include <plat/keypad.h> -#include <plat/menelaus.h> -#include <asm/irq.h> -#include <mach/hardware.h> -#include <asm/io.h> -#include <plat/mux.h> +#include <linux/gpio.h> +#include <linux/platform_data/gpio-omap.h> +#include <linux/platform_data/keypad-omap.h> #undef NEW_BOARD_LEARNING_MODE @@ -96,28 +92,8 @@ static u8 get_row_gpio_val(struct omap_kp *omap_kp) static irqreturn_t omap_kp_interrupt(int irq, void *dev_id) { - struct omap_kp *omap_kp = dev_id; - /* disable keyboard interrupt and schedule for handling */ - if (cpu_is_omap24xx()) { - int i; - - for (i = 0; i < omap_kp->rows; i++) { - int gpio_irq = gpio_to_irq(row_gpios[i]); - /* - * The interrupt which we're currently handling should - * be disabled _nosync() to avoid deadlocks waiting - * for this handler to complete. All others should - * be disabled the regular way for SMP safety. - */ - if (gpio_irq == irq) - disable_irq_nosync(gpio_irq); - else - disable_irq(gpio_irq); - } - } else - /* disable keyboard interrupt and schedule for handling */ - omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); tasklet_schedule(&kp_tasklet); @@ -133,33 +109,22 @@ static void omap_kp_scan_keypad(struct omap_kp *omap_kp, unsigned char *state) { int col = 0; - /* read the keypad status */ - if (cpu_is_omap24xx()) { - /* read the keypad status */ - for (col = 0; col < omap_kp->cols; col++) { - set_col_gpio_val(omap_kp, ~(1 << col)); - state[col] = ~(get_row_gpio_val(omap_kp)) & 0xff; - } - set_col_gpio_val(omap_kp, 0); - - } else { - /* disable keyboard interrupt and schedule for handling */ - omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + /* disable keyboard interrupt and schedule for handling */ + omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); - /* read the keypad status */ - omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); - for (col = 0; col < omap_kp->cols; col++) { - omap_writew(~(1 << col) & 0xff, - OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); + /* read the keypad status */ + omap_writew(0xff, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); + for (col = 0; col < omap_kp->cols; col++) { + omap_writew(~(1 << col) & 0xff, + OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); - udelay(omap_kp->delay); + udelay(omap_kp->delay); - state[col] = ~omap_readw(OMAP1_MPUIO_BASE + - OMAP_MPUIO_KBR_LATCH) & 0xff; - } - omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); - udelay(2); + state[col] = ~omap_readw(OMAP1_MPUIO_BASE + + OMAP_MPUIO_KBR_LATCH) & 0xff; } + omap_writew(0x00, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBC); + udelay(2); } static void omap_kp_tasklet(unsigned long data) @@ -214,7 +179,7 @@ static void omap_kp_tasklet(unsigned long data) memcpy(keypad_state, new_state, sizeof(keypad_state)); if (key_down) { - int delay = HZ / 20; + int delay = HZ / 20; /* some key is pressed - keep irq disabled and use timer * to poll the keypad */ if (spurious) @@ -222,14 +187,8 @@ static void omap_kp_tasklet(unsigned long data) mod_timer(&omap_kp_data->timer, jiffies + delay); } else { /* enable interrupts */ - if (cpu_is_omap24xx()) { - int i; - for (i = 0; i < omap_kp_data->rows; i++) - enable_irq(gpio_to_irq(row_gpios[i])); - } else { - omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); - kp_cur_group = -1; - } + omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + kp_cur_group = -1; } } @@ -242,6 +201,7 @@ static ssize_t omap_kp_enable_show(struct device *dev, static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + struct omap_kp *omap_kp = dev_get_drvdata(dev); int state; if (sscanf(buf, "%u", &state) != 1) @@ -253,9 +213,9 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute mutex_lock(&kp_enable_mutex); if (state != kp_enable) { if (state) - enable_irq(INT_KEYBOARD); + enable_irq(omap_kp->irq); else - disable_irq(INT_KEYBOARD); + disable_irq(omap_kp->irq); kp_enable = state; } mutex_unlock(&kp_enable_mutex); @@ -289,7 +249,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) struct omap_kp *omap_kp; struct input_dev *input_dev; struct omap_kp_platform_data *pdata = pdev->dev.platform_data; - int i, col_idx, row_idx, irq_idx, ret; + int i, col_idx, row_idx, ret; unsigned int row_shift, keycodemax; if (!pdata->rows || !pdata->cols || !pdata->keymap_data) { @@ -314,8 +274,7 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) omap_kp->input = input_dev; /* Disable the interrupt for the MPUIO keyboard */ - if (!cpu_is_omap24xx()) - omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); if (pdata->delay) omap_kp->delay = pdata->delay; @@ -328,31 +287,8 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) omap_kp->rows = pdata->rows; omap_kp->cols = pdata->cols; - if (cpu_is_omap24xx()) { - /* Cols: outputs */ - for (col_idx = 0; col_idx < omap_kp->cols; col_idx++) { - if (gpio_request(col_gpios[col_idx], "omap_kp_col") < 0) { - printk(KERN_ERR "Failed to request" - "GPIO%d for keypad\n", - col_gpios[col_idx]); - goto err1; - } - gpio_direction_output(col_gpios[col_idx], 0); - } - /* Rows: inputs */ - for (row_idx = 0; row_idx < omap_kp->rows; row_idx++) { - if (gpio_request(row_gpios[row_idx], "omap_kp_row") < 0) { - printk(KERN_ERR "Failed to request" - "GPIO%d for keypad\n", - row_gpios[row_idx]); - goto err2; - } - gpio_direction_input(row_gpios[row_idx]); - } - } else { - col_idx = 0; - row_idx = 0; - } + col_idx = 0; + row_idx = 0; setup_timer(&omap_kp->timer, omap_kp_timer, (unsigned long)omap_kp); @@ -394,37 +330,25 @@ static int __devinit omap_kp_probe(struct platform_device *pdev) /* scan current status and enable interrupt */ omap_kp_scan_keypad(omap_kp, keypad_state); - if (!cpu_is_omap24xx()) { - omap_kp->irq = platform_get_irq(pdev, 0); - if (omap_kp->irq >= 0) { - if (request_irq(omap_kp->irq, omap_kp_interrupt, 0, - "omap-keypad", omap_kp) < 0) - goto err4; - } - omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); - } else { - for (irq_idx = 0; irq_idx < omap_kp->rows; irq_idx++) { - if (request_irq(gpio_to_irq(row_gpios[irq_idx]), - omap_kp_interrupt, - IRQF_TRIGGER_FALLING, - "omap-keypad", omap_kp) < 0) - goto err5; - } + omap_kp->irq = platform_get_irq(pdev, 0); + if (omap_kp->irq >= 0) { + if (request_irq(omap_kp->irq, omap_kp_interrupt, 0, + "omap-keypad", omap_kp) < 0) + goto err4; } + omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + return 0; -err5: - for (i = irq_idx - 1; i >=0; i--) - free_irq(row_gpios[i], omap_kp); + err4: input_unregister_device(omap_kp->input); input_dev = NULL; err3: device_remove_file(&pdev->dev, &dev_attr_enable); err2: - for (i = row_idx - 1; i >=0; i--) + for (i = row_idx - 1; i >= 0; i--) gpio_free(row_gpios[i]); -err1: - for (i = col_idx - 1; i >=0; i--) + for (i = col_idx - 1; i >= 0; i--) gpio_free(col_gpios[i]); kfree(omap_kp); @@ -439,18 +363,8 @@ static int __devexit omap_kp_remove(struct platform_device *pdev) /* disable keypad interrupt handling */ tasklet_disable(&kp_tasklet); - if (cpu_is_omap24xx()) { - int i; - for (i = 0; i < omap_kp->cols; i++) - gpio_free(col_gpios[i]); - for (i = 0; i < omap_kp->rows; i++) { - gpio_free(row_gpios[i]); - free_irq(gpio_to_irq(row_gpios[i]), omap_kp); - } - } else { - omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); - free_irq(omap_kp->irq, omap_kp); - } + omap_writew(1, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); + free_irq(omap_kp->irq, omap_kp); del_timer_sync(&omap_kp->timer); tasklet_kill(&kp_tasklet); diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 7f7b72464a3..803ff6fe021 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -32,7 +32,7 @@ #include <asm/mach/map.h> #include <mach/hardware.h> -#include <plat/pxa27x_keypad.h> +#include <linux/platform_data/keypad-pxa27x.h> /* * Keypad Controller registers */ diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index d7f1134b789..41488f9add2 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -15,7 +15,7 @@ #include <linux/io.h> #include <linux/slab.h> -#include <mach/pxa930_rotary.h> +#include <linux/platform_data/keyboard-pxa930_rotary.h> #define SBCR (0x04) #define ERCR (0x0c) diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index e7a5e36e120..76b7d430d03 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -156,8 +156,7 @@ static irqreturn_t qt2160_irq(int irq, void *_qt2160) spin_lock_irqsave(&qt2160->lock, flags); - __cancel_delayed_work(&qt2160->dwork); - schedule_delayed_work(&qt2160->dwork, 0); + mod_delayed_work(system_wq, &qt2160->dwork, 0); spin_unlock_irqrestore(&qt2160->lock, flags); diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index a061ba603a2..9d7a111486f 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -256,7 +256,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( struct matrix_keymap_data *keymap_data; uint32_t *keymap, num_rows = 0, num_cols = 0; struct device_node *np = dev->of_node, *key_np; - unsigned int key_count = 0; + unsigned int key_count; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { @@ -280,9 +280,7 @@ static struct samsung_keypad_platdata *samsung_keypad_parse_dt( } pdata->keymap_data = keymap_data; - for_each_child_of_node(np, key_np) - key_count++; - + key_count = of_get_child_count(np); keymap_data->keymap_size = key_count; keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL); if (!keymap) { @@ -433,6 +431,12 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) goto err_unmap_base; } + error = clk_prepare(keypad->clk); + if (error) { + dev_err(&pdev->dev, "keypad clock prepare failed\n"); + goto err_put_clk; + } + keypad->input_dev = input_dev; keypad->pdev = pdev; keypad->row_shift = row_shift; @@ -463,7 +467,7 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) keypad->keycodes, input_dev); if (error) { dev_err(&pdev->dev, "failed to build keymap\n"); - goto err_put_clk; + goto err_unprepare_clk; } input_set_capability(input_dev, EV_MSC, MSC_SCAN); @@ -505,6 +509,8 @@ err_free_irq: pm_runtime_disable(&pdev->dev); device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); +err_unprepare_clk: + clk_unprepare(keypad->clk); err_put_clk: clk_put(keypad->clk); samsung_keypad_dt_gpio_free(keypad); @@ -533,6 +539,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev) */ free_irq(keypad->irq, keypad); + clk_unprepare(keypad->clk); clk_put(keypad->clk); samsung_keypad_dt_gpio_free(keypad); @@ -662,8 +669,6 @@ static const struct of_device_id samsung_keypad_dt_match[] = { {}, }; MODULE_DEVICE_TABLE(of, samsung_keypad_dt_match); -#else -#define samsung_keypad_dt_match NULL #endif static struct platform_device_id samsung_keypad_driver_ids[] = { @@ -684,7 +689,7 @@ static struct platform_driver samsung_keypad_driver = { .driver = { .name = "samsung-keypad", .owner = THIS_MODULE, - .of_match_table = samsung_keypad_dt_match, + .of_match_table = of_match_ptr(samsung_keypad_dt_match), .pm = &samsung_keypad_pm_ops, }, .id_table = samsung_keypad_driver_ids, diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 72ef01be336..c7ca97f44bf 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -24,7 +24,7 @@ #include <linux/pm_wakeup.h> #include <linux/slab.h> #include <linux/types.h> -#include <plat/keyboard.h> +#include <linux/platform_data/keyboard-spear.h> /* Keyboard Registers */ #define MODE_CTL_REG 0x00 diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 2c1c9ed1bd9..5faaf2553e3 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -29,8 +29,8 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/input/tegra_kbc.h> #include <mach/clk.h> -#include <mach/kbc.h> #define KBC_MAX_DEBOUNCE_CNT 0x3ffu diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 085ede4d972..e0f6cd1ad0f 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -21,7 +21,7 @@ #include <linux/io.h> #include <linux/slab.h> -#include <mach/w90p910_keypad.h> +#include <linux/platform_data/keypad-w90p910.h> /* Keypad Interface Control Registers */ #define KPI_CONF 0x00 diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 601f7372f9c..26f13131639 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -151,22 +151,7 @@ static struct acpi_driver atlas_acpi_driver = { .remove = atlas_acpi_button_remove, }, }; - -static int __init atlas_acpi_init(void) -{ - if (acpi_disabled) - return -ENODEV; - - return acpi_bus_register_driver(&atlas_acpi_driver); -} - -static void __exit atlas_acpi_exit(void) -{ - acpi_bus_unregister_driver(&atlas_acpi_driver); -} - -module_init(atlas_acpi_init); -module_exit(atlas_acpi_exit); +module_acpi_driver(atlas_acpi_driver); MODULE_AUTHOR("Jaya Kumar"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index f07f784198b..99a49e4968d 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -24,12 +24,14 @@ #include <linux/gpio.h> #include <linux/rotary_encoder.h> #include <linux/slab.h> +#include <linux/of_platform.h> +#include <linux/of_gpio.h> #define DRV_NAME "rotary-encoder" struct rotary_encoder { struct input_dev *input; - struct rotary_encoder_platform_data *pdata; + const struct rotary_encoder_platform_data *pdata; unsigned int axis; unsigned int pos; @@ -43,7 +45,7 @@ struct rotary_encoder { char last_stable; }; -static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) +static int rotary_encoder_get_state(const struct rotary_encoder_platform_data *pdata) { int a = !!gpio_get_value(pdata->gpio_a); int b = !!gpio_get_value(pdata->gpio_b); @@ -56,7 +58,7 @@ static int rotary_encoder_get_state(struct rotary_encoder_platform_data *pdata) static void rotary_encoder_report_event(struct rotary_encoder *encoder) { - struct rotary_encoder_platform_data *pdata = encoder->pdata; + const struct rotary_encoder_platform_data *pdata = encoder->pdata; if (pdata->relative_axis) { input_report_rel(encoder->input, @@ -140,36 +142,89 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_OF +static struct of_device_id rotary_encoder_of_match[] = { + { .compatible = "rotary-encoder", }, + { }, +}; +MODULE_DEVICE_TABLE(of, rotary_encoder_of_match); + +static struct rotary_encoder_platform_data * __devinit +rotary_encoder_parse_dt(struct device *dev) +{ + const struct of_device_id *of_id = + of_match_device(rotary_encoder_of_match, dev); + struct device_node *np = dev->of_node; + struct rotary_encoder_platform_data *pdata; + enum of_gpio_flags flags; + + if (!of_id || !np) + return NULL; + + pdata = kzalloc(sizeof(struct rotary_encoder_platform_data), + GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + of_property_read_u32(np, "rotary-encoder,steps", &pdata->steps); + of_property_read_u32(np, "linux,axis", &pdata->axis); + + pdata->gpio_a = of_get_gpio_flags(np, 0, &flags); + pdata->inverted_a = flags & OF_GPIO_ACTIVE_LOW; + + pdata->gpio_b = of_get_gpio_flags(np, 1, &flags); + pdata->inverted_b = flags & OF_GPIO_ACTIVE_LOW; + + pdata->relative_axis = !!of_get_property(np, + "rotary-encoder,relative-axis", NULL); + pdata->rollover = !!of_get_property(np, + "rotary-encoder,rollover", NULL); + pdata->half_period = !!of_get_property(np, + "rotary-encoder,half-period", NULL); + + return pdata; +} +#else +static inline struct rotary_encoder_platform_data * +rotary_encoder_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + static int __devinit rotary_encoder_probe(struct platform_device *pdev) { - struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev); struct rotary_encoder *encoder; struct input_dev *input; irq_handler_t handler; int err; if (!pdata) { - dev_err(&pdev->dev, "missing platform data\n"); - return -ENOENT; + pdata = rotary_encoder_parse_dt(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } } encoder = kzalloc(sizeof(struct rotary_encoder), GFP_KERNEL); input = input_allocate_device(); if (!encoder || !input) { - dev_err(&pdev->dev, "failed to allocate memory for device\n"); err = -ENOMEM; goto exit_free_mem; } encoder->input = input; encoder->pdata = pdata; - encoder->irq_a = gpio_to_irq(pdata->gpio_a); - encoder->irq_b = gpio_to_irq(pdata->gpio_b); - /* create and register the input driver */ input->name = pdev->name; input->id.bustype = BUS_HOST; - input->dev.parent = &pdev->dev; + input->dev.parent = dev; if (pdata->relative_axis) { input->evbit[0] = BIT_MASK(EV_REL); @@ -180,40 +235,21 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) pdata->axis, 0, pdata->steps, 0, 1); } - err = input_register_device(input); - if (err) { - dev_err(&pdev->dev, "failed to register input device\n"); - goto exit_free_mem; - } - /* request the GPIOs */ - err = gpio_request(pdata->gpio_a, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "unable to request GPIO %d\n", - pdata->gpio_a); - goto exit_unregister_input; - } - - err = gpio_direction_input(pdata->gpio_a); + err = gpio_request_one(pdata->gpio_a, GPIOF_IN, dev_name(dev)); if (err) { - dev_err(&pdev->dev, "unable to set GPIO %d for input\n", - pdata->gpio_a); - goto exit_unregister_input; + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_a); + goto exit_free_mem; } - err = gpio_request(pdata->gpio_b, DRV_NAME); + err = gpio_request_one(pdata->gpio_b, GPIOF_IN, dev_name(dev)); if (err) { - dev_err(&pdev->dev, "unable to request GPIO %d\n", - pdata->gpio_b); + dev_err(dev, "unable to request GPIO %d\n", pdata->gpio_b); goto exit_free_gpio_a; } - err = gpio_direction_input(pdata->gpio_b); - if (err) { - dev_err(&pdev->dev, "unable to set GPIO %d for input\n", - pdata->gpio_b); - goto exit_free_gpio_a; - } + encoder->irq_a = gpio_to_irq(pdata->gpio_a); + encoder->irq_b = gpio_to_irq(pdata->gpio_b); /* request the IRQs */ if (pdata->half_period) { @@ -227,8 +263,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { - dev_err(&pdev->dev, "unable to request IRQ %d\n", - encoder->irq_a); + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_a); goto exit_free_gpio_b; } @@ -236,43 +271,55 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { - dev_err(&pdev->dev, "unable to request IRQ %d\n", - encoder->irq_b); + dev_err(dev, "unable to request IRQ %d\n", encoder->irq_b); goto exit_free_irq_a; } + err = input_register_device(input); + if (err) { + dev_err(dev, "failed to register input device\n"); + goto exit_free_irq_b; + } + platform_set_drvdata(pdev, encoder); return 0; +exit_free_irq_b: + free_irq(encoder->irq_b, encoder); exit_free_irq_a: free_irq(encoder->irq_a, encoder); exit_free_gpio_b: gpio_free(pdata->gpio_b); exit_free_gpio_a: gpio_free(pdata->gpio_a); -exit_unregister_input: - input_unregister_device(input); - input = NULL; /* so we don't try to free it */ exit_free_mem: input_free_device(input); kfree(encoder); + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + return err; } static int __devexit rotary_encoder_remove(struct platform_device *pdev) { struct rotary_encoder *encoder = platform_get_drvdata(pdev); - struct rotary_encoder_platform_data *pdata = pdev->dev.platform_data; + const struct rotary_encoder_platform_data *pdata = encoder->pdata; free_irq(encoder->irq_a, encoder); free_irq(encoder->irq_b, encoder); gpio_free(pdata->gpio_a); gpio_free(pdata->gpio_b); + input_unregister_device(encoder->input); - platform_set_drvdata(pdev, NULL); kfree(encoder); + if (!dev_get_platdata(&pdev->dev)) + kfree(pdata); + + platform_set_drvdata(pdev, NULL); + return 0; } @@ -282,6 +329,7 @@ static struct platform_driver rotary_encoder_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rotary_encoder_of_match), } }; module_platform_driver(rotary_encoder_driver); diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index 38e4b507b94..b3dd96d6448 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -42,6 +42,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); if (!err) { + pm_wakeup_event(pwr->dev.parent, 0); input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); input_sync(pwr); } else { diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index fc0ed9b4342..2194a3c7236 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -26,6 +26,7 @@ #include <linux/module.h> #include <linux/jiffies.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <linux/workqueue.h> #include <linux/i2c/twl.h> #include <linux/mfd/twl4030-audio.h> @@ -194,13 +195,26 @@ static int twl4030_vibra_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, twl4030_vibra_suspend, twl4030_vibra_resume); +static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, + struct device_node *node) +{ + if (pdata && pdata->coexist) + return true; + + if (of_find_node_by_name(node, "codec")) + return true; + + return false; +} + static int __devinit twl4030_vibra_probe(struct platform_device *pdev) { struct twl4030_vibra_data *pdata = pdev->dev.platform_data; + struct device_node *twl4030_core_node = pdev->dev.parent->of_node; struct vibra_info *info; int ret; - if (!pdata) { + if (!pdata && !twl4030_core_node) { dev_dbg(&pdev->dev, "platform_data not available\n"); return -EINVAL; } @@ -210,7 +224,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev) return -ENOMEM; info->dev = &pdev->dev; - info->coexist = pdata->coexist; + info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node); INIT_WORK(&info->play_work, vibra_play_work); info->input_dev = input_allocate_device(); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 6b1797503e3..a0a4bbaef02 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -40,7 +40,8 @@ #include <linux/input/mt.h> #include "../input-compat.h" -static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) +static int uinput_dev_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { struct uinput_device *udev = input_get_drvdata(dev); @@ -56,10 +57,11 @@ static int uinput_dev_event(struct input_dev *dev, unsigned int type, unsigned i } /* Atomically allocate an ID for the given request. Returns 0 on success. */ -static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_request *request) +static bool uinput_request_alloc_id(struct uinput_device *udev, + struct uinput_request *request) { - int id; - int err = -1; + unsigned int id; + bool reserved = false; spin_lock(&udev->requests_lock); @@ -67,32 +69,35 @@ static int uinput_request_alloc_id(struct uinput_device *udev, struct uinput_req if (!udev->requests[id]) { request->id = id; udev->requests[id] = request; - err = 0; + reserved = true; break; } } spin_unlock(&udev->requests_lock); - return err; + return reserved; } -static struct uinput_request *uinput_request_find(struct uinput_device *udev, int id) +static struct uinput_request *uinput_request_find(struct uinput_device *udev, + unsigned int id) { /* Find an input request, by ID. Returns NULL if the ID isn't valid. */ - if (id >= UINPUT_NUM_REQUESTS || id < 0) + if (id >= UINPUT_NUM_REQUESTS) return NULL; return udev->requests[id]; } -static inline int uinput_request_reserve_slot(struct uinput_device *udev, struct uinput_request *request) +static int uinput_request_reserve_slot(struct uinput_device *udev, + struct uinput_request *request) { /* Allocate slot. If none are available right away, wait. */ return wait_event_interruptible(udev->requests_waitq, - !uinput_request_alloc_id(udev, request)); + uinput_request_alloc_id(udev, request)); } -static void uinput_request_done(struct uinput_device *udev, struct uinput_request *request) +static void uinput_request_done(struct uinput_device *udev, + struct uinput_request *request) { /* Mark slot as available */ udev->requests[request->id] = NULL; @@ -101,14 +106,11 @@ static void uinput_request_done(struct uinput_device *udev, struct uinput_reques complete(&request->done); } -static int uinput_request_submit(struct uinput_device *udev, struct uinput_request *request) +static int uinput_request_send(struct uinput_device *udev, + struct uinput_request *request) { int retval; - retval = uinput_request_reserve_slot(udev, request); - if (retval) - return retval; - retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -118,7 +120,12 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque goto out; } - /* Tell our userspace app about this new request by queueing an input event */ + init_completion(&request->done); + + /* + * Tell our userspace application about this new request + * by queueing an input event. + */ uinput_dev_event(udev->dev, EV_UINPUT, request->code, request->id); out: @@ -126,8 +133,27 @@ static int uinput_request_submit(struct uinput_device *udev, struct uinput_reque return retval; } +static int uinput_request_submit(struct uinput_device *udev, + struct uinput_request *request) +{ + int error; + + error = uinput_request_reserve_slot(udev, request); + if (error) + return error; + + error = uinput_request_send(udev, request); + if (error) { + uinput_request_done(udev, request); + return error; + } + + wait_for_completion(&request->done); + return request->retval; +} + /* - * Fail all ouitstanding requests so handlers don't wait for the userspace + * Fail all outstanding requests so handlers don't wait for the userspace * to finish processing them. */ static void uinput_flush_requests(struct uinput_device *udev) @@ -163,11 +189,12 @@ static int uinput_dev_playback(struct input_dev *dev, int effect_id, int value) return uinput_dev_event(dev, EV_FF, effect_id, value); } -static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) +static int uinput_dev_upload_effect(struct input_dev *dev, + struct ff_effect *effect, + struct ff_effect *old) { struct uinput_device *udev = input_get_drvdata(dev); struct uinput_request request; - int retval; /* * uinput driver does not currently support periodic effects with @@ -180,42 +207,25 @@ static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *eff effect->u.periodic.waveform == FF_CUSTOM) return -EINVAL; - request.id = -1; - init_completion(&request.done); request.code = UI_FF_UPLOAD; request.u.upload.effect = effect; request.u.upload.old = old; - retval = uinput_request_submit(udev, &request); - if (!retval) { - wait_for_completion(&request.done); - retval = request.retval; - } - - return retval; + return uinput_request_submit(udev, &request); } static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id) { struct uinput_device *udev = input_get_drvdata(dev); struct uinput_request request; - int retval; if (!test_bit(EV_FF, dev->evbit)) return -ENOSYS; - request.id = -1; - init_completion(&request.done); request.code = UI_FF_ERASE; request.u.effect_id = effect_id; - retval = uinput_request_submit(udev, &request); - if (!retval) { - wait_for_completion(&request.done); - retval = request.retval; - } - - return retval; + return uinput_request_submit(udev, &request); } static void uinput_destroy_device(struct uinput_device *udev) @@ -347,7 +357,8 @@ static int uinput_allocate_device(struct uinput_device *udev) return 0; } -static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count) +static int uinput_setup_device(struct uinput_device *udev, + const char __user *buffer, size_t count) { struct uinput_user_dev *user_dev; struct input_dev *dev; @@ -419,7 +430,8 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu return retval; } -static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char __user *buffer, size_t count) +static ssize_t uinput_inject_event(struct uinput_device *udev, + const char __user *buffer, size_t count) { struct input_event ev; @@ -434,11 +446,15 @@ static inline ssize_t uinput_inject_event(struct uinput_device *udev, const char return input_event_size(); } -static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) +static ssize_t uinput_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { struct uinput_device *udev = file->private_data; int retval; + if (count == 0) + return 0; + retval = mutex_lock_interruptible(&udev->mutex); if (retval) return retval; @@ -452,42 +468,74 @@ static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t return retval; } -static ssize_t uinput_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) +static bool uinput_fetch_next_event(struct uinput_device *udev, + struct input_event *event) { - struct uinput_device *udev = file->private_data; - int retval = 0; + bool have_event; - if (udev->state != UIST_CREATED) - return -ENODEV; + spin_lock_irq(&udev->dev->event_lock); - if (udev->head == udev->tail && (file->f_flags & O_NONBLOCK)) - return -EAGAIN; + have_event = udev->head != udev->tail; + if (have_event) { + *event = udev->buff[udev->tail]; + udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; + } - retval = wait_event_interruptible(udev->waitq, - udev->head != udev->tail || udev->state != UIST_CREATED); - if (retval) - return retval; + spin_unlock_irq(&udev->dev->event_lock); - retval = mutex_lock_interruptible(&udev->mutex); - if (retval) - return retval; + return have_event; +} - if (udev->state != UIST_CREATED) { - retval = -ENODEV; - goto out; - } +static ssize_t uinput_events_to_user(struct uinput_device *udev, + char __user *buffer, size_t count) +{ + struct input_event event; + size_t read = 0; - while (udev->head != udev->tail && retval + input_event_size() <= count) { - if (input_event_to_user(buffer + retval, &udev->buff[udev->tail])) { - retval = -EFAULT; - goto out; - } - udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE; - retval += input_event_size(); + while (read + input_event_size() <= count && + uinput_fetch_next_event(udev, &event)) { + + if (input_event_to_user(buffer + read, &event)) + return -EFAULT; + + read += input_event_size(); } - out: - mutex_unlock(&udev->mutex); + return read; +} + +static ssize_t uinput_read(struct file *file, char __user *buffer, + size_t count, loff_t *ppos) +{ + struct uinput_device *udev = file->private_data; + ssize_t retval; + + if (count != 0 && count < input_event_size()) + return -EINVAL; + + do { + retval = mutex_lock_interruptible(&udev->mutex); + if (retval) + return retval; + + if (udev->state != UIST_CREATED) + retval = -ENODEV; + else if (udev->head == udev->tail && + (file->f_flags & O_NONBLOCK)) + retval = -EAGAIN; + else + retval = uinput_events_to_user(udev, buffer, count); + + mutex_unlock(&udev->mutex); + + if (retval || count == 0) + break; + + if (!(file->f_flags & O_NONBLOCK)) + retval = wait_event_interruptible(udev->waitq, + udev->head != udev->tail || + udev->state != UIST_CREATED); + } while (retval == 0); return retval; } @@ -516,8 +564,8 @@ static int uinput_release(struct inode *inode, struct file *file) #ifdef CONFIG_COMPAT struct uinput_ff_upload_compat { - int request_id; - int retval; + __u32 request_id; + __s32 retval; struct ff_effect_compat effect; struct ff_effect_compat old; }; @@ -703,7 +751,8 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, break; req = uinput_request_find(udev, ff_up.request_id); - if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) { + if (!req || req->code != UI_FF_UPLOAD || + !req->u.upload.effect) { retval = -EINVAL; break; } @@ -786,7 +835,8 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } #ifdef CONFIG_COMPAT -static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long uinput_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) { return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg)); } @@ -831,4 +881,3 @@ MODULE_VERSION("0.3"); module_init(uinput_init); module_exit(uinput_exit); - diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 575f880727f..62be888e83d 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -334,11 +334,8 @@ static bool hgpk_is_byte_valid(struct psmouse *psmouse, unsigned char *packet) if (!valid) psmouse_dbg(psmouse, - "bad data, mode %d (%d) %02x %02x %02x %02x %02x %02x\n", - priv->mode, pktcnt, - psmouse->packet[0], psmouse->packet[1], - psmouse->packet[2], psmouse->packet[3], - psmouse->packet[4], psmouse->packet[5]); + "bad data, mode %d (%d) %*ph\n", + priv->mode, pktcnt, 6, psmouse->packet); return valid; } @@ -1030,7 +1027,7 @@ static enum hgpk_model_t hgpk_get_model(struct psmouse *psmouse) return -EIO; } - psmouse_dbg(psmouse, "ID: %02x %02x %02x\n", param[0], param[1], param[2]); + psmouse_dbg(psmouse, "ID: %*ph\n", 3, param); /* HGPK signature: 0x67, 0x00, 0x<model> */ if (param[0] != 0x67 || param[1] != 0x00) diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index a9e4bfdf31f..4fe055f2c53 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -20,7 +20,7 @@ #include <linux/slab.h> #include <mach/hardware.h> -#include <mach/pxa930_trkball.h> +#include <linux/platform_data/mouse-pxa930_trkball.h> /* Trackball Controller Register Definitions */ #define TBCR (0x000C) diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index 272deddc8db..21c60fea5d3 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c @@ -42,7 +42,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id) x = (short) iomd_readl(IOMD_MOUSEX); y = (short) iomd_readl(IOMD_MOUSEY); - b = (short) (__raw_readl(0xe0310000) ^ 0x70); + b = (short) (__raw_readl(IOMEM(0xe0310000)) ^ 0x70); dx = x - rpcmouse_lastx; dy = y - rpcmouse_lasty; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 37033ade79d..12d12ca3fee 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -53,14 +53,19 @@ #define ABS_POS_BITS 13 /* - * Any position values from the hardware above the following limits are - * treated as "wrapped around negative" values that have been truncated to - * the 13-bit reporting range of the hardware. These are just reasonable - * guesses and can be adjusted if hardware is found that operates outside - * of these parameters. + * These values should represent the absolute maximum value that will + * be reported for a positive position value. Some Synaptics firmware + * uses this value to indicate a finger near the edge of the touchpad + * whose precise position cannot be determined. + * + * At least one touchpad is known to report positions in excess of this + * value which are actually negative values truncated to the 13-bit + * reporting range. These values have never been observed to be lower + * than 8184 (i.e. -8), so we treat all values greater than 8176 as + * negative and any other value as positive. */ -#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2) -#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2) +#define X_MAX_POSITIVE 8176 +#define Y_MAX_POSITIVE 8176 /***************************************************************************** * Stuff we need even when we do not want native Synaptics support @@ -604,11 +609,21 @@ static int synaptics_parse_hw_state(const unsigned char buf[], hw->right = (buf[0] & 0x02) ? 1 : 0; } - /* Convert wrap-around values to negative */ + /* + * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE + * is used by some firmware to indicate a finger at the edge of + * the touchpad whose precise position cannot be determined, so + * convert these values to the maximum axis value. + */ if (hw->x > X_MAX_POSITIVE) hw->x -= 1 << ABS_POS_BITS; + else if (hw->x == X_MAX_POSITIVE) + hw->x = XMAX; + if (hw->y > Y_MAX_POSITIVE) hw->y -= 1 << ABS_POS_BITS; + else if (hw->y == Y_MAX_POSITIVE) + hw->y = YMAX; return 0; } diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index f14675702c0..063a174d3a8 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -376,12 +376,7 @@ static void synaptics_i2c_reschedule_work(struct synaptics_i2c *touch, spin_lock_irqsave(&touch->lock, flags); - /* - * If work is already scheduled then subsequent schedules will not - * change the scheduled time that's why we have to cancel it first. - */ - __cancel_delayed_work(&touch->dwork); - schedule_delayed_work(&touch->dwork, delay); + mod_delayed_work(system_wq, &touch->dwork, delay); spin_unlock_irqrestore(&touch->lock, flags); } diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 0110b5a3a16..8f02e3d0e71 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -24,10 +24,8 @@ #include <linux/random.h> #include <linux/major.h> #include <linux/device.h> +#include <linux/cdev.h> #include <linux/kernel.h> -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX -#include <linux/miscdevice.h> -#endif MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_DESCRIPTION("Mouse (ExplorerPS/2) device interfaces"); @@ -61,17 +59,18 @@ struct mousedev_hw_data { struct mousedev { int open; - int minor; struct input_handle handle; wait_queue_head_t wait; struct list_head client_list; spinlock_t client_lock; /* protects client_list */ struct mutex mutex; struct device dev; + struct cdev cdev; bool exist; + bool is_mixdev; struct list_head mixdev_node; - int mixdev_open; + bool opened_by_mixdev; struct mousedev_hw_data packet; unsigned int pkt_count; @@ -114,10 +113,6 @@ struct mousedev_client { static unsigned char mousedev_imps_seq[] = { 0xf3, 200, 0xf3, 100, 0xf3, 80 }; static unsigned char mousedev_imex_seq[] = { 0xf3, 200, 0xf3, 200, 0xf3, 80 }; -static struct input_handler mousedev_handler; - -static struct mousedev *mousedev_table[MOUSEDEV_MINORS]; -static DEFINE_MUTEX(mousedev_table_mutex); static struct mousedev *mousedev_mix; static LIST_HEAD(mousedev_mix_list); @@ -433,7 +428,7 @@ static int mousedev_open_device(struct mousedev *mousedev) if (retval) return retval; - if (mousedev->minor == MOUSEDEV_MIX) + if (mousedev->is_mixdev) mixdev_open_devices(); else if (!mousedev->exist) retval = -ENODEV; @@ -451,7 +446,7 @@ static void mousedev_close_device(struct mousedev *mousedev) { mutex_lock(&mousedev->mutex); - if (mousedev->minor == MOUSEDEV_MIX) + if (mousedev->is_mixdev) mixdev_close_devices(); else if (mousedev->exist && !--mousedev->open) input_close_device(&mousedev->handle); @@ -472,11 +467,11 @@ static void mixdev_open_devices(void) return; list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { - if (!mousedev->mixdev_open) { + if (!mousedev->opened_by_mixdev) { if (mousedev_open_device(mousedev)) continue; - mousedev->mixdev_open = 1; + mousedev->opened_by_mixdev = true; } } } @@ -494,8 +489,8 @@ static void mixdev_close_devices(void) return; list_for_each_entry(mousedev, &mousedev_mix_list, mixdev_node) { - if (mousedev->mixdev_open) { - mousedev->mixdev_open = 0; + if (mousedev->opened_by_mixdev) { + mousedev->opened_by_mixdev = false; mousedev_close_device(mousedev); } } @@ -528,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file) kfree(client); mousedev_close_device(mousedev); - put_device(&mousedev->dev); return 0; } @@ -538,36 +532,17 @@ static int mousedev_open(struct inode *inode, struct file *file) struct mousedev_client *client; struct mousedev *mousedev; int error; - int i; #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (imajor(inode) == MISC_MAJOR) - i = MOUSEDEV_MIX; + mousedev = mousedev_mix; else #endif - i = iminor(inode) - MOUSEDEV_MINOR_BASE; - - if (i >= MOUSEDEV_MINORS) - return -ENODEV; - - error = mutex_lock_interruptible(&mousedev_table_mutex); - if (error) { - return error; - } - mousedev = mousedev_table[i]; - if (mousedev) - get_device(&mousedev->dev); - mutex_unlock(&mousedev_table_mutex); - - if (!mousedev) { - return -ENODEV; - } + mousedev = container_of(inode->i_cdev, struct mousedev, cdev); client = kzalloc(sizeof(struct mousedev_client), GFP_KERNEL); - if (!client) { - error = -ENOMEM; - goto err_put_mousedev; - } + if (!client) + return -ENOMEM; spin_lock_init(&client->packet_lock); client->pos_x = xres / 2; @@ -580,13 +555,13 @@ static int mousedev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; + nonseekable_open(inode, file); + return 0; err_free_client: mousedev_detach_client(mousedev, client); kfree(client); - err_put_mousedev: - put_device(&mousedev->dev); return error; } @@ -786,29 +761,16 @@ static unsigned int mousedev_poll(struct file *file, poll_table *wait) } static const struct file_operations mousedev_fops = { - .owner = THIS_MODULE, - .read = mousedev_read, - .write = mousedev_write, - .poll = mousedev_poll, - .open = mousedev_open, - .release = mousedev_release, - .fasync = mousedev_fasync, - .llseek = noop_llseek, + .owner = THIS_MODULE, + .read = mousedev_read, + .write = mousedev_write, + .poll = mousedev_poll, + .open = mousedev_open, + .release = mousedev_release, + .fasync = mousedev_fasync, + .llseek = noop_llseek, }; -static int mousedev_install_chrdev(struct mousedev *mousedev) -{ - mousedev_table[mousedev->minor] = mousedev; - return 0; -} - -static void mousedev_remove_chrdev(struct mousedev *mousedev) -{ - mutex_lock(&mousedev_table_mutex); - mousedev_table[mousedev->minor] = NULL; - mutex_unlock(&mousedev_table_mutex); -} - /* * Mark device non-existent. This disables writes, ioctls and * prevents new users from opening the device. Already posted @@ -843,24 +805,50 @@ static void mousedev_cleanup(struct mousedev *mousedev) mousedev_mark_dead(mousedev); mousedev_hangup(mousedev); - mousedev_remove_chrdev(mousedev); + + cdev_del(&mousedev->cdev); /* mousedev is marked dead so no one else accesses mousedev->open */ if (mousedev->open) input_close_device(handle); } +static int mousedev_reserve_minor(bool mixdev) +{ + int minor; + + if (mixdev) { + minor = input_get_new_minor(MOUSEDEV_MIX, 1, false); + if (minor < 0) + pr_err("failed to reserve mixdev minor: %d\n", minor); + } else { + minor = input_get_new_minor(MOUSEDEV_MINOR_BASE, + MOUSEDEV_MINORS, true); + if (minor < 0) + pr_err("failed to reserve new minor: %d\n", minor); + } + + return minor; +} + static struct mousedev *mousedev_create(struct input_dev *dev, struct input_handler *handler, - int minor) + bool mixdev) { struct mousedev *mousedev; + int minor; int error; + minor = mousedev_reserve_minor(mixdev); + if (minor < 0) { + error = minor; + goto err_out; + } + mousedev = kzalloc(sizeof(struct mousedev), GFP_KERNEL); if (!mousedev) { error = -ENOMEM; - goto err_out; + goto err_free_minor; } INIT_LIST_HEAD(&mousedev->client_list); @@ -868,16 +856,21 @@ static struct mousedev *mousedev_create(struct input_dev *dev, spin_lock_init(&mousedev->client_lock); mutex_init(&mousedev->mutex); lockdep_set_subclass(&mousedev->mutex, - minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0); + mixdev ? SINGLE_DEPTH_NESTING : 0); init_waitqueue_head(&mousedev->wait); - if (minor == MOUSEDEV_MIX) + if (mixdev) { dev_set_name(&mousedev->dev, "mice"); - else - dev_set_name(&mousedev->dev, "mouse%d", minor); + } else { + int dev_no = minor; + /* Normalize device number if it falls into legacy range */ + if (dev_no < MOUSEDEV_MINOR_BASE + MOUSEDEV_MINORS) + dev_no -= MOUSEDEV_MINOR_BASE; + dev_set_name(&mousedev->dev, "mouse%d", dev_no); + } - mousedev->minor = minor; mousedev->exist = true; + mousedev->is_mixdev = mixdev; mousedev->handle.dev = input_get_device(dev); mousedev->handle.name = dev_name(&mousedev->dev); mousedev->handle.handler = handler; @@ -886,17 +879,19 @@ static struct mousedev *mousedev_create(struct input_dev *dev, mousedev->dev.class = &input_class; if (dev) mousedev->dev.parent = &dev->dev; - mousedev->dev.devt = MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor); + mousedev->dev.devt = MKDEV(INPUT_MAJOR, minor); mousedev->dev.release = mousedev_free; device_initialize(&mousedev->dev); - if (minor != MOUSEDEV_MIX) { + if (!mixdev) { error = input_register_handle(&mousedev->handle); if (error) goto err_free_mousedev; } - error = mousedev_install_chrdev(mousedev); + cdev_init(&mousedev->cdev, &mousedev_fops); + mousedev->cdev.kobj.parent = &mousedev->dev.kobj; + error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1); if (error) goto err_unregister_handle; @@ -909,10 +904,12 @@ static struct mousedev *mousedev_create(struct input_dev *dev, err_cleanup_mousedev: mousedev_cleanup(mousedev); err_unregister_handle: - if (minor != MOUSEDEV_MIX) + if (!mixdev) input_unregister_handle(&mousedev->handle); err_free_mousedev: put_device(&mousedev->dev); + err_free_minor: + input_free_minor(minor); err_out: return ERR_PTR(error); } @@ -921,7 +918,8 @@ static void mousedev_destroy(struct mousedev *mousedev) { device_del(&mousedev->dev); mousedev_cleanup(mousedev); - if (mousedev->minor != MOUSEDEV_MIX) + input_free_minor(MINOR(mousedev->dev.devt)); + if (!mousedev->is_mixdev) input_unregister_handle(&mousedev->handle); put_device(&mousedev->dev); } @@ -939,7 +937,7 @@ static int mixdev_add_device(struct mousedev *mousedev) if (retval) goto out; - mousedev->mixdev_open = 1; + mousedev->opened_by_mixdev = true; } get_device(&mousedev->dev); @@ -954,8 +952,8 @@ static void mixdev_remove_device(struct mousedev *mousedev) { mutex_lock(&mousedev_mix->mutex); - if (mousedev->mixdev_open) { - mousedev->mixdev_open = 0; + if (mousedev->opened_by_mixdev) { + mousedev->opened_by_mixdev = false; mousedev_close_device(mousedev); } @@ -970,19 +968,9 @@ static int mousedev_connect(struct input_handler *handler, const struct input_device_id *id) { struct mousedev *mousedev; - int minor; int error; - for (minor = 0; minor < MOUSEDEV_MINORS; minor++) - if (!mousedev_table[minor]) - break; - - if (minor == MOUSEDEV_MINORS) { - pr_err("no more free mousedev devices\n"); - return -ENFILE; - } - - mousedev = mousedev_create(dev, handler, minor); + mousedev = mousedev_create(dev, handler, false); if (IS_ERR(mousedev)) return PTR_ERR(mousedev); @@ -1055,27 +1043,53 @@ static const struct input_device_id mousedev_ids[] = { MODULE_DEVICE_TABLE(input, mousedev_ids); static struct input_handler mousedev_handler = { - .event = mousedev_event, - .connect = mousedev_connect, - .disconnect = mousedev_disconnect, - .fops = &mousedev_fops, - .minor = MOUSEDEV_MINOR_BASE, - .name = "mousedev", - .id_table = mousedev_ids, + .event = mousedev_event, + .connect = mousedev_connect, + .disconnect = mousedev_disconnect, + .legacy_minors = true, + .minor = MOUSEDEV_MINOR_BASE, + .name = "mousedev", + .id_table = mousedev_ids, }; #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX +#include <linux/miscdevice.h> + static struct miscdevice psaux_mouse = { - PSMOUSE_MINOR, "psaux", &mousedev_fops + .minor = PSMOUSE_MINOR, + .name = "psaux", + .fops = &mousedev_fops, }; -static int psaux_registered; + +static bool psaux_registered; + +static void __init mousedev_psaux_register(void) +{ + int error; + + error = misc_register(&psaux_mouse); + if (error) + pr_warn("could not register psaux device, error: %d\n", + error); + else + psaux_registered = true; +} + +static void __exit mousedev_psaux_unregister(void) +{ + if (psaux_registered) + misc_deregister(&psaux_mouse); +} +#else +static inline void mousedev_psaux_register(void) { } +static inline void mousedev_psaux_unregister(void) { } #endif static int __init mousedev_init(void) { int error; - mousedev_mix = mousedev_create(NULL, &mousedev_handler, MOUSEDEV_MIX); + mousedev_mix = mousedev_create(NULL, &mousedev_handler, true); if (IS_ERR(mousedev_mix)) return PTR_ERR(mousedev_mix); @@ -1085,14 +1099,7 @@ static int __init mousedev_init(void) return error; } -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - error = misc_register(&psaux_mouse); - if (error) - pr_warning("could not register psaux device, error: %d\n", - error); - else - psaux_registered = 1; -#endif + mousedev_psaux_register(); pr_info("PS/2 mouse device common for all mice\n"); @@ -1101,10 +1108,7 @@ static int __init mousedev_init(void) static void __exit mousedev_exit(void) { -#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX - if (psaux_registered) - misc_deregister(&psaux_mouse); -#endif + mousedev_psaux_unregister(); input_unregister_handler(&mousedev_handler); mousedev_destroy(mousedev_mix); } diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index f5fbdf94de3..45887e31242 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c @@ -27,7 +27,7 @@ #include <linux/module.h> #include <asm/mach-types.h> -#include <plat/board-ams-delta.h> +#include <mach/board-ams-delta.h> #include <mach/ams-delta-fiq.h> diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 75fb040a343..a70aa555bbf 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -180,11 +180,11 @@ int sparse_keymap_setup(struct input_dev *dev, for (e = keymap; e->type != KE_END; e++) map_size++; - map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL); + map = kcalloc(map_size, sizeof(struct key_entry), GFP_KERNEL); if (!map) return -ENOMEM; - memcpy(map, keymap, map_size * sizeof (struct key_entry)); + memcpy(map, keymap, map_size * sizeof(struct key_entry)); for (i = 0; i < map_size; i++) { entry = &map[i]; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 0d3219f2974..2c1e12bf2ab 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -172,6 +172,76 @@ static void wacom_close(struct input_dev *dev) } /* + * Calculate the resolution of the X or Y axis, given appropriate HID data. + * This function is little more than hidinput_calc_abs_res stripped down. + */ +static int wacom_calc_hid_res(int logical_extents, int physical_extents, + unsigned char unit, unsigned char exponent) +{ + int prev, unit_exponent; + + /* Check if the extents are sane */ + if (logical_extents <= 0 || physical_extents <= 0) + return 0; + + /* Get signed value of nybble-sized twos-compliment exponent */ + unit_exponent = exponent; + if (unit_exponent > 7) + unit_exponent -= 16; + + /* Convert physical_extents to millimeters */ + if (unit == 0x11) { /* If centimeters */ + unit_exponent += 1; + } else if (unit == 0x13) { /* If inches */ + prev = physical_extents; + physical_extents *= 254; + if (physical_extents < prev) + return 0; + unit_exponent -= 1; + } else { + return 0; + } + + /* Apply negative unit exponent */ + for (; unit_exponent < 0; unit_exponent++) { + prev = logical_extents; + logical_extents *= 10; + if (logical_extents < prev) + return 0; + } + /* Apply positive unit exponent */ + for (; unit_exponent > 0; unit_exponent--) { + prev = physical_extents; + physical_extents *= 10; + if (physical_extents < prev) + return 0; + } + + /* Calculate resolution */ + return logical_extents / physical_extents; +} + +/* + * The physical dimension specified by the HID descriptor is likely not in + * the "100th of a mm" units expected by wacom_calculate_touch_res. This + * function adjusts the value of [xy]_phy based on the unit and exponent + * provided by the HID descriptor. If an error occurs durring conversion + * (e.g. from the unit being left unspecified) [xy]_phy is not modified. + */ +static void wacom_fix_phy_from_hid(struct wacom_features *features) +{ + int xres = wacom_calc_hid_res(features->x_max, features->x_phy, + features->unit, features->unitExpo); + int yres = wacom_calc_hid_res(features->y_max, features->y_phy, + features->unit, features->unitExpo); + + if (xres > 0 && yres > 0) { + features->x_phy = (100 * features->x_max) / xres; + features->y_phy = (100 * features->y_max) / yres; + } +} + +/* * Static values for max X/Y and resolution of Pen interface is stored in * features. This mean physical size of active area can be computed. * This is useful to do when Pen and Touch have same active area of tablet. @@ -321,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf, features->pktlen = WACOM_PKGLEN_TPC2FG; } - if (features->type == MTSCREEN) + if (features->type == MTSCREEN || WACOM_24HDT) features->pktlen = WACOM_PKGLEN_MTOUCH; if (features->type == BAMBOO_PT) { @@ -332,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf, features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; + } else if (features->type == WACOM_24HDT) { + features->x_max = + get_unaligned_le16(&report[i + 3]); + features->x_phy = + get_unaligned_le16(&report[i + 8]); + features->unit = report[i - 1]; + features->unitExpo = report[i - 3]; + i += 12; } else { features->x_max = get_unaligned_le16(&report[i + 3]); @@ -364,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf, features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; + } else if (type == WACOM_24HDT) { + features->y_max = + get_unaligned_le16(&report[i + 3]); + features->y_phy = + get_unaligned_le16(&report[i - 2]); + i += 7; } else if (type == BAMBOO_PT) { features->y_phy = get_unaligned_le16(&report[i + 3]); @@ -432,56 +516,55 @@ static int wacom_parse_hid(struct usb_interface *intf, return result; } -static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) +static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int length, int mode) { unsigned char *rep_data; - int limit = 0, report_id = 2; - int error = -ENOMEM; + int error = -ENOMEM, limit = 0; - rep_data = kmalloc(4, GFP_KERNEL); + rep_data = kzalloc(length, GFP_KERNEL); if (!rep_data) return error; - /* ask to report Wacom data */ + rep_data[0] = report_id; + rep_data[1] = mode; + + do { + error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, + report_id, rep_data, length, 1); + if (error >= 0) + error = wacom_get_report(intf, WAC_HID_FEATURE_REPORT, + report_id, rep_data, length, 1); + } while ((error < 0 || rep_data[1] != mode) && limit++ < WAC_MSG_RETRIES); + + kfree(rep_data); + + return error < 0 ? error : 0; +} + +/* + * Switch the tablet into its most-capable mode. Wacom tablets are + * typically configured to power-up in a mode which sends mouse-like + * reports to the OS. To get absolute position, pressure data, etc. + * from the tablet, it is necessary to switch the tablet out of this + * mode and into one which sends the full range of tablet data. + */ +static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) +{ if (features->device_type == BTN_TOOL_FINGER) { - /* if it is an MT Tablet PC touch */ if (features->type > TABLETPC) { - do { - rep_data[0] = 3; - rep_data[1] = 4; - rep_data[2] = 0; - rep_data[3] = 0; - report_id = 3; - error = wacom_set_report(intf, - WAC_HID_FEATURE_REPORT, - report_id, - rep_data, 4, 1); - if (error >= 0) - error = wacom_get_report(intf, - WAC_HID_FEATURE_REPORT, - report_id, - rep_data, 4, 1); - } while ((error < 0 || rep_data[1] != 4) && - limit++ < WAC_MSG_RETRIES); + /* MT Tablet PC touch */ + return wacom_set_device_mode(intf, 3, 4, 4); + } + else if (features->type == WACOM_24HDT) { + return wacom_set_device_mode(intf, 18, 3, 2); + } + } else if (features->device_type == BTN_TOOL_PEN) { + if (features->type <= BAMBOO_PT && features->type != WIRELESS) { + return wacom_set_device_mode(intf, 2, 2, 2); } - } else if (features->type <= BAMBOO_PT && - features->type != WIRELESS && - features->device_type == BTN_TOOL_PEN) { - do { - rep_data[0] = 2; - rep_data[1] = 2; - error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, - report_id, rep_data, 2, 1); - if (error >= 0) - error = wacom_get_report(intf, - WAC_HID_FEATURE_REPORT, - report_id, rep_data, 2, 1); - } while ((error < 0 || rep_data[1] != 2) && limit++ < WAC_MSG_RETRIES); } - kfree(rep_data); - - return error < 0 ? error : 0; + return 0; } static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, @@ -531,6 +614,7 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, error = wacom_parse_hid(intf, hid_desc, features); if (error) goto out; + wacom_fix_phy_from_hid(features); out: return error; @@ -546,6 +630,30 @@ struct wacom_usbdev_data { static LIST_HEAD(wacom_udev_list); static DEFINE_MUTEX(wacom_udev_list_lock); +static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product) +{ + int port1; + struct usb_device *sibling; + + if (vendor == 0 && product == 0) + return dev; + + if (dev->parent == NULL) + return NULL; + + usb_hub_for_each_child(dev->parent, port1, sibling) { + struct usb_device_descriptor *d; + if (sibling == NULL) + continue; + + d = &sibling->descriptor; + if (d->idVendor == vendor && d->idProduct == product) + return sibling; + } + + return NULL; +} + static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev) { struct wacom_usbdev_data *data; @@ -1190,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); if (features->quirks & WACOM_QUIRK_MULTI_INPUT) { + struct usb_device *other_dev; + /* Append the device type to the name */ strlcat(wacom_wac->name, features->device_type == BTN_TOOL_PEN ? " Pen" : " Finger", sizeof(wacom_wac->name)); - error = wacom_add_shared_data(wacom_wac, dev); + + other_dev = wacom_get_sibling(dev, features->oVid, features->oPid); + if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL) + other_dev = dev; + error = wacom_add_shared_data(wacom_wac, other_dev); if (error) goto fail3; } diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 2a81ce375f7..aa601013117 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -25,6 +25,11 @@ #define WACOM_INTUOS_RES 100 #define WACOM_INTUOS3_RES 200 +/* Scale factor relating reported contact size to logical contact area. + * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo + */ +#define WACOM_CONTACT_AREA_SCALE 2607 + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -326,7 +331,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { - if (features->type >= INTUOS5S && features->type <= INTUOS5L) + if (features->quirks == WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = true; /* serial number of the tool */ @@ -414,7 +419,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Exit report */ if ((data[1] & 0xfe) == 0x80) { - if (features->type >= INTUOS5S && features->type <= INTUOS5L) + if (features->quirks == WACOM_QUIRK_MULTI_INPUT) wacom->shared->stylus_in_proximity = false; /* @@ -606,7 +611,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_WHEEL, 0); } - if (data[2] | (data[3] & 0x01) | data[4]) { + if (data[2] | (data[3] & 0x01) | data[4] | data[5]) { input_report_key(input, wacom->tool[1], 1); input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); } else { @@ -801,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) return -1; } +static int int_dist(int x1, int y1, int x2, int y2) +{ + int x = x2 - x1; + int y = y2 - y1; + + return int_sqrt(x*x + y*y); +} + +static int wacom_24hdt_irq(struct wacom_wac *wacom) +{ + struct input_dev *input = wacom->input; + char *data = wacom->data; + int i; + int current_num_contacts = data[61]; + int contacts_to_send = 0; + + /* + * First packet resets the counter since only the first + * packet in series will have non-zero current_num_contacts. + */ + if (current_num_contacts) + wacom->num_contacts_left = current_num_contacts; + + /* There are at most 4 contacts per packet */ + contacts_to_send = min(4, wacom->num_contacts_left); + + for (i = 0; i < contacts_to_send; i++) { + int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; + bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; + int id = data[offset + 1]; + int slot = find_slot_from_contactid(wacom, id); + + if (slot < 0) + continue; + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); + + if (touch) { + int t_x = le16_to_cpup((__le16 *)&data[offset + 2]); + int c_x = le16_to_cpup((__le16 *)&data[offset + 4]); + int t_y = le16_to_cpup((__le16 *)&data[offset + 6]); + int c_y = le16_to_cpup((__le16 *)&data[offset + 8]); + int w = le16_to_cpup((__le16 *)&data[offset + 10]); + int h = le16_to_cpup((__le16 *)&data[offset + 12]); + + input_report_abs(input, ABS_MT_POSITION_X, t_x); + input_report_abs(input, ABS_MT_POSITION_Y, t_y); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h)); + input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y)); + input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); + input_report_abs(input, ABS_MT_ORIENTATION, w > h); + } + wacom->slots[slot] = touch ? id : -1; + } + + input_mt_report_pointer_emulation(input, true); + + wacom->num_contacts_left -= contacts_to_send; + if (wacom->num_contacts_left <= 0) + wacom->num_contacts_left = 0; + + return 1; +} + static int wacom_mt_touch(struct wacom_wac *wacom) { struct input_dev *input = wacom->input; @@ -1043,11 +1112,19 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) if (touch) { int x = (data[2] << 4) | (data[4] >> 4); int y = (data[3] << 4) | (data[4] & 0x0f); - int w = data[6]; + int a = data[5]; + + // "a" is a scaled-down area which we assume is roughly + // circular and which can be described as: a=(pi*r^2)/C. + int x_res = input_abs_get_res(input, ABS_X); + int y_res = input_abs_get_res(input, ABS_Y); + int width = 2 * int_sqrt(a * WACOM_CONTACT_AREA_SCALE); + int height = width * y_res / x_res; input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); - input_report_abs(input, ABS_MT_TOUCH_MAJOR, w); + input_report_abs(input, ABS_MT_TOUCH_MAJOR, width); + input_report_abs(input, ABS_MT_TOUCH_MINOR, height); } } @@ -1242,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) sync = wacom_intuos_irq(wacom_wac); break; + case WACOM_24HDT: + sync = wacom_24hdt_irq(wacom_wac); + break; + case INTUOS5S: case INTUOS5: case INTUOS5L: @@ -1327,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features) /* these device have multiple inputs */ if (features->type >= WIRELESS || - (features->type >= INTUOS5S && features->type <= INTUOS5L)) + (features->type >= INTUOS5S && features->type <= INTUOS5L) || + (features->oVid && features->oPid)) features->quirks |= WACOM_QUIRK_MULTI_INPUT; /* quirk for bamboo touch with 2 low res touches */ @@ -1533,7 +1615,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, input_mt_init_slots(input_dev, features->touch_max, 0); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - 0, 255, 0, 0); + 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, + 0, features->y_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, features->x_max, @@ -1560,6 +1644,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); break; + case WACOM_24HDT: + if (features->device_type == BTN_TOOL_FINGER) { + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + } + /* fall through */ + case MTSCREEN: if (features->device_type == BTN_TOOL_FINGER) { wacom_wac->slots = kmalloc(features->touch_max * @@ -1641,7 +1734,10 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, - 0, 255, 0, 0); + 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MINOR, + 0, features->y_max, 0, 0); } input_set_abs_params(input_dev, ABS_MT_POSITION_X, @@ -1851,8 +1947,11 @@ static const struct wacom_features wacom_features_0xF4 = { "Wacom Cintiq 24HD", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, - 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; + { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS, 104480, 65600, 2047, /* Pen */ + 63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; +static const struct wacom_features wacom_features_0xF6 = + { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 }; static const struct wacom_features wacom_features_0x3F = { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2095,6 +2194,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, + { USB_DEVICE_WACOM(0xF6) }, { USB_DEVICE_WACOM(0xFA) }, { USB_DEVICE_LENOVO(0x6004) }, { } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 96c185cc301..345f1e76975 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -29,6 +29,7 @@ /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 +#define WACOM_BYTES_PER_24HDT_PACKET 14 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -49,6 +50,7 @@ #define WACOM_REPORT_TPCHID 15 #define WACOM_REPORT_TPCST 16 #define WACOM_REPORT_TPC1FGE 18 +#define WACOM_REPORT_24HDT 1 /* device quirks */ #define WACOM_QUIRK_MULTI_INPUT 0x0001 @@ -81,6 +83,7 @@ enum { WACOM_MO, WIRELESS, BAMBOO_PT, + WACOM_24HDT, TABLETPC, /* add new TPC below */ TABLETPCE, TABLETPC2FG, @@ -109,6 +112,8 @@ struct wacom_features { int distance_fuzz; unsigned quirks; unsigned touch_max; + int oVid; + int oPid; }; struct wacom_shared { diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 05f30b73c3c..326218dbd6e 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -10,6 +10,7 @@ */ #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/input.h> @@ -113,14 +114,69 @@ static void pm860x_touch_close(struct input_dev *dev) pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); } +#ifdef CONFIG_OF +static int __devinit pm860x_touch_dt_init(struct platform_device *pdev, + struct pm860x_chip *chip, + int *res_x) +{ + struct device_node *np = pdev->dev.parent->of_node; + struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ + : chip->companion; + int data, n, ret; + if (!np) + return -ENODEV; + np = of_find_node_by_name(np, "touch"); + if (!np) { + dev_err(&pdev->dev, "Can't find touch node\n"); + return -EINVAL; + } + /* set GPADC MISC1 register */ + data = 0; + if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-prebias", &n)) + data |= (n << 1) & PM8607_GPADC_PREBIAS_MASK; + if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-slot-cycle", &n)) + data |= (n << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; + if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-off-scale", &n)) + data |= (n << 5) & PM8607_GPADC_OFF_SCALE_MASK; + if (!of_property_read_u32(np, "marvell,88pm860x-gpadc-sw-cal", &n)) + data |= (n << 7) & PM8607_GPADC_SW_CAL_MASK; + if (data) { + ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); + if (ret < 0) + return -EINVAL; + } + /* set tsi prebias time */ + if (!of_property_read_u32(np, "marvell,88pm860x-tsi-prebias", &data)) { + ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); + if (ret < 0) + return -EINVAL; + } + /* set prebias & prechg time of pen detect */ + data = 0; + if (!of_property_read_u32(np, "marvell,88pm860x-pen-prebias", &n)) + data |= n & PM8607_PD_PREBIAS_MASK; + if (!of_property_read_u32(np, "marvell,88pm860x-pen-prechg", &n)) + data |= n & PM8607_PD_PRECHG_MASK; + if (data) { + ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); + if (ret < 0) + return -EINVAL; + } + of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x); + return 0; +} +#else +#define pm860x_touch_dt_init(x, y, z) (-1) +#endif + 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_pdata *pdata = pdev->dev.platform_data; struct pm860x_touch *touch; - int irq, ret; + struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ + : chip->companion; + int irq, ret, res_x = 0, data = 0; irq = platform_get_irq(pdev, 0); if (irq < 0) { @@ -128,16 +184,55 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev) 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; + if (pm860x_touch_dt_init(pdev, chip, &res_x)) { + if (pdata) { + /* set GPADC MISC1 register */ + data = 0; + data |= (pdata->gpadc_prebias << 1) + & PM8607_GPADC_PREBIAS_MASK; + data |= (pdata->slot_cycle << 3) + & PM8607_GPADC_SLOT_CYCLE_MASK; + data |= (pdata->off_scale << 5) + & PM8607_GPADC_OFF_SCALE_MASK; + data |= (pdata->sw_cal << 7) + & PM8607_GPADC_SW_CAL_MASK; + if (data) { + ret = pm860x_reg_write(i2c, + PM8607_GPADC_MISC1, data); + if (ret < 0) + return -EINVAL; + } + /* set tsi prebias time */ + if (pdata->tsi_prebias) { + data = pdata->tsi_prebias; + ret = pm860x_reg_write(i2c, + PM8607_TSI_PREBIAS, data); + if (ret < 0) + return -EINVAL; + } + /* set prebias & prechg time of pen detect */ + data = 0; + data |= pdata->pen_prebias + & PM8607_PD_PREBIAS_MASK; + data |= (pdata->pen_prechg << 5) + & PM8607_PD_PRECHG_MASK; + if (data) { + ret = pm860x_reg_write(i2c, + PM8607_PD_PREBIAS, data); + if (ret < 0) + return -EINVAL; + } + res_x = pdata->res_x; + } else { + dev_err(&pdev->dev, "failed to get platform data\n"); + return -EINVAL; + } } + /* enable GPADC */ + ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, PM8607_GPADC_EN, + PM8607_GPADC_EN); + if (ret) + return ret; touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); if (touch == NULL) @@ -158,9 +253,9 @@ static int __devinit pm860x_touch_probe(struct platform_device *pdev) 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; + touch->i2c = i2c; + touch->irq = irq; + touch->res_x = res_x; input_set_drvdata(touch->idev, touch); ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index e92615d0b1b..1df2396af00 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -320,10 +320,8 @@ static bool mxt_object_writable(unsigned int type) static void mxt_dump_message(struct device *dev, struct mxt_message *message) { - dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n", - message->reportid, message->message[0], message->message[1], - message->message[2], message->message[3], message->message[4], - message->message[5], message->message[6]); + dev_dbg(dev, "reportid: %u\tmessage: %*ph\n", + message->reportid, 7, message->message); } static int mxt_check_bootloader(struct i2c_client *client, diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index bf1a0640006..549fa29548f 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -37,7 +37,7 @@ #include <plat/adc.h> #include <plat/regs-adc.h> -#include <plat/ts.h> +#include <linux/platform_data/touchscreen-s3c2410.h> #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) @@ -406,7 +406,7 @@ static int s3c2410ts_resume(struct device *dev) return 0; } -static struct dev_pm_ops s3c_ts_pmops = { +static const struct dev_pm_ops s3c_ts_pmops = { .suspend = s3c2410ts_suspend, .resume = s3c2410ts_resume, }; diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index e83410721e3..52abb98a8ae 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -221,7 +221,7 @@ static void wm831x_ts_input_close(struct input_dev *idev) synchronize_irq(wm831x_ts->pd_irq); /* Make sure the IRQ completion work is quiesced */ - flush_work_sync(&wm831x_ts->pd_data_work); + flush_work(&wm831x_ts->pd_data_work); /* If we ended up with the pen down then make sure we revert back * to pen detection state for the next time we start up. |