diff options
Diffstat (limited to 'drivers/input')
345 files changed, 6847 insertions, 9458 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 3bdbd34314b3..88ecdf5218ee 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -152,20 +152,6 @@ config INPUT_EVDEV To compile this driver as a module, choose M here: the module will be called evdev. -config INPUT_EVBUG - tristate "Event debugging" - help - Say Y here if you have a problem with the input subsystem and - want all events (keypresses, mouse movements), to be output to - the system log. While this is useful for debugging, it's also - a security threat - your keypresses include your passwords, of - course. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called evbug. - config INPUT_KUNIT_TEST tristate "KUnit tests for Input" if !KUNIT_ALL_TESTS depends on INPUT && KUNIT diff --git a/drivers/input/Makefile b/drivers/input/Makefile index c78753274921..930b64d2115e 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -18,7 +18,6 @@ obj-$(CONFIG_INPUT_LEDS) += input-leds.o obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o obj-$(CONFIG_INPUT_JOYDEV) += joydev.o obj-$(CONFIG_INPUT_EVDEV) += evdev.o -obj-$(CONFIG_INPUT_EVBUG) += evbug.o obj-$(CONFIG_INPUT_KEYBOARD) += keyboard/ obj-$(CONFIG_INPUT_MOUSE) += mouse/ diff --git a/drivers/input/evbug.c b/drivers/input/evbug.c deleted file mode 100644 index e47bdf92088a..000000000000 --- a/drivers/input/evbug.c +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (c) 1999-2001 Vojtech Pavlik - */ - -/* - * Input driver event debug module - dumps all events into syslog - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/input.h> -#include <linux/init.h> -#include <linux/device.h> - -MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); -MODULE_DESCRIPTION("Input driver event debug module"); -MODULE_LICENSE("GPL"); - -static void evbug_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) -{ - printk(KERN_DEBUG pr_fmt("Event. Dev: %s, Type: %d, Code: %d, Value: %d\n"), - dev_name(&handle->dev->dev), type, code, value); -} - -static int evbug_connect(struct input_handler *handler, struct input_dev *dev, - const struct input_device_id *id) -{ - struct input_handle *handle; - int error; - - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; - - handle->dev = dev; - handle->handler = handler; - handle->name = "evbug"; - - error = input_register_handle(handle); - if (error) - goto err_free_handle; - - error = input_open_device(handle); - if (error) - goto err_unregister_handle; - - printk(KERN_DEBUG pr_fmt("Connected device: %s (%s at %s)\n"), - dev_name(&dev->dev), - dev->name ?: "unknown", - dev->phys ?: "unknown"); - - return 0; - - err_unregister_handle: - input_unregister_handle(handle); - err_free_handle: - kfree(handle); - return error; -} - -static void evbug_disconnect(struct input_handle *handle) -{ - printk(KERN_DEBUG pr_fmt("Disconnected device: %s\n"), - dev_name(&handle->dev->dev)); - - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); -} - -static const struct input_device_id evbug_ids[] = { - { .driver_info = 1 }, /* Matches all devices */ - { }, /* Terminating zero entry */ -}; - -MODULE_DEVICE_TABLE(input, evbug_ids); - -static struct input_handler evbug_handler = { - .event = evbug_event, - .connect = evbug_connect, - .disconnect = evbug_disconnect, - .name = "evbug", - .id_table = evbug_ids, -}; - -static int __init evbug_init(void) -{ - return input_register_handler(&evbug_handler); -} - -static void __exit evbug_exit(void) -{ - input_unregister_handler(&evbug_handler); -} - -module_init(evbug_init); -module_exit(evbug_exit); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 51e0c4954600..b5cbb57ee5f6 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -288,8 +288,8 @@ static void evdev_pass_values(struct evdev_client *client, /* * Pass incoming events to all connected clients. */ -static void evdev_events(struct input_handle *handle, - const struct input_value *vals, unsigned int count) +static unsigned int evdev_events(struct input_handle *handle, + struct input_value *vals, unsigned int count) { struct evdev *evdev = handle->private; struct evdev_client *client; @@ -306,17 +306,8 @@ static void evdev_events(struct input_handle *handle, evdev_pass_values(client, vals, count, ev_time); rcu_read_unlock(); -} - -/* - * Pass incoming event to all connected clients. - */ -static void evdev_event(struct input_handle *handle, - unsigned int type, unsigned int code, int value) -{ - struct input_value vals[] = { { type, code, value } }; - evdev_events(handle, vals, 1); + return count; } static int evdev_fasync(int fd, struct file *file, int on) @@ -507,6 +498,13 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer, struct input_event event; int retval = 0; + /* + * Limit amount of data we inject into the input subsystem so that + * we do not hold evdev->mutex for too long. 4096 bytes corresponds + * to 170 input events. + */ + count = min(count, 4096); + if (count != 0 && count < input_event_size()) return -EINVAL; @@ -1301,7 +1299,6 @@ static const struct file_operations evdev_fops = { .compat_ioctl = evdev_ioctl_compat, #endif .fasync = evdev_fasync, - .llseek = no_llseek, }; /* @@ -1418,7 +1415,6 @@ static const struct input_device_id evdev_ids[] = { MODULE_DEVICE_TABLE(input, evdev_ids); static struct input_handler evdev_handler = { - .event = evdev_event, .events = evdev_events, .connect = evdev_connect, .disconnect = evdev_disconnect, diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 16231fe080b0..b527308cb52e 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -9,8 +9,10 @@ /* #define DEBUG */ #include <linux/input.h> +#include <linux/limits.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/overflow.h> #include <linux/sched.h> #include <linux/slab.h> @@ -91,7 +93,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, { struct ff_device *ff = dev->ff; struct ff_effect *old; - int ret = 0; + int error; int id; if (!test_bit(EV_FF, dev->evbit)) @@ -112,22 +114,20 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, } if (!test_bit(effect->type, ff->ffbit)) { - ret = compat_effect(ff, effect); - if (ret) - return ret; + error = compat_effect(ff, effect); + if (error) + return error; } - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); if (effect->id == -1) { for (id = 0; id < ff->max_effects; id++) if (!ff->effect_owners[id]) break; - if (id >= ff->max_effects) { - ret = -ENOSPC; - goto out; - } + if (id >= ff->max_effects) + return -ENOSPC; effect->id = id; old = NULL; @@ -135,30 +135,26 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, } else { id = effect->id; - ret = check_effect_access(ff, id, file); - if (ret) - goto out; + error = check_effect_access(ff, id, file); + if (error) + return error; old = &ff->effects[id]; - if (!check_effects_compatible(effect, old)) { - ret = -EINVAL; - goto out; - } + if (!check_effects_compatible(effect, old)) + return -EINVAL; } - ret = ff->upload(dev, effect, old); - if (ret) - goto out; + error = ff->upload(dev, effect, old); + if (error) + return error; - spin_lock_irq(&dev->event_lock); - ff->effects[id] = *effect; - ff->effect_owners[id] = file; - spin_unlock_irq(&dev->event_lock); + scoped_guard(spinlock_irq, &dev->event_lock) { + ff->effects[id] = *effect; + ff->effect_owners[id] = file; + } - out: - mutex_unlock(&ff->mutex); - return ret; + return 0; } EXPORT_SYMBOL_GPL(input_ff_upload); @@ -176,17 +172,16 @@ static int erase_effect(struct input_dev *dev, int effect_id, if (error) return error; - spin_lock_irq(&dev->event_lock); - ff->playback(dev, effect_id, 0); - ff->effect_owners[effect_id] = NULL; - spin_unlock_irq(&dev->event_lock); + scoped_guard(spinlock_irq, &dev->event_lock) { + ff->playback(dev, effect_id, 0); + ff->effect_owners[effect_id] = NULL; + } if (ff->erase) { error = ff->erase(dev, effect_id); if (error) { - spin_lock_irq(&dev->event_lock); - ff->effect_owners[effect_id] = file; - spin_unlock_irq(&dev->event_lock); + scoped_guard(spinlock_irq, &dev->event_lock) + ff->effect_owners[effect_id] = file; return error; } @@ -208,16 +203,12 @@ static int erase_effect(struct input_dev *dev, int effect_id, int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) { struct ff_device *ff = dev->ff; - int ret; if (!test_bit(EV_FF, dev->evbit)) return -ENOSYS; - mutex_lock(&ff->mutex); - ret = erase_effect(dev, effect_id, file); - mutex_unlock(&ff->mutex); - - return ret; + guard(mutex)(&ff->mutex); + return erase_effect(dev, effect_id, file); } EXPORT_SYMBOL_GPL(input_ff_erase); @@ -237,13 +228,11 @@ int input_ff_flush(struct input_dev *dev, struct file *file) dev_dbg(&dev->dev, "flushing now\n"); - mutex_lock(&ff->mutex); + guard(mutex)(&ff->mutex); for (i = 0; i < ff->max_effects; i++) erase_effect(dev, i, file); - mutex_unlock(&ff->mutex); - return 0; } EXPORT_SYMBOL_GPL(input_ff_flush); @@ -301,8 +290,6 @@ EXPORT_SYMBOL_GPL(input_ff_event); */ int input_ff_create(struct input_dev *dev, unsigned int max_effects) { - struct ff_device *ff; - size_t ff_dev_size; int i; if (!max_effects) { @@ -315,26 +302,19 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) return -EINVAL; } - ff_dev_size = sizeof(struct ff_device) + - max_effects * sizeof(struct file *); - if (ff_dev_size < max_effects) /* overflow */ - return -EINVAL; - - ff = kzalloc(ff_dev_size, GFP_KERNEL); + struct ff_device *ff __free(kfree) = + kzalloc(struct_size(ff, effect_owners, max_effects), + GFP_KERNEL); if (!ff) return -ENOMEM; - ff->effects = kcalloc(max_effects, sizeof(struct ff_effect), - GFP_KERNEL); - if (!ff->effects) { - kfree(ff); + ff->effects = kcalloc(max_effects, sizeof(*ff->effects), GFP_KERNEL); + if (!ff->effects) return -ENOMEM; - } ff->max_effects = max_effects; mutex_init(&ff->mutex); - dev->ff = ff; dev->flush = input_ff_flush; dev->event = input_ff_event; __set_bit(EV_FF, dev->evbit); @@ -347,6 +327,8 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects) if (test_bit(FF_PERIODIC, ff->ffbit)) __set_bit(FF_RUMBLE, dev->ffbit); + dev->ff = no_free_ptr(ff); + return 0; } EXPORT_SYMBOL_GPL(input_ff_create); diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index c321cdabd214..009822fa61b8 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -136,7 +136,7 @@ static void ml_schedule_timer(struct ml_device *ml) if (!events) { pr_debug("no actions\n"); - del_timer(&ml->timer); + timer_delete(&ml->timer); } else { pr_debug("timer set\n"); mod_timer(&ml->timer, earliest); @@ -401,13 +401,11 @@ static void ml_effect_timer(struct timer_list *t) { struct ml_device *ml = from_timer(ml, t, timer); struct input_dev *dev = ml->dev; - unsigned long flags; pr_debug("timer: updating effects\n"); - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); ml_play_effects(ml); - spin_unlock_irqrestore(&dev->event_lock, flags); } /* @@ -465,7 +463,7 @@ static int ml_ff_upload(struct input_dev *dev, struct ml_device *ml = dev->ff->private; struct ml_effect_state *state = &ml->states[effect->id]; - spin_lock_irq(&dev->event_lock); + guard(spinlock_irq)(&dev->event_lock); if (test_bit(FF_EFFECT_STARTED, &state->flags)) { __clear_bit(FF_EFFECT_PLAYING, &state->flags); @@ -477,8 +475,6 @@ static int ml_ff_upload(struct input_dev *dev, ml_schedule_timer(ml); } - spin_unlock_irq(&dev->event_lock); - return 0; } @@ -493,7 +489,7 @@ static void ml_ff_destroy(struct ff_device *ff) * do not actually stop the timer, and therefore we should * do it here. */ - del_timer_sync(&ml->timer); + timer_delete_sync(&ml->timer); kfree(ml->private); } @@ -507,12 +503,11 @@ static void ml_ff_destroy(struct ff_device *ff) int input_ff_create_memless(struct input_dev *dev, void *data, int (*play_effect)(struct input_dev *, void *, struct ff_effect *)) { - struct ml_device *ml; struct ff_device *ff; int error; int i; - ml = kzalloc(sizeof(struct ml_device), GFP_KERNEL); + struct ml_device *ml __free(kfree) = kzalloc(sizeof(*ml), GFP_KERNEL); if (!ml) return -ENOMEM; @@ -525,13 +520,10 @@ int input_ff_create_memless(struct input_dev *dev, void *data, set_bit(FF_GAIN, dev->ffbit); error = input_ff_create(dev, FF_MEMLESS_EFFECTS); - if (error) { - kfree(ml); + if (error) return error; - } ff = dev->ff; - ff->private = ml; ff->upload = ml_ff_upload; ff->playback = ml_ff_playback; ff->set_gain = ml_ff_set_gain; @@ -548,6 +540,8 @@ int input_ff_create_memless(struct input_dev *dev, void *data, for (i = 0; i < FF_MEMLESS_EFFECTS; i++) ml->states[i].effect = &ff->effects[i]; + ff->private = no_free_ptr(ml); + return 0; } EXPORT_SYMBOL_GPL(input_ff_create_memless); diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index 76ce41e58df0..4f4583048f24 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -43,7 +43,7 @@ static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct gameport *port; int error; - emu = kzalloc(sizeof(struct emu), GFP_KERNEL); + emu = kzalloc(sizeof(*emu), GFP_KERNEL); port = gameport_allocate_port(); if (!emu || !port) { printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index e785d36b1926..7ae5009385cc 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -68,7 +68,7 @@ static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id) struct gameport *port; int error; - gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL); + gp = kzalloc(sizeof(*gp), GFP_KERNEL); port = gameport_allocate_port(); if (!gp || !port) { printk(KERN_ERR "fm801-gp: Memory allocation failed\n"); diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index cfcc81c47b50..ae51f108bfae 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -191,7 +191,7 @@ void gameport_stop_polling(struct gameport *gameport) spin_lock(&gameport->timer_lock); if (!--gameport->poll_cnt) - del_timer(&gameport->poll_timer); + timer_delete(&gameport->poll_timer); spin_unlock(&gameport->timer_lock); } @@ -372,7 +372,7 @@ static int gameport_queue_event(void *object, struct module *owner, } } - event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); + event = kmalloc(sizeof(*event), GFP_ATOMIC); if (!event) { pr_err("Not enough memory to queue event %d\n", event_type); retval = -ENOMEM; @@ -806,9 +806,9 @@ start_over: } EXPORT_SYMBOL(gameport_unregister_driver); -static int gameport_bus_match(struct device *dev, struct device_driver *drv) +static int gameport_bus_match(struct device *dev, const struct device_driver *drv) { - struct gameport_driver *gameport_drv = to_gameport_driver(drv); + const struct gameport_driver *gameport_drv = to_gameport_driver(drv); return !gameport_drv->ignore; } @@ -847,7 +847,7 @@ EXPORT_SYMBOL(gameport_open); void gameport_close(struct gameport *gameport) { - del_timer_sync(&gameport->poll_timer); + timer_delete_sync(&gameport->poll_timer); gameport->poll_handler = NULL; gameport->poll_interval = 0; gameport_set_drv(gameport, NULL); diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 91a8cd346e9b..880e714b49bc 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c @@ -120,7 +120,7 @@ static int ns558_isa_probe(int io) return -EBUSY; } - ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); + ns558 = kzalloc(sizeof(*ns558), GFP_KERNEL); port = gameport_allocate_port(); if (!ns558 || !port) { printk(KERN_ERR "ns558: Memory allocation failed.\n"); @@ -192,7 +192,7 @@ static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did) if (!request_region(ioport, iolen, "ns558-pnp")) return -EBUSY; - ns558 = kzalloc(sizeof(struct ns558), GFP_KERNEL); + ns558 = kzalloc(sizeof(*ns558), GFP_KERNEL); port = gameport_allocate_port(); if (!ns558 || !port) { printk(KERN_ERR "ns558: Memory allocation failed\n"); diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 14b53dac1253..337006dd9dcf 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -39,17 +39,20 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, unsigned int flags) { - struct input_mt *mt = dev->mt; - int i; - if (!num_slots) return 0; - if (mt) - return mt->num_slots != num_slots ? -EINVAL : 0; - mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL); + if (dev->mt) + return dev->mt->num_slots != num_slots ? -EINVAL : 0; + + /* Arbitrary limit for avoiding too large memory allocation. */ + if (num_slots > 1024) + return -EINVAL; + + struct input_mt *mt __free(kfree) = + kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL); if (!mt) - goto err_mem; + return -ENOMEM; mt->num_slots = num_slots; mt->flags = flags; @@ -83,21 +86,18 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots, unsigned int n2 = num_slots * num_slots; mt->red = kcalloc(n2, sizeof(*mt->red), GFP_KERNEL); if (!mt->red) - goto err_mem; + return -ENOMEM; } /* Mark slots as 'inactive' */ - for (i = 0; i < num_slots; i++) + for (unsigned int i = 0; i < num_slots; i++) input_mt_set_value(&mt->slots[i], ABS_MT_TRACKING_ID, -1); /* Mark slots as 'unused' */ mt->frame = 1; - dev->mt = mt; + dev->mt = no_free_ptr(mt); return 0; -err_mem: - kfree(mt); - return -ENOMEM; } EXPORT_SYMBOL(input_mt_init_slots); @@ -282,14 +282,10 @@ void input_mt_drop_unused(struct input_dev *dev) struct input_mt *mt = dev->mt; if (mt) { - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); __input_mt_drop_unused(dev, mt); mt->frame++; - - spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_mt_drop_unused); @@ -336,11 +332,8 @@ void input_mt_sync_frame(struct input_dev *dev) return; if (mt->flags & INPUT_MT_DROP_UNUSED) { - unsigned long flags; - - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); __input_mt_drop_unused(dev, mt); - spin_unlock_irqrestore(&dev->event_lock, flags); } if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT)) diff --git a/drivers/input/input-poller.c b/drivers/input/input-poller.c index 688e3cb1c2a0..9c57713a6151 100644 --- a/drivers/input/input-poller.c +++ b/drivers/input/input-poller.c @@ -162,7 +162,7 @@ static ssize_t input_dev_set_poll_interval(struct device *dev, if (interval > poller->poll_interval_max) return -EINVAL; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); poller->poll_interval = interval; @@ -172,8 +172,6 @@ static ssize_t input_dev_set_poll_interval(struct device *dev, input_dev_poller_queue_work(poller); } - mutex_unlock(&input->mutex); - return count; } diff --git a/drivers/input/input.c b/drivers/input/input.c index 711485437567..ec4346f20efd 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -96,48 +96,16 @@ static void input_start_autorepeat(struct input_dev *dev, int code) static void input_stop_autorepeat(struct input_dev *dev) { - del_timer(&dev->timer); -} - -/* - * Pass event first through all filters and then, if event has not been - * filtered out, through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. - */ -static unsigned int input_to_handler(struct input_handle *handle, - struct input_value *vals, unsigned int count) -{ - struct input_handler *handler = handle->handler; - struct input_value *end = vals; - struct input_value *v; - - if (handler->filter) { - for (v = vals; v != vals + count; v++) { - if (handler->filter(handle, v->type, v->code, v->value)) - continue; - if (end != v) - *end = *v; - end++; - } - count = end - vals; - } - - if (!count) - return 0; - - if (handler->events) - handler->events(handle, vals, count); - else if (handler->event) - for (v = vals; v != vals + count; v++) - handler->event(handle, v->type, v->code, v->value); - - return count; + timer_delete(&dev->timer); } /* * Pass values first through all filters and then, if event has not been - * filtered out, through all open handles. This function is called with - * dev->event_lock held and interrupts disabled. + * filtered out, through all open handles. This order is achieved by placing + * filters at the head of the list of handles attached to the device, and + * placing regular handles at the tail of the list. + * + * This function is called with dev->event_lock held and interrupts disabled. */ static void input_pass_values(struct input_dev *dev, struct input_value *vals, unsigned int count) @@ -147,25 +115,23 @@ static void input_pass_values(struct input_dev *dev, lockdep_assert_held(&dev->event_lock); - if (!count) - return; - - rcu_read_lock(); + scoped_guard(rcu) { + handle = rcu_dereference(dev->grab); + if (handle) { + count = handle->handle_events(handle, vals, count); + break; + } - handle = rcu_dereference(dev->grab); - if (handle) { - count = input_to_handler(handle, vals, count); - } else { - list_for_each_entry_rcu(handle, &dev->h_list, d_node) + list_for_each_entry_rcu(handle, &dev->h_list, d_node) { if (handle->open) { - count = input_to_handler(handle, vals, count); + count = handle->handle_events(handle, vals, + count); if (!count) break; } + } } - rcu_read_unlock(); - /* trigger auto repeat for key events */ if (test_bit(EV_REP, dev->evbit) && test_bit(EV_KEY, dev->evbit)) { for (v = vals; v != vals + count; v++) { @@ -354,9 +320,6 @@ static void input_event_dispose(struct input_dev *dev, int disposition, if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (!dev->vals) - return; - if (disposition & INPUT_PASS_TO_HANDLERS) { struct input_value *v; @@ -427,13 +390,9 @@ void input_handle_event(struct input_dev *dev, void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { - unsigned long flags; - if (is_event_supported(type, dev->evbit, EV_MAX)) { - - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); input_handle_event(dev, type, code, value); - spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_event); @@ -454,18 +413,15 @@ void input_inject_event(struct input_handle *handle, { struct input_dev *dev = handle->dev; struct input_handle *grab; - unsigned long flags; if (is_event_supported(type, dev->evbit, EV_MAX)) { - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); + guard(rcu)(); - rcu_read_lock(); grab = rcu_dereference(dev->grab); if (!grab || grab == handle) input_handle_event(dev, type, code, value); - rcu_read_unlock(); - spin_unlock_irqrestore(&dev->event_lock, flags); } } EXPORT_SYMBOL(input_inject_event); @@ -563,22 +519,15 @@ EXPORT_SYMBOL(input_copy_abs); int input_grab_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - int retval; - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->grab) + return -EBUSY; - if (dev->grab) { - retval = -EBUSY; - goto out; + rcu_assign_pointer(dev->grab, handle); } - rcu_assign_pointer(dev->grab, handle); - - out: - mutex_unlock(&dev->mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_grab_device); @@ -613,9 +562,8 @@ void input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); __input_release_device(handle); - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_release_device); @@ -629,64 +577,57 @@ EXPORT_SYMBOL(input_release_device); int input_open_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - int retval; - - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; + int error; - if (dev->going_away) { - retval = -ENODEV; - goto out; - } + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->going_away) + return -ENODEV; - handle->open++; + handle->open++; - if (dev->users++ || dev->inhibited) { - /* - * Device is already opened and/or inhibited, - * so we can exit immediately and report success. - */ - goto out; - } + if (handle->handler->passive_observer) + return 0; - if (dev->open) { - retval = dev->open(dev); - if (retval) { - dev->users--; - handle->open--; + if (dev->users++ || dev->inhibited) { /* - * Make sure we are not delivering any more events - * through this handle + * Device is already opened and/or inhibited, + * so we can exit immediately and report success. */ - synchronize_rcu(); - goto out; + return 0; } - } - if (dev->poller) - input_dev_poller_start(dev->poller); + if (dev->open) { + error = dev->open(dev); + if (error) { + dev->users--; + handle->open--; + /* + * Make sure we are not delivering any more + * events through this handle. + */ + synchronize_rcu(); + return error; + } + } - out: - mutex_unlock(&dev->mutex); - return retval; + if (dev->poller) + input_dev_poller_start(dev->poller); + } + + return 0; } EXPORT_SYMBOL(input_open_device); int input_flush_device(struct input_handle *handle, struct file *file) { struct input_dev *dev = handle->dev; - int retval; - - retval = mutex_lock_interruptible(&dev->mutex); - if (retval) - return retval; - if (dev->flush) - retval = dev->flush(dev, file); + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + if (dev->flush) + return dev->flush(dev, file); + } - mutex_unlock(&dev->mutex); - return retval; + return 0; } EXPORT_SYMBOL(input_flush_device); @@ -701,15 +642,17 @@ void input_close_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); __input_release_device(handle); - if (!--dev->users && !dev->inhibited) { - if (dev->poller) - input_dev_poller_stop(dev->poller); - if (dev->close) - dev->close(dev); + if (!handle->handler->passive_observer) { + if (!--dev->users && !dev->inhibited) { + if (dev->poller) + input_dev_poller_stop(dev->poller); + if (dev->close) + dev->close(dev); + } } if (!--handle->open) { @@ -720,8 +663,6 @@ void input_close_device(struct input_handle *handle) */ synchronize_rcu(); } - - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_close_device); @@ -758,11 +699,10 @@ static void input_disconnect_device(struct input_dev *dev) * not to protect access to dev->going_away but rather to ensure * that there are no threads in the middle of input_open_device() */ - mutex_lock(&dev->mutex); - dev->going_away = true; - mutex_unlock(&dev->mutex); + scoped_guard(mutex, &dev->mutex) + dev->going_away = true; - spin_lock_irq(&dev->event_lock); + guard(spinlock_irq)(&dev->event_lock); /* * Simulate keyup events for all pressed keys so that handlers @@ -775,8 +715,6 @@ static void input_disconnect_device(struct input_dev *dev) list_for_each_entry(handle, &dev->h_list, d_node) handle->open = 0; - - spin_unlock_irq(&dev->event_lock); } /** @@ -933,14 +871,9 @@ static int input_default_setkeycode(struct input_dev *dev, */ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke) { - unsigned long flags; - int retval; - - spin_lock_irqsave(&dev->event_lock, flags); - retval = dev->getkeycode(dev, ke); - spin_unlock_irqrestore(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); - return retval; + return dev->getkeycode(dev, ke); } EXPORT_SYMBOL(input_get_keycode); @@ -955,18 +888,17 @@ EXPORT_SYMBOL(input_get_keycode); int input_set_keycode(struct input_dev *dev, const struct input_keymap_entry *ke) { - unsigned long flags; unsigned int old_keycode; - int retval; + int error; if (ke->keycode > KEY_MAX) return -EINVAL; - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); - retval = dev->setkeycode(dev, ke, &old_keycode); - if (retval) - goto out; + error = dev->setkeycode(dev, ke, &old_keycode); + if (error) + return error; /* Make sure KEY_RESERVED did not get enabled. */ __clear_bit(KEY_RESERVED, dev->keybit); @@ -994,10 +926,7 @@ int input_set_keycode(struct input_dev *dev, EV_SYN, SYN_REPORT, 1); } - out: - spin_unlock_irqrestore(&dev->event_lock, flags); - - return retval; + return 0; } EXPORT_SYMBOL(input_set_keycode); @@ -1116,33 +1045,31 @@ static inline void input_wakeup_procfs_readers(void) wake_up(&input_devices_poll_wait); } +struct input_seq_state { + unsigned short pos; + bool mutex_acquired; + int input_devices_state; +}; + static __poll_t input_proc_devices_poll(struct file *file, poll_table *wait) { + struct seq_file *seq = file->private_data; + struct input_seq_state *state = seq->private; + poll_wait(file, &input_devices_poll_wait, wait); - if (file->f_version != input_devices_state) { - file->f_version = input_devices_state; + if (state->input_devices_state != input_devices_state) { + state->input_devices_state = input_devices_state; return EPOLLIN | EPOLLRDNORM; } return 0; } -union input_seq_state { - struct { - unsigned short pos; - bool mutex_acquired; - }; - void *p; -}; - static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; int error; - /* We need to fit into seq->private pointer */ - BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private)); - error = mutex_lock_interruptible(&input_mutex); if (error) { state->mutex_acquired = false; @@ -1161,7 +1088,7 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void input_seq_stop(struct seq_file *seq, void *v) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; if (state->mutex_acquired) mutex_unlock(&input_mutex); @@ -1247,7 +1174,8 @@ static const struct seq_operations input_devices_seq_ops = { static int input_proc_devices_open(struct inode *inode, struct file *file) { - return seq_open(file, &input_devices_seq_ops); + return seq_open_private(file, &input_devices_seq_ops, + sizeof(struct input_seq_state)); } static const struct proc_ops input_devices_proc_ops = { @@ -1255,17 +1183,14 @@ static const struct proc_ops input_devices_proc_ops = { .proc_poll = input_proc_devices_poll, .proc_read = seq_read, .proc_lseek = seq_lseek, - .proc_release = seq_release, + .proc_release = seq_release_private, }; static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; int error; - /* We need to fit into seq->private pointer */ - BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private)); - error = mutex_lock_interruptible(&input_mutex); if (error) { state->mutex_acquired = false; @@ -1280,7 +1205,7 @@ static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos) static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; state->pos = *pos + 1; return seq_list_next(v, &input_handler_list, pos); @@ -1289,7 +1214,7 @@ static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos) static int input_handlers_seq_show(struct seq_file *seq, void *v) { struct input_handler *handler = container_of(v, struct input_handler, node); - union input_seq_state *state = (union input_seq_state *)&seq->private; + struct input_seq_state *state = seq->private; seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); if (handler->filter) @@ -1310,14 +1235,15 @@ static const struct seq_operations input_handlers_seq_ops = { static int input_proc_handlers_open(struct inode *inode, struct file *file) { - return seq_open(file, &input_handlers_seq_ops); + return seq_open_private(file, &input_handlers_seq_ops, + sizeof(struct input_seq_state)); } static const struct proc_ops input_handlers_proc_ops = { .proc_open = input_proc_handlers_open, .proc_read = seq_read, .proc_lseek = seq_lseek, - .proc_release = seq_release, + .proc_release = seq_release_private, }; static int __init input_proc_init(void) @@ -1378,19 +1304,19 @@ static int input_print_modalias_bits(char *buf, int size, char name, const unsigned long *bm, unsigned int min_bit, unsigned int max_bit) { - int len = 0, i; + int bit = min_bit; + int len = 0; len += snprintf(buf, max(size, 0), "%c", name); - for (i = min_bit; i < max_bit; i++) - if (bm[BIT_WORD(i)] & BIT_MASK(i)) - len += snprintf(buf + len, max(size - len, 0), "%X,", i); + for_each_set_bit_from(bit, bm, max_bit) + len += snprintf(buf + len, max(size - len, 0), "%X,", bit); return len; } -static int input_print_modalias(char *buf, int size, const struct input_dev *id, - int add_cr) +static int input_print_modalias_parts(char *buf, int size, int full_len, + const struct input_dev *id) { - int len; + int len, klen, remainder, space; len = snprintf(buf, max(size, 0), "input:b%04Xv%04Xp%04Xe%04X-", @@ -1399,8 +1325,48 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, len += input_print_modalias_bits(buf + len, size - len, 'e', id->evbit, 0, EV_MAX); - len += input_print_modalias_bits(buf + len, size - len, + + /* + * Calculate the remaining space in the buffer making sure we + * have place for the terminating 0. + */ + space = max(size - (len + 1), 0); + + klen = input_print_modalias_bits(buf + len, size - len, 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX); + len += klen; + + /* + * If we have more data than we can fit in the buffer, check + * if we can trim key data to fit in the rest. We will indicate + * that key data is incomplete by adding "+" sign at the end, like + * this: * "k1,2,3,45,+,". + * + * Note that we shortest key info (if present) is "k+," so we + * can only try to trim if key data is longer than that. + */ + if (full_len && size < full_len + 1 && klen > 3) { + remainder = full_len - len; + /* + * We can only trim if we have space for the remainder + * and also for at least "k+," which is 3 more characters. + */ + if (remainder <= space - 3) { + /* + * We are guaranteed to have 'k' in the buffer, so + * we need at least 3 additional bytes for storing + * "+," in addition to the remainder. + */ + for (int i = size - 1 - remainder - 3; i >= 0; i--) { + if (buf[i] == 'k' || buf[i] == ',') { + strcpy(buf + i + 1, "+,"); + len = i + 3; /* Not counting '\0' */ + break; + } + } + } + } + len += input_print_modalias_bits(buf + len, size - len, 'r', id->relbit, 0, REL_MAX); len += input_print_modalias_bits(buf + len, size - len, @@ -1416,12 +1382,25 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id, len += input_print_modalias_bits(buf + len, size - len, 'w', id->swbit, 0, SW_MAX); - if (add_cr) - len += snprintf(buf + len, max(size - len, 0), "\n"); - return len; } +static int input_print_modalias(char *buf, int size, const struct input_dev *id) +{ + int full_len; + + /* + * Printing is done in 2 passes: first one figures out total length + * needed for the modalias string, second one will try to trim key + * data in case when buffer is too small for the entire modalias. + * If the buffer is too small regardless, it will fill as much as it + * can (without trimming key data) into the buffer and leave it to + * the caller to figure out what to do with the result. + */ + full_len = input_print_modalias_parts(NULL, 0, 0, id); + return input_print_modalias_parts(buf, size, full_len, id); +} + static ssize_t input_dev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) @@ -1429,7 +1408,9 @@ static ssize_t input_dev_show_modalias(struct device *dev, struct input_dev *id = to_input_dev(dev); ssize_t len; - len = input_print_modalias(buf, PAGE_SIZE, id, 1); + len = input_print_modalias(buf, PAGE_SIZE, id); + if (len < PAGE_SIZE - 2) + len += snprintf(buf + len, PAGE_SIZE - len, "\n"); return min_t(int, len, PAGE_SIZE); } @@ -1641,6 +1622,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, return 0; } +/* + * This is a pretty gross hack. When building uevent data the driver core + * may try adding more environment variables to kobj_uevent_env without + * telling us, so we have no idea how much of the buffer we can use to + * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially + * reduce amount of memory we will use for the modalias environment variable. + * + * The potential additions are: + * + * SEQNUM=18446744073709551615 - (%llu - 28 bytes) + * HOME=/ (6 bytes) + * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes) + * + * 68 bytes total. Allow extra buffer - 96 bytes + */ +#define UEVENT_ENV_EXTRA_LEN 96 + static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, const struct input_dev *dev) { @@ -1650,9 +1648,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, return -ENOMEM; len = input_print_modalias(&env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen, - dev, 0); - if (len >= (sizeof(env->buf) - env->buflen)) + (int)sizeof(env->buf) - env->buflen - + UEVENT_ENV_EXTRA_LEN, + dev); + if (len >= ((int)sizeof(env->buf) - env->buflen - + UEVENT_ENV_EXTRA_LEN)) return -ENOMEM; env->buflen += len; @@ -1760,26 +1760,21 @@ static void input_dev_toggle(struct input_dev *dev, bool activate) */ void input_reset_device(struct input_dev *dev) { - unsigned long flags; - - mutex_lock(&dev->mutex); - spin_lock_irqsave(&dev->event_lock, flags); + guard(mutex)(&dev->mutex); + guard(spinlock_irqsave)(&dev->event_lock); input_dev_toggle(dev, true); if (input_dev_release_keys(dev)) input_handle_event(dev, EV_SYN, SYN_REPORT, 1); - - spin_unlock_irqrestore(&dev->event_lock, flags); - mutex_unlock(&dev->mutex); } EXPORT_SYMBOL(input_reset_device); static int input_inhibit_device(struct input_dev *dev) { - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); if (dev->inhibited) - goto out; + return 0; if (dev->users) { if (dev->close) @@ -1788,54 +1783,50 @@ static int input_inhibit_device(struct input_dev *dev) input_dev_poller_stop(dev->poller); } - spin_lock_irq(&dev->event_lock); - input_mt_release_slots(dev); - input_dev_release_keys(dev); - input_handle_event(dev, EV_SYN, SYN_REPORT, 1); - input_dev_toggle(dev, false); - spin_unlock_irq(&dev->event_lock); + scoped_guard(spinlock_irq, &dev->event_lock) { + input_mt_release_slots(dev); + input_dev_release_keys(dev); + input_handle_event(dev, EV_SYN, SYN_REPORT, 1); + input_dev_toggle(dev, false); + } dev->inhibited = true; -out: - mutex_unlock(&dev->mutex); return 0; } static int input_uninhibit_device(struct input_dev *dev) { - int ret = 0; + int error; - mutex_lock(&dev->mutex); + guard(mutex)(&dev->mutex); if (!dev->inhibited) - goto out; + return 0; if (dev->users) { if (dev->open) { - ret = dev->open(dev); - if (ret) - goto out; + error = dev->open(dev); + if (error) + return error; } if (dev->poller) input_dev_poller_start(dev->poller); } dev->inhibited = false; - spin_lock_irq(&dev->event_lock); - input_dev_toggle(dev, true); - spin_unlock_irq(&dev->event_lock); -out: - mutex_unlock(&dev->mutex); - return ret; + scoped_guard(spinlock_irq, &dev->event_lock) + input_dev_toggle(dev, true); + + return 0; } static int input_dev_suspend(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* * Keys that are pressed now are unlikely to be @@ -1847,8 +1838,6 @@ static int input_dev_suspend(struct device *dev) /* Turn off LEDs and sounds, if any are active. */ input_dev_toggle(input_dev, false); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1856,13 +1845,11 @@ static int input_dev_resume(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* Restore state of LEDs and sounds, if any were active. */ input_dev_toggle(input_dev, true); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1870,7 +1857,7 @@ static int input_dev_freeze(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* * Keys that are pressed now are unlikely to be @@ -1879,8 +1866,6 @@ static int input_dev_freeze(struct device *dev) if (input_dev_release_keys(input_dev)) input_handle_event(input_dev, EV_SYN, SYN_REPORT, 1); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1888,13 +1873,11 @@ static int input_dev_poweroff(struct device *dev) { struct input_dev *input_dev = to_input_dev(dev); - spin_lock_irq(&input_dev->event_lock); + guard(spinlock_irq)(&input_dev->event_lock); /* Turn off LEDs and sounds, if any are active. */ input_dev_toggle(input_dev, false); - spin_unlock_irq(&input_dev->event_lock); - return 0; } @@ -1939,22 +1922,41 @@ struct input_dev *input_allocate_device(void) struct input_dev *dev; dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev) { - dev->dev.type = &input_dev_type; - dev->dev.class = &input_class; - device_initialize(&dev->dev); - mutex_init(&dev->mutex); - spin_lock_init(&dev->event_lock); - timer_setup(&dev->timer, NULL, 0); - INIT_LIST_HEAD(&dev->h_list); - INIT_LIST_HEAD(&dev->node); - - dev_set_name(&dev->dev, "input%lu", - (unsigned long)atomic_inc_return(&input_no)); + if (!dev) + return NULL; - __module_get(THIS_MODULE); + /* + * Start with space for SYN_REPORT + 7 EV_KEY/EV_MSC events + 2 spare, + * see input_estimate_events_per_packet(). We will tune the number + * when we register the device. + */ + dev->max_vals = 10; + dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); + if (!dev->vals) { + kfree(dev); + return NULL; } + mutex_init(&dev->mutex); + spin_lock_init(&dev->event_lock); + timer_setup(&dev->timer, NULL, 0); + INIT_LIST_HEAD(&dev->h_list); + INIT_LIST_HEAD(&dev->node); + + dev->dev.type = &input_dev_type; + dev->dev.class = &input_class; + device_initialize(&dev->dev); + /* + * From this point on we can no longer simply "kfree(dev)", we need + * to use input_free_device() so that device core properly frees its + * resources associated with the input device. + */ + + dev_set_name(&dev->dev, "input%lu", + (unsigned long)atomic_inc_return(&input_no)); + + __module_get(THIS_MODULE); + return dev; } EXPORT_SYMBOL(input_allocate_device); @@ -2168,7 +2170,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) mt_slots = dev->mt->num_slots; } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) { mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum - - dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1, + dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1; mt_slots = clamp(mt_slots, 2, 32); } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) { mt_slots = 2; @@ -2216,18 +2218,16 @@ static void __input_unregister_device(struct input_dev *dev) input_disconnect_device(dev); - mutex_lock(&input_mutex); + scoped_guard(mutex, &input_mutex) { + list_for_each_entry_safe(handle, next, &dev->h_list, d_node) + handle->handler->disconnect(handle); + WARN_ON(!list_empty(&dev->h_list)); - list_for_each_entry_safe(handle, next, &dev->h_list, d_node) - handle->handler->disconnect(handle); - WARN_ON(!list_empty(&dev->h_list)); + timer_delete_sync(&dev->timer); + list_del_init(&dev->node); - del_timer_sync(&dev->timer); - list_del_init(&dev->node); - - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); + input_wakeup_procfs_readers(); + } device_del(&dev->dev); } @@ -2250,9 +2250,8 @@ static void devm_input_device_unregister(struct device *dev, void *res) static void input_repeat_key(struct timer_list *t) { struct input_dev *dev = from_timer(dev, t, timer); - unsigned long flags; - spin_lock_irqsave(&dev->event_lock, flags); + guard(spinlock_irqsave)(&dev->event_lock); if (!dev->inhibited && test_bit(dev->repeat_key, dev->key) && @@ -2266,8 +2265,6 @@ static void input_repeat_key(struct timer_list *t) mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); } - - spin_unlock_irqrestore(&dev->event_lock, flags); } /** @@ -2294,6 +2291,35 @@ bool input_device_enabled(struct input_dev *dev) } EXPORT_SYMBOL_GPL(input_device_enabled); +static int input_device_tune_vals(struct input_dev *dev) +{ + struct input_value *vals; + unsigned int packet_size; + unsigned int max_vals; + + packet_size = input_estimate_events_per_packet(dev); + if (dev->hint_events_per_packet < packet_size) + dev->hint_events_per_packet = packet_size; + + max_vals = dev->hint_events_per_packet + 2; + if (dev->max_vals >= max_vals) + return 0; + + vals = kcalloc(max_vals, sizeof(*vals), GFP_KERNEL); + if (!vals) + return -ENOMEM; + + scoped_guard(spinlock_irq, &dev->event_lock) { + dev->max_vals = max_vals; + swap(dev->vals, vals); + } + + /* Because of swap() above, this frees the old vals memory */ + kfree(vals); + + return 0; +} + /** * input_register_device - register device with input core * @dev: device to be registered @@ -2321,7 +2347,6 @@ int input_register_device(struct input_dev *dev) { struct input_devres *devres = NULL; struct input_handler *handler; - unsigned int packet_size; const char *path; int error; @@ -2349,16 +2374,9 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - packet_size = input_estimate_events_per_packet(dev); - if (dev->hint_events_per_packet < packet_size) - dev->hint_events_per_packet = packet_size; - - dev->max_vals = dev->hint_events_per_packet + 2; - dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); - if (!dev->vals) { - error = -ENOMEM; + error = input_device_tune_vals(dev); + if (error) goto err_devres_free; - } /* * If delay and period are pre-set by the driver, then autorepeating @@ -2378,7 +2396,7 @@ int input_register_device(struct input_dev *dev) error = device_add(&dev->dev); if (error) - goto err_free_vals; + goto err_devres_free; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n", @@ -2386,18 +2404,15 @@ int input_register_device(struct input_dev *dev) path ? path : "N/A"); kfree(path); - error = mutex_lock_interruptible(&input_mutex); - if (error) - goto err_device_del; - - list_add_tail(&dev->node, &input_dev_list); + error = -EINTR; + scoped_cond_guard(mutex_intr, goto err_device_del, &input_mutex) { + list_add_tail(&dev->node, &input_dev_list); - list_for_each_entry(handler, &input_handler_list, node) - input_attach_handler(dev, handler); + list_for_each_entry(handler, &input_handler_list, node) + input_attach_handler(dev, handler); - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); + input_wakeup_procfs_readers(); + } if (dev->devres_managed) { dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n", @@ -2408,9 +2423,6 @@ int input_register_device(struct input_dev *dev) err_device_del: device_del(&dev->dev); -err_free_vals: - kfree(dev->vals); - dev->vals = NULL; err_devres_free: devres_free(devres); return error; @@ -2443,6 +2455,26 @@ void input_unregister_device(struct input_dev *dev) } EXPORT_SYMBOL(input_unregister_device); +static int input_handler_check_methods(const struct input_handler *handler) +{ + int count = 0; + + if (handler->filter) + count++; + if (handler->events) + count++; + if (handler->event) + count++; + + if (count > 1) { + pr_err("%s: only one event processing method can be defined (%s)\n", + __func__, handler->name); + return -EINVAL; + } + + return 0; +} + /** * input_register_handler - register a new input handler * @handler: handler to be registered @@ -2456,20 +2488,21 @@ int input_register_handler(struct input_handler *handler) struct input_dev *dev; int error; - error = mutex_lock_interruptible(&input_mutex); + error = input_handler_check_methods(handler); if (error) return error; - INIT_LIST_HEAD(&handler->h_list); + scoped_cond_guard(mutex_intr, return -EINTR, &input_mutex) { + INIT_LIST_HEAD(&handler->h_list); - list_add_tail(&handler->node, &input_handler_list); + list_add_tail(&handler->node, &input_handler_list); - list_for_each_entry(dev, &input_dev_list, node) - input_attach_handler(dev, handler); + list_for_each_entry(dev, &input_dev_list, node) + input_attach_handler(dev, handler); - input_wakeup_procfs_readers(); + input_wakeup_procfs_readers(); + } - mutex_unlock(&input_mutex); return 0; } EXPORT_SYMBOL(input_register_handler); @@ -2485,7 +2518,7 @@ void input_unregister_handler(struct input_handler *handler) { struct input_handle *handle, *next; - mutex_lock(&input_mutex); + guard(mutex)(&input_mutex); list_for_each_entry_safe(handle, next, &handler->h_list, h_node) handler->disconnect(handle); @@ -2494,8 +2527,6 @@ void input_unregister_handler(struct input_handler *handler) list_del_init(&handler->node); input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); } EXPORT_SYMBOL(input_unregister_handler); @@ -2515,22 +2546,89 @@ int input_handler_for_each_handle(struct input_handler *handler, void *data, int (*fn)(struct input_handle *, void *)) { struct input_handle *handle; - int retval = 0; + int retval; - rcu_read_lock(); + guard(rcu)(); list_for_each_entry_rcu(handle, &handler->h_list, h_node) { retval = fn(handle, data); if (retval) - break; + return retval; } - rcu_read_unlock(); - - return retval; + return 0; } EXPORT_SYMBOL(input_handler_for_each_handle); +/* + * An implementation of input_handle's handle_events() method that simply + * invokes handler->event() method for each event one by one. + */ +static unsigned int input_handle_events_default(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *v; + + for (v = vals; v != vals + count; v++) + handler->event(handle, v->type, v->code, v->value); + + return count; +} + +/* + * An implementation of input_handle's handle_events() method that invokes + * handler->filter() method for each event one by one and removes events + * that were filtered out from the "vals" array. + */ +static unsigned int input_handle_events_filter(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *end = vals; + struct input_value *v; + + for (v = vals; v != vals + count; v++) { + if (handler->filter(handle, v->type, v->code, v->value)) + continue; + if (end != v) + *end = *v; + end++; + } + + return end - vals; +} + +/* + * An implementation of input_handle's handle_events() method that does nothing. + */ +static unsigned int input_handle_events_null(struct input_handle *handle, + struct input_value *vals, + unsigned int count) +{ + return count; +} + +/* + * Sets up appropriate handle->event_handler based on the input_handler + * associated with the handle. + */ +static void input_handle_setup_event_handler(struct input_handle *handle) +{ + struct input_handler *handler = handle->handler; + + if (handler->filter) + handle->handle_events = input_handle_events_filter; + else if (handler->event) + handle->handle_events = input_handle_events_default; + else if (handler->events) + handle->handle_events = handler->events; + else + handle->handle_events = input_handle_events_null; +} + /** * input_register_handle - register a new input handle * @handle: handle to register @@ -2546,26 +2644,22 @@ int input_register_handle(struct input_handle *handle) { struct input_handler *handler = handle->handler; struct input_dev *dev = handle->dev; - int error; + input_handle_setup_event_handler(handle); /* * We take dev->mutex here to prevent race with * input_release_device(). */ - error = mutex_lock_interruptible(&dev->mutex); - if (error) - return error; - - /* - * Filters go to the head of the list, normal handlers - * to the tail. - */ - if (handler->filter) - list_add_rcu(&handle->d_node, &dev->h_list); - else - list_add_tail_rcu(&handle->d_node, &dev->h_list); - - mutex_unlock(&dev->mutex); + scoped_cond_guard(mutex_intr, return -EINTR, &dev->mutex) { + /* + * Filters go to the head of the list, normal handlers + * to the tail. + */ + if (handler->filter) + list_add_rcu(&handle->d_node, &dev->h_list); + else + list_add_tail_rcu(&handle->d_node, &dev->h_list); + } /* * Since we are supposed to be called from ->connect() @@ -2601,9 +2695,8 @@ void input_unregister_handle(struct input_handle *handle) /* * Take dev->mutex to prevent race with input_release_device(). */ - mutex_lock(&dev->mutex); - list_del_rcu(&handle->d_node); - mutex_unlock(&dev->mutex); + scoped_guard(mutex, &dev->mutex) + list_del_rcu(&handle->d_node); synchronize_rcu(); } diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 5824bca02e5a..ba2b17288bcd 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -718,7 +718,6 @@ static const struct file_operations joydev_fops = { .compat_ioctl = joydev_compat_ioctl, #endif .fasync = joydev_fasync, - .llseek = no_llseek, }; /* diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index fd1827baf27c..15182f16ed19 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c @@ -249,7 +249,7 @@ static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - a3d = kzalloc(sizeof(struct a3d), GFP_KERNEL); + a3d = kzalloc(sizeof(*a3d), GFP_KERNEL); input_dev = input_allocate_device(); if (!a3d || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/adafruit-seesaw.c b/drivers/input/joystick/adafruit-seesaw.c index 1b9279f024cc..c248c15b849d 100644 --- a/drivers/input/joystick/adafruit-seesaw.c +++ b/drivers/input/joystick/adafruit-seesaw.c @@ -15,7 +15,7 @@ * - Add interrupt support */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/bits.h> #include <linux/delay.h> #include <linux/i2c.h> @@ -56,7 +56,7 @@ #define SEESAW_GAMEPAD_POLL_MIN 8 #define SEESAW_GAMEPAD_POLL_MAX 32 -static const unsigned long SEESAW_BUTTON_MASK = +static const u32 SEESAW_BUTTON_MASK = BIT(SEESAW_BUTTON_A) | BIT(SEESAW_BUTTON_B) | BIT(SEESAW_BUTTON_X) | BIT(SEESAW_BUTTON_Y) | BIT(SEESAW_BUTTON_START) | BIT(SEESAW_BUTTON_SELECT); @@ -64,6 +64,7 @@ static const unsigned long SEESAW_BUTTON_MASK = struct seesaw_gamepad { struct input_dev *input_dev; struct i2c_client *i2c_client; + u32 button_state; }; struct seesaw_data { @@ -178,10 +179,20 @@ static int seesaw_read_data(struct i2c_client *client, struct seesaw_data *data) return 0; } +static int seesaw_open(struct input_dev *input) +{ + struct seesaw_gamepad *private = input_get_drvdata(input); + + private->button_state = 0; + + return 0; +} + static void seesaw_poll(struct input_dev *input) { struct seesaw_gamepad *private = input_get_drvdata(input); struct seesaw_data data; + unsigned long changed; int err, i; err = seesaw_read_data(private->i2c_client, &data); @@ -194,8 +205,11 @@ static void seesaw_poll(struct input_dev *input) input_report_abs(input, ABS_X, data.x); input_report_abs(input, ABS_Y, data.y); - for_each_set_bit(i, &SEESAW_BUTTON_MASK, - BITS_PER_TYPE(SEESAW_BUTTON_MASK)) { + data.button_state &= SEESAW_BUTTON_MASK; + changed = private->button_state ^ data.button_state; + private->button_state = data.button_state; + + for_each_set_bit(i, &changed, fls(SEESAW_BUTTON_MASK)) { if (!sparse_keymap_report_event(input, i, data.button_state & BIT(i), false)) @@ -253,6 +267,7 @@ static int seesaw_probe(struct i2c_client *client) seesaw->input_dev->id.bustype = BUS_I2C; seesaw->input_dev->name = "Adafruit Seesaw Gamepad"; seesaw->input_dev->phys = "i2c/" SEESAW_DEVICE_NAME; + seesaw->input_dev->open = seesaw_open; input_set_drvdata(seesaw->input_dev, seesaw); input_set_abs_params(seesaw->input_dev, ABS_X, 0, SEESAW_JOYSTICK_MAX_AXIS, diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c index c0deff5d4282..ff44f9978b71 100644 --- a/drivers/input/joystick/adc-joystick.c +++ b/drivers/input/joystick/adc-joystick.c @@ -11,24 +11,30 @@ #include <linux/platform_device.h> #include <linux/property.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> struct adc_joystick_axis { u32 code; - s32 range[2]; - s32 fuzz; - s32 flat; + bool inverted; }; struct adc_joystick { struct input_dev *input; struct iio_cb_buffer *buffer; - struct adc_joystick_axis *axes; struct iio_channel *chans; - int num_chans; - bool polled; + unsigned int num_chans; + struct adc_joystick_axis axes[] __counted_by(num_chans); }; +static int adc_joystick_invert(struct input_dev *dev, + unsigned int axis, int val) +{ + int min = input_abs_get_min(dev, axis); + int max = input_abs_get_max(dev, axis); + + return (max + min) - val; +} + static void adc_joystick_poll(struct input_dev *input) { struct adc_joystick *joy = input_get_drvdata(input); @@ -38,6 +44,8 @@ static void adc_joystick_poll(struct input_dev *input) ret = iio_read_channel_raw(&joy->chans[i], &val); if (ret < 0) return; + if (joy->axes[i].inverted) + val = adc_joystick_invert(input, i, val); input_report_abs(input, joy->axes[i].code, val); } input_sync(input); @@ -86,6 +94,8 @@ static int adc_joystick_handle(const void *data, void *private) val = sign_extend32(val, msb); else val &= GENMASK(msb, 0); + if (joy->axes[i].inverted) + val = adc_joystick_invert(joy->input, i, val); input_report_abs(joy->input, joy->axes[i].code, val); } @@ -121,9 +131,10 @@ static void adc_joystick_cleanup(void *data) static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy) { - struct adc_joystick_axis *axes; - struct fwnode_handle *child; - int num_axes, error, i; + struct adc_joystick_axis *axes = joy->axes; + s32 range[2], fuzz, flat; + unsigned int num_axes; + int error, i; num_axes = device_get_child_node_count(dev); if (!num_axes) { @@ -137,72 +148,95 @@ static int adc_joystick_set_axes(struct device *dev, struct adc_joystick *joy) return -EINVAL; } - axes = devm_kmalloc_array(dev, num_axes, sizeof(*axes), GFP_KERNEL); - if (!axes) - return -ENOMEM; - - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { error = fwnode_property_read_u32(child, "reg", &i); if (error) { dev_err(dev, "reg invalid or missing\n"); - goto err_fwnode_put; + return error; } if (i >= num_axes) { - error = -EINVAL; dev_err(dev, "No matching axis for reg %d\n", i); - goto err_fwnode_put; + return -EINVAL; } error = fwnode_property_read_u32(child, "linux,code", &axes[i].code); if (error) { dev_err(dev, "linux,code invalid or missing\n"); - goto err_fwnode_put; + return error; } error = fwnode_property_read_u32_array(child, "abs-range", - axes[i].range, 2); + range, 2); if (error) { dev_err(dev, "abs-range invalid or missing\n"); - goto err_fwnode_put; + return error; + } + + if (range[0] > range[1]) { + dev_dbg(dev, "abs-axis %d inverted\n", i); + axes[i].inverted = true; + swap(range[0], range[1]); } - fwnode_property_read_u32(child, "abs-fuzz", &axes[i].fuzz); - fwnode_property_read_u32(child, "abs-flat", &axes[i].flat); + if (fwnode_property_read_u32(child, "abs-fuzz", &fuzz)) + fuzz = 0; + + if (fwnode_property_read_u32(child, "abs-flat", &flat)) + flat = 0; input_set_abs_params(joy->input, axes[i].code, - axes[i].range[0], axes[i].range[1], - axes[i].fuzz, axes[i].flat); - input_set_capability(joy->input, EV_ABS, axes[i].code); + range[0], range[1], fuzz, flat); } - joy->axes = axes; - return 0; +} + + +static int adc_joystick_count_channels(struct device *dev, + const struct iio_channel *chans, + bool polled, + unsigned int *num_chans) +{ + int bits; + int i; + + /* + * Count how many channels we got. NULL terminated. + * Do not check the storage size if using polling. + */ + for (i = 0; chans[i].indio_dev; i++) { + if (polled) + continue; + bits = chans[i].channel->scan_type.storagebits; + if (!bits || bits > 16) { + dev_err(dev, "Unsupported channel storage size\n"); + return -EINVAL; + } + if (bits != chans[0].channel->scan_type.storagebits) { + dev_err(dev, "Channels must have equal storage size\n"); + return -EINVAL; + } + } -err_fwnode_put: - fwnode_handle_put(child); - return error; + *num_chans = i; + return 0; } static int adc_joystick_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct iio_channel *chans; struct adc_joystick *joy; struct input_dev *input; + unsigned int poll_interval = 0; + unsigned int num_chans; int error; - int bits; - int i; - unsigned int poll_interval; - - joy = devm_kzalloc(dev, sizeof(*joy), GFP_KERNEL); - if (!joy) - return -ENOMEM; - joy->chans = devm_iio_channel_get_all(dev); - if (IS_ERR(joy->chans)) { - error = PTR_ERR(joy->chans); + chans = devm_iio_channel_get_all(dev); + error = PTR_ERR_OR_ZERO(chans); + if (error) { if (error != -EPROBE_DEFER) dev_err(dev, "Unable to get IIO channels"); return error; @@ -216,28 +250,19 @@ static int adc_joystick_probe(struct platform_device *pdev) } else if (poll_interval == 0) { dev_err(dev, "Unable to get poll-interval\n"); return -EINVAL; - } else { - joy->polled = true; } - /* - * Count how many channels we got. NULL terminated. - * Do not check the storage size if using polling. - */ - for (i = 0; joy->chans[i].indio_dev; i++) { - if (joy->polled) - continue; - bits = joy->chans[i].channel->scan_type.storagebits; - if (!bits || bits > 16) { - dev_err(dev, "Unsupported channel storage size\n"); - return -EINVAL; - } - if (bits != joy->chans[0].channel->scan_type.storagebits) { - dev_err(dev, "Channels must have equal storage size\n"); - return -EINVAL; - } - } - joy->num_chans = i; + error = adc_joystick_count_channels(dev, chans, poll_interval != 0, + &num_chans); + if (error) + return error; + + joy = devm_kzalloc(dev, struct_size(joy, axes, num_chans), GFP_KERNEL); + if (!joy) + return -ENOMEM; + + joy->chans = chans; + joy->num_chans = num_chans; input = devm_input_allocate_device(dev); if (!input) { @@ -253,7 +278,7 @@ static int adc_joystick_probe(struct platform_device *pdev) if (error) return error; - if (joy->polled) { + if (poll_interval != 0) { input_setup_polling(input, adc_joystick_poll); input_set_poll_interval(input, poll_interval); } else { diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index f1a720be458b..963250de24b7 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c @@ -456,7 +456,7 @@ static int adi_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - port = kzalloc(sizeof(struct adi_port), GFP_KERNEL); + port = kzalloc(sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 0c9e172a9818..c709b58d770a 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -582,7 +582,8 @@ static int analog_connect(struct gameport *gameport, struct gameport_driver *drv int i; int err; - if (!(port = kzalloc(sizeof(struct analog_port), GFP_KERNEL))) + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) return -ENOMEM; err = analog_init_port(gameport, drv, port); diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index f1822c19a289..49a0dfbbeb49 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -237,7 +237,7 @@ static int as5011_probe(struct i2c_client *client) return -ENODEV; } - as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL); + as5011 = kmalloc(sizeof(*as5011), GFP_KERNEL); input_dev = input_allocate_device(); if (!as5011 || !input_dev) { dev_err(&client->dev, @@ -337,7 +337,7 @@ static void as5011_remove(struct i2c_client *client) } static const struct i2c_device_id as5011_id[] = { - { MODULE_DEVICE_ALIAS, 0 }, + { MODULE_DEVICE_ALIAS }, { } }; MODULE_DEVICE_TABLE(i2c, as5011_id); diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c index 7ff78c9388bd..5a0ea3ad5efa 100644 --- a/drivers/input/joystick/cobra.c +++ b/drivers/input/joystick/cobra.c @@ -141,7 +141,7 @@ static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) int i, j; int err; - cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL); + cobra = kzalloc(sizeof(*cobra), GFP_KERNEL); if (!cobra) return -ENOMEM; diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 4fba28b1a1e7..d7a253835889 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c @@ -505,24 +505,22 @@ static int db9_open(struct input_dev *dev) { struct db9 *db9 = input_get_drvdata(dev); struct parport *port = db9->pd->port; - int err; - err = mutex_lock_interruptible(&db9->mutex); - if (err) - return err; - - if (!db9->used++) { - parport_claim(db9->pd); - parport_write_data(port, 0xff); - if (db9_modes[db9->mode].reverse) { - parport_data_reverse(port); - parport_write_control(port, DB9_NORMAL); + scoped_guard(mutex_intr, &db9->mutex) { + if (!db9->used++) { + parport_claim(db9->pd); + parport_write_data(port, 0xff); + if (db9_modes[db9->mode].reverse) { + parport_data_reverse(port); + parport_write_control(port, DB9_NORMAL); + } + mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); } - mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); + + return 0; } - mutex_unlock(&db9->mutex); - return 0; + return -EINTR; } static void db9_close(struct input_dev *dev) @@ -530,14 +528,14 @@ static void db9_close(struct input_dev *dev) struct db9 *db9 = input_get_drvdata(dev); struct parport *port = db9->pd->port; - mutex_lock(&db9->mutex); + guard(mutex)(&db9->mutex); + if (!--db9->used) { - del_timer_sync(&db9->timer); + timer_delete_sync(&db9->timer); parport_write_control(port, 0x00); parport_data_forward(port); parport_release(db9->pd); } - mutex_unlock(&db9->mutex); } static void db9_attach(struct parport *pp) @@ -587,7 +585,7 @@ static void db9_attach(struct parport *pp) return; } - db9 = kzalloc(sizeof(struct db9), GFP_KERNEL); + db9 = kzalloc(sizeof(*db9), GFP_KERNEL); if (!db9) goto err_unreg_pardev; @@ -673,7 +671,6 @@ static struct parport_driver db9_parport_driver = { .name = "db9", .match_port = db9_attach, .detach = db9_detach, - .devmodel = true, }; static int __init db9_init(void) diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 41d5dac05448..9fc629ad58b8 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -765,33 +765,31 @@ static void gc_timer(struct timer_list *t) static int gc_open(struct input_dev *dev) { struct gc *gc = input_get_drvdata(dev); - int err; - err = mutex_lock_interruptible(&gc->mutex); - if (err) - return err; + scoped_guard(mutex_intr, &gc->mutex) { + if (!gc->used++) { + parport_claim(gc->pd); + parport_write_control(gc->pd->port, 0x04); + mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); + } - if (!gc->used++) { - parport_claim(gc->pd); - parport_write_control(gc->pd->port, 0x04); - mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); + return 0; } - mutex_unlock(&gc->mutex); - return 0; + return -EINTR; } static void gc_close(struct input_dev *dev) { struct gc *gc = input_get_drvdata(dev); - mutex_lock(&gc->mutex); + guard(mutex)(&gc->mutex); + if (!--gc->used) { - del_timer_sync(&gc->timer); + timer_delete_sync(&gc->timer); parport_write_control(gc->pd->port, 0x00); parport_release(gc->pd); } - mutex_unlock(&gc->mutex); } static int gc_setup_pad(struct gc *gc, int idx, int pad_type) @@ -950,7 +948,7 @@ static void gc_attach(struct parport *pp) return; } - gc = kzalloc(sizeof(struct gc), GFP_KERNEL); + gc = kzalloc(sizeof(*gc), GFP_KERNEL); if (!gc) { pr_err("Not enough memory\n"); goto err_unreg_pardev; @@ -1016,7 +1014,6 @@ static struct parport_driver gc_parport_driver = { .name = "gamecon", .match_port = gc_attach, .detach = gc_detach, - .devmodel = true, }; static int __init gc_init(void) diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index abefbd1484df..e7ff7bdb1a3a 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c @@ -222,7 +222,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) unsigned char data[GF2K_LENGTH]; int i, err; - gf2k = kzalloc(sizeof(struct gf2k), GFP_KERNEL); + gf2k = kzalloc(sizeof(*gf2k), GFP_KERNEL); input_dev = input_allocate_device(); if (!gf2k || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c index 0e86b269a90e..f339ce2b7a33 100644 --- a/drivers/input/joystick/grip.c +++ b/drivers/input/joystick/grip.c @@ -284,7 +284,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) int i, j, t; int err; - if (!(grip = kzalloc(sizeof(struct grip), GFP_KERNEL))) + grip = kzalloc(sizeof(*grip), GFP_KERNEL); + if (!grip) return -ENOMEM; grip->gameport = gameport; diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 056a89ac2bdf..5eadb5a3ca37 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c @@ -632,7 +632,8 @@ static int grip_connect(struct gameport *gameport, struct gameport_driver *drv) struct grip_mp *grip; int err; - if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL))) + grip = kzalloc(sizeof(*grip), GFP_KERNEL); + if (!grip) return -ENOMEM; grip->gameport = gameport; diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c index 205eb6f8b84d..1c5a76f72239 100644 --- a/drivers/input/joystick/guillemot.c +++ b/drivers/input/joystick/guillemot.c @@ -163,7 +163,7 @@ static int guillemot_connect(struct gameport *gameport, struct gameport_driver * int i, t; int err; - guillemot = kzalloc(sizeof(struct guillemot), GFP_KERNEL); + guillemot = kzalloc(sizeof(*guillemot), GFP_KERNEL); input_dev = input_allocate_device(); if (!guillemot || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c index 95c0348843e6..8c78cbe553c8 100644 --- a/drivers/input/joystick/iforce/iforce-ff.c +++ b/drivers/input/joystick/iforce/iforce-ff.c @@ -21,14 +21,13 @@ static int make_magnitude_modifier(struct iforce* iforce, unsigned char data[3]; if (!no_alloc) { - mutex_lock(&iforce->mem_mutex); - if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, - iforce->device_memory.start, iforce->device_memory.end, 2L, - NULL, NULL)) { - mutex_unlock(&iforce->mem_mutex); + guard(mutex)(&iforce->mem_mutex); + + if (allocate_resource(&iforce->device_memory, mod_chunk, 2, + iforce->device_memory.start, + iforce->device_memory.end, + 2L, NULL, NULL)) return -ENOSPC; - } - mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -54,14 +53,13 @@ static int make_period_modifier(struct iforce* iforce, period = TIME_SCALE(period); if (!no_alloc) { - mutex_lock(&iforce->mem_mutex); - if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, - iforce->device_memory.start, iforce->device_memory.end, 2L, - NULL, NULL)) { - mutex_unlock(&iforce->mem_mutex); + guard(mutex)(&iforce->mem_mutex); + + if (allocate_resource(&iforce->device_memory, mod_chunk, 0x0c, + iforce->device_memory.start, + iforce->device_memory.end, + 2L, NULL, NULL)) return -ENOSPC; - } - mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -94,14 +92,13 @@ static int make_envelope_modifier(struct iforce* iforce, fade_duration = TIME_SCALE(fade_duration); if (!no_alloc) { - mutex_lock(&iforce->mem_mutex); + guard(mutex)(&iforce->mem_mutex); + if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, - iforce->device_memory.start, iforce->device_memory.end, 2L, - NULL, NULL)) { - mutex_unlock(&iforce->mem_mutex); + iforce->device_memory.start, + iforce->device_memory.end, + 2L, NULL, NULL)) return -ENOSPC; - } - mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); @@ -131,14 +128,13 @@ static int make_condition_modifier(struct iforce* iforce, unsigned char data[10]; if (!no_alloc) { - mutex_lock(&iforce->mem_mutex); + guard(mutex)(&iforce->mem_mutex); + if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, - iforce->device_memory.start, iforce->device_memory.end, 2L, - NULL, NULL)) { - mutex_unlock(&iforce->mem_mutex); + iforce->device_memory.start, + iforce->device_memory.end, + 2L, NULL, NULL)) return -ENOSPC; - } - mutex_unlock(&iforce->mem_mutex); } data[0] = LO(mod_chunk->start); diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 84b87526b7ba..55e6321adab9 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -6,7 +6,7 @@ * USB/RS232 I-Force joysticks and wheels. */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "iforce.h" MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>, Johann Deneux <johann.deneux@gmail.com>"); diff --git a/drivers/input/joystick/iforce/iforce-packets.c b/drivers/input/joystick/iforce/iforce-packets.c index 763642c8cee9..74181d5123cd 100644 --- a/drivers/input/joystick/iforce/iforce-packets.c +++ b/drivers/input/joystick/iforce/iforce-packets.c @@ -6,7 +6,7 @@ * USB/RS232 I-Force joysticks and wheels. */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "iforce.h" static struct { @@ -31,49 +31,42 @@ int iforce_send_packet(struct iforce *iforce, u16 cmd, unsigned char* data) int c; int empty; int head, tail; - unsigned long flags; /* * Update head and tail of xmit buffer */ - spin_lock_irqsave(&iforce->xmit_lock, flags); - - head = iforce->xmit.head; - tail = iforce->xmit.tail; - - - if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) { - dev_warn(&iforce->dev->dev, - "not enough space in xmit buffer to send new packet\n"); - spin_unlock_irqrestore(&iforce->xmit_lock, flags); - return -1; - } + scoped_guard(spinlock_irqsave, &iforce->xmit_lock) { + head = iforce->xmit.head; + tail = iforce->xmit.tail; + + if (CIRC_SPACE(head, tail, XMIT_SIZE) < n + 2) { + dev_warn(&iforce->dev->dev, + "not enough space in xmit buffer to send new packet\n"); + return -1; + } - empty = head == tail; - XMIT_INC(iforce->xmit.head, n+2); + empty = head == tail; + XMIT_INC(iforce->xmit.head, n + 2); /* * Store packet in xmit buffer */ - iforce->xmit.buf[head] = HI(cmd); - XMIT_INC(head, 1); - iforce->xmit.buf[head] = LO(cmd); - XMIT_INC(head, 1); - - c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); - if (n < c) c=n; - - memcpy(&iforce->xmit.buf[head], - data, - c); - if (n != c) { - memcpy(&iforce->xmit.buf[0], - data + c, - n - c); + iforce->xmit.buf[head] = HI(cmd); + XMIT_INC(head, 1); + iforce->xmit.buf[head] = LO(cmd); + XMIT_INC(head, 1); + + c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); + if (n < c) + c = n; + + memcpy(&iforce->xmit.buf[head], data, c); + if (n != c) + memcpy(&iforce->xmit.buf[0], data + c, n - c); + + XMIT_INC(head, n); } - XMIT_INC(head, n); - spin_unlock_irqrestore(&iforce->xmit_lock, flags); /* * If necessary, start the transmission */ diff --git a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c index 2380546d7978..75b85c46dfa4 100644 --- a/drivers/input/joystick/iforce/iforce-serio.c +++ b/drivers/input/joystick/iforce/iforce-serio.c @@ -28,45 +28,39 @@ static void iforce_serio_xmit(struct iforce *iforce) iforce); unsigned char cs; int i; - unsigned long flags; if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) { set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags); return; } - spin_lock_irqsave(&iforce->xmit_lock, flags); + guard(spinlock_irqsave)(&iforce->xmit_lock); -again: - if (iforce->xmit.head == iforce->xmit.tail) { - iforce_clear_xmit_and_wake(iforce); - spin_unlock_irqrestore(&iforce->xmit_lock, flags); - return; - } + do { + if (iforce->xmit.head == iforce->xmit.tail) + break; - cs = 0x2b; + cs = 0x2b; - serio_write(iforce_serio->serio, 0x2b); + serio_write(iforce_serio->serio, 0x2b); - serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]); - cs ^= iforce->xmit.buf[iforce->xmit.tail]; - XMIT_INC(iforce->xmit.tail, 1); - - for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) { serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]); cs ^= iforce->xmit.buf[iforce->xmit.tail]; XMIT_INC(iforce->xmit.tail, 1); - } - serio_write(iforce_serio->serio, cs); + for (i = iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) { + serio_write(iforce_serio->serio, + iforce->xmit.buf[iforce->xmit.tail]); + cs ^= iforce->xmit.buf[iforce->xmit.tail]; + XMIT_INC(iforce->xmit.tail, 1); + } - if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags)) - goto again; + serio_write(iforce_serio->serio, cs); - iforce_clear_xmit_and_wake(iforce); + } while (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags)); - spin_unlock_irqrestore(&iforce->xmit_lock, flags); + iforce_clear_xmit_and_wake(iforce); } static int iforce_serio_get_id(struct iforce *iforce, u8 id, diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index cba92bd590a8..1f00f76b0174 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -25,13 +25,11 @@ static void __iforce_usb_xmit(struct iforce *iforce) struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, iforce); int n, c; - unsigned long flags; - spin_lock_irqsave(&iforce->xmit_lock, flags); + guard(spinlock_irqsave)(&iforce->xmit_lock); if (iforce->xmit.head == iforce->xmit.tail) { iforce_clear_xmit_and_wake(iforce); - spin_unlock_irqrestore(&iforce->xmit_lock, flags); return; } @@ -45,7 +43,8 @@ static void __iforce_usb_xmit(struct iforce *iforce) /* Copy rest of data then */ c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE); - if (n < c) c=n; + if (n < c) + c = n; memcpy(iforce_usb->out->transfer_buffer + 1, &iforce->xmit.buf[iforce->xmit.tail], @@ -53,11 +52,12 @@ static void __iforce_usb_xmit(struct iforce *iforce) if (n != c) { memcpy(iforce_usb->out->transfer_buffer + 1 + c, &iforce->xmit.buf[0], - n-c); + n - c); } XMIT_INC(iforce->xmit.tail, n); - if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) { + n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC); + if (n) { dev_warn(&iforce_usb->intf->dev, "usb_submit_urb failed %d\n", n); iforce_clear_xmit_and_wake(iforce); @@ -66,7 +66,6 @@ static void __iforce_usb_xmit(struct iforce *iforce) /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended. * As long as the urb completion handler is not called, the transmiting * is considered to be running */ - spin_unlock_irqrestore(&iforce->xmit_lock, flags); } static void iforce_usb_xmit(struct iforce *iforce) diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c index 03a9f0829f7e..262f022e5695 100644 --- a/drivers/input/joystick/interact.c +++ b/drivers/input/joystick/interact.c @@ -192,7 +192,7 @@ static int interact_connect(struct gameport *gameport, struct gameport_driver *d int i, t; int err; - interact = kzalloc(sizeof(struct interact), GFP_KERNEL); + interact = kzalloc(sizeof(*interact), GFP_KERNEL); input_dev = input_allocate_device(); if (!interact || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c index 017ef8c6170b..7622638e5bb8 100644 --- a/drivers/input/joystick/magellan.c +++ b/drivers/input/joystick/magellan.c @@ -48,7 +48,7 @@ struct magellan { static int magellan_crunch_nibbles(unsigned char *data, int count) { - static unsigned char nibbles[16] = "0AB3D56GH9:K<MN?"; + static const unsigned char nibbles[16] __nonstring = "0AB3D56GH9:K<MN?"; do { if (data[count] == nibbles[data[count] & 0xf]) @@ -132,7 +132,7 @@ static int magellan_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - magellan = kzalloc(sizeof(struct magellan), GFP_KERNEL); + magellan = kzalloc(sizeof(*magellan), GFP_KERNEL); input_dev = input_allocate_device(); if (!magellan || !input_dev) goto fail1; diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c index 3833ac47b2b8..8b54f9b18e7c 100644 --- a/drivers/input/joystick/maplecontrol.c +++ b/drivers/input/joystick/maplecontrol.c @@ -102,7 +102,7 @@ static int probe_maple_controller(struct device *dev) struct input_dev *idev; unsigned long data = be32_to_cpu(mdev->devinfo.function_data[0]); - pad = kzalloc(sizeof(struct dc_pad), GFP_KERNEL); + pad = kzalloc(sizeof(*pad), GFP_KERNEL); idev = input_allocate_device(); if (!pad || !idev) { error = -ENOMEM; diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c index 9dbca366613e..94d2f4e96fe6 100644 --- a/drivers/input/joystick/n64joy.c +++ b/drivers/input/joystick/n64joy.c @@ -191,35 +191,32 @@ static void n64joy_poll(struct timer_list *t) static int n64joy_open(struct input_dev *dev) { struct n64joy_priv *priv = input_get_drvdata(dev); - int err; - - err = mutex_lock_interruptible(&priv->n64joy_mutex); - if (err) - return err; - - if (!priv->n64joy_opened) { - /* - * We could use the vblank irq, but it's not important if - * the poll point slightly changes. - */ - timer_setup(&priv->timer, n64joy_poll, 0); - mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16)); - } - priv->n64joy_opened++; + scoped_guard(mutex_intr, &priv->n64joy_mutex) { + if (!priv->n64joy_opened) { + /* + * We could use the vblank irq, but it's not important + * if the poll point slightly changes. + */ + timer_setup(&priv->timer, n64joy_poll, 0); + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(16)); + } - mutex_unlock(&priv->n64joy_mutex); - return err; + priv->n64joy_opened++; + return 0; + } + + return -EINTR; } static void n64joy_close(struct input_dev *dev) { struct n64joy_priv *priv = input_get_drvdata(dev); - mutex_lock(&priv->n64joy_mutex); + guard(mutex)(&priv->n64joy_mutex); + if (!--priv->n64joy_opened) - del_timer_sync(&priv->timer); - mutex_unlock(&priv->n64joy_mutex); + timer_delete_sync(&priv->timer); } static const u64 __initconst scandata[] ____cacheline_aligned = { @@ -246,7 +243,7 @@ static int __init n64joy_probe(struct platform_device *pdev) int err = 0; u32 i, j, found = 0; - priv = kzalloc(sizeof(struct n64joy_priv), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; mutex_init(&priv->n64joy_mutex); diff --git a/drivers/input/joystick/qwiic-joystick.c b/drivers/input/joystick/qwiic-joystick.c index 7d88d76b14d6..6f989d00d3ec 100644 --- a/drivers/input/joystick/qwiic-joystick.c +++ b/drivers/input/joystick/qwiic-joystick.c @@ -126,8 +126,8 @@ MODULE_DEVICE_TABLE(of, of_qwiic_match); #endif /* CONFIG_OF */ static const struct i2c_device_id qwiic_id_table[] = { - { KBUILD_MODNAME, 0 }, - { }, + { KBUILD_MODNAME }, + { } }; MODULE_DEVICE_TABLE(i2c, qwiic_id_table); diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c index 7282301c3ae7..3a5873e5fcb3 100644 --- a/drivers/input/joystick/sidewinder.c +++ b/drivers/input/joystick/sidewinder.c @@ -14,6 +14,7 @@ #include <linux/input.h> #include <linux/gameport.h> #include <linux/jiffies.h> +#include <linux/string_choices.h> #define DRIVER_DESC "Microsoft SideWinder joystick family driver" @@ -577,7 +578,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) comment[0] = 0; - sw = kzalloc(sizeof(struct sw), GFP_KERNEL); + sw = kzalloc(sizeof(*sw), GFP_KERNEL); buf = kmalloc(SW_LENGTH, GFP_KERNEL); idbuf = kmalloc(SW_LENGTH, GFP_KERNEL); if (!sw || !buf || !idbuf) { @@ -677,7 +678,7 @@ static int sw_connect(struct gameport *gameport, struct gameport_driver *drv) case 48: /* Ambiguous */ if (j == 14) { /* ID length 14*3 -> FFP */ sw->type = SW_ID_FFP; - sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on"); + sprintf(comment, " [AC %s]", str_off_on(sw_get_bits(idbuf,38,1,3))); } else sw->type = SW_ID_PP; break; diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index fa8ec533cd69..4f2221001a95 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/input.h> #include <linux/serio.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define DRIVER_DESC "SpaceTec SpaceBall 2003/3003/4000 FLX driver" @@ -199,7 +199,7 @@ static int spaceball_connect(struct serio *serio, struct serio_driver *drv) if ((id = serio->id.id) > SPACEBALL_MAX_ID) return -ENODEV; - spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL); + spaceball = kmalloc(sizeof(*spaceball), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceball || !input_dev) goto fail1; diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index dbbc69f17c89..7250d74d62a1 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c @@ -147,7 +147,7 @@ static int spaceorb_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - spaceorb = kzalloc(sizeof(struct spaceorb), GFP_KERNEL); + spaceorb = kzalloc(sizeof(*spaceorb), GFP_KERNEL); input_dev = input_allocate_device(); if (!spaceorb || !input_dev) goto fail1; diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c index 530de468cb61..1b24ea21aa30 100644 --- a/drivers/input/joystick/stinger.c +++ b/drivers/input/joystick/stinger.c @@ -118,7 +118,7 @@ static int stinger_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL); + stinger = kmalloc(sizeof(*stinger), GFP_KERNEL); input_dev = input_allocate_device(); if (!stinger || !input_dev) goto fail1; diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index 93562ecc0ca1..514b1026e379 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c @@ -348,7 +348,8 @@ static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv) int i; int err; - if (!(tmdc = kzalloc(sizeof(struct tmdc), GFP_KERNEL))) + tmdc = kzalloc(sizeof(*tmdc), GFP_KERNEL); + if (!tmdc) return -ENOMEM; tmdc->gameport = gameport; diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dfb9c684651f..aa3e7d471b96 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c @@ -103,33 +103,31 @@ static void tgfx_timer(struct timer_list *t) static int tgfx_open(struct input_dev *dev) { struct tgfx *tgfx = input_get_drvdata(dev); - int err; - err = mutex_lock_interruptible(&tgfx->sem); - if (err) - return err; + scoped_guard(mutex_intr, &tgfx->sem) { + if (!tgfx->used++) { + parport_claim(tgfx->pd); + parport_write_control(tgfx->pd->port, 0x04); + mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); + } - if (!tgfx->used++) { - parport_claim(tgfx->pd); - parport_write_control(tgfx->pd->port, 0x04); - mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); + return 0; } - mutex_unlock(&tgfx->sem); - return 0; + return -EINTR; } static void tgfx_close(struct input_dev *dev) { struct tgfx *tgfx = input_get_drvdata(dev); - mutex_lock(&tgfx->sem); + guard(mutex)(&tgfx->sem); + if (!--tgfx->used) { - del_timer_sync(&tgfx->timer); + timer_delete_sync(&tgfx->timer); parport_write_control(tgfx->pd->port, 0x00); parport_release(tgfx->pd); } - mutex_unlock(&tgfx->sem); } @@ -172,7 +170,7 @@ static void tgfx_attach(struct parport *pp) return; } - tgfx = kzalloc(sizeof(struct tgfx), GFP_KERNEL); + tgfx = kzalloc(sizeof(*tgfx), GFP_KERNEL); if (!tgfx) { printk(KERN_ERR "turbografx.c: Not enough memory\n"); goto err_unreg_pardev; @@ -274,7 +272,6 @@ static struct parport_driver tgfx_parport_driver = { .name = "turbografx", .match_port = tgfx_attach, .detach = tgfx_detach, - .devmodel = true, }; static int __init tgfx_init(void) diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c index 9b6792ac27f1..ab99d76e5d8d 100644 --- a/drivers/input/joystick/twidjoy.c +++ b/drivers/input/joystick/twidjoy.c @@ -171,7 +171,7 @@ static int twidjoy_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - twidjoy = kzalloc(sizeof(struct twidjoy), GFP_KERNEL); + twidjoy = kzalloc(sizeof(*twidjoy), GFP_KERNEL); input_dev = input_allocate_device(); if (!twidjoy || !input_dev) goto fail1; diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 27d95d6cf56e..15370fb82317 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -232,8 +232,7 @@ static void walkera0701_attach(struct parport *pp) goto err_unregister_device; } - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; + hrtimer_setup(&w->timer, timer_handler, CLOCK_MONOTONIC, HRTIMER_MODE_REL); w->input_dev = input_allocate_device(); if (!w->input_dev) { @@ -293,7 +292,6 @@ static struct parport_driver walkera0701_parport_driver = { .name = "walkera0701", .match_port = walkera0701_attach, .detach = walkera0701_detach, - .devmodel = true, }; module_parport_driver(walkera0701_parport_driver); diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c index f66bddf145c2..ebeab441e9ec 100644 --- a/drivers/input/joystick/warrior.c +++ b/drivers/input/joystick/warrior.c @@ -124,7 +124,7 @@ static int warrior_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - warrior = kzalloc(sizeof(struct warrior), GFP_KERNEL); + warrior = kzalloc(sizeof(*warrior), GFP_KERNEL); input_dev = input_allocate_device(); if (!warrior || !input_dev) goto fail1; diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index f50848ed5575..1008858f78e2 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -77,12 +77,13 @@ * xbox d-pads should map to buttons, as is required for DDR pads * but we map them to axes when possible to simplify things */ -#define MAP_DPAD_TO_BUTTONS (1 << 0) -#define MAP_TRIGGERS_TO_BUTTONS (1 << 1) -#define MAP_STICKS_TO_NULL (1 << 2) -#define MAP_SELECT_BUTTON (1 << 3) -#define MAP_PADDLES (1 << 4) -#define MAP_PROFILE_BUTTON (1 << 5) +#define MAP_DPAD_TO_BUTTONS BIT(0) +#define MAP_TRIGGERS_TO_BUTTONS BIT(1) +#define MAP_STICKS_TO_NULL BIT(2) +#define MAP_SHARE_BUTTON BIT(3) +#define MAP_PADDLES BIT(4) +#define MAP_PROFILE_BUTTON BIT(5) +#define MAP_SHARE_OFFSET BIT(6) #define DANCEPAD_MAP_CONFIG (MAP_DPAD_TO_BUTTONS | \ MAP_TRIGGERS_TO_BUTTONS | MAP_STICKS_TO_NULL) @@ -135,13 +136,14 @@ static const struct xpad_device { { 0x03f0, 0x048D, "HyperX Clutch", 0, XTYPE_XBOX360 }, /* wireless */ { 0x03f0, 0x0495, "HyperX Clutch Gladiate", 0, XTYPE_XBOXONE }, { 0x03f0, 0x07A0, "HyperX Clutch Gladiate RGB", 0, XTYPE_XBOXONE }, - { 0x03f0, 0x08B6, "HyperX Clutch Gladiate", 0, XTYPE_XBOXONE }, /* v2 */ + { 0x03f0, 0x08B6, "HyperX Clutch Gladiate", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, /* v2 */ { 0x03f0, 0x09B4, "HyperX Clutch Tanto", 0, XTYPE_XBOXONE }, { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, { 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX }, { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, + { 0x044f, 0xd01e, "ThrustMaster, Inc. ESWAP X 2 ELDEN RING EDITION", 0, XTYPE_XBOXONE }, { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, @@ -150,6 +152,7 @@ static const struct xpad_device { { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, + { 0x045e, 0x02a9, "Xbox 360 Wireless Receiver (Unofficial)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", MAP_PADDLES, XTYPE_XBOXONE }, @@ -157,7 +160,7 @@ static const struct xpad_device { { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0b00, "Microsoft X-Box One Elite 2 pad", MAP_PADDLES, XTYPE_XBOXONE }, { 0x045e, 0x0b0a, "Microsoft X-Box Adaptive Controller", MAP_PROFILE_BUTTON, XTYPE_XBOXONE }, - { 0x045e, 0x0b12, "Microsoft Xbox Series S|X Controller", MAP_SELECT_BUTTON, XTYPE_XBOXONE }, + { 0x045e, 0x0b12, "Microsoft Xbox Series S|X Controller", MAP_SHARE_BUTTON | MAP_SHARE_OFFSET, XTYPE_XBOXONE }, { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 }, @@ -176,6 +179,7 @@ static const struct xpad_device { { 0x06a3, 0x0200, "Saitek Racing Wheel", 0, XTYPE_XBOX }, { 0x06a3, 0x0201, "Saitek Adrenalin", 0, XTYPE_XBOX }, { 0x06a3, 0xf51a, "Saitek P3600", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4503, "Mad Catz Racing Wheel", 0, XTYPE_XBOXONE }, { 0x0738, 0x4506, "Mad Catz 4506 Wireless Controller", 0, XTYPE_XBOX }, { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, { 0x0738, 0x4520, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, @@ -202,12 +206,14 @@ static const struct xpad_device { { 0x0738, 0x9871, "Mad Catz Portable Drum", 0, XTYPE_XBOX360 }, { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 }, { 0x0738, 0xb738, "Mad Catz MVC2TE Stick 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, + { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 }, { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 }, + { 0x0b05, 0x1a38, "ASUS ROG RAIKIRI", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, + { 0x0b05, 0x1abb, "ASUS ROG RAIKIRI PRO", 0, XTYPE_XBOXONE }, { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX }, { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, @@ -216,6 +222,7 @@ static const struct xpad_device { { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0db0, 0x1901, "Micro Star International Xbox360 Controller for Windows", 0, XTYPE_XBOX360 }, { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, { 0x0e4c, 0x1103, "Radica Gamester Reflex", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, @@ -234,6 +241,7 @@ static const struct xpad_device { { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0147, "PDP Marvel Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x015c, "PDP Xbox One Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0e6f, 0x015d, "PDP Mirror's Edge Official Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0161, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0162, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0163, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, @@ -272,12 +280,18 @@ static const struct xpad_device { { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0f0d, 0x00dc, "HORIPAD FPS for Nintendo Switch", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0151, "Hori Racing Wheel Overdrive for Xbox Series X", 0, XTYPE_XBOXONE }, + { 0x0f0d, 0x0152, "Hori Racing Wheel Overdrive for Xbox Series X", 0, XTYPE_XBOXONE }, + { 0x0f0d, 0x01b2, "HORI Taiko No Tatsujin Drum Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, + { 0x10f5, 0x7005, "Turtle Beach Recon Controller", 0, XTYPE_XBOXONE }, + { 0x10f5, 0x7008, "Turtle Beach Recon Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, + { 0x10f5, 0x7073, "Turtle Beach Stealth Ultra Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, { 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 }, { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, @@ -302,6 +316,7 @@ static const struct xpad_device { { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x17ef, 0x6182, "Lenovo Legion Controller for Windows", 0, XTYPE_XBOX360 }, { 0x1949, 0x041a, "Amazon Game Controller", 0, XTYPE_XBOX360 }, + { 0x1a86, 0xe310, "Legion Go S", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, @@ -338,9 +353,14 @@ static const struct xpad_device { { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, + { 0x1ee9, 0x1590, "ZOTAC Gaming Zone", 0, XTYPE_XBOX360 }, { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE }, { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE }, + { 0x20d6, 0x2064, "PowerA Wired Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 }, + { 0x20d6, 0x400b, "PowerA FUSION Pro 4 Wired Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, + { 0x20d6, 0x890b, "PowerA MOGA XP-Ultra Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, + { 0x2345, 0xe00b, "Machenike G5 Pro Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, @@ -360,6 +380,7 @@ static const struct xpad_device { { 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x581a, "ThrustMaster XB1 Classic Controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, @@ -368,18 +389,35 @@ static const struct xpad_device { { 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 }, { 0x294b, 0x3303, "Snakebyte GAMEPAD BASE X", 0, XTYPE_XBOXONE }, { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE }, + { 0x2993, 0x2001, "TECNO Pocket Go", 0, XTYPE_XBOX360 }, { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE }, - { 0x2dc8, 0x3106, "8BitDo Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x200f, "8BitDo Ultimate 3-mode Controller for Xbox", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, + { 0x2dc8, 0x3106, "8BitDo Ultimate Wireless / Pro 2 Wired Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x3109, "8BitDo Ultimate Wireless Bluetooth", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x310a, "8BitDo Ultimate 2C Wireless Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x310b, "8BitDo Ultimate 2 Wireless Controller", 0, XTYPE_XBOX360 }, + { 0x2dc8, 0x6001, "8BitDo SN30 Pro", 0, XTYPE_XBOX360 }, + { 0x2e24, 0x0423, "Hyperkin DuchesS Xbox One pad", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x2e24, 0x1688, "Hyperkin X91 X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x2e95, 0x0504, "SCUF Gaming Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE }, { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1220, "Wooting Two HE", 0, XTYPE_XBOX360 }, + { 0x31e3, 0x1230, "Wooting Two HE (ARM)", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 }, { 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0603, "Nacon Pro Compact controller for Xbox", 0, XTYPE_XBOXONE }, { 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0614, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, + { 0x3285, 0x0646, "Nacon Pro Compact", 0, XTYPE_XBOXONE }, + { 0x3285, 0x0662, "Nacon Revolution5 Pro", 0, XTYPE_XBOX360 }, + { 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE }, { 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 }, + { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, + { 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -478,6 +516,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x03f0), /* HP HyperX Xbox 360 controllers */ XPAD_XBOXONE_VENDOR(0x03f0), /* HP HyperX Xbox One controllers */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ + XPAD_XBOXONE_VENDOR(0x044f), /* Thrustmaster Xbox One controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech Xbox 360-style controllers */ @@ -487,7 +526,9 @@ static const struct usb_device_id xpad_table[] = { { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */ + XPAD_XBOXONE_VENDOR(0x0b05), /* ASUS controllers */ XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x0db0), /* Micro Star International X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */ XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori controllers */ @@ -507,23 +548,30 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x17ef), /* Lenovo */ XPAD_XBOX360_VENDOR(0x1949), /* Amazon controllers */ + XPAD_XBOX360_VENDOR(0x1a86), /* Nanjing Qinheng Microelectronics (WCH) */ XPAD_XBOX360_VENDOR(0x1bad), /* Harmonix Rock Band guitar and drums */ + XPAD_XBOX360_VENDOR(0x1ee9), /* ZOTAC Technology Limited */ XPAD_XBOX360_VENDOR(0x20d6), /* PowerA controllers */ XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA controllers */ + XPAD_XBOX360_VENDOR(0x2345), /* Machenike Controllers */ XPAD_XBOX360_VENDOR(0x24c6), /* PowerA controllers */ XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */ XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */ XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */ - XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */ + XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */ + XPAD_XBOX360_VENDOR(0x2993), /* TECNO Mobile */ XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */ - XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */ - XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */ - XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke Xbox One pad */ - XPAD_XBOX360_VENDOR(0x2f24), /* GameSir controllers */ + XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Controllers */ + XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Controllers */ + XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Controllers */ + XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ + XPAD_XBOXONE_VENDOR(0x2e95), /* SCUF Gaming Controller */ XPAD_XBOX360_VENDOR(0x31e3), /* Wooting Keyboards */ XPAD_XBOX360_VENDOR(0x3285), /* Nacon GC-100 */ + XPAD_XBOXONE_VENDOR(0x3285), /* Nacon Evol-X */ XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ + XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */ { } }; @@ -676,7 +724,11 @@ static const struct xboxone_init_packet xboxone_init_packets[] = { XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init), XBOXONE_INIT_PKT(0x045e, 0x0b00, extra_input_packet_init), XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_led_on), + XBOXONE_INIT_PKT(0x0f0d, 0x01b2, xboxone_pdp_led_on), + XBOXONE_INIT_PKT(0x20d6, 0xa01a, xboxone_pdp_led_on), XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_auth), + XBOXONE_INIT_PKT(0x0f0d, 0x01b2, xboxone_pdp_auth), + XBOXONE_INIT_PKT(0x20d6, 0xa01a, xboxone_pdp_auth), XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), @@ -987,7 +1039,7 @@ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned cha * The report format was gleaned from * https://github.com/kylelemons/xbox/blob/master/xbox.go */ -static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) +static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data, u32 len) { struct input_dev *dev = xpad->dev; bool do_sync = false; @@ -1028,8 +1080,12 @@ static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char /* menu/view buttons */ input_report_key(dev, BTN_START, data[4] & BIT(2)); input_report_key(dev, BTN_SELECT, data[4] & BIT(3)); - if (xpad->mapping & MAP_SELECT_BUTTON) - input_report_key(dev, KEY_RECORD, data[22] & BIT(0)); + if (xpad->mapping & MAP_SHARE_BUTTON) { + if (xpad->mapping & MAP_SHARE_OFFSET) + input_report_key(dev, KEY_RECORD, data[len - 26] & BIT(0)); + else + input_report_key(dev, KEY_RECORD, data[len - 18] & BIT(0)); + } /* buttons A,B,X,Y */ input_report_key(dev, BTN_A, data[4] & BIT(4)); @@ -1177,7 +1233,7 @@ static void xpad_irq_in(struct urb *urb) xpad360w_process_packet(xpad, 0, xpad->idata); break; case XTYPE_XBOXONE: - xpadone_process_packet(xpad, 0, xpad->idata); + xpadone_process_packet(xpad, 0, xpad->idata, urb->actual_length); break; default: xpad_process_packet(xpad, 0, xpad->idata); @@ -1284,9 +1340,8 @@ static void xpad_irq_out(struct urb *urb) struct device *dev = &xpad->intf->dev; int status = urb->status; int error; - unsigned long flags; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); switch (status) { case 0: @@ -1320,8 +1375,6 @@ static void xpad_irq_out(struct urb *urb) xpad->irq_out_active = false; } } - - spin_unlock_irqrestore(&xpad->odata_lock, flags); } static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad, @@ -1386,10 +1439,8 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) { struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_CMD_IDX]; - unsigned long flags; - int retval; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); packet->data[0] = 0x08; packet->data[1] = 0x00; @@ -1408,17 +1459,12 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) /* Reset the sequence so we send out presence first */ xpad->last_out_packet = -1; - retval = xpad_try_sending_next_out_packet(xpad); - - spin_unlock_irqrestore(&xpad->odata_lock, flags); - - return retval; + return xpad_try_sending_next_out_packet(xpad); } static int xpad_start_xbox_one(struct usb_xpad *xpad) { - unsigned long flags; - int retval; + int error; if (usb_ifnum_to_if(xpad->udev, GIP_WIRED_INTF_AUDIO)) { /* @@ -1427,15 +1473,15 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad) * Controller for Series X|S (0x20d6:0x200e) to report the * guide button. */ - retval = usb_set_interface(xpad->udev, - GIP_WIRED_INTF_AUDIO, 0); - if (retval) + error = usb_set_interface(xpad->udev, + GIP_WIRED_INTF_AUDIO, 0); + if (error) dev_warn(&xpad->dev->dev, "unable to disable audio interface: %d\n", - retval); + error); } - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); /* * Begin the init sequence by attempting to send a packet. @@ -1443,16 +1489,11 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad) * sending any packets from the output ring. */ xpad->init_seq = 0; - retval = xpad_try_sending_next_out_packet(xpad); - - spin_unlock_irqrestore(&xpad->odata_lock, flags); - - return retval; + return xpad_try_sending_next_out_packet(xpad); } static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num) { - unsigned long flags; struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_CMD_IDX]; static const u8 mode_report_ack[] = { @@ -1460,7 +1501,7 @@ static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num) 0x00, GIP_CMD_VIRTUAL_KEY, GIP_OPT_INTERNAL, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); packet->len = sizeof(mode_report_ack); memcpy(packet->data, mode_report_ack, packet->len); @@ -1470,8 +1511,6 @@ static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num) /* Reset the sequence so we send out the ack now */ xpad->last_out_packet = -1; xpad_try_sending_next_out_packet(xpad); - - spin_unlock_irqrestore(&xpad->odata_lock, flags); } #ifdef CONFIG_JOYSTICK_XPAD_FF @@ -1481,8 +1520,6 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_FF_IDX]; __u16 strong; __u16 weak; - int retval; - unsigned long flags; if (effect->type != FF_RUMBLE) return 0; @@ -1490,7 +1527,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect strong = effect->u.rumble.strong_magnitude; weak = effect->u.rumble.weak_magnitude; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); switch (xpad->xtype) { case XTYPE_XBOX: @@ -1556,15 +1593,10 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect dev_dbg(&xpad->dev->dev, "%s - rumble command sent to unsupported xpad type: %d\n", __func__, xpad->xtype); - retval = -EINVAL; - goto out; + return -EINVAL; } - retval = xpad_try_sending_next_out_packet(xpad); - -out: - spin_unlock_irqrestore(&xpad->odata_lock, flags); - return retval; + return xpad_try_sending_next_out_packet(xpad); } static int xpad_init_ff(struct usb_xpad *xpad) @@ -1617,11 +1649,10 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command) { struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_LED_IDX]; - unsigned long flags; command %= 16; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); switch (xpad->xtype) { case XTYPE_XBOX360: @@ -1651,8 +1682,6 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command) } xpad_try_sending_next_out_packet(xpad); - - spin_unlock_irqrestore(&xpad->odata_lock, flags); } /* @@ -1682,7 +1711,7 @@ static int xpad_led_probe(struct usb_xpad *xpad) if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX360W) return 0; - xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); + xpad->led = led = kzalloc(sizeof(*led), GFP_KERNEL); if (!led) return -ENOMEM; @@ -1777,11 +1806,10 @@ static void xpad_stop_input(struct usb_xpad *xpad) static void xpad360w_poweroff_controller(struct usb_xpad *xpad) { - unsigned long flags; struct xpad_output_packet *packet = &xpad->out_packets[XPAD_OUT_CMD_IDX]; - spin_lock_irqsave(&xpad->odata_lock, flags); + guard(spinlock_irqsave)(&xpad->odata_lock); packet->data[0] = 0x00; packet->data[1] = 0x00; @@ -1801,8 +1829,6 @@ static void xpad360w_poweroff_controller(struct usb_xpad *xpad) /* Reset the sequence so we send out poweroff now */ xpad->last_out_packet = -1; xpad_try_sending_next_out_packet(xpad); - - spin_unlock_irqrestore(&xpad->odata_lock, flags); } static int xpad360w_start_input(struct usb_xpad *xpad) @@ -1934,7 +1960,7 @@ static int xpad_init_input(struct usb_xpad *xpad) xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) input_set_capability(input_dev, EV_KEY, xpad360_btn[i]); - if (xpad->mapping & MAP_SELECT_BUTTON) + if (xpad->mapping & MAP_SHARE_BUTTON) input_set_capability(input_dev, EV_KEY, KEY_RECORD); } else { for (i = 0; xpad_btn[i] >= 0; i++) @@ -2018,7 +2044,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id break; } - xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); + xpad = kzalloc(sizeof(*xpad), GFP_KERNEL); if (!xpad) return -ENOMEM; @@ -2226,10 +2252,10 @@ static int xpad_suspend(struct usb_interface *intf, pm_message_t message) if (auto_poweroff && xpad->pad_present) xpad360w_poweroff_controller(xpad); } else { - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); + if (input_device_enabled(input)) xpad_stop_input(xpad); - mutex_unlock(&input->mutex); } xpad_stop_output(xpad); @@ -2241,26 +2267,25 @@ static int xpad_resume(struct usb_interface *intf) { struct usb_xpad *xpad = usb_get_intfdata(intf); struct input_dev *input = xpad->dev; - int retval = 0; - if (xpad->xtype == XTYPE_XBOX360W) { - retval = xpad360w_start_input(xpad); - } else { - mutex_lock(&input->mutex); - if (input_device_enabled(input)) { - retval = xpad_start_input(xpad); - } else if (xpad->xtype == XTYPE_XBOXONE) { - /* - * Even if there are no users, we'll send Xbox One pads - * the startup sequence so they don't sit there and - * blink until somebody opens the input device again. - */ - retval = xpad_start_xbox_one(xpad); - } - mutex_unlock(&input->mutex); + if (xpad->xtype == XTYPE_XBOX360W) + return xpad360w_start_input(xpad); + + guard(mutex)(&input->mutex); + + if (input_device_enabled(input)) + return xpad_start_input(xpad); + + if (xpad->xtype == XTYPE_XBOXONE) { + /* + * Even if there are no users, we'll send Xbox One pads + * the startup sequence so they don't sit there and + * blink until somebody opens the input device again. + */ + return xpad_start_xbox_one(xpad); } - return retval; + return 0; } static struct usb_driver xpad_driver = { diff --git a/drivers/input/joystick/zhenhua.c b/drivers/input/joystick/zhenhua.c index 3f2460e2b095..cc0e2a77ac5e 100644 --- a/drivers/input/joystick/zhenhua.c +++ b/drivers/input/joystick/zhenhua.c @@ -131,7 +131,7 @@ static int zhenhua_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - zhenhua = kzalloc(sizeof(struct zhenhua), GFP_KERNEL); + zhenhua = kzalloc(sizeof(*zhenhua), GFP_KERNEL); input_dev = input_allocate_device(); if (!zhenhua || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 1d0c5f4c0f99..721ab69e84ac 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -421,18 +421,6 @@ config KEYBOARD_MAX7359 To compile this driver as a module, choose M here: the module will be called max7359_keypad. -config KEYBOARD_MCS - tristate "MELFAS MCS Touchkey" - depends on I2C - help - Say Y here if you have the MELFAS MCS5000/5080 touchkey controller - chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mcs_touchkey. - config KEYBOARD_MPR121 tristate "Freescale MPR121 Touchkey" depends on I2C @@ -466,6 +454,17 @@ config KEYBOARD_IMX To compile this driver as a module, choose M here: the module will be called imx_keypad. +config KEYBOARD_IMX_BBM_SCMI + tristate "IMX BBM SCMI Key Driver" + depends on IMX_SCMI_BBM_EXT || COMPILE_TEST + default y if ARCH_MXC + help + This is the BBM key driver for NXP i.MX SoCs managed through + SCMI protocol. + + To compile this driver as a module, choose M here: the + module will be called scmi-imx-bbm-key. + config KEYBOARD_IMX_SC_KEY tristate "IMX SCU Key Driver" depends on IMX_SCU @@ -485,17 +484,6 @@ config KEYBOARD_NEWTON To compile this driver as a module, choose M here: the module will be called newtonkbd. -config KEYBOARD_NOMADIK - tristate "ST-Ericsson Nomadik SKE keyboard" - depends on (ARCH_NOMADIK || ARCH_U8500 || COMPILE_TEST) - select INPUT_MATRIXKMAP - help - Say Y here if you want to use a keypad provided on the SKE controller - used on the Ux500 and Nomadik platforms - - To compile this driver as a module, choose M here: the - module will be called nmk-ske-keypad. - config KEYBOARD_NSPIRE tristate "TI-NSPIRE built-in keyboard" depends on ARCH_NSPIRE && OF diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index aecef00c5d09..1e0721c30709 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_KEYBOARD_IPAQ_MICRO) += ipaq-micro-keys.o obj-$(CONFIG_KEYBOARD_IQS62X) += iqs62x-keys.o obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o obj-$(CONFIG_KEYBOARD_IMX_SC_KEY) += imx_sc_key.o +obj-$(CONFIG_KEYBOARD_IMX_BBM_SCMI) += imx-sm-bbm-key.o obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o @@ -41,12 +42,10 @@ obj-$(CONFIG_KEYBOARD_LPC32XX) += lpc32xx-keys.o obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o -obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o obj-$(CONFIG_KEYBOARD_MT6779) += mt6779-keypad.o obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o -obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c index bf72ab8df817..f1753207429d 100644 --- a/drivers/input/keyboard/adc-keys.c +++ b/drivers/input/keyboard/adc-keys.c @@ -66,7 +66,6 @@ static void adc_keys_poll(struct input_dev *input) static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st) { struct adc_keys_button *map; - struct fwnode_handle *child; int i; st->num_keys = device_get_child_node_count(dev); @@ -80,11 +79,10 @@ static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st) return -ENOMEM; i = 0; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { if (fwnode_property_read_u32(child, "press-threshold-microvolt", &map[i].voltage)) { dev_err(dev, "Key with invalid or missing voltage\n"); - fwnode_handle_put(child); return -EINVAL; } map[i].voltage /= 1000; @@ -92,7 +90,6 @@ static int adc_keys_load_keymap(struct device *dev, struct adc_keys_state *st) if (fwnode_property_read_u32(child, "linux,code", &map[i].keycode)) { dev_err(dev, "Key with invalid or missing linux,code\n"); - fwnode_handle_put(child); return -EINVAL; } diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index 10c248f0c1fc..980d739e45b8 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -181,7 +181,7 @@ static struct platform_driver adp5520_keys_driver = { .name = "adp5520-keys", }, .probe = adp5520_keys_probe, - .remove_new = adp5520_keys_remove, + .remove = adp5520_keys_remove, }; module_platform_driver(adp5520_keys_driver); diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 61e8e43e9c2b..dc734974ce06 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -188,6 +188,7 @@ struct adp5588_kpad { u32 cols; u32 unlock_keys[2]; int nkeys_unlock; + bool gpio_only; unsigned short keycode[ADP5588_KEYMAPSIZE]; unsigned char gpiomap[ADP5588_MAXGPIO]; struct gpio_chip gc; @@ -221,15 +222,13 @@ static int adp5588_gpio_get_value(struct gpio_chip *chip, unsigned int off) unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); int val; - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); if (kpad->dir[bank] & bit) val = kpad->dat_out[bank]; else val = adp5588_read(kpad->client, GPIO_DAT_STAT1 + bank); - mutex_unlock(&kpad->gpio_lock); - return !!(val & bit); } @@ -240,7 +239,7 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); if (val) kpad->dat_out[bank] |= bit; @@ -248,8 +247,6 @@ static void adp5588_gpio_set_value(struct gpio_chip *chip, kpad->dat_out[bank] &= ~bit; adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, kpad->dat_out[bank]); - - mutex_unlock(&kpad->gpio_lock); } static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off, @@ -259,7 +256,6 @@ static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off, unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); bool pull_disable; - int ret; switch (pinconf_to_config_param(config)) { case PIN_CONFIG_BIAS_PULL_UP: @@ -272,19 +268,15 @@ static int adp5588_gpio_set_config(struct gpio_chip *chip, unsigned int off, return -ENOTSUPP; } - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); if (pull_disable) kpad->pull_dis[bank] |= bit; else kpad->pull_dis[bank] &= bit; - ret = adp5588_write(kpad->client, GPIO_PULL1 + bank, - kpad->pull_dis[bank]); - - mutex_unlock(&kpad->gpio_lock); - - return ret; + return adp5588_write(kpad->client, GPIO_PULL1 + bank, + kpad->pull_dis[bank]); } static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned int off) @@ -292,16 +284,11 @@ static int adp5588_gpio_direction_input(struct gpio_chip *chip, unsigned int off struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); - int ret; - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); kpad->dir[bank] &= ~bit; - ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); - - mutex_unlock(&kpad->gpio_lock); - - return ret; + return adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); } static int adp5588_gpio_direction_output(struct gpio_chip *chip, @@ -310,9 +297,9 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, struct adp5588_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = ADP5588_BANK(kpad->gpiomap[off]); unsigned int bit = ADP5588_BIT(kpad->gpiomap[off]); - int ret; + int error; - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); kpad->dir[bank] |= bit; @@ -321,17 +308,16 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, else kpad->dat_out[bank] &= ~bit; - ret = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, - kpad->dat_out[bank]); - if (ret) - goto out_unlock; - - ret = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); + error = adp5588_write(kpad->client, GPIO_DAT_OUT1 + bank, + kpad->dat_out[bank]); + if (error) + return error; -out_unlock: - mutex_unlock(&kpad->gpio_lock); + error = adp5588_write(kpad->client, GPIO_DIR1 + bank, kpad->dir[bank]); + if (error) + return error; - return ret; + return 0; } static int adp5588_build_gpiomap(struct adp5588_kpad *kpad) @@ -446,10 +432,17 @@ static int adp5588_gpio_add(struct adp5588_kpad *kpad) kpad->gc.label = kpad->client->name; kpad->gc.owner = THIS_MODULE; - girq = &kpad->gc.irq; - gpio_irq_chip_set_chip(girq, &adp5588_irq_chip); - girq->handler = handle_bad_irq; - girq->threaded = true; + if (device_property_present(dev, "interrupt-controller")) { + if (!kpad->client->irq) { + dev_err(dev, "Unable to serve as interrupt controller without interrupt"); + return -EINVAL; + } + + girq = &kpad->gc.irq; + gpio_irq_chip_set_chip(girq, &adp5588_irq_chip); + girq->handler = handle_bad_irq; + girq->threaded = true; + } mutex_init(&kpad->gpio_lock); @@ -627,7 +620,7 @@ static int adp5588_setup(struct adp5588_kpad *kpad) for (i = 0; i < KEYP_MAX_EVENT; i++) { ret = adp5588_read(client, KEY_EVENTA); - if (ret) + if (ret < 0) return ret; } @@ -647,6 +640,18 @@ static int adp5588_fw_parse(struct adp5588_kpad *kpad) struct i2c_client *client = kpad->client; int ret, i; + /* + * Check if the device is to be operated purely in GPIO mode. To do + * so, check that no keypad rows or columns have been specified, + * since all GPINS should be configured as GPIO. + */ + if (!device_property_present(&client->dev, "keypad,num-rows") && + !device_property_present(&client->dev, "keypad,num-columns")) { + /* If purely GPIO, skip keypad setup */ + kpad->gpio_only = true; + return 0; + } + ret = matrix_keypad_parse_properties(&client->dev, &kpad->rows, &kpad->cols); if (ret) @@ -790,17 +795,19 @@ static int adp5588_probe(struct i2c_client *client) if (error) return error; - error = devm_request_threaded_irq(&client->dev, client->irq, - adp5588_hard_irq, adp5588_thread_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, kpad); - if (error) { - dev_err(&client->dev, "failed to request irq %d: %d\n", - client->irq, error); - return error; + if (client->irq) { + error = devm_request_threaded_irq(&client->dev, client->irq, + adp5588_hard_irq, adp5588_thread_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + client->dev.driver->name, kpad); + if (error) { + dev_err(&client->dev, "failed to request irq %d: %d\n", + client->irq, error); + return error; + } } - dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); + dev_info(&client->dev, "Rev.%d controller\n", revid); return 0; } @@ -815,7 +822,8 @@ static int adp5588_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - disable_irq(client->irq); + if (client->irq) + disable_irq(client->irq); return 0; } @@ -824,7 +832,8 @@ static int adp5588_resume(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); - enable_irq(client->irq); + if (client->irq) + enable_irq(client->irq); return 0; } @@ -832,8 +841,8 @@ static int adp5588_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(adp5588_dev_pm_ops, adp5588_suspend, adp5588_resume); static const struct i2c_device_id adp5588_id[] = { - { "adp5588-keys", 0 }, - { "adp5587-keys", 0 }, + { "adp5588-keys" }, + { "adp5587-keys" }, { } }; MODULE_DEVICE_TABLE(i2c, adp5588_id); diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 8996e00cd63a..81d0876ee358 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -391,10 +391,17 @@ static int adp5589_gpio_get_value(struct gpio_chip *chip, unsigned off) struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); + int val; - return !!(adp5589_read(kpad->client, - kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) & - bit); + mutex_lock(&kpad->gpio_lock); + if (kpad->dir[bank] & bit) + val = kpad->dat_out[bank]; + else + val = adp5589_read(kpad->client, + kpad->var->reg(ADP5589_GPI_STATUS_A) + bank); + mutex_unlock(&kpad->gpio_lock); + + return !!(val & bit); } static void adp5589_gpio_set_value(struct gpio_chip *chip, @@ -404,7 +411,7 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); if (val) kpad->dat_out[bank] |= bit; @@ -413,8 +420,6 @@ static void adp5589_gpio_set_value(struct gpio_chip *chip, adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + bank, kpad->dat_out[bank]); - - mutex_unlock(&kpad->gpio_lock); } static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) @@ -422,18 +427,13 @@ static int adp5589_gpio_direction_input(struct gpio_chip *chip, unsigned off) struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - int ret; - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); kpad->dir[bank] &= ~bit; - ret = adp5589_write(kpad->client, - kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, - kpad->dir[bank]); - - mutex_unlock(&kpad->gpio_lock); - - return ret; + return adp5589_write(kpad->client, + kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, + kpad->dir[bank]); } static int adp5589_gpio_direction_output(struct gpio_chip *chip, @@ -442,9 +442,9 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, struct adp5589_kpad *kpad = gpiochip_get_data(chip); unsigned int bank = kpad->var->bank(kpad->gpiomap[off]); unsigned int bit = kpad->var->bit(kpad->gpiomap[off]); - int ret; + int error; - mutex_lock(&kpad->gpio_lock); + guard(mutex)(&kpad->gpio_lock); kpad->dir[bank] |= bit; @@ -453,15 +453,19 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, else kpad->dat_out[bank] &= ~bit; - ret = adp5589_write(kpad->client, kpad->var->reg(ADP5589_GPO_DATA_OUT_A) - + bank, kpad->dat_out[bank]); - ret |= adp5589_write(kpad->client, - kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, - kpad->dir[bank]); + error = adp5589_write(kpad->client, + kpad->var->reg(ADP5589_GPO_DATA_OUT_A) + bank, + kpad->dat_out[bank]); + if (error) + return error; - mutex_unlock(&kpad->gpio_lock); + error = adp5589_write(kpad->client, + kpad->var->reg(ADP5589_GPIO_DIRECTION_A) + bank, + kpad->dir[bank]); + if (error) + return error; - return ret; + return 0; } static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, @@ -936,10 +940,9 @@ static int adp5589_keypad_add(struct adp5589_kpad *kpad, unsigned int revid) static void adp5589_clear_config(void *data) { - struct i2c_client *client = data; - struct adp5589_kpad *kpad = i2c_get_clientdata(client); + struct adp5589_kpad *kpad = data; - adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); + adp5589_write(kpad->client, kpad->var->reg(ADP5589_GENERAL_CFG), 0); } static int adp5589_probe(struct i2c_client *client) @@ -983,7 +986,7 @@ static int adp5589_probe(struct i2c_client *client) } error = devm_add_action_or_reset(&client->dev, adp5589_clear_config, - client); + kpad); if (error) return error; @@ -1010,8 +1013,6 @@ static int adp5589_probe(struct i2c_client *client) if (error) return error; - i2c_set_clientdata(client, kpad); - dev_info(&client->dev, "Rev.%d keypad, irq %d\n", revid, client->irq); return 0; } diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c index cf25177b4830..b5ff71cd5a70 100644 --- a/drivers/input/keyboard/applespi.c +++ b/drivers/input/keyboard/applespi.c @@ -57,7 +57,7 @@ #include <linux/workqueue.h> #include <asm/barrier.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define CREATE_TRACE_POINTS #include "applespi.h" @@ -717,9 +717,7 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi); static void applespi_msg_complete(struct applespi_data *applespi, bool is_write_msg, bool is_read_compl) { - unsigned long flags; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); if (is_read_compl) applespi->read_active = false; @@ -733,8 +731,6 @@ static void applespi_msg_complete(struct applespi_data *applespi, applespi->cmd_msg_queued = 0; applespi_send_cmd_msg(applespi); } - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } static void applespi_async_write_complete(void *context) @@ -888,33 +884,22 @@ static int applespi_send_cmd_msg(struct applespi_data *applespi) static void applespi_init(struct applespi_data *applespi, bool is_resume) { - unsigned long flags; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); if (is_resume) applespi->want_mt_init_cmd = true; else applespi->want_tp_info_cmd = true; applespi_send_cmd_msg(applespi); - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } static int applespi_set_capsl_led(struct applespi_data *applespi, bool capslock_on) { - unsigned long flags; - int sts; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); applespi->want_cl_led_on = capslock_on; - sts = applespi_send_cmd_msg(applespi); - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); - - return sts; + return applespi_send_cmd_msg(applespi); } static void applespi_set_bl_level(struct led_classdev *led_cdev, @@ -922,9 +907,8 @@ static void applespi_set_bl_level(struct led_classdev *led_cdev, { struct applespi_data *applespi = container_of(led_cdev, struct applespi_data, backlight_info); - unsigned long flags; - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); if (value == 0) { applespi->want_bl_level = value; @@ -940,8 +924,6 @@ static void applespi_set_bl_level(struct led_classdev *led_cdev, } applespi_send_cmd_msg(applespi); - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } static int applespi_event(struct input_dev *dev, unsigned int type, @@ -1007,7 +989,6 @@ static const struct file_operations applespi_tp_dim_fops = { .owner = THIS_MODULE, .open = applespi_tp_dim_open, .read = applespi_tp_dim_read, - .llseek = no_llseek, }; static void report_finger_data(struct input_dev *input, int slot, @@ -1428,9 +1409,7 @@ static void applespi_got_data(struct applespi_data *applespi) /* process packet header */ if (!applespi_verify_crc(applespi, applespi->rx_buffer, APPLESPI_PACKET_SIZE)) { - unsigned long flags; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); if (applespi->drain) { applespi->read_active = false; @@ -1439,8 +1418,6 @@ static void applespi_got_data(struct applespi_data *applespi) wake_up_all(&applespi->drain_complete); } - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); - return; } @@ -1573,11 +1550,10 @@ static u32 applespi_notify(acpi_handle gpe_device, u32 gpe, void *context) { struct applespi_data *applespi = context; int sts; - unsigned long flags; trace_applespi_irq_received(ET_RD_IRQ, PT_READ); - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); if (!applespi->suspended) { sts = applespi_async(applespi, &applespi->rd_m, @@ -1590,8 +1566,6 @@ static u32 applespi_notify(acpi_handle gpe_device, u32 gpe, void *context) applespi->read_active = true; } - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); - return ACPI_INTERRUPT_HANDLED; } @@ -1819,29 +1793,21 @@ static int applespi_probe(struct spi_device *spi) static void applespi_drain_writes(struct applespi_data *applespi) { - unsigned long flags; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); applespi->drain = true; wait_event_lock_irq(applespi->drain_complete, !applespi->write_active, applespi->cmd_msg_lock); - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } static void applespi_drain_reads(struct applespi_data *applespi) { - unsigned long flags; - - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); + guard(spinlock_irqsave)(&applespi->cmd_msg_lock); wait_event_lock_irq(applespi->drain_complete, !applespi->read_active, applespi->cmd_msg_lock); applespi->suspended = true; - - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); } static void applespi_remove(struct spi_device *spi) @@ -1908,21 +1874,18 @@ static int applespi_resume(struct device *dev) struct spi_device *spi = to_spi_device(dev); struct applespi_data *applespi = spi_get_drvdata(spi); acpi_status acpi_sts; - unsigned long flags; /* ensure our flags and state reflect a newly resumed device */ - spin_lock_irqsave(&applespi->cmd_msg_lock, flags); - - applespi->drain = false; - applespi->have_cl_led_on = false; - applespi->have_bl_level = 0; - applespi->cmd_msg_queued = 0; - applespi->read_active = false; - applespi->write_active = false; - - applespi->suspended = false; + scoped_guard(spinlock_irqsave, &applespi->cmd_msg_lock) { + applespi->drain = false; + applespi->have_cl_led_on = false; + applespi->have_bl_level = 0; + applespi->cmd_msg_queued = 0; + applespi->read_active = false; + applespi->write_active = false; - spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags); + applespi->suspended = false; + } /* switch on the SPI interface */ applespi_enable_spi(applespi); diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 7f67f9f2946b..adf0f311996c 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -89,7 +89,7 @@ static const unsigned short atkbd_set2_keycode[ATKBD_KEYMAP_SIZE] = { 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183, 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185, 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0, - 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85, + 0, 89, 40, 0, 26, 13, 0,193, 58, 54, 28, 27, 0, 43, 0, 85, 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0, 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99, @@ -639,7 +639,7 @@ static void atkbd_event_work(struct work_struct *work) { struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); - mutex_lock(&atkbd->mutex); + guard(mutex)(&atkbd->mutex); if (!atkbd->enabled) { /* @@ -657,8 +657,6 @@ static void atkbd_event_work(struct work_struct *work) if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) atkbd_set_repeat_rate(atkbd); } - - mutex_unlock(&atkbd->mutex); } /* @@ -715,9 +713,9 @@ static int atkbd_event(struct input_dev *dev, static inline void atkbd_enable(struct atkbd *atkbd) { - serio_pause_rx(atkbd->ps2dev.serio); + guard(serio_pause_rx)(atkbd->ps2dev.serio); + atkbd->enabled = true; - serio_continue_rx(atkbd->ps2dev.serio); } /* @@ -727,9 +725,9 @@ static inline void atkbd_enable(struct atkbd *atkbd) static inline void atkbd_disable(struct atkbd *atkbd) { - serio_pause_rx(atkbd->ps2dev.serio); + guard(serio_pause_rx)(atkbd->ps2dev.serio); + atkbd->enabled = false; - serio_continue_rx(atkbd->ps2dev.serio); } static int atkbd_activate(struct atkbd *atkbd) @@ -1279,7 +1277,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *dev; int err = -ENOMEM; - atkbd = kzalloc(sizeof(struct atkbd), GFP_KERNEL); + atkbd = kzalloc(sizeof(*atkbd), GFP_KERNEL); dev = input_allocate_device(); if (!atkbd || !dev) goto fail1; @@ -1361,7 +1359,7 @@ static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = atkbd_from_serio(serio); struct serio_driver *drv = serio->drv; - int retval = -1; + int error; if (!atkbd || !drv) { dev_dbg(&serio->dev, @@ -1369,16 +1367,17 @@ static int atkbd_reconnect(struct serio *serio) return -1; } - mutex_lock(&atkbd->mutex); + guard(mutex)(&atkbd->mutex); atkbd_disable(atkbd); if (atkbd->write) { - if (atkbd_probe(atkbd)) - goto out; + error = atkbd_probe(atkbd); + if (error) + return error; if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) - goto out; + return -EIO; /* * Restore LED state and repeat rate. While input core @@ -1404,11 +1403,7 @@ static int atkbd_reconnect(struct serio *serio) if (atkbd->write) atkbd_activate(atkbd); - retval = 0; - - out: - mutex_unlock(&atkbd->mutex); - return retval; + return 0; } static const struct serio_device_id atkbd_serio_ids[] = { @@ -1465,17 +1460,15 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t struct atkbd *atkbd = atkbd_from_serio(serio); int retval; - retval = mutex_lock_interruptible(&atkbd->mutex); - if (retval) - return retval; + scoped_guard(mutex_intr, &atkbd->mutex) { + atkbd_disable(atkbd); + retval = handler(atkbd, buf, count); + atkbd_enable(atkbd); - atkbd_disable(atkbd); - retval = handler(atkbd, buf, count); - atkbd_enable(atkbd); - - mutex_unlock(&atkbd->mutex); + return retval; + } - return retval; + return -EINTR; } static ssize_t atkbd_show_extra(struct atkbd *atkbd, char *buf) diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c index 52fba9ee7c1d..0c17cbaa3d27 100644 --- a/drivers/input/keyboard/cap11xx.c +++ b/drivers/input/keyboard/cap11xx.c @@ -86,7 +86,6 @@ struct cap11xx_priv { struct device *dev; struct input_dev *idev; const struct cap11xx_hw_model *model; - u8 id; struct cap11xx_led *leds; int num_leds; @@ -104,27 +103,10 @@ struct cap11xx_hw_model { u8 product_id; unsigned int num_channels; unsigned int num_leds; - bool no_gain; -}; - -enum { - CAP1106, - CAP1126, - CAP1188, - CAP1203, - CAP1206, - CAP1293, - CAP1298 -}; - -static const struct cap11xx_hw_model cap11xx_devices[] = { - [CAP1106] = { .product_id = 0x55, .num_channels = 6, .num_leds = 0, .no_gain = false }, - [CAP1126] = { .product_id = 0x53, .num_channels = 6, .num_leds = 2, .no_gain = false }, - [CAP1188] = { .product_id = 0x50, .num_channels = 8, .num_leds = 8, .no_gain = false }, - [CAP1203] = { .product_id = 0x6d, .num_channels = 3, .num_leds = 0, .no_gain = true }, - [CAP1206] = { .product_id = 0x67, .num_channels = 6, .num_leds = 0, .no_gain = true }, - [CAP1293] = { .product_id = 0x6f, .num_channels = 3, .num_leds = 0, .no_gain = false }, - [CAP1298] = { .product_id = 0x71, .num_channels = 8, .num_leds = 0, .no_gain = false }, + bool has_gain; + bool has_irq_config; + bool has_sensitivity_control; + bool has_signal_guard; }; static const struct reg_default cap11xx_reg_defaults[] = { @@ -224,7 +206,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (!of_property_read_u32(node, "microchip,sensor-gain", &u32_val)) { - if (priv->model->no_gain) { + if (!priv->model->has_gain) { dev_warn(dev, "This model doesn't support 'sensor-gain'\n"); } else if (is_power_of_2(u32_val) && u32_val <= 8) { @@ -243,9 +225,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (of_property_read_bool(node, "microchip,irq-active-high")) { - if (priv->id == CAP1106 || - priv->id == CAP1126 || - priv->id == CAP1188) { + if (priv->model->has_irq_config) { error = regmap_update_bits(priv->regmap, CAP11XX_REG_CONFIG2, CAP11XX_REG_CONFIG2_ALT_POL, @@ -296,7 +276,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) if (!of_property_read_u32_array(node, "microchip,calib-sensitivity", priv->calib_sensitivities, priv->model->num_channels)) { - if (priv->id == CAP1293 || priv->id == CAP1298) { + if (priv->model->has_sensitivity_control) { for (i = 0; i < priv->model->num_channels; i++) { if (!is_power_of_2(priv->calib_sensitivities[i]) || priv->calib_sensitivities[i] > 4) { @@ -311,7 +291,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) if (error) return error; - if (priv->id == CAP1298) { + if (priv->model->num_channels > 4) { error = cap11xx_write_calib_sens_config_2(priv); if (error) return error; @@ -333,7 +313,7 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv) } if (priv->signal_guard_inputs_mask) { - if (priv->id == CAP1293 || priv->id == CAP1298) { + if (priv->model->has_signal_guard) { error = regmap_write(priv->regmap, CAP11XX_REG_SIGNAL_GUARD_ENABLE, priv->signal_guard_inputs_mask); @@ -436,7 +416,7 @@ static int cap11xx_led_set(struct led_classdev *cdev, static int cap11xx_init_leds(struct device *dev, struct cap11xx_priv *priv, int num_leds) { - struct device_node *node = dev->of_node, *child; + struct device_node *node = dev->of_node; struct cap11xx_led *led; int cnt = of_get_child_count(node); int error; @@ -465,7 +445,7 @@ static int cap11xx_init_leds(struct device *dev, if (error) return error; - for_each_child_of_node(node, child) { + for_each_child_of_node_scoped(node, child) { u32 reg; led->cdev.name = @@ -478,19 +458,15 @@ static int cap11xx_init_leds(struct device *dev, led->cdev.brightness = LED_OFF; error = of_property_read_u32(child, "reg", ®); - if (error != 0 || reg >= num_leds) { - of_node_put(child); + if (error != 0 || reg >= num_leds) return -EINVAL; - } led->reg = reg; led->priv = priv; error = devm_led_classdev_register(dev, &led->cdev); - if (error) { - of_node_put(child); + if (error) return error; - } priv->num_leds++; led++; @@ -508,20 +484,16 @@ static int cap11xx_init_leds(struct device *dev, static int cap11xx_i2c_probe(struct i2c_client *i2c_client) { - const struct i2c_device_id *id = i2c_client_get_device_id(i2c_client); + const struct i2c_device_id *id; + const struct cap11xx_hw_model *cap; struct device *dev = &i2c_client->dev; struct cap11xx_priv *priv; - const struct cap11xx_hw_model *cap; int i, error; unsigned int val, rev; - if (id->driver_data >= ARRAY_SIZE(cap11xx_devices)) { - dev_err(dev, "Invalid device ID %lu\n", id->driver_data); - return -EINVAL; - } - - cap = &cap11xx_devices[id->driver_data]; - if (!cap || !cap->num_channels) { + id = i2c_client_get_device_id(i2c_client); + cap = i2c_get_match_data(i2c_client); + if (!id || !cap || !cap->num_channels) { dev_err(dev, "Invalid device configuration\n"); return -EINVAL; } @@ -566,7 +538,6 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client) id->name, rev); priv->model = cap; - priv->id = id->driver_data; dev_info(dev, "CAP11XX device detected, model %s, revision 0x%02x\n", id->name, rev); @@ -627,27 +598,67 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client) return 0; } +static const struct cap11xx_hw_model cap1106_model = { + .product_id = 0x55, .num_channels = 6, .num_leds = 0, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1126_model = { + .product_id = 0x53, .num_channels = 6, .num_leds = 2, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1188_model = { + .product_id = 0x50, .num_channels = 8, .num_leds = 8, + .has_gain = true, + .has_irq_config = true, +}; + +static const struct cap11xx_hw_model cap1203_model = { + .product_id = 0x6d, .num_channels = 3, .num_leds = 0, +}; + +static const struct cap11xx_hw_model cap1206_model = { + .product_id = 0x67, .num_channels = 6, .num_leds = 0, +}; + +static const struct cap11xx_hw_model cap1293_model = { + .product_id = 0x6f, .num_channels = 3, .num_leds = 0, + .has_gain = true, + .has_sensitivity_control = true, + .has_signal_guard = true, +}; + +static const struct cap11xx_hw_model cap1298_model = { + .product_id = 0x71, .num_channels = 8, .num_leds = 0, + .has_gain = true, + .has_sensitivity_control = true, + .has_signal_guard = true, +}; + static const struct of_device_id cap11xx_dt_ids[] = { - { .compatible = "microchip,cap1106", }, - { .compatible = "microchip,cap1126", }, - { .compatible = "microchip,cap1188", }, - { .compatible = "microchip,cap1203", }, - { .compatible = "microchip,cap1206", }, - { .compatible = "microchip,cap1293", }, - { .compatible = "microchip,cap1298", }, - {} + { .compatible = "microchip,cap1106", .data = &cap1106_model }, + { .compatible = "microchip,cap1126", .data = &cap1126_model }, + { .compatible = "microchip,cap1188", .data = &cap1188_model }, + { .compatible = "microchip,cap1203", .data = &cap1203_model }, + { .compatible = "microchip,cap1206", .data = &cap1206_model }, + { .compatible = "microchip,cap1293", .data = &cap1293_model }, + { .compatible = "microchip,cap1298", .data = &cap1298_model }, + { } }; MODULE_DEVICE_TABLE(of, cap11xx_dt_ids); static const struct i2c_device_id cap11xx_i2c_ids[] = { - { "cap1106", CAP1106 }, - { "cap1126", CAP1126 }, - { "cap1188", CAP1188 }, - { "cap1203", CAP1203 }, - { "cap1206", CAP1206 }, - { "cap1293", CAP1293 }, - { "cap1298", CAP1298 }, - {} + { "cap1106", (kernel_ulong_t)&cap1106_model }, + { "cap1126", (kernel_ulong_t)&cap1126_model }, + { "cap1188", (kernel_ulong_t)&cap1188_model }, + { "cap1203", (kernel_ulong_t)&cap1203_model }, + { "cap1206", (kernel_ulong_t)&cap1206_model }, + { "cap1293", (kernel_ulong_t)&cap1293_model }, + { "cap1298", (kernel_ulong_t)&cap1298_model }, + { } }; MODULE_DEVICE_TABLE(i2c, cap11xx_i2c_ids); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 30678a34cf64..c1e53d87c8a7 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -27,7 +27,7 @@ #include <linux/platform_data/cros_ec_commands.h> #include <linux/platform_data/cros_ec_proto.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /** * struct cros_ec_keyb - Structure representing EC keyboard device @@ -35,7 +35,6 @@ * @rows: Number of rows in the keypad * @cols: Number of columns in the keypad * @row_shift: log2 or number of rows, rounded up - * @keymap_data: Matrix keymap data used to convert to keyscan values * @ghost_filter: true to enable the matrix key-ghosting filter * @valid_keys: bitmap of existing keys for each matrix column * @old_kb_state: bitmap of keys pressed last scan @@ -50,7 +49,6 @@ struct cros_ec_keyb { unsigned int rows; unsigned int cols; int row_shift; - const struct matrix_keymap_data *keymap_data; bool ghost_filter; uint8_t *valid_keys; uint8_t *old_kb_state; @@ -772,7 +770,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume); static struct platform_driver cros_ec_keyb_driver = { .probe = cros_ec_keyb_probe, - .remove_new = cros_ec_keyb_remove, + .remove = cros_ec_keyb_remove, .driver = { .name = "cros-ec-keyb", .dev_groups = cros_ec_keyb_groups, diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c index 2bacd9d80ecf..335b72efc5aa 100644 --- a/drivers/input/keyboard/cypress-sf.c +++ b/drivers/input/keyboard/cypress-sf.c @@ -208,8 +208,8 @@ static int cypress_sf_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops, cypress_sf_suspend, cypress_sf_resume); -static struct i2c_device_id cypress_sf_id_table[] = { - { CYPRESS_SF_DEV_NAME, 0 }, +static const struct i2c_device_id cypress_sf_id_table[] = { + { CYPRESS_SF_DEV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, cypress_sf_id_table); diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c index 6c065eff5a5a..4184dd2eaeeb 100644 --- a/drivers/input/keyboard/dlink-dir685-touchkeys.c +++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c @@ -14,6 +14,7 @@ #include <linux/delay.h> #include <linux/input.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/bitops.h> struct dir685_touchkeys { @@ -48,7 +49,7 @@ static irqreturn_t dir685_tk_irq_thread(int irq, void *data) changed = tk->cur_key ^ key; for_each_set_bit(i, &changed, num_bits) { dev_dbg(tk->dev, "key %d is %s\n", i, - test_bit(i, &key) ? "down" : "up"); + str_down_up(test_bit(i, &key))); input_report_key(tk->input, tk->codes[i], test_bit(i, &key)); } @@ -127,7 +128,7 @@ static int dir685_tk_probe(struct i2c_client *client) } static const struct i2c_device_id dir685_tk_id[] = { - { "dir685tk", 0 }, + { "dir685tk" }, { } }; MODULE_DEVICE_TABLE(i2c, dir685_tk_id); diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 6b811d6bf625..817c23438f6e 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -6,20 +6,13 @@ * * Based on the pxa27x matrix keypad controller by Rodolfo Giometti. * - * NOTE: - * - * The 3-key reset is triggered by pressing the 3 keys in - * Row 0, Columns 2, 4, and 7 at the same time. This action can - * be disabled by setting the EP93XX_KEYPAD_DISABLE_3_KEY flag. - * - * Normal operation for the matrix does not autorepeat the key press. - * This action can be enabled by setting the EP93XX_KEYPAD_AUTOREPEAT - * flag. */ #include <linux/bits.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/interrupt.h> #include <linux/clk.h> #include <linux/io.h> @@ -27,7 +20,6 @@ #include <linux/input/matrix_keypad.h> #include <linux/slab.h> #include <linux/soc/cirrus/ep93xx.h> -#include <linux/platform_data/keypad-ep93xx.h> #include <linux/pm_wakeirq.h> /* @@ -61,12 +53,16 @@ #define KEY_REG_KEY1_MASK GENMASK(5, 0) #define KEY_REG_KEY1_SHIFT 0 +#define EP93XX_MATRIX_ROWS (8) +#define EP93XX_MATRIX_COLS (8) + #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS) struct ep93xx_keypad { - struct ep93xx_keypad_platform_data *pdata; struct input_dev *input_dev; struct clk *clk; + unsigned int debounce; + u16 prescale; void __iomem *mmio_base; @@ -133,23 +129,11 @@ static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) { - struct ep93xx_keypad_platform_data *pdata = keypad->pdata; unsigned int val = 0; - clk_set_rate(keypad->clk, pdata->clk_rate); + val |= (keypad->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK; - if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) - val |= KEY_INIT_DIS3KY; - if (pdata->flags & EP93XX_KEYPAD_DIAG_MODE) - val |= KEY_INIT_DIAG; - if (pdata->flags & EP93XX_KEYPAD_BACK_DRIVE) - val |= KEY_INIT_BACK; - if (pdata->flags & EP93XX_KEYPAD_TEST_MODE) - val |= KEY_INIT_T2; - - val |= ((pdata->debounce << KEY_INIT_DBNC_SHIFT) & KEY_INIT_DBNC_MASK); - - val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); + val |= (keypad->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK; __raw_writel(val, keypad->mmio_base + KEY_INIT); } @@ -184,15 +168,13 @@ static int ep93xx_keypad_suspend(struct device *dev) struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (keypad->enabled) { clk_disable(keypad->clk); keypad->enabled = false; } - mutex_unlock(&input_dev->mutex); - return 0; } @@ -202,7 +184,7 @@ static int ep93xx_keypad_resume(struct device *dev) struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) { if (!keypad->enabled) { @@ -212,25 +194,16 @@ static int ep93xx_keypad_resume(struct device *dev) } } - mutex_unlock(&input_dev->mutex); - return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, ep93xx_keypad_suspend, ep93xx_keypad_resume); -static void ep93xx_keypad_release_gpio_action(void *_pdev) -{ - struct platform_device *pdev = _pdev; - - ep93xx_keypad_release_gpio(pdev); -} - static int ep93xx_keypad_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct ep93xx_keypad *keypad; - const struct matrix_keymap_data *keymap_data; struct input_dev *input_dev; int err; @@ -238,14 +211,6 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) if (!keypad) return -ENOMEM; - keypad->pdata = dev_get_platdata(&pdev->dev); - if (!keypad->pdata) - return -EINVAL; - - keymap_data = keypad->pdata->keymap_data; - if (!keymap_data) - return -EINVAL; - keypad->irq = platform_get_irq(pdev, 0); if (keypad->irq < 0) return keypad->irq; @@ -254,19 +219,13 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) if (IS_ERR(keypad->mmio_base)) return PTR_ERR(keypad->mmio_base); - err = ep93xx_keypad_acquire_gpio(pdev); - if (err) - return err; - - err = devm_add_action_or_reset(&pdev->dev, - ep93xx_keypad_release_gpio_action, pdev); - if (err) - return err; - keypad->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) return PTR_ERR(keypad->clk); + device_property_read_u32(dev, "debounce-delay-ms", &keypad->debounce); + device_property_read_u16(dev, "cirrus,prescale", &keypad->prescale); + input_dev = devm_input_allocate_device(&pdev->dev); if (!input_dev) return -ENOMEM; @@ -278,13 +237,13 @@ static int ep93xx_keypad_probe(struct platform_device *pdev) input_dev->open = ep93xx_keypad_open; input_dev->close = ep93xx_keypad_close; - err = matrix_keypad_build_keymap(keymap_data, NULL, + err = matrix_keypad_build_keymap(NULL, NULL, EP93XX_MATRIX_ROWS, EP93XX_MATRIX_COLS, keypad->keycodes, input_dev); if (err) return err; - if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) + if (device_property_read_bool(&pdev->dev, "autorepeat")) __set_bit(EV_REP, input_dev->evbit); input_set_drvdata(input_dev, keypad); @@ -313,13 +272,20 @@ static void ep93xx_keypad_remove(struct platform_device *pdev) dev_pm_clear_wake_irq(&pdev->dev); } +static const struct of_device_id ep93xx_keypad_of_ids[] = { + { .compatible = "cirrus,ep9307-keypad" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, ep93xx_keypad_of_ids); + static struct platform_driver ep93xx_keypad_driver = { .driver = { .name = "ep93xx-keypad", .pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops), + .of_match_table = ep93xx_keypad_of_ids, }, .probe = ep93xx_keypad_probe, - .remove_new = ep93xx_keypad_remove, + .remove = ep93xx_keypad_remove, }; module_platform_driver(ep93xx_keypad_driver); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 9f3bcd41cf67..5c39a217b94c 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -245,23 +245,20 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, { int n_events = get_n_events_by_type(type); const unsigned long *bitmap = get_bm_events_by_type(ddata->input, type); - unsigned long *bits; ssize_t error; int i; - bits = bitmap_alloc(n_events, GFP_KERNEL); + unsigned long *bits __free(bitmap) = bitmap_alloc(n_events, GFP_KERNEL); if (!bits) return -ENOMEM; error = bitmap_parselist(buf, bits, n_events); if (error) - goto out; + return error; /* First validate */ - if (!bitmap_subset(bits, bitmap, n_events)) { - error = -EINVAL; - goto out; - } + if (!bitmap_subset(bits, bitmap, n_events)) + return -EINVAL; for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; @@ -271,12 +268,11 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, if (test_bit(*bdata->code, bits) && !bdata->button->can_disable) { - error = -EINVAL; - goto out; + return -EINVAL; } } - mutex_lock(&ddata->disable_lock); + guard(mutex)(&ddata->disable_lock); for (i = 0; i < ddata->pdata->nbuttons; i++) { struct gpio_button_data *bdata = &ddata->data[i]; @@ -290,11 +286,7 @@ static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, gpio_keys_enable_button(bdata); } - mutex_unlock(&ddata->disable_lock); - -out: - bitmap_free(bits); - return error; + return 0; } #define ATTR_SHOW_FN(name, type, only_disabled) \ @@ -470,11 +462,10 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) { struct gpio_button_data *bdata = dev_id; struct input_dev *input = bdata->input; - unsigned long flags; BUG_ON(irq != bdata->irq); - spin_lock_irqsave(&bdata->lock, flags); + guard(spinlock_irqsave)(&bdata->lock); if (!bdata->key_pressed) { if (bdata->button->wakeup) @@ -497,7 +488,6 @@ static irqreturn_t gpio_keys_irq_isr(int irq, void *dev_id) ms_to_ktime(bdata->release_delay), HRTIMER_MODE_REL_HARD); out: - spin_unlock_irqrestore(&bdata->lock, flags); return IRQ_HANDLED; } @@ -541,12 +531,7 @@ static int gpio_keys_setup_key(struct platform_device *pdev, * Legacy GPIO number, so request the GPIO here and * convert it to descriptor. */ - unsigned flags = GPIOF_IN; - - if (button->active_low) - flags |= GPIOF_ACTIVE_LOW; - - error = devm_gpio_request_one(dev, button->gpio, flags, desc); + error = devm_gpio_request_one(dev, button->gpio, GPIOF_IN, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); @@ -556,6 +541,9 @@ static int gpio_keys_setup_key(struct platform_device *pdev, bdata->gpiod = gpio_to_desc(button->gpio); if (!bdata->gpiod) return -EINVAL; + + if (button->active_low ^ gpiod_is_active_low(bdata->gpiod)) + gpiod_toggle_active_low(bdata->gpiod); } if (bdata->gpiod) { @@ -602,9 +590,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); - hrtimer_init(&bdata->debounce_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL); - bdata->debounce_timer.function = gpio_keys_debounce_timer; + hrtimer_setup(&bdata->debounce_timer, gpio_keys_debounce_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; @@ -640,9 +627,8 @@ static int gpio_keys_setup_key(struct platform_device *pdev, } bdata->release_delay = button->debounce_interval; - hrtimer_init(&bdata->release_timer, - CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); - bdata->release_timer.function = gpio_keys_irq_timer; + hrtimer_setup(&bdata->release_timer, gpio_keys_irq_timer, + CLOCK_REALTIME, HRTIMER_MODE_REL_HARD); isr = gpio_keys_irq_isr; irqflags = 0; @@ -768,7 +754,6 @@ gpio_keys_get_devtree_pdata(struct device *dev) { struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; - struct fwnode_handle *child; int nbuttons, irq; nbuttons = device_get_child_node_count(dev); @@ -790,7 +775,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) device_property_read_string(dev, "label", &pdata->name); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { if (is_of_node(child)) { irq = of_irq_get_byname(to_of_node(child), "irq"); if (irq > 0) @@ -808,7 +793,6 @@ gpio_keys_get_devtree_pdata(struct device *dev) if (fwnode_property_read_u32(child, "linux,code", &button->code)) { dev_err(dev, "Button without keycode\n"); - fwnode_handle_put(child); return ERR_PTR(-EINVAL); } @@ -1064,10 +1048,10 @@ static int gpio_keys_suspend(struct device *dev) if (error) return error; } else { - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); + if (input_device_enabled(input)) gpio_keys_close(input); - mutex_unlock(&input->mutex); } return 0; @@ -1077,20 +1061,20 @@ static int gpio_keys_resume(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); struct input_dev *input = ddata->input; - int error = 0; + int error; if (device_may_wakeup(dev)) { gpio_keys_disable_wakeup(ddata); } else { - mutex_lock(&input->mutex); - if (input_device_enabled(input)) + guard(mutex)(&input->mutex); + + if (input_device_enabled(input)) { error = gpio_keys_open(input); - mutex_unlock(&input->mutex); + if (error) + return error; + } } - if (error) - return error; - gpio_keys_report_state(ddata); return 0; } diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index b41fd1240f43..e6707d72210e 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -144,7 +144,6 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev) { struct gpio_keys_platform_data *pdata; struct gpio_keys_button *button; - struct fwnode_handle *child; int nbuttons; nbuttons = device_get_child_node_count(dev); @@ -166,11 +165,10 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev) device_property_read_string(dev, "label", &pdata->name); - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { if (fwnode_property_read_u32(child, "linux,code", &button->code)) { dev_err(dev, "button without keycode\n"); - fwnode_handle_put(child); return ERR_PTR(-EINVAL); } @@ -308,13 +306,8 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) * Legacy GPIO number so request the GPIO here and * convert it to descriptor. */ - unsigned flags = GPIOF_IN; - - if (button->active_low) - flags |= GPIOF_ACTIVE_LOW; - - error = devm_gpio_request_one(dev, button->gpio, - flags, button->desc ? : DRV_NAME); + error = devm_gpio_request_one(dev, button->gpio, GPIOF_IN, + button->desc ? : DRV_NAME); if (error) return dev_err_probe(dev, error, "unable to claim gpio %u\n", @@ -327,6 +320,9 @@ static int gpio_keys_polled_probe(struct platform_device *pdev) button->gpio); return -EINVAL; } + + if (button->active_low ^ gpiod_is_active_low(bdata->gpiod)) + gpiod_toggle_active_low(bdata->gpiod); } bdata->last_state = -1; diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index c1a4d5055de6..c8d8d0ea35b0 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -180,9 +180,8 @@ static irqreturn_t hil_interrupt(int irq, void *handle) /* send a command to the HIL */ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) { - unsigned long flags; + guard(spinlock_irqsave)(&hil_dev.lock); - spin_lock_irqsave(&hil_dev.lock, flags); while (hil_busy()) /* wait */; hil_command(cmd); @@ -191,7 +190,6 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) /* wait */; hil_write_data(*(data++)); } - spin_unlock_irqrestore(&hil_dev.lock, flags); } diff --git a/drivers/input/keyboard/imx-sm-bbm-key.c b/drivers/input/keyboard/imx-sm-bbm-key.c new file mode 100644 index 000000000000..96486bd23d60 --- /dev/null +++ b/drivers/input/keyboard/imx-sm-bbm-key.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 NXP. + */ + +#include <linux/input.h> +#include <linux/jiffies.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/scmi_protocol.h> +#include <linux/scmi_imx_protocol.h> +#include <linux/suspend.h> + +#define DEBOUNCE_TIME 30 +#define REPEAT_INTERVAL 60 + +struct scmi_imx_bbm { + struct scmi_protocol_handle *ph; + const struct scmi_imx_bbm_proto_ops *ops; + struct notifier_block nb; + int keycode; + int keystate; /* 1:pressed */ + bool suspended; + struct delayed_work check_work; + struct input_dev *input; +}; + +static void scmi_imx_bbm_pwrkey_check_for_events(struct work_struct *work) +{ + struct scmi_imx_bbm *bbnsm = container_of(to_delayed_work(work), + struct scmi_imx_bbm, check_work); + struct scmi_protocol_handle *ph = bbnsm->ph; + struct input_dev *input = bbnsm->input; + u32 state = 0; + int ret; + + ret = bbnsm->ops->button_get(ph, &state); + if (ret) { + pr_err("%s: %d\n", __func__, ret); + return; + } + + pr_debug("%s: state: %d, keystate %d\n", __func__, state, bbnsm->keystate); + + /* only report new event if status changed */ + if (state ^ bbnsm->keystate) { + bbnsm->keystate = state; + input_event(input, EV_KEY, bbnsm->keycode, state); + input_sync(input); + pm_relax(bbnsm->input->dev.parent); + pr_debug("EV_KEY: %x\n", bbnsm->keycode); + } + + /* repeat check if pressed long */ + if (state) + schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(REPEAT_INTERVAL)); +} + +static int scmi_imx_bbm_pwrkey_event(struct scmi_imx_bbm *bbnsm) +{ + struct input_dev *input = bbnsm->input; + + pm_wakeup_event(input->dev.parent, 0); + + /* + * Directly report key event after resume to make no key press + * event is missed. + */ + if (READ_ONCE(bbnsm->suspended)) { + bbnsm->keystate = 1; + input_event(input, EV_KEY, bbnsm->keycode, 1); + input_sync(input); + WRITE_ONCE(bbnsm->suspended, false); + } + + schedule_delayed_work(&bbnsm->check_work, msecs_to_jiffies(DEBOUNCE_TIME)); + + return 0; +} + +static void scmi_imx_bbm_pwrkey_act(void *pdata) +{ + struct scmi_imx_bbm *bbnsm = pdata; + + cancel_delayed_work_sync(&bbnsm->check_work); +} + +static int scmi_imx_bbm_key_notifier(struct notifier_block *nb, unsigned long event, void *data) +{ + struct scmi_imx_bbm *bbnsm = container_of(nb, struct scmi_imx_bbm, nb); + struct scmi_imx_bbm_notif_report *r = data; + + if (r->is_button) { + pr_debug("BBM Button Power key pressed\n"); + scmi_imx_bbm_pwrkey_event(bbnsm); + } else { + /* Should never reach here */ + pr_err("Unexpected BBM event: %s\n", __func__); + } + + return 0; +} + +static int scmi_imx_bbm_pwrkey_init(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + struct device *dev = &sdev->dev; + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + struct input_dev *input; + int ret; + + if (device_property_read_u32(dev, "linux,code", &bbnsm->keycode)) { + bbnsm->keycode = KEY_POWER; + dev_warn(dev, "key code is not specified, using default KEY_POWER\n"); + } + + INIT_DELAYED_WORK(&bbnsm->check_work, scmi_imx_bbm_pwrkey_check_for_events); + + input = devm_input_allocate_device(dev); + if (!input) { + dev_err(dev, "failed to allocate the input device for SCMI IMX BBM\n"); + return -ENOMEM; + } + + input->name = dev_name(dev); + input->phys = "bbnsm-pwrkey/input0"; + input->id.bustype = BUS_HOST; + + input_set_capability(input, EV_KEY, bbnsm->keycode); + + ret = devm_add_action_or_reset(dev, scmi_imx_bbm_pwrkey_act, bbnsm); + if (ret) { + dev_err(dev, "failed to register remove action\n"); + return ret; + } + + bbnsm->input = input; + + bbnsm->nb.notifier_call = &scmi_imx_bbm_key_notifier; + ret = handle->notify_ops->devm_event_notifier_register(sdev, SCMI_PROTOCOL_IMX_BBM, + SCMI_EVENT_IMX_BBM_BUTTON, + NULL, &bbnsm->nb); + + if (ret) + dev_err(dev, "Failed to register BBM Button Events %d:", ret); + + ret = input_register_device(input); + if (ret) { + dev_err(dev, "failed to register input device\n"); + return ret; + } + + return 0; +} + +static int scmi_imx_bbm_key_probe(struct scmi_device *sdev) +{ + const struct scmi_handle *handle = sdev->handle; + struct device *dev = &sdev->dev; + struct scmi_protocol_handle *ph; + struct scmi_imx_bbm *bbnsm; + int ret; + + if (!handle) + return -ENODEV; + + bbnsm = devm_kzalloc(dev, sizeof(*bbnsm), GFP_KERNEL); + if (!bbnsm) + return -ENOMEM; + + bbnsm->ops = handle->devm_protocol_get(sdev, SCMI_PROTOCOL_IMX_BBM, &ph); + if (IS_ERR(bbnsm->ops)) + return PTR_ERR(bbnsm->ops); + + bbnsm->ph = ph; + + device_init_wakeup(dev, true); + + dev_set_drvdata(dev, bbnsm); + + ret = scmi_imx_bbm_pwrkey_init(sdev); + if (ret) + device_init_wakeup(dev, false); + + return ret; +} + +static int __maybe_unused scmi_imx_bbm_key_suspend(struct device *dev) +{ + struct scmi_imx_bbm *bbnsm = dev_get_drvdata(dev); + + WRITE_ONCE(bbnsm->suspended, true); + + return 0; +} + +static int __maybe_unused scmi_imx_bbm_key_resume(struct device *dev) +{ + return 0; +} + +static SIMPLE_DEV_PM_OPS(scmi_imx_bbm_pm_key_ops, scmi_imx_bbm_key_suspend, + scmi_imx_bbm_key_resume); + +static const struct scmi_device_id scmi_id_table[] = { + { SCMI_PROTOCOL_IMX_BBM, "imx-bbm-key" }, + { }, +}; +MODULE_DEVICE_TABLE(scmi, scmi_id_table); + +static struct scmi_driver scmi_imx_bbm_key_driver = { + .driver = { + .pm = &scmi_imx_bbm_pm_key_ops, + }, + .name = "scmi-imx-bbm-key", + .probe = scmi_imx_bbm_key_probe, + .id_table = scmi_id_table, +}; +module_scmi_driver(scmi_imx_bbm_key_driver); + +MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>"); +MODULE_DESCRIPTION("IMX SM BBM Key driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index e15a93619e82..3cd47fa44efc 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -370,7 +370,7 @@ static void imx_keypad_close(struct input_dev *dev) /* Mark keypad as being inactive */ keypad->enabled = false; synchronize_irq(keypad->irq); - del_timer_sync(&keypad->check_matrix_timer); + timer_delete_sync(&keypad->check_matrix_timer); imx_keypad_inhibit(keypad); @@ -521,13 +521,11 @@ static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev) struct input_dev *input_dev = kbd->input_dev; unsigned short reg_val = readw(kbd->mmio_base + KPSR); - /* imx kbd can wake up system even clock is disabled */ - mutex_lock(&input_dev->mutex); - - if (input_device_enabled(input_dev)) - clk_disable_unprepare(kbd->clk); - - mutex_unlock(&input_dev->mutex); + scoped_guard(mutex, &input_dev->mutex) { + /* imx kbd can wake up system even clock is disabled */ + if (input_device_enabled(input_dev)) + clk_disable_unprepare(kbd->clk); + } if (device_may_wakeup(&pdev->dev)) { if (reg_val & KBD_STAT_KPKD) @@ -547,23 +545,20 @@ static int __maybe_unused imx_kbd_noirq_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; - int ret = 0; + int error; if (device_may_wakeup(&pdev->dev)) disable_irq_wake(kbd->irq); - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) { - ret = clk_prepare_enable(kbd->clk); - if (ret) - goto err_clk; + error = clk_prepare_enable(kbd->clk); + if (error) + return error; } -err_clk: - mutex_unlock(&input_dev->mutex); - - return ret; + return 0; } static const struct dev_pm_ops imx_kbd_pm_ops = { diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c index 1d71dd79ffd2..ca7ec054b1ce 100644 --- a/drivers/input/keyboard/ipaq-micro-keys.c +++ b/drivers/input/keyboard/ipaq-micro-keys.c @@ -54,18 +54,18 @@ static void micro_key_receive(void *data, int len, unsigned char *msg) static void micro_key_start(struct ipaq_micro_keys *keys) { - spin_lock(&keys->micro->lock); + guard(spinlock)(&keys->micro->lock); + keys->micro->key = micro_key_receive; keys->micro->key_data = keys; - spin_unlock(&keys->micro->lock); } static void micro_key_stop(struct ipaq_micro_keys *keys) { - spin_lock(&keys->micro->lock); + guard(spinlock)(&keys->micro->lock); + keys->micro->key = NULL; keys->micro->key_data = NULL; - spin_unlock(&keys->micro->lock); } static int micro_key_open(struct input_dev *input) @@ -102,9 +102,8 @@ static int micro_key_probe(struct platform_device *pdev) keys->input->keycodesize = sizeof(micro_keycodes[0]); keys->input->keycodemax = ARRAY_SIZE(micro_keycodes); - keys->codes = devm_kmemdup(&pdev->dev, micro_keycodes, - keys->input->keycodesize * keys->input->keycodemax, - GFP_KERNEL); + keys->codes = devm_kmemdup_array(&pdev->dev, micro_keycodes, keys->input->keycodemax, + keys->input->keycodesize, GFP_KERNEL); if (!keys->codes) return -ENOMEM; @@ -141,13 +140,11 @@ static int micro_key_resume(struct device *dev) struct ipaq_micro_keys *keys = dev_get_drvdata(dev); struct input_dev *input = keys->input; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); if (input_device_enabled(input)) micro_key_start(keys); - mutex_unlock(&input->mutex); - return 0; } diff --git a/drivers/input/keyboard/iqs62x-keys.c b/drivers/input/keyboard/iqs62x-keys.c index 688d61244b5f..b086c7b28d5c 100644 --- a/drivers/input/keyboard/iqs62x-keys.c +++ b/drivers/input/keyboard/iqs62x-keys.c @@ -45,7 +45,6 @@ struct iqs62x_keys_private { static int iqs62x_keys_parse_prop(struct platform_device *pdev, struct iqs62x_keys_private *iqs62x_keys) { - struct fwnode_handle *child; unsigned int val; int ret, i; @@ -68,7 +67,8 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev, } for (i = 0; i < ARRAY_SIZE(iqs62x_keys->switches); i++) { - child = device_get_named_child_node(&pdev->dev, + struct fwnode_handle *child __free(fwnode_handle) = + device_get_named_child_node(&pdev->dev, iqs62x_switch_names[i]); if (!child) continue; @@ -77,7 +77,6 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev, if (ret) { dev_err(&pdev->dev, "Failed to read switch code: %d\n", ret); - fwnode_handle_put(child); return ret; } iqs62x_keys->switches[i].code = val; @@ -91,8 +90,6 @@ static int iqs62x_keys_parse_prop(struct platform_device *pdev, iqs62x_keys->switches[i].flag = (i == IQS62X_SW_HALL_N ? IQS62X_EVENT_HALL_N_T : IQS62X_EVENT_HALL_S_T); - - fwnode_handle_put(child); } return 0; @@ -326,7 +323,7 @@ static struct platform_driver iqs62x_keys_platform_driver = { .name = "iqs62x-keys", }, .probe = iqs62x_keys_probe, - .remove_new = iqs62x_keys_remove, + .remove = iqs62x_keys_remove, }; module_platform_driver(iqs62x_keys_platform_driver); diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 047b654b3752..c035216dd27c 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -608,7 +608,7 @@ static int lkkbd_connect(struct serio *serio, struct serio_driver *drv) int i; int err; - lk = kzalloc(sizeof(struct lkkbd), GFP_KERNEL); + lk = kzalloc(sizeof(*lk), GFP_KERNEL); input_dev = input_allocate_device(); if (!lk || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 7bee93e9b0f5..e19442c6f80f 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -21,6 +21,7 @@ #include <linux/platform_data/lm8323.h> #include <linux/pm.h> #include <linux/slab.h> +#include <linux/string_choices.h> /* Commands to send to the chip. */ #define LM8323_CMD_READ_ID 0x80 /* Read chip ID. */ @@ -269,7 +270,7 @@ static void process_keys(struct lm8323_chip *lm) unsigned short keycode = lm->keymap[key]; dev_vdbg(&lm->client->dev, "key 0x%02x %s\n", - key, isdown ? "down" : "up"); + key, str_down_up(isdown)); if (lm->kp_enabled) { input_event(lm->idev, EV_MSC, MSC_SCAN, key); @@ -350,11 +351,11 @@ static int lm8323_configure(struct lm8323_chip *lm) static void pwm_done(struct lm8323_pwm *pwm) { - mutex_lock(&pwm->lock); + guard(mutex)(&pwm->lock); + pwm->running = false; if (pwm->desired_brightness != pwm->brightness) schedule_work(&pwm->work); - mutex_unlock(&pwm->lock); } /* @@ -367,7 +368,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm) u8 ints; int i; - mutex_lock(&lm->lock); + guard(mutex)(&lm->lock); while ((lm8323_read(lm, LM8323_CMD_READ_INT, &ints, 1) == 1) && ints) { if (likely(ints & INT_KEYPAD)) @@ -394,8 +395,6 @@ static irqreturn_t lm8323_irq(int irq, void *_lm) } } - mutex_unlock(&lm->lock); - return IRQ_HANDLED; } @@ -445,7 +444,7 @@ static void lm8323_pwm_work(struct work_struct *work) u16 pwm_cmds[3]; int num_cmds = 0; - mutex_lock(&pwm->lock); + guard(mutex)(&pwm->lock); /* * Do nothing if we're already at the requested level, @@ -454,7 +453,7 @@ static void lm8323_pwm_work(struct work_struct *work) * finishes. */ if (pwm->running || pwm->desired_brightness == pwm->brightness) - goto out; + return; kill = (pwm->desired_brightness == 0); up = (pwm->desired_brightness > pwm->brightness); @@ -489,9 +488,6 @@ static void lm8323_pwm_work(struct work_struct *work) lm8323_write_pwm(pwm, kill, num_cmds, pwm_cmds); pwm->brightness = pwm->desired_brightness; - - out: - mutex_unlock(&pwm->lock); } static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev, @@ -500,9 +496,9 @@ static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev, struct lm8323_pwm *pwm = cdev_to_pwm(led_cdev); struct lm8323_chip *lm = pwm->chip; - mutex_lock(&pwm->lock); - pwm->desired_brightness = brightness; - mutex_unlock(&pwm->lock); + scoped_guard(mutex, &pwm->lock) { + pwm->desired_brightness = brightness; + } if (in_interrupt()) { schedule_work(&pwm->work); @@ -510,12 +506,12 @@ static void lm8323_pwm_set_brightness(struct led_classdev *led_cdev, /* * Schedule PWM work as usual unless we are going into suspend */ - mutex_lock(&lm->lock); - if (likely(!lm->pm_suspend)) - schedule_work(&pwm->work); - else - lm8323_pwm_work(&pwm->work); - mutex_unlock(&lm->lock); + scoped_guard(mutex, &lm->lock) { + if (likely(!lm->pm_suspend)) + schedule_work(&pwm->work); + else + lm8323_pwm_work(&pwm->work); + } } } @@ -608,9 +604,9 @@ static ssize_t lm8323_set_disable(struct device *dev, if (ret) return ret; - mutex_lock(&lm->lock); + guard(mutex)(&lm->lock); + lm->kp_enabled = !i; - mutex_unlock(&lm->lock); return count; } @@ -758,9 +754,9 @@ static int lm8323_suspend(struct device *dev) irq_set_irq_wake(client->irq, 0); disable_irq(client->irq); - mutex_lock(&lm->lock); - lm->pm_suspend = true; - mutex_unlock(&lm->lock); + scoped_guard(mutex, &lm->lock) { + lm->pm_suspend = true; + } for (i = 0; i < 3; i++) if (lm->pwm[i].enabled) @@ -775,9 +771,9 @@ static int lm8323_resume(struct device *dev) struct lm8323_chip *lm = i2c_get_clientdata(client); int i; - mutex_lock(&lm->lock); - lm->pm_suspend = false; - mutex_unlock(&lm->lock); + scoped_guard(mutex, &lm->lock) { + lm->pm_suspend = false; + } for (i = 0; i < 3; i++) if (lm->pwm[i].enabled) @@ -792,7 +788,7 @@ static int lm8323_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume); static const struct i2c_device_id lm8323_id[] = { - { "lm8323", 0 }, + { "lm8323" }, { } }; diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 1c070c499c85..384baabf9924 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -194,7 +194,7 @@ static int lm8333_probe(struct i2c_client *client) } static const struct i2c_device_id lm8333_id[] = { - { "lm8333", 0 }, + { "lm8333" }, { } }; MODULE_DEVICE_TABLE(i2c, lm8333_id); diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index f866c03b9d0e..c501a93a4417 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -112,11 +112,10 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) static void locomokbd_scankeyboard(struct locomokbd *locomokbd) { unsigned int row, col, rowd; - unsigned long flags; unsigned int num_pressed; unsigned long membase = locomokbd->base; - spin_lock_irqsave(&locomokbd->lock, flags); + guard(spinlock_irqsave)(&locomokbd->lock); locomokbd_charge_all(membase); @@ -167,8 +166,6 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd) mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL); else locomokbd->count_cancel = 0; - - spin_unlock_irqrestore(&locomokbd->lock, flags); } /* @@ -227,7 +224,7 @@ static int locomokbd_probe(struct locomo_dev *dev) struct input_dev *input_dev; int i, err; - locomokbd = kzalloc(sizeof(struct locomokbd), GFP_KERNEL); + locomokbd = kzalloc(sizeof(*locomokbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!locomokbd || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index 322a87807159..2392e7ec3b19 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -57,14 +57,13 @@ struct lpc32xx_kscan_drv { struct input_dev *input; struct clk *clk; void __iomem *kscan_base; - unsigned int irq; u32 matrix_sz; /* Size of matrix in XxY, ie. 3 = 3x3 */ u32 deb_clks; /* Debounce clocks (based on 32KHz clock) */ u32 scan_delay; /* Scan delay (based on 32KHz clock) */ - unsigned short *keymap; /* Pointer to key map for the scan matrix */ unsigned int row_shift; + unsigned short *keymap; /* Pointer to key map for the scan matrix */ u8 lastkeystates[8]; }; @@ -263,7 +262,7 @@ static int lpc32xx_kscan_suspend(struct device *dev) struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev); struct input_dev *input = kscandat->input; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); if (input_device_enabled(input)) { /* Clear IRQ and disable clock */ @@ -271,7 +270,6 @@ static int lpc32xx_kscan_suspend(struct device *dev) clk_disable_unprepare(kscandat->clk); } - mutex_unlock(&input->mutex); return 0; } @@ -280,19 +278,20 @@ static int lpc32xx_kscan_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev); struct input_dev *input = kscandat->input; - int retval = 0; + int error; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); if (input_device_enabled(input)) { /* Enable clock and clear IRQ */ - retval = clk_prepare_enable(kscandat->clk); - if (retval == 0) - writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base)); + error = clk_prepare_enable(kscandat->clk); + if (error) + return error; + + writel(1, LPC32XX_KS_IRQ(kscandat->kscan_base)); } - mutex_unlock(&input->mutex); - return retval; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend, diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index d08b565be24c..1a8f1fa53fbb 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c @@ -132,14 +132,11 @@ static void dc_kbd_callback(struct mapleq *mq) * We should always get the lock because the only * time it may be locked is if the driver is in the cleanup phase. */ - if (likely(mutex_trylock(&maple_keyb_mutex))) { - + scoped_guard(mutex_try, &maple_keyb_mutex) { if (buf[1] == mapledev->function) { memcpy(kbd->new, buf + 2, 8); dc_scan_kbd(kbd); } - - mutex_unlock(&maple_keyb_mutex); } } @@ -154,7 +151,7 @@ static int probe_maple_kbd(struct device *dev) mdev = to_maple_dev(dev); mdrv = to_maple_driver(dev->driver); - kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); + kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); if (!kbd) { error = -ENOMEM; goto fail; @@ -211,14 +208,12 @@ static int remove_maple_kbd(struct device *dev) struct maple_device *mdev = to_maple_dev(dev); struct dc_kbd *kbd = maple_get_drvdata(mdev); - mutex_lock(&maple_keyb_mutex); + guard(mutex)(&maple_keyb_mutex); input_unregister_device(kbd->dev); kfree(kbd); maple_set_drvdata(mdev, NULL); - - mutex_unlock(&maple_keyb_mutex); return 0; } diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 695c03e075b5..e46473cb817c 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -20,16 +20,24 @@ #include <linux/input/matrix_keypad.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_gpio.h> -#include <linux/of_platform.h> struct matrix_keypad { - const struct matrix_keypad_platform_data *pdata; struct input_dev *input_dev; unsigned int row_shift; + unsigned int col_scan_delay_us; + unsigned int all_cols_on_delay_us; + /* key debounce interval in milli-second */ + unsigned int debounce_ms; + bool drive_inactive_cols; + + struct gpio_desc *row_gpios[MATRIX_MAX_ROWS]; + unsigned int num_row_gpios; + + struct gpio_desc *col_gpios[MATRIX_MAX_ROWS]; + unsigned int num_col_gpios; + unsigned int row_irqs[MATRIX_MAX_ROWS]; - unsigned int num_row_irqs; DECLARE_BITMAP(wakeup_enabled_irqs, MATRIX_MAX_ROWS); uint32_t last_key_state[MATRIX_MAX_COLS]; @@ -37,7 +45,6 @@ struct matrix_keypad { spinlock_t lock; bool scan_pending; bool stopped; - bool gpio_all_disabled; }; /* @@ -46,50 +53,46 @@ struct matrix_keypad { * columns. In that case it is configured here to be input, otherwise it is * driven with the inactive value. */ -static void __activate_col(const struct matrix_keypad_platform_data *pdata, - int col, bool on) +static void __activate_col(struct matrix_keypad *keypad, int col, bool on) { - bool level_on = !pdata->active_low; - if (on) { - gpio_direction_output(pdata->col_gpios[col], level_on); + gpiod_direction_output(keypad->col_gpios[col], 1); } else { - gpio_set_value_cansleep(pdata->col_gpios[col], !level_on); - if (!pdata->drive_inactive_cols) - gpio_direction_input(pdata->col_gpios[col]); + gpiod_set_value_cansleep(keypad->col_gpios[col], 0); + if (!keypad->drive_inactive_cols) + gpiod_direction_input(keypad->col_gpios[col]); } } -static void activate_col(const struct matrix_keypad_platform_data *pdata, - int col, bool on) +static void activate_col(struct matrix_keypad *keypad, int col, bool on) { - __activate_col(pdata, col, on); + __activate_col(keypad, col, on); - if (on && pdata->col_scan_delay_us) - udelay(pdata->col_scan_delay_us); + if (on && keypad->col_scan_delay_us) + fsleep(keypad->col_scan_delay_us); } -static void activate_all_cols(const struct matrix_keypad_platform_data *pdata, - bool on) +static void activate_all_cols(struct matrix_keypad *keypad, bool on) { int col; - for (col = 0; col < pdata->num_col_gpios; col++) - __activate_col(pdata, col, on); + for (col = 0; col < keypad->num_col_gpios; col++) + __activate_col(keypad, col, on); + + if (on && keypad->all_cols_on_delay_us) + fsleep(keypad->all_cols_on_delay_us); } -static bool row_asserted(const struct matrix_keypad_platform_data *pdata, - int row) +static bool row_asserted(struct matrix_keypad *keypad, int row) { - return gpio_get_value_cansleep(pdata->row_gpios[row]) ? - !pdata->active_low : pdata->active_low; + return gpiod_get_value_cansleep(keypad->row_gpios[row]); } static void enable_row_irqs(struct matrix_keypad *keypad) { int i; - for (i = 0; i < keypad->num_row_irqs; i++) + for (i = 0; i < keypad->num_row_gpios; i++) enable_irq(keypad->row_irqs[i]); } @@ -97,7 +100,7 @@ static void disable_row_irqs(struct matrix_keypad *keypad) { int i; - for (i = 0; i < keypad->num_row_irqs; i++) + for (i = 0; i < keypad->num_row_gpios; i++) disable_irq_nosync(keypad->row_irqs[i]); } @@ -110,39 +113,38 @@ static void matrix_keypad_scan(struct work_struct *work) container_of(work, struct matrix_keypad, work.work); struct input_dev *input_dev = keypad->input_dev; const unsigned short *keycodes = input_dev->keycode; - const struct matrix_keypad_platform_data *pdata = keypad->pdata; uint32_t new_state[MATRIX_MAX_COLS]; int row, col, code; /* de-activate all columns for scanning */ - activate_all_cols(pdata, false); + activate_all_cols(keypad, false); memset(new_state, 0, sizeof(new_state)); - for (row = 0; row < pdata->num_row_gpios; row++) - gpio_direction_input(pdata->row_gpios[row]); + for (row = 0; row < keypad->num_row_gpios; row++) + gpiod_direction_input(keypad->row_gpios[row]); /* assert each column and read the row status out */ - for (col = 0; col < pdata->num_col_gpios; col++) { + for (col = 0; col < keypad->num_col_gpios; col++) { - activate_col(pdata, col, true); + activate_col(keypad, col, true); - for (row = 0; row < pdata->num_row_gpios; row++) + for (row = 0; row < keypad->num_row_gpios; row++) new_state[col] |= - row_asserted(pdata, row) ? (1 << row) : 0; + row_asserted(keypad, row) ? BIT(row) : 0; - activate_col(pdata, col, false); + activate_col(keypad, col, false); } - for (col = 0; col < pdata->num_col_gpios; col++) { + for (col = 0; col < keypad->num_col_gpios; col++) { uint32_t bits_changed; bits_changed = keypad->last_key_state[col] ^ new_state[col]; if (bits_changed == 0) continue; - for (row = 0; row < pdata->num_row_gpios; row++) { - if ((bits_changed & (1 << row)) == 0) + for (row = 0; row < keypad->num_row_gpios; row++) { + if (!(bits_changed & BIT(row))) continue; code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); @@ -156,21 +158,20 @@ static void matrix_keypad_scan(struct work_struct *work) memcpy(keypad->last_key_state, new_state, sizeof(new_state)); - activate_all_cols(pdata, true); + activate_all_cols(keypad, true); /* Enable IRQs again */ - spin_lock_irq(&keypad->lock); - keypad->scan_pending = false; - enable_row_irqs(keypad); - spin_unlock_irq(&keypad->lock); + scoped_guard(spinlock_irq, &keypad->lock) { + keypad->scan_pending = false; + enable_row_irqs(keypad); + } } static irqreturn_t matrix_keypad_interrupt(int irq, void *id) { struct matrix_keypad *keypad = id; - unsigned long flags; - spin_lock_irqsave(&keypad->lock, flags); + guard(spinlock_irqsave)(&keypad->lock); /* * See if another IRQ beaten us to it and scheduled the @@ -183,10 +184,9 @@ static irqreturn_t matrix_keypad_interrupt(int irq, void *id) disable_row_irqs(keypad); keypad->scan_pending = true; schedule_delayed_work(&keypad->work, - msecs_to_jiffies(keypad->pdata->debounce_ms)); + msecs_to_jiffies(keypad->debounce_ms)); out: - spin_unlock_irqrestore(&keypad->lock, flags); return IRQ_HANDLED; } @@ -210,9 +210,9 @@ static void matrix_keypad_stop(struct input_dev *dev) { struct matrix_keypad *keypad = input_get_drvdata(dev); - spin_lock_irq(&keypad->lock); - keypad->stopped = true; - spin_unlock_irq(&keypad->lock); + scoped_guard(spinlock_irq, &keypad->lock) { + keypad->stopped = true; + } flush_delayed_work(&keypad->work); /* @@ -226,7 +226,8 @@ static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad) { int i; - for_each_clear_bit(i, keypad->wakeup_enabled_irqs, keypad->num_row_irqs) + for_each_clear_bit(i, keypad->wakeup_enabled_irqs, + keypad->num_row_gpios) if (enable_irq_wake(keypad->row_irqs[i]) == 0) __set_bit(i, keypad->wakeup_enabled_irqs); } @@ -235,7 +236,8 @@ static void matrix_keypad_disable_wakeup(struct matrix_keypad *keypad) { int i; - for_each_set_bit(i, keypad->wakeup_enabled_irqs, keypad->num_row_irqs) { + for_each_set_bit(i, keypad->wakeup_enabled_irqs, + keypad->num_row_gpios) { disable_irq_wake(keypad->row_irqs[i]); __clear_bit(i, keypad->wakeup_enabled_irqs); } @@ -273,182 +275,108 @@ static DEFINE_SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, static int matrix_keypad_init_gpio(struct platform_device *pdev, struct matrix_keypad *keypad) { - const struct matrix_keypad_platform_data *pdata = keypad->pdata; - int i, irq, err; - - /* initialized strobe lines as outputs, activated */ - for (i = 0; i < pdata->num_col_gpios; i++) { - err = devm_gpio_request(&pdev->dev, - pdata->col_gpios[i], "matrix_kbd_col"); - if (err) { - dev_err(&pdev->dev, - "failed to request GPIO%d for COL%d\n", - pdata->col_gpios[i], i); - return err; - } + bool active_low; + int nrow, ncol; + int err; + int i; - gpio_direction_output(pdata->col_gpios[i], !pdata->active_low); + nrow = gpiod_count(&pdev->dev, "row"); + ncol = gpiod_count(&pdev->dev, "col"); + if (nrow < 0 || ncol < 0) { + dev_err(&pdev->dev, "missing row or column GPIOs\n"); + return -EINVAL; } - for (i = 0; i < pdata->num_row_gpios; i++) { - err = devm_gpio_request(&pdev->dev, - pdata->row_gpios[i], "matrix_kbd_row"); + keypad->num_row_gpios = nrow; + keypad->num_col_gpios = ncol; + + active_low = device_property_read_bool(&pdev->dev, "gpio-activelow"); + + /* initialize strobe lines as outputs, activated */ + for (i = 0; i < keypad->num_col_gpios; i++) { + keypad->col_gpios[i] = devm_gpiod_get_index(&pdev->dev, "col", + i, GPIOD_ASIS); + err = PTR_ERR_OR_ZERO(keypad->col_gpios[i]); if (err) { dev_err(&pdev->dev, - "failed to request GPIO%d for ROW%d\n", - pdata->row_gpios[i], i); + "failed to request GPIO for COL%d: %d\n", + i, err); return err; } - gpio_direction_input(pdata->row_gpios[i]); + gpiod_set_consumer_name(keypad->col_gpios[i], "matrix_kbd_col"); + + if (active_low ^ gpiod_is_active_low(keypad->col_gpios[i])) + gpiod_toggle_active_low(keypad->col_gpios[i]); + + gpiod_direction_output(keypad->col_gpios[i], 1); } - if (pdata->clustered_irq > 0) { - err = devm_request_any_context_irq(&pdev->dev, - pdata->clustered_irq, - matrix_keypad_interrupt, - pdata->clustered_irq_flags, - "matrix-keypad", keypad); - if (err < 0) { + for (i = 0; i < keypad->num_row_gpios; i++) { + keypad->row_gpios[i] = devm_gpiod_get_index(&pdev->dev, "row", + i, GPIOD_IN); + err = PTR_ERR_OR_ZERO(keypad->row_gpios[i]); + if (err) { dev_err(&pdev->dev, - "Unable to acquire clustered interrupt\n"); + "failed to request GPIO for ROW%d: %d\n", + i, err); return err; } - keypad->row_irqs[0] = pdata->clustered_irq; - keypad->num_row_irqs = 1; - } else { - for (i = 0; i < pdata->num_row_gpios; i++) { - irq = gpio_to_irq(pdata->row_gpios[i]); - if (irq < 0) { - err = irq; - dev_err(&pdev->dev, - "Unable to convert GPIO line %i to irq: %d\n", - pdata->row_gpios[i], err); - return err; - } - - err = devm_request_any_context_irq(&pdev->dev, - irq, - matrix_keypad_interrupt, - IRQF_TRIGGER_RISING | - IRQF_TRIGGER_FALLING, - "matrix-keypad", keypad); - if (err < 0) { - dev_err(&pdev->dev, - "Unable to acquire interrupt for GPIO line %i\n", - pdata->row_gpios[i]); - return err; - } - - keypad->row_irqs[i] = irq; - } + gpiod_set_consumer_name(keypad->row_gpios[i], "matrix_kbd_row"); - keypad->num_row_irqs = pdata->num_row_gpios; + if (active_low ^ gpiod_is_active_low(keypad->row_gpios[i])) + gpiod_toggle_active_low(keypad->row_gpios[i]); } - /* initialized as disabled - enabled by input->open */ - disable_row_irqs(keypad); - return 0; } -#ifdef CONFIG_OF -static struct matrix_keypad_platform_data * -matrix_keypad_parse_dt(struct device *dev) +static int matrix_keypad_setup_interrupts(struct platform_device *pdev, + struct matrix_keypad *keypad) { - struct matrix_keypad_platform_data *pdata; - struct device_node *np = dev->of_node; - unsigned int *gpios; - int ret, i, nrow, ncol; - - if (!np) { - dev_err(dev, "device lacks DT data\n"); - return ERR_PTR(-ENODEV); - } - - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "could not allocate memory for platform data\n"); - return ERR_PTR(-ENOMEM); - } - - pdata->num_row_gpios = nrow = gpiod_count(dev, "row"); - pdata->num_col_gpios = ncol = gpiod_count(dev, "col"); - if (nrow < 0 || ncol < 0) { - dev_err(dev, "number of keypad rows/columns not specified\n"); - return ERR_PTR(-EINVAL); - } - - pdata->no_autorepeat = of_property_read_bool(np, "linux,no-autorepeat"); - - pdata->wakeup = of_property_read_bool(np, "wakeup-source") || - of_property_read_bool(np, "linux,wakeup"); /* legacy */ - - pdata->active_low = of_property_read_bool(np, "gpio-activelow"); - - pdata->drive_inactive_cols = - of_property_read_bool(np, "drive-inactive-cols"); - - of_property_read_u32(np, "debounce-delay-ms", &pdata->debounce_ms); - of_property_read_u32(np, "col-scan-delay-us", - &pdata->col_scan_delay_us); + int err; + int irq; + int i; - gpios = devm_kcalloc(dev, - pdata->num_row_gpios + pdata->num_col_gpios, - sizeof(unsigned int), - GFP_KERNEL); - if (!gpios) { - dev_err(dev, "could not allocate memory for gpios\n"); - return ERR_PTR(-ENOMEM); - } + for (i = 0; i < keypad->num_row_gpios; i++) { + irq = gpiod_to_irq(keypad->row_gpios[i]); + if (irq < 0) { + err = irq; + dev_err(&pdev->dev, + "Unable to convert GPIO line %i to irq: %d\n", + i, err); + return err; + } - for (i = 0; i < nrow; i++) { - ret = of_get_named_gpio(np, "row-gpios", i); - if (ret < 0) - return ERR_PTR(ret); - gpios[i] = ret; - } + err = devm_request_any_context_irq(&pdev->dev, irq, + matrix_keypad_interrupt, + IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "matrix-keypad", keypad); + if (err < 0) { + dev_err(&pdev->dev, + "Unable to acquire interrupt for row %i: %d\n", + i, err); + return err; + } - for (i = 0; i < ncol; i++) { - ret = of_get_named_gpio(np, "col-gpios", i); - if (ret < 0) - return ERR_PTR(ret); - gpios[nrow + i] = ret; + keypad->row_irqs[i] = irq; } - pdata->row_gpios = gpios; - pdata->col_gpios = &gpios[pdata->num_row_gpios]; - - return pdata; -} -#else -static inline struct matrix_keypad_platform_data * -matrix_keypad_parse_dt(struct device *dev) -{ - dev_err(dev, "no platform data defined\n"); + /* initialized as disabled - enabled by input->open */ + disable_row_irqs(keypad); - return ERR_PTR(-EINVAL); + return 0; } -#endif static int matrix_keypad_probe(struct platform_device *pdev) { - const struct matrix_keypad_platform_data *pdata; struct matrix_keypad *keypad; struct input_dev *input_dev; + bool wakeup; int err; - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - pdata = matrix_keypad_parse_dt(&pdev->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } else if (!pdata->keymap_data) { - dev_err(&pdev->dev, "no keymap data defined\n"); - return -EINVAL; - } - keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad), GFP_KERNEL); if (!keypad) return -ENOMEM; @@ -458,40 +386,58 @@ static int matrix_keypad_probe(struct platform_device *pdev) return -ENOMEM; keypad->input_dev = input_dev; - keypad->pdata = pdata; - keypad->row_shift = get_count_order(pdata->num_col_gpios); keypad->stopped = true; INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); spin_lock_init(&keypad->lock); + keypad->drive_inactive_cols = + device_property_read_bool(&pdev->dev, "drive-inactive-cols"); + device_property_read_u32(&pdev->dev, "debounce-delay-ms", + &keypad->debounce_ms); + device_property_read_u32(&pdev->dev, "col-scan-delay-us", + &keypad->col_scan_delay_us); + device_property_read_u32(&pdev->dev, "all-cols-on-delay-us", + &keypad->all_cols_on_delay_us); + + err = matrix_keypad_init_gpio(pdev, keypad); + if (err) + return err; + + keypad->row_shift = get_count_order(keypad->num_col_gpios); + + err = matrix_keypad_setup_interrupts(pdev, keypad); + if (err) + return err; + input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; - err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, - pdata->num_row_gpios, - pdata->num_col_gpios, + err = matrix_keypad_build_keymap(NULL, NULL, + keypad->num_row_gpios, + keypad->num_col_gpios, NULL, input_dev); if (err) { dev_err(&pdev->dev, "failed to build keymap\n"); return -ENOMEM; } - if (!pdata->no_autorepeat) + if (!device_property_read_bool(&pdev->dev, "linux,no-autorepeat")) __set_bit(EV_REP, input_dev->evbit); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); - err = matrix_keypad_init_gpio(pdev, keypad); - if (err) - return err; - err = input_register_device(keypad->input_dev); if (err) return err; - device_init_wakeup(&pdev->dev, pdata->wakeup); + wakeup = device_property_read_bool(&pdev->dev, "wakeup-source") || + /* legacy */ + device_property_read_bool(&pdev->dev, "linux,wakeup"); + device_init_wakeup(&pdev->dev, wakeup); + platform_set_drvdata(pdev, keypad); return 0; diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index faab7691c219..c10726b5e4d1 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -270,7 +270,7 @@ static int max7359_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume); static const struct i2c_device_id max7359_ids[] = { - { "max7359", 0 }, + { "max7359" }, { } }; MODULE_DEVICE_TABLE(i2c, max7359_ids); diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c deleted file mode 100644 index 2410f676c7f9..000000000000 --- a/drivers/input/keyboard/mcs_touchkey.c +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Touchkey driver for MELFAS MCS5000/5080 controller - * - * Copyright (C) 2010 Samsung Electronics Co.Ltd - * Author: HeungJun Kim <riverful.kim@samsung.com> - * Author: Joonyoung Shim <jy0922.shim@samsung.com> - */ - -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/irq.h> -#include <linux/slab.h> -#include <linux/platform_data/mcs.h> -#include <linux/pm.h> - -/* MCS5000 Touchkey */ -#define MCS5000_TOUCHKEY_STATUS 0x04 -#define MCS5000_TOUCHKEY_STATUS_PRESS 7 -#define MCS5000_TOUCHKEY_FW 0x0a -#define MCS5000_TOUCHKEY_BASE_VAL 0x61 - -/* MCS5080 Touchkey */ -#define MCS5080_TOUCHKEY_STATUS 0x00 -#define MCS5080_TOUCHKEY_STATUS_PRESS 3 -#define MCS5080_TOUCHKEY_FW 0x01 -#define MCS5080_TOUCHKEY_BASE_VAL 0x1 - -enum mcs_touchkey_type { - MCS5000_TOUCHKEY, - MCS5080_TOUCHKEY, -}; - -struct mcs_touchkey_chip { - unsigned int status_reg; - unsigned int pressbit; - unsigned int press_invert; - unsigned int baseval; -}; - -struct mcs_touchkey_data { - void (*poweron)(bool); - - struct i2c_client *client; - struct input_dev *input_dev; - struct mcs_touchkey_chip chip; - unsigned int key_code; - unsigned int key_val; - unsigned short keycodes[]; -}; - -static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) -{ - struct mcs_touchkey_data *data = dev_id; - struct mcs_touchkey_chip *chip = &data->chip; - struct i2c_client *client = data->client; - struct input_dev *input = data->input_dev; - unsigned int key_val; - unsigned int pressed; - int val; - - val = i2c_smbus_read_byte_data(client, chip->status_reg); - if (val < 0) { - dev_err(&client->dev, "i2c read error [%d]\n", val); - goto out; - } - - pressed = (val & (1 << chip->pressbit)) >> chip->pressbit; - if (chip->press_invert) - pressed ^= chip->press_invert; - - /* key_val is 0 when released, so we should use key_val of press. */ - if (pressed) { - key_val = val & (0xff >> (8 - chip->pressbit)); - if (!key_val) - goto out; - key_val -= chip->baseval; - data->key_code = data->keycodes[key_val]; - data->key_val = key_val; - } - - input_event(input, EV_MSC, MSC_SCAN, data->key_val); - input_report_key(input, data->key_code, pressed); - input_sync(input); - - dev_dbg(&client->dev, "key %d %d %s\n", data->key_val, data->key_code, - pressed ? "pressed" : "released"); - - out: - return IRQ_HANDLED; -} - -static void mcs_touchkey_poweroff(void *data) -{ - struct mcs_touchkey_data *touchkey = data; - - touchkey->poweron(false); -} - -static int mcs_touchkey_probe(struct i2c_client *client) -{ - const struct i2c_device_id *id = i2c_client_get_device_id(client); - const struct mcs_platform_data *pdata; - struct mcs_touchkey_data *data; - struct input_dev *input_dev; - unsigned int fw_reg; - int fw_ver; - int error; - int i; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) { - dev_err(&client->dev, "no platform data defined\n"); - return -EINVAL; - } - - data = devm_kzalloc(&client->dev, - struct_size(data, keycodes, pdata->key_maxval + 1), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - input_dev = devm_input_allocate_device(&client->dev); - if (!input_dev) { - dev_err(&client->dev, "Failed to allocate input device\n"); - return -ENOMEM; - } - - data->client = client; - data->input_dev = input_dev; - - if (id->driver_data == MCS5000_TOUCHKEY) { - data->chip.status_reg = MCS5000_TOUCHKEY_STATUS; - data->chip.pressbit = MCS5000_TOUCHKEY_STATUS_PRESS; - data->chip.baseval = MCS5000_TOUCHKEY_BASE_VAL; - fw_reg = MCS5000_TOUCHKEY_FW; - } else { - data->chip.status_reg = MCS5080_TOUCHKEY_STATUS; - data->chip.pressbit = MCS5080_TOUCHKEY_STATUS_PRESS; - data->chip.press_invert = 1; - data->chip.baseval = MCS5080_TOUCHKEY_BASE_VAL; - fw_reg = MCS5080_TOUCHKEY_FW; - } - - fw_ver = i2c_smbus_read_byte_data(client, fw_reg); - if (fw_ver < 0) { - dev_err(&client->dev, "i2c read error[%d]\n", fw_ver); - return fw_ver; - } - dev_info(&client->dev, "Firmware version: %d\n", fw_ver); - - input_dev->name = "MELFAS MCS Touchkey"; - input_dev->id.bustype = BUS_I2C; - input_dev->evbit[0] = BIT_MASK(EV_KEY); - if (!pdata->no_autorepeat) - input_dev->evbit[0] |= BIT_MASK(EV_REP); - input_dev->keycode = data->keycodes; - input_dev->keycodesize = sizeof(data->keycodes[0]); - input_dev->keycodemax = pdata->key_maxval + 1; - - for (i = 0; i < pdata->keymap_size; i++) { - unsigned int val = MCS_KEY_VAL(pdata->keymap[i]); - unsigned int code = MCS_KEY_CODE(pdata->keymap[i]); - - data->keycodes[val] = code; - __set_bit(code, input_dev->keybit); - } - - input_set_capability(input_dev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, data); - - if (pdata->cfg_pin) - pdata->cfg_pin(); - - if (pdata->poweron) { - data->poweron = pdata->poweron; - data->poweron(true); - - error = devm_add_action_or_reset(&client->dev, - mcs_touchkey_poweroff, data); - if (error) - return error; - } - - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, mcs_touchkey_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->dev.driver->name, data); - if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); - return error; - } - - error = input_register_device(input_dev); - if (error) - return error; - - i2c_set_clientdata(client, data); - return 0; -} - -static void mcs_touchkey_shutdown(struct i2c_client *client) -{ - struct mcs_touchkey_data *data = i2c_get_clientdata(client); - - if (data->poweron) - data->poweron(false); -} - -static int mcs_touchkey_suspend(struct device *dev) -{ - struct mcs_touchkey_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - - /* Disable the work */ - disable_irq(client->irq); - - /* Finally turn off the power */ - if (data->poweron) - data->poweron(false); - - return 0; -} - -static int mcs_touchkey_resume(struct device *dev) -{ - struct mcs_touchkey_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - - /* Enable the device first */ - if (data->poweron) - data->poweron(true); - - /* Enable irq again */ - enable_irq(client->irq); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops, - mcs_touchkey_suspend, mcs_touchkey_resume); - -static const struct i2c_device_id mcs_touchkey_id[] = { - { "mcs5000_touchkey", MCS5000_TOUCHKEY }, - { "mcs5080_touchkey", MCS5080_TOUCHKEY }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id); - -static struct i2c_driver mcs_touchkey_driver = { - .driver = { - .name = "mcs_touchkey", - .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops), - }, - .probe = mcs_touchkey_probe, - .shutdown = mcs_touchkey_shutdown, - .id_table = mcs_touchkey_id, -}; - -module_i2c_driver(mcs_touchkey_driver); - -/* Module information */ -MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); -MODULE_AUTHOR("HeungJun Kim <riverful.kim@samsung.com>"); -MODULE_DESCRIPTION("Touchkey driver for MELFAS MCS5000/5080 controller"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index d434753afab1..bd1a944ded46 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -82,42 +82,6 @@ static const struct mpr121_init_register init_reg_table[] = { { AUTO_CONFIG_CTRL_ADDR, 0x0b }, }; -static void mpr121_vdd_supply_disable(void *data) -{ - struct regulator *vdd_supply = data; - - regulator_disable(vdd_supply); -} - -static struct regulator *mpr121_vdd_supply_init(struct device *dev) -{ - struct regulator *vdd_supply; - int err; - - vdd_supply = devm_regulator_get(dev, "vdd"); - if (IS_ERR(vdd_supply)) { - dev_err(dev, "failed to get vdd regulator: %ld\n", - PTR_ERR(vdd_supply)); - return vdd_supply; - } - - err = regulator_enable(vdd_supply); - if (err) { - dev_err(dev, "failed to enable vdd regulator: %d\n", err); - return ERR_PTR(err); - } - - err = devm_add_action_or_reset(dev, mpr121_vdd_supply_disable, - vdd_supply); - if (err) { - dev_err(dev, "failed to add disable regulator action: %d\n", - err); - return ERR_PTR(err); - } - - return vdd_supply; -} - static void mpr_touchkey_report(struct input_dev *dev) { struct mpr121_touchkey *mpr121 = input_get_drvdata(dev); @@ -233,7 +197,6 @@ err_i2c_write: static int mpr_touchkey_probe(struct i2c_client *client) { struct device *dev = &client->dev; - struct regulator *vdd_supply; int vdd_uv; struct mpr121_touchkey *mpr121; struct input_dev *input_dev; @@ -241,11 +204,9 @@ static int mpr_touchkey_probe(struct i2c_client *client) int error; int i; - vdd_supply = mpr121_vdd_supply_init(dev); - if (IS_ERR(vdd_supply)) - return PTR_ERR(vdd_supply); - - vdd_uv = regulator_get_voltage(vdd_supply); + vdd_uv = devm_regulator_get_enable_read_voltage(dev, "vdd"); + if (vdd_uv < 0) + return dev_err_probe(dev, vdd_uv, "failed to get vdd voltage\n"); mpr121 = devm_kzalloc(dev, sizeof(*mpr121), GFP_KERNEL); if (!mpr121) @@ -369,7 +330,7 @@ static int mpr_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume); static const struct i2c_device_id mpr121_id[] = { - { "mpr121_touchkey", 0 }, + { "mpr121_touchkey" }, { } }; MODULE_DEVICE_TABLE(i2c, mpr121_id); diff --git a/drivers/input/keyboard/mt6779-keypad.c b/drivers/input/keyboard/mt6779-keypad.c index 19f69d167fbd..e5eb025c5e99 100644 --- a/drivers/input/keyboard/mt6779-keypad.c +++ b/drivers/input/keyboard/mt6779-keypad.c @@ -92,11 +92,6 @@ static irqreturn_t mt6779_keypad_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static void mt6779_keypad_clk_disable(void *data) -{ - clk_disable_unprepare(data); -} - static void mt6779_keypad_calc_row_col_single(unsigned int key, unsigned int *row, unsigned int *col) @@ -213,21 +208,10 @@ static int mt6779_keypad_pdrv_probe(struct platform_device *pdev) regmap_update_bits(keypad->regmap, MTK_KPD_SEL, MTK_KPD_SEL_COL, MTK_KPD_SEL_COLMASK(keypad->n_cols)); - keypad->clk = devm_clk_get(&pdev->dev, "kpd"); + keypad->clk = devm_clk_get_enabled(&pdev->dev, "kpd"); if (IS_ERR(keypad->clk)) return PTR_ERR(keypad->clk); - error = clk_prepare_enable(keypad->clk); - if (error) { - dev_err(&pdev->dev, "cannot prepare/enable keypad clock\n"); - return error; - } - - error = devm_add_action_or_reset(&pdev->dev, mt6779_keypad_clk_disable, - keypad->clk); - if (error) - return error; - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -260,6 +244,7 @@ static const struct of_device_id mt6779_keypad_of_match[] = { { .compatible = "mediatek,mt6873-keypad" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, mt6779_keypad_of_match); static struct platform_driver mt6779_keypad_pdrv = { .probe = mt6779_keypad_pdrv_probe, diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c index 4364c3401ff1..061d48350df6 100644 --- a/drivers/input/keyboard/mtk-pmic-keys.c +++ b/drivers/input/keyboard/mtk-pmic-keys.c @@ -147,8 +147,8 @@ static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys, u32 value, mask; int error; - kregs_home = keys->keys[MTK_PMIC_HOMEKEY_INDEX].regs; - kregs_pwr = keys->keys[MTK_PMIC_PWRKEY_INDEX].regs; + kregs_home = ®s->keys_regs[MTK_PMIC_HOMEKEY_INDEX]; + kregs_pwr = ®s->keys_regs[MTK_PMIC_PWRKEY_INDEX]; error = of_property_read_u32(keys->dev->of_node, "power-off-time-sec", &long_press_debounce); @@ -307,7 +307,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) int error, index = 0; unsigned int keycount; struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent); - struct device_node *node = pdev->dev.of_node, *child; + struct device_node *node = pdev->dev.of_node; static const char *const irqnames[] = { "powerkey", "homekey" }; static const char *const irqnames_r[] = { "powerkey_r", "homekey_r" }; struct mtk_pmic_keys *keys; @@ -343,24 +343,20 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) return -EINVAL; } - for_each_child_of_node(node, child) { + for_each_child_of_node_scoped(node, child) { keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index]; keys->keys[index].irq = platform_get_irq_byname(pdev, irqnames[index]); - if (keys->keys[index].irq < 0) { - of_node_put(child); + if (keys->keys[index].irq < 0) return keys->keys[index].irq; - } if (of_device_is_compatible(node, "mediatek,mt6358-keys")) { keys->keys[index].irq_r = platform_get_irq_byname(pdev, irqnames_r[index]); - if (keys->keys[index].irq_r < 0) { - of_node_put(child); + if (keys->keys[index].irq_r < 0) return keys->keys[index].irq_r; - } } error = of_property_read_u32(child, @@ -369,7 +365,6 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) dev_err(keys->dev, "failed to read key:%d linux,keycode property: %d\n", index, error); - of_node_put(child); return error; } @@ -377,10 +372,8 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) keys->keys[index].wakeup = true; error = mtk_pmic_key_setup(keys, &keys->keys[index]); - if (error) { - of_node_put(child); + if (error) return error; - } index++; } diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c index df00a119aa9a..71e0a3f830dd 100644 --- a/drivers/input/keyboard/newtonkbd.c +++ b/drivers/input/keyboard/newtonkbd.c @@ -68,7 +68,7 @@ static int nkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - nkbd = kzalloc(sizeof(struct nkbd), GFP_KERNEL); + nkbd = kzalloc(sizeof(*nkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!nkbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c deleted file mode 100644 index b3ccc97f61e1..000000000000 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ /dev/null @@ -1,378 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson - * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson - * - * Keypad controller driver for the SKE (Scroll Key Encoder) module used in - * the Nomadik 8815 and Ux500 platforms. - */ - -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/clk.h> -#include <linux/module.h> - -#include <linux/platform_data/keypad-nomadik-ske.h> - -/* SKE_CR bits */ -#define SKE_KPMLT (0x1 << 6) -#define SKE_KPCN (0x7 << 3) -#define SKE_KPASEN (0x1 << 2) -#define SKE_KPASON (0x1 << 7) - -/* SKE_IMSC bits */ -#define SKE_KPIMA (0x1 << 2) - -/* SKE_ICR bits */ -#define SKE_KPICS (0x1 << 3) -#define SKE_KPICA (0x1 << 2) - -/* SKE_RIS bits */ -#define SKE_KPRISA (0x1 << 2) - -#define SKE_KEYPAD_ROW_SHIFT 3 -#define SKE_KPD_NUM_ROWS 8 -#define SKE_KPD_NUM_COLS 8 - -/* keypad auto scan registers */ -#define SKE_ASR0 0x20 -#define SKE_ASR1 0x24 -#define SKE_ASR2 0x28 -#define SKE_ASR3 0x2C - -#define SKE_NUM_ASRX_REGISTERS (4) -#define KEY_PRESSED_DELAY 10 - -/** - * struct ske_keypad - data structure used by keypad driver - * @irq: irq no - * @reg_base: ske registers base address - * @input: pointer to input device object - * @board: keypad platform device - * @keymap: matrix scan code table for keycodes - * @clk: clock structure pointer - * @pclk: clock structure pointer - * @ske_keypad_lock: spinlock protecting the keypad read/writes - */ -struct ske_keypad { - int irq; - void __iomem *reg_base; - struct input_dev *input; - const struct ske_keypad_platform_data *board; - unsigned short keymap[SKE_KPD_NUM_ROWS * SKE_KPD_NUM_COLS]; - struct clk *clk; - struct clk *pclk; - spinlock_t ske_keypad_lock; -}; - -static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr, - u8 mask, u8 data) -{ - u32 ret; - - spin_lock(&keypad->ske_keypad_lock); - - ret = readl(keypad->reg_base + addr); - ret &= ~mask; - ret |= data; - writel(ret, keypad->reg_base + addr); - - spin_unlock(&keypad->ske_keypad_lock); -} - -/* - * ske_keypad_chip_init: init keypad controller configuration - * - * Enable Multi key press detection, auto scan mode - */ -static int __init ske_keypad_chip_init(struct ske_keypad *keypad) -{ - u32 value; - int timeout = keypad->board->debounce_ms; - - /* check SKE_RIS to be 0 */ - while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--) - cpu_relax(); - - if (timeout == -1) - return -EINVAL; - - /* - * set debounce value - * keypad dbounce is configured in DBCR[15:8] - * dbounce value in steps of 32/32.768 ms - */ - spin_lock(&keypad->ske_keypad_lock); - value = readl(keypad->reg_base + SKE_DBCR); - value = value & 0xff; - value |= ((keypad->board->debounce_ms * 32000)/32768) << 8; - writel(value, keypad->reg_base + SKE_DBCR); - spin_unlock(&keypad->ske_keypad_lock); - - /* enable multi key detection */ - ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT); - - /* - * set up the number of columns - * KPCN[5:3] defines no. of keypad columns to be auto scanned - */ - value = (keypad->board->kcol - 1) << 3; - ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value); - - /* clear keypad interrupt for auto(and pending SW) scans */ - ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS); - - /* un-mask keypad interrupts */ - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - /* enable automatic scan */ - ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN); - - return 0; -} - -static void ske_keypad_report(struct ske_keypad *keypad, u8 status, int col) -{ - int row = 0, code, pos; - struct input_dev *input = keypad->input; - u32 ske_ris; - int key_pressed; - int num_of_rows; - - /* find out the row */ - num_of_rows = hweight8(status); - do { - pos = __ffs(status); - row = pos; - status &= ~(1 << pos); - - code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT); - ske_ris = readl(keypad->reg_base + SKE_RIS); - key_pressed = ske_ris & SKE_KPRISA; - - input_event(input, EV_MSC, MSC_SCAN, code); - input_report_key(input, keypad->keymap[code], key_pressed); - input_sync(input); - num_of_rows--; - } while (num_of_rows); -} - -static void ske_keypad_read_data(struct ske_keypad *keypad) -{ - u8 status; - int col = 0; - int ske_asr, i; - - /* - * Read the auto scan registers - * - * Each SKE_ASRx (x=0 to x=3) contains two row values. - * lower byte contains row value for column 2*x, - * upper byte contains row value for column 2*x + 1 - */ - for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) { - ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i)); - if (!ske_asr) - continue; - - /* now that ASRx is zero, find out the coloumn x and row y */ - status = ske_asr & 0xff; - if (status) { - col = i * 2; - ske_keypad_report(keypad, status, col); - } - status = (ske_asr & 0xff00) >> 8; - if (status) { - col = (i * 2) + 1; - ske_keypad_report(keypad, status, col); - } - } -} - -static irqreturn_t ske_keypad_irq(int irq, void *dev_id) -{ - struct ske_keypad *keypad = dev_id; - int timeout = keypad->board->debounce_ms; - - /* disable auto scan interrupt; mask the interrupt generated */ - ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0); - ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA); - - while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --timeout) - cpu_relax(); - - /* SKEx registers are stable and can be read */ - ske_keypad_read_data(keypad); - - /* wait until raw interrupt is clear */ - while ((readl(keypad->reg_base + SKE_RIS)) && --timeout) - msleep(KEY_PRESSED_DELAY); - - /* enable auto scan interrupts */ - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - return IRQ_HANDLED; -} - -static void ske_keypad_board_exit(void *data) -{ - struct ske_keypad *keypad = data; - - keypad->board->exit(); -} - -static int __init ske_keypad_probe(struct platform_device *pdev) -{ - const struct ske_keypad_platform_data *plat = - dev_get_platdata(&pdev->dev); - struct device *dev = &pdev->dev; - struct ske_keypad *keypad; - struct input_dev *input; - int irq; - int error; - - if (!plat) { - dev_err(&pdev->dev, "invalid keypad platform data\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - keypad = devm_kzalloc(dev, sizeof(struct ske_keypad), - GFP_KERNEL); - input = devm_input_allocate_device(dev); - if (!keypad || !input) { - dev_err(&pdev->dev, "failed to allocate keypad memory\n"); - return -ENOMEM; - } - - keypad->irq = irq; - keypad->board = plat; - keypad->input = input; - spin_lock_init(&keypad->ske_keypad_lock); - - keypad->reg_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(keypad->reg_base)) - return PTR_ERR(keypad->reg_base); - - keypad->pclk = devm_clk_get_enabled(dev, "apb_pclk"); - if (IS_ERR(keypad->pclk)) { - dev_err(&pdev->dev, "failed to get pclk\n"); - return PTR_ERR(keypad->pclk); - } - - keypad->clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(keypad->clk)) { - dev_err(&pdev->dev, "failed to get clk\n"); - return PTR_ERR(keypad->clk); - } - - input->id.bustype = BUS_HOST; - input->name = "ux500-ske-keypad"; - input->dev.parent = &pdev->dev; - - error = matrix_keypad_build_keymap(plat->keymap_data, NULL, - SKE_KPD_NUM_ROWS, SKE_KPD_NUM_COLS, - keypad->keymap, input); - if (error) { - dev_err(&pdev->dev, "Failed to build keymap\n"); - return error; - } - - input_set_capability(input, EV_MSC, MSC_SCAN); - if (!plat->no_autorepeat) - __set_bit(EV_REP, input->evbit); - - /* go through board initialization helpers */ - if (keypad->board->init) - keypad->board->init(); - - if (keypad->board->exit) { - error = devm_add_action_or_reset(dev, ske_keypad_board_exit, - keypad); - if (error) - return error; - } - - error = ske_keypad_chip_init(keypad); - if (error) { - dev_err(&pdev->dev, "unable to init keypad hardware\n"); - return error; - } - - error = devm_request_threaded_irq(dev, keypad->irq, - NULL, ske_keypad_irq, - IRQF_ONESHOT, "ske-keypad", keypad); - if (error) { - dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq); - return error; - } - - error = input_register_device(input); - if (error) { - dev_err(&pdev->dev, - "unable to register input device: %d\n", error); - return error; - } - - if (plat->wakeup_enable) - device_init_wakeup(&pdev->dev, true); - - platform_set_drvdata(pdev, keypad); - - return 0; -} - -static int ske_keypad_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ske_keypad *keypad = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (device_may_wakeup(dev)) - enable_irq_wake(irq); - else - ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0); - - return 0; -} - -static int ske_keypad_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct ske_keypad *keypad = platform_get_drvdata(pdev); - int irq = platform_get_irq(pdev, 0); - - if (device_may_wakeup(dev)) - disable_irq_wake(irq); - else - ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops, - ske_keypad_suspend, ske_keypad_resume); - -static struct platform_driver ske_keypad_driver = { - .driver = { - .name = "nmk-ske-keypad", - .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops), - }, -}; - -module_platform_driver_probe(ske_keypad_driver, ske_keypad_probe); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>"); -MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver"); -MODULE_ALIAS("platform:nomadik-ske-keypad"); diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 16f936db7305..9e13f3f70a81 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -156,21 +156,27 @@ static ssize_t omap_kp_enable_store(struct device *dev, struct device_attribute if ((state != 1) && (state != 0)) return -EINVAL; - mutex_lock(&kp_enable_mutex); - if (state != kp_enable) { - if (state) - enable_irq(omap_kp->irq); - else - disable_irq(omap_kp->irq); - kp_enable = state; + scoped_guard(mutex, &kp_enable_mutex) { + if (state != kp_enable) { + if (state) + enable_irq(omap_kp->irq); + else + disable_irq(omap_kp->irq); + kp_enable = state; + } } - mutex_unlock(&kp_enable_mutex); return strnlen(buf, count); } static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, omap_kp_enable_show, omap_kp_enable_store); +static struct attribute *omap_kp_attrs[] = { + &dev_attr_enable.attr, + NULL +}; +ATTRIBUTE_GROUPS(omap_kp); + static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; @@ -214,10 +220,6 @@ static int omap_kp_probe(struct platform_device *pdev) kp_tasklet.data = (unsigned long) omap_kp; tasklet_enable(&kp_tasklet); - ret = device_create_file(&pdev->dev, &dev_attr_enable); - if (ret < 0) - goto err2; - /* setup input device */ input_dev->name = "omap-keypad"; input_dev->phys = "omap-keypad/input0"; @@ -235,12 +237,12 @@ static int omap_kp_probe(struct platform_device *pdev) pdata->rows, pdata->cols, omap_kp->keymap, input_dev); if (ret < 0) - goto err3; + goto err2; ret = input_register_device(omap_kp->input); if (ret < 0) { printk(KERN_ERR "Unable to register omap-keypad input device\n"); - goto err3; + goto err2; } if (pdata->dbounce) @@ -252,17 +254,15 @@ static int omap_kp_probe(struct platform_device *pdev) if (omap_kp->irq >= 0) { if (request_irq(omap_kp->irq, omap_kp_interrupt, 0, "omap-keypad", omap_kp) < 0) - goto err4; + goto err3; } omap_writew(0, OMAP1_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT); return 0; -err4: +err3: input_unregister_device(omap_kp->input); input_dev = NULL; -err3: - device_remove_file(&pdev->dev, &dev_attr_enable); err2: kfree(omap_kp); input_free_device(input_dev); @@ -290,9 +290,10 @@ static void omap_kp_remove(struct platform_device *pdev) static struct platform_driver omap_kp_driver = { .probe = omap_kp_probe, - .remove_new = omap_kp_remove, + .remove = omap_kp_remove, .driver = { .name = "omap-keypad", + .dev_groups = omap_kp_groups, }, }; module_platform_driver(omap_kp_driver); diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 040b340995d8..bffe89c0717a 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -144,7 +144,7 @@ static void omap4_keypad_scan_keys(struct omap4_keypad *keypad_data, u64 keys) { u64 changed; - mutex_lock(&keypad_data->lock); + guard(mutex)(&keypad_data->lock); changed = keys ^ keypad_data->keys; @@ -158,8 +158,6 @@ static void omap4_keypad_scan_keys(struct omap4_keypad *keypad_data, u64 keys) omap4_keypad_report_keys(keypad_data, changed & keys, true); keypad_data->keys = keys; - - mutex_unlock(&keypad_data->lock); } /* Interrupt handlers */ @@ -487,7 +485,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); static struct platform_driver omap4_keypad_driver = { .probe = omap4_keypad_probe, - .remove_new = omap4_keypad_remove, + .remove = omap4_keypad_remove, .driver = { .name = "omap4-keypad", .of_match_table = omap_keypad_dt_match, diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 26a005f9ace3..35d1aa2a22a5 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -630,12 +630,10 @@ static int pmic8xxx_kp_suspend(struct device *dev) if (device_may_wakeup(dev)) { enable_irq_wake(kp->key_sense_irq); } else { - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) pmic8xxx_kp_disable(kp); - - mutex_unlock(&input_dev->mutex); } return 0; @@ -650,12 +648,10 @@ static int pmic8xxx_kp_resume(struct device *dev) if (device_may_wakeup(dev)) { disable_irq_wake(kp->key_sense_irq); } else { - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) pmic8xxx_kp_enable(kp); - - mutex_unlock(&input_dev->mutex); } return 0; diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 3724363d140e..38ec619aa359 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -682,7 +682,7 @@ static int pxa27x_keypad_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); struct input_dev *input_dev = keypad->input_dev; - int ret = 0; + int error; /* * If the keypad is used as wake up source, the clock is not turned @@ -691,19 +691,19 @@ static int pxa27x_keypad_resume(struct device *dev) if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(keypad->irq); } else { - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) { /* Enable unit clock */ - ret = clk_prepare_enable(keypad->clk); - if (!ret) - pxa27x_keypad_config(keypad); - } + error = clk_prepare_enable(keypad->clk); + if (error) + return error; - mutex_unlock(&input_dev->mutex); + pxa27x_keypad_config(keypad); + } } - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops, diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c index b51dfcd76038..bce8157d1871 100644 --- a/drivers/input/keyboard/qt1050.c +++ b/drivers/input/keyboard/qt1050.c @@ -208,7 +208,7 @@ static const struct regmap_access_table qt1050_writeable_table = { .n_yes_ranges = ARRAY_SIZE(qt1050_writeable_ranges), }; -static struct regmap_config qt1050_regmap_config = { +static const struct regmap_config qt1050_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = QT1050_RES_CAL, @@ -226,7 +226,12 @@ static bool qt1050_identify(struct qt1050_priv *ts) int err; /* Read Chip ID */ - regmap_read(ts->regmap, QT1050_CHIP_ID, &val); + err = regmap_read(ts->regmap, QT1050_CHIP_ID, &val); + if (err) { + dev_err(&ts->client->dev, "Failed to read chip ID: %d\n", err); + return false; + } + if (val != QT1050_CHIP_ID_VER) { dev_err(&ts->client->dev, "ID %d not supported\n", val); return false; @@ -341,35 +346,34 @@ static int qt1050_apply_fw_data(struct qt1050_priv *ts) static int qt1050_parse_fw(struct qt1050_priv *ts) { struct device *dev = &ts->client->dev; - struct fwnode_handle *child; int nbuttons; nbuttons = device_get_child_node_count(dev); if (nbuttons == 0 || nbuttons > QT1050_MAX_KEYS) return -ENODEV; - device_for_each_child_node(dev, child) { + device_for_each_child_node_scoped(dev, child) { struct qt1050_key button; /* Required properties */ if (fwnode_property_read_u32(child, "linux,code", &button.keycode)) { dev_err(dev, "Button without keycode\n"); - goto err; + return -EINVAL; } if (button.keycode >= KEY_MAX) { dev_err(dev, "Invalid keycode 0x%x\n", button.keycode); - goto err; + return -EINVAL; } if (fwnode_property_read_u32(child, "reg", &button.num)) { dev_err(dev, "Button without pad number\n"); - goto err; + return -EINVAL; } if (button.num < 0 || button.num > QT1050_MAX_KEYS - 1) - goto err; + return -EINVAL; ts->reg_keys |= BIT(button.num); @@ -419,10 +423,6 @@ static int qt1050_parse_fw(struct qt1050_priv *ts) } return 0; - -err: - fwnode_handle_put(child); - return -EINVAL; } static int qt1050_probe(struct i2c_client *client) diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index 9b093b042bf1..b3db2c7d0957 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -234,8 +234,8 @@ static int qt1070_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume); static const struct i2c_device_id qt1070_id[] = { - { "qt1070", 0 }, - { }, + { "qt1070" }, + { } }; MODULE_DEVICE_TABLE(i2c, qt1070_id); diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 7e3b09642ab7..53f5255fd19d 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -393,7 +393,7 @@ static int qt2160_probe(struct i2c_client *client) } static const struct i2c_device_id qt2160_idtable[] = { - { "qt2160", 0, }, + { "qt2160" }, { } }; diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index e212eff7687c..9f1049aa3048 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -587,7 +587,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids); static struct platform_driver samsung_keypad_driver = { .probe = samsung_keypad_probe, - .remove_new = samsung_keypad_remove, + .remove = samsung_keypad_remove, .driver = { .name = "samsung-keypad", .of_match_table = of_match_ptr(samsung_keypad_dt_match), diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 4ea4fd25c5d2..159f41eedd41 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -319,7 +319,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops, static struct platform_driver sh_keysc_device_driver = { .probe = sh_keysc_probe, - .remove_new = sh_keysc_remove, + .remove = sh_keysc_remove, .driver = { .name = "sh_keysc", .pm = pm_sleep_ptr(&sh_keysc_dev_pm_ops), diff --git a/drivers/input/keyboard/snvs_pwrkey.c b/drivers/input/keyboard/snvs_pwrkey.c index ad8660be0127..bbf409dda89f 100644 --- a/drivers/input/keyboard/snvs_pwrkey.c +++ b/drivers/input/keyboard/snvs_pwrkey.c @@ -100,16 +100,11 @@ static irqreturn_t imx_snvs_pwrkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void imx_snvs_pwrkey_disable_clk(void *data) -{ - clk_disable_unprepare(data); -} - static void imx_snvs_pwrkey_act(void *pdata) { struct pwrkey_drv_data *pd = pdata; - del_timer_sync(&pd->check_timer); + timer_delete_sync(&pd->check_timer); } static int imx_snvs_pwrkey_probe(struct platform_device *pdev) @@ -141,28 +136,12 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n"); } - clk = devm_clk_get_optional(&pdev->dev, NULL); + clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) { dev_err(&pdev->dev, "Failed to get snvs clock (%pe)\n", clk); return PTR_ERR(clk); } - error = clk_prepare_enable(clk); - if (error) { - dev_err(&pdev->dev, "Failed to enable snvs clock (%pe)\n", - ERR_PTR(error)); - return error; - } - - error = devm_add_action_or_reset(&pdev->dev, - imx_snvs_pwrkey_disable_clk, clk); - if (error) { - dev_err(&pdev->dev, - "Failed to register clock cleanup handler (%pe)\n", - ERR_PTR(error)); - return error; - } - pdata->wakeup = of_property_read_bool(np, "wakeup-source"); pdata->irq = platform_get_irq(pdev, 0); @@ -204,7 +183,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device *pdev) error = devm_request_irq(&pdev->dev, pdata->irq, imx_snvs_pwrkey_interrupt, 0, pdev->name, pdev); - if (error) { dev_err(&pdev->dev, "interrupt not available.\n"); return error; diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index 557d00a667ce..2fae337562a2 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -20,7 +20,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/pm_wakeup.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/platform_data/keyboard-spear.h> @@ -222,7 +221,7 @@ static int spear_kbd_probe(struct platform_device *pdev) if (IS_ERR(kbd->io_base)) return PTR_ERR(kbd->io_base); - kbd->clk = devm_clk_get(&pdev->dev, NULL); + kbd->clk = devm_clk_get_prepared(&pdev->dev, NULL); if (IS_ERR(kbd->clk)) return PTR_ERR(kbd->clk); @@ -255,14 +254,9 @@ static int spear_kbd_probe(struct platform_device *pdev) return error; } - error = clk_prepare(kbd->clk); - if (error) - return error; - error = input_register_device(input_dev); if (error) { dev_err(&pdev->dev, "Unable to register keyboard device\n"); - clk_unprepare(kbd->clk); return error; } @@ -272,14 +266,6 @@ static int spear_kbd_probe(struct platform_device *pdev) return 0; } -static void spear_kbd_remove(struct platform_device *pdev) -{ - struct spear_kbd *kbd = platform_get_drvdata(pdev); - - input_unregister_device(kbd->input); - clk_unprepare(kbd->clk); -} - static int spear_kbd_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -287,7 +273,7 @@ static int spear_kbd_suspend(struct device *dev) struct input_dev *input_dev = kbd->input; unsigned int rate = 0, mode_ctl_reg, val; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); /* explicitly enable clock as we may program device */ clk_enable(kbd->clk); @@ -328,8 +314,6 @@ static int spear_kbd_suspend(struct device *dev) /* restore previous clk state */ clk_disable(kbd->clk); - mutex_unlock(&input_dev->mutex); - return 0; } @@ -339,7 +323,7 @@ static int spear_kbd_resume(struct device *dev) struct spear_kbd *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (device_may_wakeup(&pdev->dev)) { if (kbd->irq_wake_enabled) { @@ -355,8 +339,6 @@ static int spear_kbd_resume(struct device *dev) if (input_device_enabled(input_dev)) writel_relaxed(kbd->mode_ctl_reg, kbd->io_base + MODE_CTL_REG); - mutex_unlock(&input_dev->mutex); - return 0; } @@ -373,7 +355,6 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table); static struct platform_driver spear_kbd_driver = { .probe = spear_kbd_probe, - .remove_new = spear_kbd_remove, .driver = { .name = "keyboard", .pm = pm_sleep_ptr(&spear_kbd_pm_ops), diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c index 0d27324af809..e53ef4c670e4 100644 --- a/drivers/input/keyboard/st-keyscan.c +++ b/drivers/input/keyboard/st-keyscan.c @@ -216,14 +216,13 @@ static int keyscan_suspend(struct device *dev) struct st_keyscan *keypad = platform_get_drvdata(pdev); struct input_dev *input = keypad->input_dev; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); if (device_may_wakeup(dev)) enable_irq_wake(keypad->irq); else if (input_device_enabled(input)) keyscan_stop(keypad); - mutex_unlock(&input->mutex); return 0; } @@ -232,17 +231,19 @@ static int keyscan_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct st_keyscan *keypad = platform_get_drvdata(pdev); struct input_dev *input = keypad->input_dev; - int retval = 0; + int error; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); - if (device_may_wakeup(dev)) + if (device_may_wakeup(dev)) { disable_irq_wake(keypad->irq); - else if (input_device_enabled(input)) - retval = keyscan_start(keypad); + } else if (input_device_enabled(input)) { + error = keyscan_start(keypad); + if (error) + return error; + } - mutex_unlock(&input->mutex); - return retval; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 2013c0afd0c3..0acded4fb9c9 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -413,9 +413,8 @@ static void stmpe_keypad_remove(struct platform_device *pdev) static struct platform_driver stmpe_keypad_driver = { .driver.name = "stmpe-keypad", - .driver.owner = THIS_MODULE, .probe = stmpe_keypad_probe, - .remove_new = stmpe_keypad_remove, + .remove = stmpe_keypad_remove, }; module_platform_driver(stmpe_keypad_driver); diff --git a/drivers/input/keyboard/stowaway.c b/drivers/input/keyboard/stowaway.c index 56e784936059..7ef0b3f4f549 100644 --- a/drivers/input/keyboard/stowaway.c +++ b/drivers/input/keyboard/stowaway.c @@ -72,7 +72,7 @@ static int skbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - skbd = kzalloc(sizeof(struct skbd), GFP_KERNEL); + skbd = kzalloc(sizeof(*skbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!skbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index f304cab0ebdb..5730f08f82d7 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -24,7 +24,6 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_wakeirq.h> -#include <linux/pm_wakeup.h> #include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> @@ -202,7 +201,7 @@ static void sun4i_lradc_close(struct input_dev *dev) static int sun4i_lradc_load_dt_keymap(struct device *dev, struct sun4i_lradc_data *lradc) { - struct device_node *np, *pp; + struct device_node *np; int i; int error; @@ -223,28 +222,25 @@ static int sun4i_lradc_load_dt_keymap(struct device *dev, return -ENOMEM; i = 0; - for_each_child_of_node(np, pp) { + for_each_child_of_node_scoped(np, pp) { struct sun4i_lradc_keymap *map = &lradc->chan0_map[i]; u32 channel; error = of_property_read_u32(pp, "channel", &channel); if (error || channel != 0) { dev_err(dev, "%pOFn: Inval channel prop\n", pp); - of_node_put(pp); return -EINVAL; } error = of_property_read_u32(pp, "voltage", &map->voltage); if (error) { dev_err(dev, "%pOFn: Inval voltage prop\n", pp); - of_node_put(pp); return -EINVAL; } error = of_property_read_u32(pp, "linux,code", &map->keycode); if (error) { dev_err(dev, "%pOFn: Inval linux,code prop\n", pp); - of_node_put(pp); return -EINVAL; } diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index b123a208ef36..3299e1919b37 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -241,9 +241,8 @@ static void sunkbd_reinit(struct work_struct *work) static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) { - serio_pause_rx(sunkbd->serio); - sunkbd->enabled = enable; - serio_continue_rx(sunkbd->serio); + scoped_guard(serio_pause_rx, sunkbd->serio) + sunkbd->enabled = enable; if (!enable) { wake_up_interruptible(&sunkbd->wait); @@ -263,7 +262,7 @@ static int sunkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - sunkbd = kzalloc(sizeof(struct sunkbd), GFP_KERNEL); + sunkbd = kzalloc(sizeof(*sunkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!sunkbd || !input_dev) goto fail1; diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index b0d86621c60a..11988cffdfae 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -325,7 +325,6 @@ tc3589x_keypad_of_probe(struct device *dev) struct tc3589x_keypad_platform_data *plat; u32 cols, rows; u32 debounce_ms; - int proplen; if (!np) return ERR_PTR(-ENODEV); @@ -346,7 +345,7 @@ tc3589x_keypad_of_probe(struct device *dev) return ERR_PTR(-EINVAL); } - if (!of_get_property(np, "linux,keymap", &proplen)) { + if (!of_property_present(np, "linux,keymap")) { dev_err(dev, "property linux,keymap not found\n"); return ERR_PTR(-ENOENT); } diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 677bc4baa5d1..fbc674d7b9f0 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -32,11 +32,6 @@ static const struct i2c_device_id tca6416_id[] = { }; MODULE_DEVICE_TABLE(i2c, tca6416_id); -struct tca6416_drv_data { - struct input_dev *input; - struct tca6416_button data[]; -}; - struct tca6416_keypad_chip { uint16_t reg_output; uint16_t reg_direction; @@ -45,7 +40,6 @@ struct tca6416_keypad_chip { struct i2c_client *client; struct input_dev *input; int io_size; - int irqnum; u16 pinmask; bool use_polling; struct tca6416_button buttons[]; diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index a1765ed8c825..32a676f0de53 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -241,11 +241,10 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) static void tegra_kbc_keypress_timer(struct timer_list *t) { struct tegra_kbc *kbc = from_timer(kbc, t, timer); - unsigned long flags; u32 val; unsigned int i; - spin_lock_irqsave(&kbc->lock, flags); + guard(spinlock_irqsave)(&kbc->lock); val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf; if (val) { @@ -270,17 +269,14 @@ static void tegra_kbc_keypress_timer(struct timer_list *t) /* All keys are released so enable the keypress interrupt */ tegra_kbc_set_fifo_interrupt(kbc, true); } - - spin_unlock_irqrestore(&kbc->lock, flags); } static irqreturn_t tegra_kbc_isr(int irq, void *args) { struct tegra_kbc *kbc = args; - unsigned long flags; u32 val; - spin_lock_irqsave(&kbc->lock, flags); + guard(spinlock_irqsave)(&kbc->lock); /* * Quickly bail out & reenable interrupts if the fifo threshold @@ -301,8 +297,6 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args) kbc->keypress_caused_wake = true; } - spin_unlock_irqrestore(&kbc->lock, flags); - return IRQ_HANDLED; } @@ -413,17 +407,16 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) static void tegra_kbc_stop(struct tegra_kbc *kbc) { - unsigned long flags; u32 val; - spin_lock_irqsave(&kbc->lock, flags); - val = readl(kbc->mmio + KBC_CONTROL_0); - val &= ~1; - writel(val, kbc->mmio + KBC_CONTROL_0); - spin_unlock_irqrestore(&kbc->lock, flags); + scoped_guard(spinlock_irqsave, &kbc->lock) { + val = readl(kbc->mmio + KBC_CONTROL_0); + val &= ~1; + writel(val, kbc->mmio + KBC_CONTROL_0); + } disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); clk_disable_unprepare(kbc->clk); } @@ -491,12 +484,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) struct device_node *np = kbc->dev->of_node; u32 prop; int i; - u32 num_rows = 0; - u32 num_cols = 0; + int num_rows; + int num_cols; u32 cols_cfg[KBC_MAX_GPIO]; u32 rows_cfg[KBC_MAX_GPIO]; - int proplen; - int ret; if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) kbc->debounce_cnt = prop; @@ -510,56 +501,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ kbc->wakeup = true; - if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { - dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); - return -ENOENT; - } - num_rows = proplen / sizeof(u32); - - if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { - dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); - return -ENOENT; - } - num_cols = proplen / sizeof(u32); - - if (num_rows > kbc->hw_support->max_rows) { - dev_err(kbc->dev, - "Number of rows is more than supported by hardware\n"); - return -EINVAL; - } - - if (num_cols > kbc->hw_support->max_columns) { - dev_err(kbc->dev, - "Number of cols is more than supported by hardware\n"); - return -EINVAL; - } - - if (!of_get_property(np, "linux,keymap", &proplen)) { + if (!of_property_present(np, "linux,keymap")) { dev_err(kbc->dev, "property linux,keymap not found\n"); return -ENOENT; } - if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { - dev_err(kbc->dev, - "keypad rows/columns not properly specified\n"); - return -EINVAL; - } - /* Set all pins as non-configured */ for (i = 0; i < kbc->num_rows_and_columns; i++) kbc->pin_cfg[i].type = PIN_CFG_IGNORE; - ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", - rows_cfg, num_rows); - if (ret < 0) { + num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins", + rows_cfg, 1, KBC_MAX_GPIO); + if (num_rows < 0) { dev_err(kbc->dev, "Rows configurations are not proper\n"); - return -EINVAL; - } - - ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", - cols_cfg, num_cols); - if (ret < 0) { - dev_err(kbc->dev, "Cols configurations are not proper\n"); + return num_rows; + } else if (num_rows > kbc->hw_support->max_rows) { + dev_err(kbc->dev, + "Number of rows is more than supported by hardware\n"); return -EINVAL; } @@ -568,11 +526,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) kbc->pin_cfg[rows_cfg[i]].num = i; } + num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins", + cols_cfg, 1, KBC_MAX_GPIO); + if (num_cols < 0) { + dev_err(kbc->dev, "Cols configurations are not proper\n"); + return num_cols; + } else if (num_cols > kbc->hw_support->max_columns) { + dev_err(kbc->dev, + "Number of cols is more than supported by hardware\n"); + return -EINVAL; + } + for (i = 0; i < num_cols; i++) { kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; kbc->pin_cfg[cols_cfg[i]].num = i; } + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { + dev_err(kbc->dev, + "keypad rows/columns not properly specified\n"); + return -EINVAL; + } + return 0; } @@ -724,10 +699,11 @@ static int tegra_kbc_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct tegra_kbc *kbc = platform_get_drvdata(pdev); - mutex_lock(&kbc->idev->mutex); + guard(mutex)(&kbc->idev->mutex); + if (device_may_wakeup(&pdev->dev)) { disable_irq(kbc->irq); - del_timer_sync(&kbc->timer); + timer_delete_sync(&kbc->timer); tegra_kbc_set_fifo_interrupt(kbc, false); /* Forcefully clear the interrupt status */ @@ -747,11 +723,9 @@ static int tegra_kbc_suspend(struct device *dev) tegra_kbc_set_keypress_interrupt(kbc, true); enable_irq(kbc->irq); enable_irq_wake(kbc->irq); - } else { - if (input_device_enabled(kbc->idev)) - tegra_kbc_stop(kbc); + } else if (input_device_enabled(kbc->idev)) { + tegra_kbc_stop(kbc); } - mutex_unlock(&kbc->idev->mutex); return 0; } @@ -760,9 +734,10 @@ static int tegra_kbc_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct tegra_kbc *kbc = platform_get_drvdata(pdev); - int err = 0; + int err; + + guard(mutex)(&kbc->idev->mutex); - mutex_lock(&kbc->idev->mutex); if (device_may_wakeup(&pdev->dev)) { disable_irq_wake(kbc->irq); tegra_kbc_setup_wakekeys(kbc, false); @@ -787,13 +762,13 @@ static int tegra_kbc_resume(struct device *dev) input_report_key(kbc->idev, kbc->wakeup_key, 0); input_sync(kbc->idev); } - } else { - if (input_device_enabled(kbc->idev)) - err = tegra_kbc_start(kbc); + } else if (input_device_enabled(kbc->idev)) { + err = tegra_kbc_start(kbc); + if (err) + return err; } - mutex_unlock(&kbc->idev->mutex); - return err; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c index 0fd761ae052f..55d699d9037d 100644 --- a/drivers/input/keyboard/tm2-touchkey.c +++ b/drivers/input/keyboard/tm2-touchkey.c @@ -326,8 +326,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops, tm2_touchkey_suspend, tm2_touchkey_resume); static const struct i2c_device_id tm2_touchkey_id_table[] = { - { TM2_TOUCHKEY_DEV_NAME, 0 }, - { }, + { TM2_TOUCHKEY_DEV_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, tm2_touchkey_id_table); diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c index c9d7c2481726..befa713268ae 100644 --- a/drivers/input/keyboard/xtkbd.c +++ b/drivers/input/keyboard/xtkbd.c @@ -70,7 +70,7 @@ static int xtkbd_connect(struct serio *serio, struct serio_driver *drv) int err = -ENOMEM; int i; - xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL); + xtkbd = kmalloc(sizeof(*xtkbd), GFP_KERNEL); input_dev = input_allocate_device(); if (!xtkbd || !input_dev) goto fail1; diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index 4fa53423f56c..3bea3575a0a9 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c @@ -73,10 +73,9 @@ static int matrix_keypad_parse_keymap(const char *propname, struct device *dev = input_dev->dev.parent; unsigned int row_shift = get_count_order(cols); unsigned int max_keys = rows << row_shift; - u32 *keys; int i; int size; - int retval; + int error; if (!propname) propname = "linux,keymap"; @@ -94,30 +93,24 @@ static int matrix_keypad_parse_keymap(const char *propname, return -EINVAL; } - keys = kmalloc_array(size, sizeof(u32), GFP_KERNEL); + u32 *keys __free(kfree) = kmalloc_array(size, sizeof(*keys), GFP_KERNEL); if (!keys) return -ENOMEM; - retval = device_property_read_u32_array(dev, propname, keys, size); - if (retval) { + error = device_property_read_u32_array(dev, propname, keys, size); + if (error) { dev_err(dev, "failed to read %s property: %d\n", - propname, retval); - goto out; + propname, error); + return error; } for (i = 0; i < size; i++) { if (!matrix_keypad_map_key(input_dev, rows, cols, - row_shift, keys[i])) { - retval = -EINVAL; - goto out; - } + row_shift, keys[i])) + return -EINVAL; } - retval = 0; - -out: - kfree(keys); - return retval; + return 0; } /** @@ -199,4 +192,5 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, } EXPORT_SYMBOL(matrix_keypad_build_keymap); +MODULE_DESCRIPTION("Helpers for matrix keyboard bindings"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c index 4b0685f96113..9159b5fec129 100644 --- a/drivers/input/misc/88pm80x_onkey.c +++ b/drivers/input/misc/88pm80x_onkey.c @@ -57,7 +57,7 @@ static int pm80x_onkey_probe(struct platform_device *pdev) struct pm80x_onkey_info *info; int err; - info = kzalloc(sizeof(struct pm80x_onkey_info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -141,7 +141,7 @@ static struct platform_driver pm80x_onkey_driver = { .pm = &pm80x_onkey_pm_ops, }, .probe = pm80x_onkey_probe, - .remove_new = pm80x_onkey_remove, + .remove = pm80x_onkey_remove, }; module_platform_driver(pm80x_onkey_driver); diff --git a/drivers/input/misc/88pm886-onkey.c b/drivers/input/misc/88pm886-onkey.c new file mode 100644 index 000000000000..284ff5190b6e --- /dev/null +++ b/drivers/input/misc/88pm886-onkey.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <linux/input.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <linux/mfd/88pm886.h> + +struct pm886_onkey { + struct input_dev *idev; + struct pm886_chip *chip; +}; + +static irqreturn_t pm886_onkey_irq_handler(int irq, void *data) +{ + struct pm886_onkey *onkey = data; + struct regmap *regmap = onkey->chip->regmap; + struct input_dev *idev = onkey->idev; + struct device *parent = idev->dev.parent; + unsigned int val; + int err; + + err = regmap_read(regmap, PM886_REG_STATUS1, &val); + if (err) { + dev_err(parent, "Failed to read status: %d\n", err); + return IRQ_NONE; + } + val &= PM886_ONKEY_STS1; + + input_report_key(idev, KEY_POWER, val); + input_sync(idev); + + return IRQ_HANDLED; +} + +static int pm886_onkey_probe(struct platform_device *pdev) +{ + struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct pm886_onkey *onkey; + struct input_dev *idev; + int irq, err; + + onkey = devm_kzalloc(dev, sizeof(*onkey), GFP_KERNEL); + if (!onkey) + return -ENOMEM; + + onkey->chip = chip; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "Failed to get IRQ\n"); + + idev = devm_input_allocate_device(dev); + if (!idev) { + dev_err(dev, "Failed to allocate input device\n"); + return -ENOMEM; + } + onkey->idev = idev; + + idev->name = "88pm886-onkey"; + idev->phys = "88pm886-onkey/input0"; + idev->id.bustype = BUS_I2C; + + input_set_capability(idev, EV_KEY, KEY_POWER); + + err = devm_request_threaded_irq(dev, irq, NULL, pm886_onkey_irq_handler, + IRQF_ONESHOT | IRQF_NO_SUSPEND, "onkey", + onkey); + if (err) + return dev_err_probe(dev, err, "Failed to request IRQ\n"); + + err = input_register_device(idev); + if (err) + return dev_err_probe(dev, err, "Failed to register input device\n"); + + return 0; +} + +static const struct platform_device_id pm886_onkey_id_table[] = { + { "88pm886-onkey", }, + { } +}; +MODULE_DEVICE_TABLE(platform, pm886_onkey_id_table); + +static struct platform_driver pm886_onkey_driver = { + .driver = { + .name = "88pm886-onkey", + }, + .probe = pm886_onkey_probe, + .id_table = pm886_onkey_id_table, +}; +module_platform_driver(pm886_onkey_driver); + +MODULE_DESCRIPTION("Marvell 88PM886 onkey driver"); +MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 6ba984d7f0b1..f5496ca0c0d2 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -33,6 +33,13 @@ config INPUT_88PM80X_ONKEY To compile this driver as a module, choose M here: the module will be called 88pm80x_onkey. +config INPUT_88PM886_ONKEY + tristate "Marvell 88PM886 onkey support" + depends on MFD_88PM886_PMIC + help + Support the onkey of Marvell 88PM886 PMIC as an input device + reporting power button status. + config INPUT_AB8500_PONKEY tristate "AB8500 Pon (PowerOn) Key" depends on AB8500_CORE @@ -140,6 +147,16 @@ config INPUT_BMA150 To compile this driver as a module, choose M here: the module will be called bma150. +config INPUT_CS40L50_VIBRA + tristate "CS40L50 Haptic Driver support" + depends on MFD_CS40L50_CORE + help + Say Y here to enable support for Cirrus Logic's CS40L50 + haptic driver. + + To compile this driver as a module, choose M here: the + module will be called cs40l50-vibra. + config INPUT_E3X0_BUTTON tristate "NI Ettus Research USRP E3xx Button support." default n @@ -223,12 +240,12 @@ config INPUT_MAX77650_ONKEY will be called max77650-onkey. config INPUT_MAX77693_HAPTIC - tristate "MAXIM MAX77693/MAX77843 haptic controller support" - depends on (MFD_MAX77693 || MFD_MAX77843) && PWM + tristate "MAXIM MAX77693/MAX77705/MAX77843 haptic controller support" + depends on (MFD_MAX77693 || MFD_MAX77705 || MFD_MAX77843) && PWM select INPUT_FF_MEMLESS help This option enables support for the haptic controller on - MAXIM MAX77693 and MAX77843 chips. + MAXIM MAX77693, MAX77705 and MAX77843 chips. To compile this driver as module, choose M here: the module will be called max77693-haptic. @@ -900,6 +917,18 @@ config INPUT_HISI_POWERKEY To compile this driver as a module, choose M here: the module will be called hisi_powerkey. +config INPUT_QNAP_MCU + tristate "Input Support for QNAP MCU controllers" + depends on MFD_QNAP_MCU + help + This option enables support for input elements available on + embedded controllers used in QNAP NAS devices. + + This includes a polled power-button as well as a beeper. + + To compile this driver as a module, choose M here: the + module will be called qnap-mcu-input. + config INPUT_RAVE_SP_PWRBUTTON tristate "RAVE SP Power button Driver" depends on RAVE_SP_CORE diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 04296a4abe8e..6d91804d0a6f 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o obj-$(CONFIG_INPUT_88PM80X_ONKEY) += 88pm80x_onkey.o +obj-$(CONFIG_INPUT_88PM886_ONKEY) += 88pm886-onkey.o obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o obj-$(CONFIG_INPUT_AD714X) += ad714x.o obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o @@ -28,6 +29,7 @@ obj-$(CONFIG_INPUT_CMA3000) += cma3000_d0x.o obj-$(CONFIG_INPUT_CMA3000_I2C) += cma3000_d0x_i2c.o obj-$(CONFIG_INPUT_COBALT_BTNS) += cobalt_btns.o obj-$(CONFIG_INPUT_CPCAP_PWRBUTTON) += cpcap-pwrbutton.o +obj-$(CONFIG_INPUT_CS40L50_VIBRA) += cs40l50-vibra.o obj-$(CONFIG_INPUT_DA7280_HAPTICS) += da7280.o obj-$(CONFIG_INPUT_DA9052_ONKEY) += da9052_onkey.o obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o @@ -66,6 +68,7 @@ obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o obj-$(CONFIG_INPUT_POWERMATE) += powermate.o obj-$(CONFIG_INPUT_PWM_BEEPER) += pwm-beeper.o obj-$(CONFIG_INPUT_PWM_VIBRA) += pwm-vibra.o +obj-$(CONFIG_INPUT_QNAP_MCU) += qnap-mcu-input.o obj-$(CONFIG_INPUT_RAVE_SP_PWRBUTTON) += rave-sp-pwrbutton.o obj-$(CONFIG_INPUT_RB532_BUTTON) += rb532_button.o obj-$(CONFIG_INPUT_REGULATOR_HAPTIC) += regulator-haptic.o diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index 679fcfea942c..2adb7a058362 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -72,11 +72,11 @@ static int ad714x_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ad714x_id[] = { - { "ad7142_captouch", 0 }, - { "ad7143_captouch", 0 }, - { "ad7147_captouch", 0 }, - { "ad7147a_captouch", 0 }, - { "ad7148_captouch", 0 }, + { "ad7142_captouch" }, + { "ad7143_captouch" }, + { "ad7147_captouch" }, + { "ad7147a_captouch" }, + { "ad7148_captouch" }, { } }; MODULE_DEVICE_TABLE(i2c, ad714x_id); diff --git a/drivers/input/misc/ad714x.c b/drivers/input/misc/ad714x.c index 1acd8429c56c..d106f37df6bc 100644 --- a/drivers/input/misc/ad714x.c +++ b/drivers/input/misc/ad714x.c @@ -941,7 +941,7 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data) struct ad714x_chip *ad714x = data; int i; - mutex_lock(&ad714x->mutex); + guard(mutex)(&ad714x->mutex); ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3); @@ -954,8 +954,6 @@ static irqreturn_t ad714x_interrupt_thread(int irq, void *data) for (i = 0; i < ad714x->hw->touchpad_num; i++) ad714x_touchpad_state_machine(ad714x, i); - mutex_unlock(&ad714x->mutex); - return IRQ_HANDLED; } @@ -1169,13 +1167,11 @@ static int ad714x_suspend(struct device *dev) dev_dbg(ad714x->dev, "%s enter\n", __func__); - mutex_lock(&ad714x->mutex); + guard(mutex)(&ad714x->mutex); data = ad714x->hw->sys_cfg_reg[AD714X_PWR_CTRL] | 0x3; ad714x->write(ad714x, AD714X_PWR_CTRL, data); - mutex_unlock(&ad714x->mutex); - return 0; } @@ -1184,7 +1180,7 @@ static int ad714x_resume(struct device *dev) struct ad714x_chip *ad714x = dev_get_drvdata(dev); dev_dbg(ad714x->dev, "%s enter\n", __func__); - mutex_lock(&ad714x->mutex); + guard(mutex)(&ad714x->mutex); /* resume to non-shutdown mode */ @@ -1197,8 +1193,6 @@ static int ad714x_resume(struct device *dev) ad714x->read(ad714x, STG_LOW_INT_STA_REG, &ad714x->l_state, 3); - mutex_unlock(&ad714x->mutex); - return 0; } diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index 6b880e282d99..c05d898898e8 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -98,15 +98,8 @@ static int adxl34x_i2c_probe(struct i2c_client *client) return 0; } -static void adxl34x_i2c_remove(struct i2c_client *client) -{ - struct adxl34x *ac = i2c_get_clientdata(client); - - adxl34x_remove(ac); -} - static const struct i2c_device_id adxl34x_id[] = { - { "adxl34x", 0 }, + { "adxl34x" }, { } }; @@ -132,11 +125,11 @@ MODULE_DEVICE_TABLE(of, adxl34x_of_id); static struct i2c_driver adxl34x_driver = { .driver = { .name = "adxl34x", + .dev_groups = adxl34x_groups, .pm = pm_sleep_ptr(&adxl34x_pm), .of_match_table = adxl34x_of_id, }, .probe = adxl34x_i2c_probe, - .remove = adxl34x_i2c_remove, .id_table = adxl34x_id, }; diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index f1094a8ccdd5..fd716d861832 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -87,20 +87,13 @@ static int adxl34x_spi_probe(struct spi_device *spi) return 0; } -static void adxl34x_spi_remove(struct spi_device *spi) -{ - struct adxl34x *ac = spi_get_drvdata(spi); - - adxl34x_remove(ac); -} - static struct spi_driver adxl34x_driver = { .driver = { .name = "adxl34x", + .dev_groups = adxl34x_groups, .pm = pm_sleep_ptr(&adxl34x_pm), }, .probe = adxl34x_spi_probe, - .remove = adxl34x_spi_remove, }; module_spi_driver(adxl34x_driver); diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index a3f45e0ee0c7..7cafbf8d5f1a 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -241,7 +241,8 @@ static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) ac->bops->read_block(ac->dev, DATAX0, DATAZ1 - DATAX0 + 1, buf); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); + ac->saved.x = (s16) le16_to_cpu(buf[0]); axis->x = ac->saved.x; @@ -250,7 +251,6 @@ static void adxl34x_get_triple(struct adxl34x *ac, struct axis_triple *axis) ac->saved.z = (s16) le16_to_cpu(buf[2]); axis->z = ac->saved.z; - mutex_unlock(&ac->mutex); } static void adxl34x_service_ev_fifo(struct adxl34x *ac) @@ -416,15 +416,13 @@ static int adxl34x_suspend(struct device *dev) { struct adxl34x *ac = dev_get_drvdata(dev); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled && ac->opened) __adxl34x_disable(ac); ac->suspended = true; - mutex_unlock(&ac->mutex); - return 0; } @@ -432,15 +430,13 @@ static int adxl34x_resume(struct device *dev) { struct adxl34x *ac = dev_get_drvdata(dev); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (ac->suspended && !ac->disabled && ac->opened) __adxl34x_enable(ac); ac->suspended = false; - mutex_unlock(&ac->mutex); - return 0; } @@ -464,7 +460,7 @@ static ssize_t adxl34x_disable_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && ac->opened) { if (val) { @@ -478,8 +474,6 @@ static ssize_t adxl34x_disable_store(struct device *dev, ac->disabled = !!val; - mutex_unlock(&ac->mutex); - return count; } @@ -489,16 +483,13 @@ static ssize_t adxl34x_calibrate_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adxl34x *ac = dev_get_drvdata(dev); - ssize_t count; - mutex_lock(&ac->mutex); - count = sprintf(buf, "%d,%d,%d\n", - ac->hwcal.x * 4 + ac->swcal.x, - ac->hwcal.y * 4 + ac->swcal.y, - ac->hwcal.z * 4 + ac->swcal.z); - mutex_unlock(&ac->mutex); + guard(mutex)(&ac->mutex); - return count; + return sprintf(buf, "%d,%d,%d\n", + ac->hwcal.x * 4 + ac->swcal.x, + ac->hwcal.y * 4 + ac->swcal.y, + ac->hwcal.z * 4 + ac->swcal.z); } static ssize_t adxl34x_calibrate_store(struct device *dev, @@ -512,7 +503,8 @@ static ssize_t adxl34x_calibrate_store(struct device *dev, * We use HW calibration and handle the remaining bits in SW. (4mg/LSB) */ - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); + ac->hwcal.x -= (ac->saved.x / 4); ac->swcal.x = ac->saved.x % 4; @@ -525,7 +517,6 @@ static ssize_t adxl34x_calibrate_store(struct device *dev, AC_WRITE(ac, OFSX, (s8) ac->hwcal.x); AC_WRITE(ac, OFSY, (s8) ac->hwcal.y); AC_WRITE(ac, OFSZ, (s8) ac->hwcal.z); - mutex_unlock(&ac->mutex); return count; } @@ -553,15 +544,13 @@ static ssize_t adxl34x_rate_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); ac->pdata.data_rate = RATE(val); AC_WRITE(ac, BW_RATE, ac->pdata.data_rate | (ac->pdata.low_power_mode ? LOW_POWER : 0)); - mutex_unlock(&ac->mutex); - return count; } @@ -588,7 +577,7 @@ static ssize_t adxl34x_autosleep_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (val) ac->pdata.power_mode |= (PCTL_AUTO_SLEEP | PCTL_LINK); @@ -598,8 +587,6 @@ static ssize_t adxl34x_autosleep_store(struct device *dev, if (!ac->disabled && !ac->suspended && ac->opened) AC_WRITE(ac, POWER_CTL, ac->pdata.power_mode | PCTL_MEASURE); - mutex_unlock(&ac->mutex); - return count; } @@ -610,14 +597,11 @@ static ssize_t adxl34x_position_show(struct device *dev, struct device_attribute *attr, char *buf) { struct adxl34x *ac = dev_get_drvdata(dev); - ssize_t count; - mutex_lock(&ac->mutex); - count = sprintf(buf, "(%d, %d, %d)\n", - ac->saved.x, ac->saved.y, ac->saved.z); - mutex_unlock(&ac->mutex); + guard(mutex)(&ac->mutex); - return count; + return sprintf(buf, "(%d, %d, %d)\n", + ac->saved.x, ac->saved.y, ac->saved.z); } static DEVICE_ATTR(position, S_IRUGO, adxl34x_position_show, NULL); @@ -638,9 +622,8 @@ static ssize_t adxl34x_write_store(struct device *dev, if (error) return error; - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); AC_WRITE(ac, val >> 8, val & 0xFF); - mutex_unlock(&ac->mutex); return count; } @@ -664,19 +647,23 @@ static const struct attribute_group adxl34x_attr_group = { .attrs = adxl34x_attributes, }; +const struct attribute_group *adxl34x_groups[] = { + &adxl34x_attr_group, + NULL +}; +EXPORT_SYMBOL_GPL(adxl34x_groups); + static int adxl34x_input_open(struct input_dev *input) { struct adxl34x *ac = input_get_drvdata(input); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled) __adxl34x_enable(ac); ac->opened = true; - mutex_unlock(&ac->mutex); - return 0; } @@ -684,14 +671,12 @@ static void adxl34x_input_close(struct input_dev *input) { struct adxl34x *ac = input_get_drvdata(input); - mutex_lock(&ac->mutex); + guard(mutex)(&ac->mutex); if (!ac->suspended && !ac->disabled) __adxl34x_disable(ac); ac->opened = false; - - mutex_unlock(&ac->mutex); } struct adxl34x *adxl34x_probe(struct device *dev, int irq, @@ -701,21 +686,21 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, struct adxl34x *ac; struct input_dev *input_dev; const struct adxl34x_platform_data *pdata; - int err, range, i; + int error, range, i; int revid; if (!irq) { dev_err(dev, "no IRQ?\n"); - err = -ENODEV; - goto err_out; + return ERR_PTR(-ENODEV); } - ac = kzalloc(sizeof(*ac), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ac || !input_dev) { - err = -ENOMEM; - goto err_free_mem; - } + ac = devm_kzalloc(dev, sizeof(*ac), GFP_KERNEL); + if (!ac) + return ERR_PTR(-ENOMEM); + + input_dev = devm_input_allocate_device(dev); + if (!input_dev) + return ERR_PTR(-ENOMEM); ac->fifo_delay = fifo_delay_default; @@ -748,14 +733,12 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, break; default: dev_err(dev, "Failed to probe %s\n", input_dev->name); - err = -ENODEV; - goto err_free_mem; + return ERR_PTR(-ENODEV); } snprintf(ac->phys, sizeof(ac->phys), "%s/input0", dev_name(dev)); input_dev->phys = ac->phys; - input_dev->dev.parent = dev; input_dev->id.product = ac->model; input_dev->id.bustype = bops->bustype; input_dev->open = adxl34x_input_open; @@ -763,18 +746,12 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, input_set_drvdata(input_dev, ac); - __set_bit(ac->pdata.ev_type, input_dev->evbit); - if (ac->pdata.ev_type == EV_REL) { - __set_bit(REL_X, input_dev->relbit); - __set_bit(REL_Y, input_dev->relbit); - __set_bit(REL_Z, input_dev->relbit); + input_set_capability(input_dev, EV_REL, REL_X); + input_set_capability(input_dev, EV_REL, REL_Y); + input_set_capability(input_dev, EV_REL, REL_Z); } else { /* EV_ABS */ - __set_bit(ABS_X, input_dev->absbit); - __set_bit(ABS_Y, input_dev->absbit); - __set_bit(ABS_Z, input_dev->absbit); - if (pdata->data_range & FULL_RES) range = ADXL_FULLRES_MAX_VAL; /* Signed 13-bit */ else @@ -785,18 +762,18 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, input_set_abs_params(input_dev, ABS_Z, -range, range, 3, 3); } - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(pdata->ev_code_tap[ADXL_X_AXIS], input_dev->keybit); - __set_bit(pdata->ev_code_tap[ADXL_Y_AXIS], input_dev->keybit); - __set_bit(pdata->ev_code_tap[ADXL_Z_AXIS], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_X_AXIS]); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_Y_AXIS]); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_tap[ADXL_Z_AXIS]); if (pdata->ev_code_ff) { ac->int_mask = FREE_FALL; - __set_bit(pdata->ev_code_ff, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, pdata->ev_code_ff); } if (pdata->ev_code_act_inactivity) - __set_bit(pdata->ev_code_act_inactivity, input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_code_act_inactivity); ac->int_mask |= ACTIVITY | INACTIVITY; @@ -816,20 +793,16 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, AC_WRITE(ac, POWER_CTL, 0); - err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, - IRQF_ONESHOT, dev_name(dev), ac); - if (err) { + error = devm_request_threaded_irq(dev, ac->irq, NULL, adxl34x_irq, + IRQF_ONESHOT, dev_name(dev), ac); + if (error) { dev_err(dev, "irq %d busy?\n", ac->irq); - goto err_free_mem; + return ERR_PTR(error); } - err = sysfs_create_group(&dev->kobj, &adxl34x_attr_group); - if (err) - goto err_free_irq; - - err = input_register_device(input_dev); - if (err) - goto err_remove_attr; + error = input_register_device(input_dev); + if (error) + return ERR_PTR(error); AC_WRITE(ac, OFSX, pdata->x_axis_offset); ac->hwcal.x = pdata->x_axis_offset; @@ -872,13 +845,13 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (pdata->orientation_enable & ADXL_EN_ORIENTATION_3D) for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_3d); i++) - __set_bit(pdata->ev_codes_orient_3d[i], - input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_codes_orient_3d[i]); if (pdata->orientation_enable & ADXL_EN_ORIENTATION_2D) for (i = 0; i < ARRAY_SIZE(pdata->ev_codes_orient_2d); i++) - __set_bit(pdata->ev_codes_orient_2d[i], - input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + pdata->ev_codes_orient_2d[i]); } else { ac->pdata.orientation_enable = 0; } @@ -888,29 +861,9 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, ac->pdata.power_mode &= (PCTL_AUTO_SLEEP | PCTL_LINK); return ac; - - err_remove_attr: - sysfs_remove_group(&dev->kobj, &adxl34x_attr_group); - err_free_irq: - free_irq(ac->irq, ac); - err_free_mem: - input_free_device(input_dev); - kfree(ac); - err_out: - return ERR_PTR(err); } EXPORT_SYMBOL_GPL(adxl34x_probe); -void adxl34x_remove(struct adxl34x *ac) -{ - sysfs_remove_group(&ac->dev->kobj, &adxl34x_attr_group); - free_irq(ac->irq, ac); - input_unregister_device(ac->input); - dev_dbg(ac->dev, "unregistered accelerometer\n"); - kfree(ac); -} -EXPORT_SYMBOL_GPL(adxl34x_remove); - EXPORT_GPL_SIMPLE_DEV_PM_OPS(adxl34x_pm, adxl34x_suspend, adxl34x_resume); MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); diff --git a/drivers/input/misc/adxl34x.h b/drivers/input/misc/adxl34x.h index f9272a2e7a96..718e90c2046d 100644 --- a/drivers/input/misc/adxl34x.h +++ b/drivers/input/misc/adxl34x.h @@ -23,8 +23,8 @@ struct adxl34x_bus_ops { struct adxl34x *adxl34x_probe(struct device *dev, int irq, bool fifo_delay_default, const struct adxl34x_bus_ops *bops); -void adxl34x_remove(struct adxl34x *ac); extern const struct dev_pm_ops adxl34x_pm; +extern const struct attribute_group *adxl34x_groups[]; #endif diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index b5219bbe856d..d43aebd785b7 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c @@ -192,7 +192,7 @@ static void apanel_shutdown(struct i2c_client *client) } static const struct i2c_device_id apanel_id[] = { - { "fujitsu_apanel", 0 }, + { "fujitsu_apanel" }, { } }; MODULE_DEVICE_TABLE(i2c, apanel_id); diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 946bf75aa106..e84649af801d 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -204,26 +204,7 @@ struct ati_remote2 { unsigned int mode_mask; }; -static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id); -static void ati_remote2_disconnect(struct usb_interface *interface); -static int ati_remote2_suspend(struct usb_interface *interface, pm_message_t message); -static int ati_remote2_resume(struct usb_interface *interface); -static int ati_remote2_reset_resume(struct usb_interface *interface); -static int ati_remote2_pre_reset(struct usb_interface *interface); -static int ati_remote2_post_reset(struct usb_interface *interface); - -static struct usb_driver ati_remote2_driver = { - .name = "ati_remote2", - .probe = ati_remote2_probe, - .disconnect = ati_remote2_disconnect, - .id_table = ati_remote2_id_table, - .suspend = ati_remote2_suspend, - .resume = ati_remote2_resume, - .reset_resume = ati_remote2_reset_resume, - .pre_reset = ati_remote2_pre_reset, - .post_reset = ati_remote2_post_reset, - .supports_autosuspend = 1, -}; +static struct usb_driver ati_remote2_driver; static int ati_remote2_submit_urbs(struct ati_remote2 *ar2) { @@ -263,29 +244,21 @@ static int ati_remote2_open(struct input_dev *idev) if (r) { dev_err(&ar2->intf[0]->dev, "%s(): usb_autopm_get_interface() = %d\n", __func__, r); - goto fail1; + return r; } - mutex_lock(&ati_remote2_mutex); + scoped_guard(mutex, &ati_remote2_mutex) { + if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) { + r = ati_remote2_submit_urbs(ar2); + if (r) + break; + } - if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) { - r = ati_remote2_submit_urbs(ar2); - if (r) - goto fail2; + ar2->flags |= ATI_REMOTE2_OPENED; } - ar2->flags |= ATI_REMOTE2_OPENED; - - mutex_unlock(&ati_remote2_mutex); - usb_autopm_put_interface(ar2->intf[0]); - return 0; - - fail2: - mutex_unlock(&ati_remote2_mutex); - usb_autopm_put_interface(ar2->intf[0]); - fail1: return r; } @@ -295,14 +268,12 @@ static void ati_remote2_close(struct input_dev *idev) dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); - mutex_lock(&ati_remote2_mutex); + guard(mutex)(&ati_remote2_mutex); if (!(ar2->flags & ATI_REMOTE2_SUSPENDED)) ati_remote2_kill_urbs(ar2); ar2->flags &= ~ATI_REMOTE2_OPENED; - - mutex_unlock(&ati_remote2_mutex); } static void ati_remote2_input_mouse(struct ati_remote2 *ar2) @@ -732,16 +703,14 @@ static ssize_t ati_remote2_store_channel_mask(struct device *dev, return r; } - mutex_lock(&ati_remote2_mutex); - - if (mask != ar2->channel_mask) { - r = ati_remote2_setup(ar2, mask); - if (!r) - ar2->channel_mask = mask; + scoped_guard(mutex, &ati_remote2_mutex) { + if (mask != ar2->channel_mask) { + r = ati_remote2_setup(ar2, mask); + if (!r) + ar2->channel_mask = mask; + } } - mutex_unlock(&ati_remote2_mutex); - usb_autopm_put_interface(ar2->intf[0]); return r ? r : count; @@ -791,10 +760,7 @@ static struct attribute *ati_remote2_attrs[] = { &dev_attr_mode_mask.attr, NULL, }; - -static struct attribute_group ati_remote2_attr_group = { - .attrs = ati_remote2_attrs, -}; +ATTRIBUTE_GROUPS(ati_remote2); static int ati_remote2_probe(struct usb_interface *interface, const struct usb_device_id *id) { @@ -861,13 +827,9 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d strlcat(ar2->name, "ATI Remote Wonder II", sizeof(ar2->name)); - r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); - if (r) - goto fail3; - r = ati_remote2_input_init(ar2); if (r) - goto fail4; + goto fail3; usb_set_intfdata(interface, ar2); @@ -875,8 +837,6 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d return 0; - fail4: - sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); fail3: ati_remote2_urb_cleanup(ar2); fail2: @@ -900,8 +860,6 @@ static void ati_remote2_disconnect(struct usb_interface *interface) input_unregister_device(ar2->idev); - sysfs_remove_group(&ar2->udev->dev.kobj, &ati_remote2_attr_group); - ati_remote2_urb_cleanup(ar2); usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); @@ -922,15 +880,13 @@ static int ati_remote2_suspend(struct usb_interface *interface, dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); - mutex_lock(&ati_remote2_mutex); + guard(mutex)(&ati_remote2_mutex); if (ar2->flags & ATI_REMOTE2_OPENED) ati_remote2_kill_urbs(ar2); ar2->flags |= ATI_REMOTE2_SUSPENDED; - mutex_unlock(&ati_remote2_mutex); - return 0; } @@ -947,7 +903,7 @@ static int ati_remote2_resume(struct usb_interface *interface) dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); - mutex_lock(&ati_remote2_mutex); + guard(mutex)(&ati_remote2_mutex); if (ar2->flags & ATI_REMOTE2_OPENED) r = ati_remote2_submit_urbs(ar2); @@ -955,8 +911,6 @@ static int ati_remote2_resume(struct usb_interface *interface) if (!r) ar2->flags &= ~ATI_REMOTE2_SUSPENDED; - mutex_unlock(&ati_remote2_mutex); - return r; } @@ -973,11 +927,11 @@ static int ati_remote2_reset_resume(struct usb_interface *interface) dev_dbg(&ar2->intf[0]->dev, "%s()\n", __func__); - mutex_lock(&ati_remote2_mutex); + guard(mutex)(&ati_remote2_mutex); r = ati_remote2_setup(ar2, ar2->channel_mask); if (r) - goto out; + return r; if (ar2->flags & ATI_REMOTE2_OPENED) r = ati_remote2_submit_urbs(ar2); @@ -985,9 +939,6 @@ static int ati_remote2_reset_resume(struct usb_interface *interface) if (!r) ar2->flags &= ~ATI_REMOTE2_SUSPENDED; - out: - mutex_unlock(&ati_remote2_mutex); - return r; } @@ -1032,4 +983,18 @@ static int ati_remote2_post_reset(struct usb_interface *interface) return r; } +static struct usb_driver ati_remote2_driver = { + .name = "ati_remote2", + .probe = ati_remote2_probe, + .disconnect = ati_remote2_disconnect, + .dev_groups = ati_remote2_groups, + .id_table = ati_remote2_id_table, + .suspend = ati_remote2_suspend, + .resume = ati_remote2_resume, + .reset_resume = ati_remote2_reset_resume, + .pre_reset = ati_remote2_pre_reset, + .post_reset = ati_remote2_post_reset, + .supports_autosuspend = 1, +}; + module_usb_driver(ati_remote2_driver); diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 3c9bbd04e143..5b9be2957746 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -127,7 +127,6 @@ MODULE_DEVICE_TABLE(acpi, atlas_device_ids); static struct acpi_driver atlas_acpi_driver = { .name = ACPI_ATLAS_NAME, .class = ACPI_ATLAS_CLASS, - .owner = THIS_MODULE, .ids = atlas_device_ids, .ops = { .add = atlas_acpi_button_add, diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c index b6a30044e814..f9744cf0ca80 100644 --- a/drivers/input/misc/atmel_captouch.c +++ b/drivers/input/misc/atmel_captouch.c @@ -257,7 +257,7 @@ static const struct of_device_id atmel_captouch_of_id[] = { MODULE_DEVICE_TABLE(of, atmel_captouch_of_id); static const struct i2c_device_id atmel_captouch_id[] = { - { "atmel_captouch", 0 }, + { "atmel_captouch" }, { } }; MODULE_DEVICE_TABLE(i2c, atmel_captouch_id); diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index 0fb4cc628f29..4cc2a0dcaa75 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -536,9 +536,9 @@ static int __maybe_unused bma150_resume(struct device *dev) static UNIVERSAL_DEV_PM_OPS(bma150_pm, bma150_suspend, bma150_resume, NULL); static const struct i2c_device_id bma150_id[] = { - { "bma150", 0 }, - { "smb380", 0 }, - { "bma023", 0 }, + { "bma150" }, + { "smb380" }, + { "bma023" }, { } }; diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 728325a2d574..0cfe5d4a573c 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -355,6 +355,35 @@ static void cm109_submit_buzz_toggle(struct cm109_dev *dev) __func__, error); } +static void cm109_submit_ctl(struct cm109_dev *dev) +{ + int error; + + guard(spinlock_irqsave)(&dev->ctl_submit_lock); + + dev->irq_urb_pending = 0; + + if (unlikely(dev->shutdown)) + return; + + if (dev->buzzer_state) + dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; + else + dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; + + dev->ctl_data->byte[HID_OR1] = dev->keybit; + dev->ctl_data->byte[HID_OR2] = dev->keybit; + + dev->buzzer_pending = 0; + dev->ctl_urb_pending = 1; + + error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); + if (error) + dev_err(&dev->intf->dev, + "%s: usb_submit_urb (urb_ctl) failed %d\n", + __func__, error); +} + /* * IRQ handler */ @@ -362,8 +391,6 @@ static void cm109_urb_irq_callback(struct urb *urb) { struct cm109_dev *dev = urb->context; const int status = urb->status; - int error; - unsigned long flags; dev_dbg(&dev->intf->dev, "### URB IRQ: [0x%02x 0x%02x 0x%02x 0x%02x] keybit=0x%02x\n", dev->irq_data->byte[0], @@ -401,32 +428,7 @@ static void cm109_urb_irq_callback(struct urb *urb) } out: - - spin_lock_irqsave(&dev->ctl_submit_lock, flags); - - dev->irq_urb_pending = 0; - - if (likely(!dev->shutdown)) { - - if (dev->buzzer_state) - dev->ctl_data->byte[HID_OR0] |= BUZZER_ON; - else - dev->ctl_data->byte[HID_OR0] &= ~BUZZER_ON; - - dev->ctl_data->byte[HID_OR1] = dev->keybit; - dev->ctl_data->byte[HID_OR2] = dev->keybit; - - dev->buzzer_pending = 0; - dev->ctl_urb_pending = 1; - - error = usb_submit_urb(dev->urb_ctl, GFP_ATOMIC); - if (error) - dev_err(&dev->intf->dev, - "%s: usb_submit_urb (urb_ctl) failed %d\n", - __func__, error); - } - - spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); + cm109_submit_ctl(dev); } static void cm109_urb_ctl_callback(struct urb *urb) @@ -434,7 +436,6 @@ static void cm109_urb_ctl_callback(struct urb *urb) struct cm109_dev *dev = urb->context; const int status = urb->status; int error; - unsigned long flags; dev_dbg(&dev->intf->dev, "### URB CTL: [0x%02x 0x%02x 0x%02x 0x%02x]\n", dev->ctl_data->byte[0], @@ -449,35 +450,31 @@ static void cm109_urb_ctl_callback(struct urb *urb) __func__, status); } - spin_lock_irqsave(&dev->ctl_submit_lock, flags); + guard(spinlock_irqsave)(&dev->ctl_submit_lock); dev->ctl_urb_pending = 0; - if (likely(!dev->shutdown)) { - - if (dev->buzzer_pending || status) { - dev->buzzer_pending = 0; - dev->ctl_urb_pending = 1; - cm109_submit_buzz_toggle(dev); - } else if (likely(!dev->irq_urb_pending)) { - /* ask for key data */ - dev->irq_urb_pending = 1; - error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); - if (error) - dev_err(&dev->intf->dev, - "%s: usb_submit_urb (urb_irq) failed %d\n", - __func__, error); - } - } + if (unlikely(dev->shutdown)) + return; - spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); + if (dev->buzzer_pending || status) { + dev->buzzer_pending = 0; + dev->ctl_urb_pending = 1; + cm109_submit_buzz_toggle(dev); + } else if (likely(!dev->irq_urb_pending)) { + /* ask for key data */ + dev->irq_urb_pending = 1; + error = usb_submit_urb(dev->urb_irq, GFP_ATOMIC); + if (error) + dev_err(&dev->intf->dev, + "%s: usb_submit_urb (urb_irq) failed %d\n", + __func__, error); + } } static void cm109_toggle_buzzer_async(struct cm109_dev *dev) { - unsigned long flags; - - spin_lock_irqsave(&dev->ctl_submit_lock, flags); + guard(spinlock_irqsave)(&dev->ctl_submit_lock); if (dev->ctl_urb_pending) { /* URB completion will resubmit */ @@ -486,8 +483,6 @@ static void cm109_toggle_buzzer_async(struct cm109_dev *dev) dev->ctl_urb_pending = 1; cm109_submit_buzz_toggle(dev); } - - spin_unlock_irqrestore(&dev->ctl_submit_lock, flags); } static void cm109_toggle_buzzer_sync(struct cm109_dev *dev, int on) @@ -556,32 +551,30 @@ static int cm109_input_open(struct input_dev *idev) return error; } - mutex_lock(&dev->pm_mutex); - - dev->buzzer_state = 0; - dev->key_code = -1; /* no keys pressed */ - dev->keybit = 0xf; + scoped_guard(mutex, &dev->pm_mutex) { + dev->buzzer_state = 0; + dev->key_code = -1; /* no keys pressed */ + dev->keybit = 0xf; - /* issue INIT */ - dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; - dev->ctl_data->byte[HID_OR1] = dev->keybit; - dev->ctl_data->byte[HID_OR2] = dev->keybit; - dev->ctl_data->byte[HID_OR3] = 0x00; + /* issue INIT */ + dev->ctl_data->byte[HID_OR0] = HID_OR_GPO_BUZ_SPDIF; + dev->ctl_data->byte[HID_OR1] = dev->keybit; + dev->ctl_data->byte[HID_OR2] = dev->keybit; + dev->ctl_data->byte[HID_OR3] = 0x00; - dev->ctl_urb_pending = 1; - error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); - if (error) { - dev->ctl_urb_pending = 0; - dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n", - __func__, error); - } else { - dev->open = 1; + dev->ctl_urb_pending = 1; + error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); + if (!error) { + dev->open = 1; + return 0; + } } - mutex_unlock(&dev->pm_mutex); + dev->ctl_urb_pending = 0; + usb_autopm_put_interface(dev->intf); - if (error) - usb_autopm_put_interface(dev->intf); + dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n", + __func__, error); return error; } @@ -590,17 +583,15 @@ static void cm109_input_close(struct input_dev *idev) { struct cm109_dev *dev = input_get_drvdata(idev); - mutex_lock(&dev->pm_mutex); - - /* - * Once we are here event delivery is stopped so we - * don't need to worry about someone starting buzzer - * again - */ - cm109_stop_traffic(dev); - dev->open = 0; - - mutex_unlock(&dev->pm_mutex); + scoped_guard(mutex, &dev->pm_mutex) { + /* + * Once we are here event delivery is stopped so we + * don't need to worry about someone starting buzzer + * again + */ + cm109_stop_traffic(dev); + dev->open = 0; + } usb_autopm_put_interface(dev->intf); } @@ -823,9 +814,9 @@ static int cm109_usb_suspend(struct usb_interface *intf, pm_message_t message) dev_info(&intf->dev, "cm109: usb_suspend (event=%d)\n", message.event); - mutex_lock(&dev->pm_mutex); + guard(mutex)(&dev->pm_mutex); + cm109_stop_traffic(dev); - mutex_unlock(&dev->pm_mutex); return 0; } @@ -836,9 +827,9 @@ static int cm109_usb_resume(struct usb_interface *intf) dev_info(&intf->dev, "cm109: usb_resume\n"); - mutex_lock(&dev->pm_mutex); + guard(mutex)(&dev->pm_mutex); + cm109_restore_state(dev); - mutex_unlock(&dev->pm_mutex); return 0; } diff --git a/drivers/input/misc/cma3000_d0x.c b/drivers/input/misc/cma3000_d0x.c index 1772846708d2..cfc12332bee1 100644 --- a/drivers/input/misc/cma3000_d0x.c +++ b/drivers/input/misc/cma3000_d0x.c @@ -217,15 +217,13 @@ static int cma3000_open(struct input_dev *input_dev) { struct cma3000_accl_data *data = input_get_drvdata(input_dev); - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); if (!data->suspended) cma3000_poweron(data); data->opened = true; - mutex_unlock(&data->mutex); - return 0; } @@ -233,40 +231,34 @@ static void cma3000_close(struct input_dev *input_dev) { struct cma3000_accl_data *data = input_get_drvdata(input_dev); - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); if (!data->suspended) cma3000_poweroff(data); data->opened = false; - - mutex_unlock(&data->mutex); } void cma3000_suspend(struct cma3000_accl_data *data) { - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); if (!data->suspended && data->opened) cma3000_poweroff(data); data->suspended = true; - - mutex_unlock(&data->mutex); } EXPORT_SYMBOL(cma3000_suspend); void cma3000_resume(struct cma3000_accl_data *data) { - mutex_lock(&data->mutex); + guard(mutex)(&data->mutex); if (data->suspended && data->opened) cma3000_poweron(data); data->suspended = false; - - mutex_unlock(&data->mutex); } EXPORT_SYMBOL(cma3000_resume); @@ -292,7 +284,7 @@ struct cma3000_accl_data *cma3000_init(struct device *dev, int irq, goto err_out; } - data = kzalloc(sizeof(struct cma3000_accl_data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); input_dev = input_allocate_device(); if (!data || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index a4dfb3052dc0..f892c5b1e4bd 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c @@ -90,8 +90,8 @@ static const struct dev_pm_ops cma3000_i2c_pm_ops = { }; static const struct i2c_device_id cma3000_i2c_id[] = { - { "cma3000_d01", 0 }, - { }, + { "cma3000_d01" }, + { } }; MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id); diff --git a/drivers/input/misc/cs40l50-vibra.c b/drivers/input/misc/cs40l50-vibra.c new file mode 100644 index 000000000000..dce3b0ec8cf3 --- /dev/null +++ b/drivers/input/misc/cs40l50-vibra.c @@ -0,0 +1,557 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CS40L50 Advanced Haptic Driver with waveform memory, + * integrated DSP, and closed-loop algorithms + * + * Copyright 2024 Cirrus Logic, Inc. + * + * Author: James Ogletree <james.ogletree@cirrus.com> + */ + +#include <linux/bitfield.h> +#include <linux/input.h> +#include <linux/mfd/cs40l50.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +/* Wavetables */ +#define CS40L50_RAM_INDEX_START 0x1000000 +#define CS40L50_RAM_INDEX_END 0x100007F +#define CS40L50_RTH_INDEX_START 0x1400000 +#define CS40L50_RTH_INDEX_END 0x1400001 +#define CS40L50_ROM_INDEX_START 0x1800000 +#define CS40L50_ROM_INDEX_END 0x180001A +#define CS40L50_TYPE_PCM 8 +#define CS40L50_TYPE_PWLE 12 +#define CS40L50_PCM_ID 0x0 +#define CS40L50_OWT_CUSTOM_DATA_SIZE 2 +#define CS40L50_CUSTOM_DATA_MASK 0xFFFFU + +/* DSP */ +#define CS40L50_GPIO_BASE 0x2804140 +#define CS40L50_OWT_BASE 0x2805C34 +#define CS40L50_OWT_SIZE 0x2805C38 +#define CS40L50_OWT_NEXT 0x2805C3C +#define CS40L50_EFFECTS_MAX 1 + +/* GPIO */ +#define CS40L50_GPIO_NUM_MASK GENMASK(14, 12) +#define CS40L50_GPIO_EDGE_MASK BIT(15) +#define CS40L50_GPIO_MAPPING_NONE 0 +#define CS40L50_GPIO_DISABLE 0x1FF + +enum cs40l50_bank_type { + CS40L50_WVFRM_BANK_RAM, + CS40L50_WVFRM_BANK_ROM, + CS40L50_WVFRM_BANK_OWT, + CS40L50_WVFRM_BANK_NUM, +}; + +/* Describes an area in DSP memory populated by effects */ +struct cs40l50_bank { + enum cs40l50_bank_type type; + u32 base_index; + u32 max_index; +}; + +struct cs40l50_effect { + enum cs40l50_bank_type type; + struct list_head list; + u32 gpio_reg; + u32 index; + int id; +}; + +/* Describes haptic interface of loaded DSP firmware */ +struct cs40l50_vibra_dsp { + struct cs40l50_bank *banks; + u32 gpio_base_reg; + u32 owt_offset_reg; + u32 owt_size_reg; + u32 owt_base_reg; + u32 push_owt_cmd; + u32 delete_owt_cmd; + u32 stop_cmd; + int (*write)(struct device *dev, struct regmap *regmap, u32 val); +}; + +/* Describes configuration and state of haptic operations */ +struct cs40l50_vibra { + struct device *dev; + struct regmap *regmap; + struct input_dev *input; + struct workqueue_struct *vib_wq; + struct list_head effect_head; + struct cs40l50_vibra_dsp dsp; +}; + +struct cs40l50_work { + struct cs40l50_vibra *vib; + struct ff_effect *effect; + struct work_struct work; + s16 *custom_data; + int custom_len; + int count; + int error; +}; + +static struct cs40l50_bank cs40l50_banks[] = { + { + .type = CS40L50_WVFRM_BANK_RAM, + .base_index = CS40L50_RAM_INDEX_START, + .max_index = CS40L50_RAM_INDEX_END, + }, + { + .type = CS40L50_WVFRM_BANK_ROM, + .base_index = CS40L50_ROM_INDEX_START, + .max_index = CS40L50_ROM_INDEX_END, + }, + { + .type = CS40L50_WVFRM_BANK_OWT, + .base_index = CS40L50_RTH_INDEX_START, + .max_index = CS40L50_RTH_INDEX_END, + }, +}; + +static struct cs40l50_vibra_dsp cs40l50_dsp = { + .banks = cs40l50_banks, + .gpio_base_reg = CS40L50_GPIO_BASE, + .owt_base_reg = CS40L50_OWT_BASE, + .owt_offset_reg = CS40L50_OWT_NEXT, + .owt_size_reg = CS40L50_OWT_SIZE, + .push_owt_cmd = CS40L50_OWT_PUSH, + .delete_owt_cmd = CS40L50_OWT_DELETE, + .stop_cmd = CS40L50_STOP_PLAYBACK, + .write = cs40l50_dsp_write, +}; + +static struct cs40l50_effect *cs40l50_find_effect(int id, struct list_head *effect_head) +{ + struct cs40l50_effect *effect; + + list_for_each_entry(effect, effect_head, list) + if (effect->id == id) + return effect; + + return NULL; +} + +static int cs40l50_effect_bank_set(struct cs40l50_work *work_data, + struct cs40l50_effect *effect) +{ + s16 bank_type = work_data->custom_data[0] & CS40L50_CUSTOM_DATA_MASK; + + if (bank_type >= CS40L50_WVFRM_BANK_NUM) { + dev_err(work_data->vib->dev, "Invalid bank (%d)\n", bank_type); + return -EINVAL; + } + + if (work_data->custom_len > CS40L50_OWT_CUSTOM_DATA_SIZE) + effect->type = CS40L50_WVFRM_BANK_OWT; + else + effect->type = bank_type; + + return 0; +} + +static int cs40l50_effect_index_set(struct cs40l50_work *work_data, + struct cs40l50_effect *effect) +{ + struct cs40l50_vibra *vib = work_data->vib; + struct cs40l50_effect *owt_effect; + u32 base_index, max_index; + + base_index = vib->dsp.banks[effect->type].base_index; + max_index = vib->dsp.banks[effect->type].max_index; + + effect->index = base_index; + + switch (effect->type) { + case CS40L50_WVFRM_BANK_OWT: + list_for_each_entry(owt_effect, &vib->effect_head, list) + if (owt_effect->type == CS40L50_WVFRM_BANK_OWT) + effect->index++; + break; + case CS40L50_WVFRM_BANK_ROM: + case CS40L50_WVFRM_BANK_RAM: + effect->index += work_data->custom_data[1] & CS40L50_CUSTOM_DATA_MASK; + break; + default: + dev_err(vib->dev, "Bank type %d not supported\n", effect->type); + return -EINVAL; + } + + if (effect->index > max_index || effect->index < base_index) { + dev_err(vib->dev, "Index out of bounds: %u\n", effect->index); + return -ENOSPC; + } + + return 0; +} + +static int cs40l50_effect_gpio_mapping_set(struct cs40l50_work *work_data, + struct cs40l50_effect *effect) +{ + u16 gpio_edge, gpio_num, button = work_data->effect->trigger.button; + struct cs40l50_vibra *vib = work_data->vib; + + if (button) { + gpio_num = FIELD_GET(CS40L50_GPIO_NUM_MASK, button); + gpio_edge = FIELD_GET(CS40L50_GPIO_EDGE_MASK, button); + effect->gpio_reg = vib->dsp.gpio_base_reg + (gpio_num * 8) - gpio_edge; + + return regmap_write(vib->regmap, effect->gpio_reg, button); + } + + effect->gpio_reg = CS40L50_GPIO_MAPPING_NONE; + + return 0; +} + +struct cs40l50_owt_header { + u32 type; + u32 data_words; + u32 offset; +} __packed; + +static int cs40l50_upload_owt(struct cs40l50_work *work_data) +{ + u8 *new_owt_effect_data __free(kfree) = NULL; + struct cs40l50_vibra *vib = work_data->vib; + size_t len = work_data->custom_len * 2; + struct cs40l50_owt_header header; + u32 offset, size; + int error; + + error = regmap_read(vib->regmap, vib->dsp.owt_size_reg, &size); + if (error) + return error; + + if ((size * sizeof(u32)) < sizeof(header) + len) { + dev_err(vib->dev, "No space in open wavetable for effect\n"); + return -ENOSPC; + } + + header.type = work_data->custom_data[0] == CS40L50_PCM_ID ? CS40L50_TYPE_PCM : + CS40L50_TYPE_PWLE; + header.offset = sizeof(header) / sizeof(u32); + header.data_words = len / sizeof(u32); + + new_owt_effect_data = kmalloc(sizeof(header) + len, GFP_KERNEL); + + memcpy(new_owt_effect_data, &header, sizeof(header)); + memcpy(new_owt_effect_data + sizeof(header), work_data->custom_data, len); + + error = regmap_read(vib->regmap, vib->dsp.owt_offset_reg, &offset); + if (error) + return error; + + error = regmap_bulk_write(vib->regmap, vib->dsp.owt_base_reg + + (offset * sizeof(u32)), new_owt_effect_data, + sizeof(header) + len); + if (error) + return error; + + error = vib->dsp.write(vib->dev, vib->regmap, vib->dsp.push_owt_cmd); + if (error) + return error; + + return 0; +} + +static void cs40l50_add_worker(struct work_struct *work) +{ + struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work); + struct cs40l50_vibra *vib = work_data->vib; + struct cs40l50_effect *effect; + bool is_new = false; + int error; + + error = pm_runtime_resume_and_get(vib->dev); + if (error) + goto err_exit; + + /* Update effect if already uploaded, otherwise create new effect */ + effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head); + if (!effect) { + effect = kzalloc(sizeof(*effect), GFP_KERNEL); + if (!effect) { + error = -ENOMEM; + goto err_pm; + } + + effect->id = work_data->effect->id; + is_new = true; + } + + error = cs40l50_effect_bank_set(work_data, effect); + if (error) + goto err_free; + + error = cs40l50_effect_index_set(work_data, effect); + if (error) + goto err_free; + + error = cs40l50_effect_gpio_mapping_set(work_data, effect); + if (error) + goto err_free; + + if (effect->type == CS40L50_WVFRM_BANK_OWT) + error = cs40l50_upload_owt(work_data); +err_free: + if (is_new) { + if (error) + kfree(effect); + else + list_add(&effect->list, &vib->effect_head); + } +err_pm: + pm_runtime_mark_last_busy(vib->dev); + pm_runtime_put_autosuspend(vib->dev); +err_exit: + work_data->error = error; +} + +static int cs40l50_add(struct input_dev *dev, struct ff_effect *effect, + struct ff_effect *old) +{ + struct ff_periodic_effect *periodic = &effect->u.periodic; + struct cs40l50_vibra *vib = input_get_drvdata(dev); + struct cs40l50_work work_data; + + if (effect->type != FF_PERIODIC || periodic->waveform != FF_CUSTOM) { + dev_err(vib->dev, "Type (%#X) or waveform (%#X) unsupported\n", + effect->type, periodic->waveform); + return -EINVAL; + } + + work_data.custom_data = memdup_array_user(effect->u.periodic.custom_data, + effect->u.periodic.custom_len, + sizeof(s16)); + if (IS_ERR(work_data.custom_data)) + return PTR_ERR(work_data.custom_data); + + work_data.custom_len = effect->u.periodic.custom_len; + work_data.vib = vib; + work_data.effect = effect; + INIT_WORK_ONSTACK(&work_data.work, cs40l50_add_worker); + + /* Push to the workqueue to serialize with playbacks */ + queue_work(vib->vib_wq, &work_data.work); + flush_work(&work_data.work); + destroy_work_on_stack(&work_data.work); + + kfree(work_data.custom_data); + + return work_data.error; +} + +static void cs40l50_start_worker(struct work_struct *work) +{ + struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work); + struct cs40l50_vibra *vib = work_data->vib; + struct cs40l50_effect *start_effect; + + if (pm_runtime_resume_and_get(vib->dev) < 0) + goto err_free; + + start_effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head); + if (start_effect) { + while (--work_data->count >= 0) { + vib->dsp.write(vib->dev, vib->regmap, start_effect->index); + usleep_range(work_data->effect->replay.length, + work_data->effect->replay.length + 100); + } + } else { + dev_err(vib->dev, "Effect to play not found\n"); + } + + pm_runtime_mark_last_busy(vib->dev); + pm_runtime_put_autosuspend(vib->dev); +err_free: + kfree(work_data); +} + +static void cs40l50_stop_worker(struct work_struct *work) +{ + struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work); + struct cs40l50_vibra *vib = work_data->vib; + + if (pm_runtime_resume_and_get(vib->dev) < 0) + return; + + vib->dsp.write(vib->dev, vib->regmap, vib->dsp.stop_cmd); + + pm_runtime_mark_last_busy(vib->dev); + pm_runtime_put_autosuspend(vib->dev); + + kfree(work_data); +} + +static int cs40l50_playback(struct input_dev *dev, int effect_id, int val) +{ + struct cs40l50_vibra *vib = input_get_drvdata(dev); + struct cs40l50_work *work_data; + + work_data = kzalloc(sizeof(*work_data), GFP_ATOMIC); + if (!work_data) + return -ENOMEM; + + work_data->vib = vib; + + if (val > 0) { + work_data->effect = &dev->ff->effects[effect_id]; + work_data->count = val; + INIT_WORK(&work_data->work, cs40l50_start_worker); + } else { + /* Stop the amplifier as device drives only one effect */ + INIT_WORK(&work_data->work, cs40l50_stop_worker); + } + + queue_work(vib->vib_wq, &work_data->work); + + return 0; +} + +static void cs40l50_erase_worker(struct work_struct *work) +{ + struct cs40l50_work *work_data = container_of(work, struct cs40l50_work, work); + struct cs40l50_effect *erase_effect, *owt_effect; + struct cs40l50_vibra *vib = work_data->vib; + int error; + + error = pm_runtime_resume_and_get(vib->dev); + if (error) + goto err_exit; + + erase_effect = cs40l50_find_effect(work_data->effect->id, &vib->effect_head); + if (!erase_effect) { + dev_err(vib->dev, "Effect to erase not found\n"); + error = -EINVAL; + goto err_pm; + } + + if (erase_effect->gpio_reg != CS40L50_GPIO_MAPPING_NONE) { + error = regmap_write(vib->regmap, erase_effect->gpio_reg, + CS40L50_GPIO_DISABLE); + if (error) + goto err_pm; + } + + if (erase_effect->type == CS40L50_WVFRM_BANK_OWT) { + error = vib->dsp.write(vib->dev, vib->regmap, + vib->dsp.delete_owt_cmd | + (erase_effect->index & 0xFF)); + if (error) + goto err_pm; + + list_for_each_entry(owt_effect, &vib->effect_head, list) + if (owt_effect->type == CS40L50_WVFRM_BANK_OWT && + owt_effect->index > erase_effect->index) + owt_effect->index--; + } + + list_del(&erase_effect->list); + kfree(erase_effect); +err_pm: + pm_runtime_mark_last_busy(vib->dev); + pm_runtime_put_autosuspend(vib->dev); +err_exit: + work_data->error = error; +} + +static int cs40l50_erase(struct input_dev *dev, int effect_id) +{ + struct cs40l50_vibra *vib = input_get_drvdata(dev); + struct cs40l50_work work_data; + + work_data.vib = vib; + work_data.effect = &dev->ff->effects[effect_id]; + + INIT_WORK_ONSTACK(&work_data.work, cs40l50_erase_worker); + + /* Push to workqueue to serialize with playbacks */ + queue_work(vib->vib_wq, &work_data.work); + flush_work(&work_data.work); + destroy_work_on_stack(&work_data.work); + + return work_data.error; +} + +static void cs40l50_remove_wq(void *data) +{ + flush_workqueue(data); + destroy_workqueue(data); +} + +static int cs40l50_vibra_probe(struct platform_device *pdev) +{ + struct cs40l50 *cs40l50 = dev_get_drvdata(pdev->dev.parent); + struct cs40l50_vibra *vib; + int error; + + vib = devm_kzalloc(pdev->dev.parent, sizeof(*vib), GFP_KERNEL); + if (!vib) + return -ENOMEM; + + vib->dev = cs40l50->dev; + vib->regmap = cs40l50->regmap; + vib->dsp = cs40l50_dsp; + + vib->input = devm_input_allocate_device(vib->dev); + if (!vib->input) + return -ENOMEM; + + vib->input->id.product = cs40l50->devid; + vib->input->id.version = cs40l50->revid; + vib->input->name = "cs40l50_vibra"; + + input_set_drvdata(vib->input, vib); + input_set_capability(vib->input, EV_FF, FF_PERIODIC); + input_set_capability(vib->input, EV_FF, FF_CUSTOM); + + error = input_ff_create(vib->input, CS40L50_EFFECTS_MAX); + if (error) { + dev_err(vib->dev, "Failed to create input device\n"); + return error; + } + + vib->input->ff->upload = cs40l50_add; + vib->input->ff->playback = cs40l50_playback; + vib->input->ff->erase = cs40l50_erase; + + INIT_LIST_HEAD(&vib->effect_head); + + vib->vib_wq = alloc_ordered_workqueue("vib_wq", WQ_HIGHPRI); + if (!vib->vib_wq) + return -ENOMEM; + + error = devm_add_action_or_reset(vib->dev, cs40l50_remove_wq, vib->vib_wq); + if (error) + return error; + + error = input_register_device(vib->input); + if (error) + return error; + + return 0; +} + +static const struct platform_device_id cs40l50_vibra_id_match[] = { + { "cs40l50-vibra", }, + {} +}; +MODULE_DEVICE_TABLE(platform, cs40l50_vibra_id_match); + +static struct platform_driver cs40l50_vibra_driver = { + .probe = cs40l50_vibra_probe, + .id_table = cs40l50_vibra_id_match, + .driver = { + .name = "cs40l50-vibra", + }, +}; +module_platform_driver(cs40l50_vibra_driver); + +MODULE_DESCRIPTION("CS40L50 Advanced Haptic Driver"); +MODULE_AUTHOR("James Ogletree, Cirrus Logic Inc. <james.ogletree@cirrus.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c index c1fa75c0f970..e4a605c6af15 100644 --- a/drivers/input/misc/da7280.c +++ b/drivers/input/misc/da7280.c @@ -230,7 +230,6 @@ struct da7280_haptic { struct i2c_client *client; struct pwm_device *pwm_dev; - bool legacy; struct work_struct work; int val; u16 gain; @@ -1264,39 +1263,37 @@ static int da7280_suspend(struct device *dev) { struct da7280_haptic *haptics = dev_get_drvdata(dev); - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); /* * Make sure no new requests will be submitted while device is * suspended. */ - spin_lock_irq(&haptics->input_dev->event_lock); - haptics->suspended = true; - spin_unlock_irq(&haptics->input_dev->event_lock); + scoped_guard(spinlock_irq, &haptics->input_dev->event_lock) { + haptics->suspended = true; + } da7280_haptic_stop(haptics); - mutex_unlock(&haptics->input_dev->mutex); - return 0; } static int da7280_resume(struct device *dev) { struct da7280_haptic *haptics = dev_get_drvdata(dev); - int retval; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); - retval = da7280_haptic_start(haptics); - if (!retval) { - spin_lock_irq(&haptics->input_dev->event_lock); + error = da7280_haptic_start(haptics); + if (error) + return error; + + scoped_guard(spinlock_irq, &haptics->input_dev->event_lock) { haptics->suspended = false; - spin_unlock_irq(&haptics->input_dev->event_lock); } - mutex_unlock(&haptics->input_dev->mutex); - return retval; + return 0; } #ifdef CONFIG_OF diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 7a1122e1efb9..cc23625019e3 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -140,8 +140,8 @@ static void da9052_onkey_remove(struct platform_device *pdev) static struct platform_driver da9052_onkey_driver = { .probe = da9052_onkey_probe, - .remove_new = da9052_onkey_remove, - .driver = { + .remove = da9052_onkey_remove, + .driver = { .name = "da9052-onkey", }, }; diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c index 871812f1b398..3e4fc2f01011 100644 --- a/drivers/input/misc/da9055_onkey.c +++ b/drivers/input/misc/da9055_onkey.c @@ -145,8 +145,8 @@ static void da9055_onkey_remove(struct platform_device *pdev) static struct platform_driver da9055_onkey_driver = { .probe = da9055_onkey_probe, - .remove_new = da9055_onkey_remove, - .driver = { + .remove = da9055_onkey_remove, + .driver = { .name = "da9055-onkey", }, }; diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c index 6717e3c9549b..96cd6a078c8a 100644 --- a/drivers/input/misc/drv260x.c +++ b/drivers/input/misc/drv260x.c @@ -537,70 +537,68 @@ static int drv260x_probe(struct i2c_client *client) static int drv260x_suspend(struct device *dev) { struct drv260x_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regmap_update_bits(haptics->regmap, - DRV260X_MODE, - DRV260X_STANDBY_MASK, - DRV260X_STANDBY); - if (ret) { + error = regmap_update_bits(haptics->regmap, + DRV260X_MODE, + DRV260X_STANDBY_MASK, + DRV260X_STANDBY); + if (error) { dev_err(dev, "Failed to set standby mode\n"); - goto out; + return error; } gpiod_set_value(haptics->enable_gpio, 0); - ret = regulator_disable(haptics->regulator); - if (ret) { + error = regulator_disable(haptics->regulator); + if (error) { dev_err(dev, "Failed to disable regulator\n"); regmap_update_bits(haptics->regmap, DRV260X_MODE, DRV260X_STANDBY_MASK, 0); + return error; } } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + + return 0; } static int drv260x_resume(struct device *dev) { struct drv260x_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regulator_enable(haptics->regulator); - if (ret) { + error = regulator_enable(haptics->regulator); + if (error) { dev_err(dev, "Failed to enable regulator\n"); - goto out; + return error; } - ret = regmap_update_bits(haptics->regmap, - DRV260X_MODE, - DRV260X_STANDBY_MASK, 0); - if (ret) { + error = regmap_update_bits(haptics->regmap, + DRV260X_MODE, + DRV260X_STANDBY_MASK, 0); + if (error) { dev_err(dev, "Failed to unset standby mode\n"); regulator_disable(haptics->regulator); - goto out; + return error; } gpiod_set_value(haptics->enable_gpio, 1); } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(drv260x_pm_ops, drv260x_suspend, drv260x_resume); static const struct i2c_device_id drv260x_id[] = { - { "drv2605l", 0 }, + { "drv2605l" }, { } }; MODULE_DEVICE_TABLE(i2c, drv260x_id); diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c index de27e6079d84..46842cb8ddd7 100644 --- a/drivers/input/misc/drv2665.c +++ b/drivers/input/misc/drv2665.c @@ -15,7 +15,7 @@ #include <linux/delay.h> #include <linux/regulator/consumer.h> -/* Contol registers */ +/* Control registers */ #define DRV2665_STATUS 0x00 #define DRV2665_CTRL_1 0x01 #define DRV2665_CTRL_2 0x02 @@ -225,65 +225,63 @@ static int drv2665_probe(struct i2c_client *client) static int drv2665_suspend(struct device *dev) { struct drv2665_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, - DRV2665_STANDBY, DRV2665_STANDBY); - if (ret) { + error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, DRV2665_STANDBY); + if (error) { dev_err(dev, "Failed to set standby mode\n"); regulator_disable(haptics->regulator); - goto out; + return error; } - ret = regulator_disable(haptics->regulator); - if (ret) { + error = regulator_disable(haptics->regulator); + if (error) { dev_err(dev, "Failed to disable regulator\n"); regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, DRV2665_STANDBY, 0); + return error; } } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + + return 0; } static int drv2665_resume(struct device *dev) { struct drv2665_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regulator_enable(haptics->regulator); - if (ret) { + error = regulator_enable(haptics->regulator); + if (error) { dev_err(dev, "Failed to enable regulator\n"); - goto out; + return error; } - ret = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, - DRV2665_STANDBY, 0); - if (ret) { + error = regmap_update_bits(haptics->regmap, DRV2665_CTRL_2, + DRV2665_STANDBY, 0); + if (error) { dev_err(dev, "Failed to unset standby mode\n"); regulator_disable(haptics->regulator); - goto out; + return error; } } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(drv2665_pm_ops, drv2665_suspend, drv2665_resume); static const struct i2c_device_id drv2665_id[] = { - { "drv2665", 0 }, + { "drv2665" }, { } }; MODULE_DEVICE_TABLE(i2c, drv2665_id); diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c index 11c5855256e8..f952a24ec595 100644 --- a/drivers/input/misc/drv2667.c +++ b/drivers/input/misc/drv2667.c @@ -16,7 +16,7 @@ #include <linux/delay.h> #include <linux/regulator/consumer.h> -/* Contol registers */ +/* Control registers */ #define DRV2667_STATUS 0x00 #define DRV2667_CTRL_1 0x01 #define DRV2667_CTRL_2 0x02 @@ -402,65 +402,63 @@ static int drv2667_probe(struct i2c_client *client) static int drv2667_suspend(struct device *dev) { struct drv2667_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, - DRV2667_STANDBY, DRV2667_STANDBY); - if (ret) { + error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, + DRV2667_STANDBY, DRV2667_STANDBY); + if (error) { dev_err(dev, "Failed to set standby mode\n"); regulator_disable(haptics->regulator); - goto out; + return error; } - ret = regulator_disable(haptics->regulator); - if (ret) { + error = regulator_disable(haptics->regulator); + if (error) { dev_err(dev, "Failed to disable regulator\n"); regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, DRV2667_STANDBY, 0); + return error; } } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + + return 0; } static int drv2667_resume(struct device *dev) { struct drv2667_data *haptics = dev_get_drvdata(dev); - int ret = 0; + int error; - mutex_lock(&haptics->input_dev->mutex); + guard(mutex)(&haptics->input_dev->mutex); if (input_device_enabled(haptics->input_dev)) { - ret = regulator_enable(haptics->regulator); - if (ret) { + error = regulator_enable(haptics->regulator); + if (error) { dev_err(dev, "Failed to enable regulator\n"); - goto out; + return error; } - ret = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, - DRV2667_STANDBY, 0); - if (ret) { + error = regmap_update_bits(haptics->regmap, DRV2667_CTRL_2, + DRV2667_STANDBY, 0); + if (error) { dev_err(dev, "Failed to unset standby mode\n"); regulator_disable(haptics->regulator); - goto out; + return error; } } -out: - mutex_unlock(&haptics->input_dev->mutex); - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(drv2667_pm_ops, drv2667_suspend, drv2667_resume); static const struct i2c_device_id drv2667_id[] = { - { "drv2667", 0 }, + { "drv2667" }, { } }; MODULE_DEVICE_TABLE(i2c, drv2667_id); diff --git a/drivers/input/misc/hisi_powerkey.c b/drivers/input/misc/hisi_powerkey.c index d3c293a95d32..d315017324d9 100644 --- a/drivers/input/misc/hisi_powerkey.c +++ b/drivers/input/misc/hisi_powerkey.c @@ -30,7 +30,7 @@ static irqreturn_t hi65xx_power_press_isr(int irq, void *q) { struct input_dev *input = q; - pm_wakeup_event(input->dev.parent, MAX_HELD_TIME); + pm_wakeup_dev_event(input->dev.parent, MAX_HELD_TIME, true); input_report_key(input, KEY_POWER, 1); input_sync(input); diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c index 867ac7aa10d2..aa48f62d7ea0 100644 --- a/drivers/input/misc/ibm-panel.c +++ b/drivers/input/misc/ibm-panel.c @@ -77,12 +77,11 @@ static void ibm_panel_process_command(struct ibm_panel *panel) static int ibm_panel_i2c_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) { - unsigned long flags; struct ibm_panel *panel = i2c_get_clientdata(client); dev_dbg(&panel->input->dev, "event: %u data: %02x\n", event, *val); - spin_lock_irqsave(&panel->lock, flags); + guard(spinlock_irqsave)(&panel->lock); switch (event) { case I2C_SLAVE_STOP: @@ -114,8 +113,6 @@ static int ibm_panel_i2c_slave_cb(struct i2c_client *client, break; } - spin_unlock_irqrestore(&panel->lock, flags); - return 0; } diff --git a/drivers/input/misc/ideapad_slidebar.c b/drivers/input/misc/ideapad_slidebar.c index fa4e7f67d713..ab2e0a401904 100644 --- a/drivers/input/misc/ideapad_slidebar.c +++ b/drivers/input/misc/ideapad_slidebar.c @@ -23,7 +23,7 @@ * * The value is in byte range, however, I only figured out * how bits 0b10011001 work. Some other bits, probably, - * are meaningfull too. + * are meaningful too. * * Possible states: * @@ -95,45 +95,33 @@ static struct platform_device *slidebar_platform_dev; static u8 slidebar_pos_get(void) { - u8 res; - unsigned long flags; + guard(spinlock_irqsave)(&io_lock); - spin_lock_irqsave(&io_lock, flags); outb(0xf4, 0xff29); outb(0xbf, 0xff2a); - res = inb(0xff2b); - spin_unlock_irqrestore(&io_lock, flags); - - return res; + return inb(0xff2b); } static u8 slidebar_mode_get(void) { - u8 res; - unsigned long flags; + guard(spinlock_irqsave)(&io_lock); - spin_lock_irqsave(&io_lock, flags); outb(0xf7, 0xff29); outb(0x8b, 0xff2a); - res = inb(0xff2b); - spin_unlock_irqrestore(&io_lock, flags); - - return res; + return inb(0xff2b); } static void slidebar_mode_set(u8 mode) { - unsigned long flags; + guard(spinlock_irqsave)(&io_lock); - spin_lock_irqsave(&io_lock, flags); outb(0xf7, 0xff29); outb(0x8b, 0xff2a); outb(mode, 0xff2b); - spin_unlock_irqrestore(&io_lock, flags); } static bool slidebar_i8042_filter(unsigned char data, unsigned char str, - struct serio *port) + struct serio *port, void *context) { static bool extended = false; @@ -231,7 +219,7 @@ static int __init ideapad_probe(struct platform_device* pdev) input_set_capability(slidebar_input_dev, EV_ABS, ABS_X); input_set_abs_params(slidebar_input_dev, ABS_X, 0, 0xff, 0, 0); - err = i8042_install_filter(slidebar_i8042_filter); + err = i8042_install_filter(slidebar_i8042_filter, NULL); if (err) { dev_err(&pdev->dev, "Failed to install i8042 filter: %d\n", err); @@ -267,7 +255,7 @@ static struct platform_driver slidebar_drv = { .driver = { .name = "ideapad_slidebar", }, - .remove_new = ideapad_remove, + .remove = ideapad_remove, }; static int __init ideapad_dmi_check(const struct dmi_system_id *id) diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 6e8cc28debd9..d9ee14b1f451 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -17,7 +17,7 @@ #include <linux/types.h> #include <linux/usb/input.h> #include <linux/usb/cdc.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define IMS_PCU_KEYMAP_LEN 32 @@ -42,8 +42,8 @@ struct ims_pcu_backlight { #define IMS_PCU_PART_NUMBER_LEN 15 #define IMS_PCU_SERIAL_NUMBER_LEN 8 #define IMS_PCU_DOM_LEN 8 -#define IMS_PCU_FW_VERSION_LEN (9 + 1) -#define IMS_PCU_BL_VERSION_LEN (9 + 1) +#define IMS_PCU_FW_VERSION_LEN 16 +#define IMS_PCU_BL_VERSION_LEN 16 #define IMS_PCU_BL_RESET_REASON_LEN (2 + 1) #define IMS_PCU_PCU_B_DEVICE_ID 5 @@ -207,8 +207,7 @@ static int ims_pcu_setup_buttons(struct ims_pcu *pcu, input = input_allocate_device(); if (!input) { - dev_err(pcu->dev, - "Not enough memory for input input device\n"); + dev_err(pcu->dev, "Not enough memory for input device\n"); return -ENOMEM; } @@ -287,7 +286,7 @@ static int ims_pcu_setup_gamepad(struct ims_pcu *pcu) struct input_dev *input; int error; - gamepad = kzalloc(sizeof(struct ims_pcu_gamepad), GFP_KERNEL); + gamepad = kzalloc(sizeof(*gamepad), GFP_KERNEL); input = input_allocate_device(); if (!gamepad || !input) { dev_err(pcu->dev, @@ -740,7 +739,7 @@ static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu) { int error; - /* Execute jump to the bootoloader */ + /* Execute jump to the bootloader */ error = ims_pcu_execute_command(pcu, JUMP_TO_BTLDR, NULL, 0); if (error) { dev_err(pcu->dev, @@ -761,7 +760,7 @@ static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu) struct ims_pcu_flash_fmt { __le32 addr; u8 len; - u8 data[]; + u8 data[] __counted_by(len); }; static unsigned int ims_pcu_count_fw_records(const struct firmware *fw) @@ -928,9 +927,8 @@ static void ims_pcu_process_async_firmware(const struct firmware *fw, goto out; } - mutex_lock(&pcu->cmd_mutex); - ims_pcu_handle_firmware_update(pcu, fw); - mutex_unlock(&pcu->cmd_mutex); + scoped_guard(mutex, &pcu->cmd_mutex) + ims_pcu_handle_firmware_update(pcu, fw); release_firmware(fw); @@ -954,7 +952,7 @@ static int ims_pcu_backlight_set_brightness(struct led_classdev *cdev, __le16 br_val = cpu_to_le16(value); int error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); error = ims_pcu_execute_command(pcu, SET_BRIGHTNESS, &br_val, sizeof(br_val)); @@ -963,8 +961,6 @@ static int ims_pcu_backlight_set_brightness(struct led_classdev *cdev, "Failed to set desired brightness %u, error: %d\n", value, error); - mutex_unlock(&pcu->cmd_mutex); - return error; } @@ -978,7 +974,7 @@ ims_pcu_backlight_get_brightness(struct led_classdev *cdev) int brightness; int error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); error = ims_pcu_execute_query(pcu, GET_BRIGHTNESS); if (error) { @@ -992,8 +988,6 @@ ims_pcu_backlight_get_brightness(struct led_classdev *cdev) get_unaligned_le16(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET]); } - mutex_unlock(&pcu->cmd_mutex); - return brightness; } @@ -1073,24 +1067,23 @@ static ssize_t ims_pcu_attribute_store(struct device *dev, if (data_len > attr->field_length) return -EINVAL; - error = mutex_lock_interruptible(&pcu->cmd_mutex); - if (error) - return error; - - memset(field, 0, attr->field_length); - memcpy(field, buf, data_len); + scoped_cond_guard(mutex_intr, return -EINTR, &pcu->cmd_mutex) { + memset(field, 0, attr->field_length); + memcpy(field, buf, data_len); - error = ims_pcu_set_info(pcu); + error = ims_pcu_set_info(pcu); - /* - * Even if update failed, let's fetch the info again as we just - * clobbered one of the fields. - */ - ims_pcu_get_info(pcu); + /* + * Even if update failed, let's fetch the info again as we just + * clobbered one of the fields. + */ + ims_pcu_get_info(pcu); - mutex_unlock(&pcu->cmd_mutex); + if (error) + return error; + } - return error < 0 ? error : count; + return count; } #define IMS_PCU_ATTR(_field, _mode) \ @@ -1153,7 +1146,6 @@ static ssize_t ims_pcu_update_firmware_store(struct device *dev, { struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); - const struct firmware *fw = NULL; int value; int error; @@ -1164,35 +1156,33 @@ static ssize_t ims_pcu_update_firmware_store(struct device *dev, if (value != 1) return -EINVAL; - error = mutex_lock_interruptible(&pcu->cmd_mutex); - if (error) - return error; - + const struct firmware *fw __free(firmware) = NULL; error = request_ihex_firmware(&fw, IMS_PCU_FIRMWARE_NAME, pcu->dev); if (error) { dev_err(pcu->dev, "Failed to request firmware %s, error: %d\n", IMS_PCU_FIRMWARE_NAME, error); - goto out; + return error; } - /* - * If we are already in bootloader mode we can proceed with - * flashing the firmware. - * - * If we are in application mode, then we need to switch into - * bootloader mode, which will cause the device to disconnect - * and reconnect as different device. - */ - if (pcu->bootloader_mode) - error = ims_pcu_handle_firmware_update(pcu, fw); - else - error = ims_pcu_switch_to_bootloader(pcu); + scoped_cond_guard(mutex_intr, return -EINTR, &pcu->cmd_mutex) { + /* + * If we are already in bootloader mode we can proceed with + * flashing the firmware. + * + * If we are in application mode, then we need to switch into + * bootloader mode, which will cause the device to disconnect + * and reconnect as different device. + */ + if (pcu->bootloader_mode) + error = ims_pcu_handle_firmware_update(pcu, fw); + else + error = ims_pcu_switch_to_bootloader(pcu); - release_firmware(fw); + if (error) + return error; + } -out: - mutex_unlock(&pcu->cmd_mutex); - return error ?: count; + return count; } static DEVICE_ATTR(update_firmware, S_IWUSR, @@ -1302,12 +1292,11 @@ static ssize_t ims_pcu_ofn_reg_data_show(struct device *dev, int error; u8 data; - mutex_lock(&pcu->cmd_mutex); - error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); - mutex_unlock(&pcu->cmd_mutex); - - if (error) - return error; + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, pcu->ofn_reg_addr, &data); + if (error) + return error; + } return sysfs_emit(buf, "%x\n", data); } @@ -1325,11 +1314,13 @@ static ssize_t ims_pcu_ofn_reg_data_store(struct device *dev, if (error) return error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); + error = ims_pcu_write_ofn_config(pcu, pcu->ofn_reg_addr, value); - mutex_unlock(&pcu->cmd_mutex); + if (error) + return error; - return error ?: count; + return count; } static DEVICE_ATTR(reg_data, S_IRUGO | S_IWUSR, @@ -1341,13 +1332,10 @@ static ssize_t ims_pcu_ofn_reg_addr_show(struct device *dev, { struct usb_interface *intf = to_usb_interface(dev); struct ims_pcu *pcu = usb_get_intfdata(intf); - int error; - mutex_lock(&pcu->cmd_mutex); - error = sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr); - mutex_unlock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); - return error; + return sysfs_emit(buf, "%x\n", pcu->ofn_reg_addr); } static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, @@ -1363,9 +1351,9 @@ static ssize_t ims_pcu_ofn_reg_addr_store(struct device *dev, if (error) return error; - mutex_lock(&pcu->cmd_mutex); + guard(mutex)(&pcu->cmd_mutex); + pcu->ofn_reg_addr = value; - mutex_unlock(&pcu->cmd_mutex); return count; } @@ -1390,12 +1378,11 @@ static ssize_t ims_pcu_ofn_bit_show(struct device *dev, int error; u8 data; - mutex_lock(&pcu->cmd_mutex); - error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); - mutex_unlock(&pcu->cmd_mutex); - - if (error) - return error; + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + if (error) + return error; + } return sysfs_emit(buf, "%d\n", !!(data & (1 << attr->nr))); } @@ -1419,21 +1406,22 @@ static ssize_t ims_pcu_ofn_bit_store(struct device *dev, if (value > 1) return -EINVAL; - mutex_lock(&pcu->cmd_mutex); + scoped_guard(mutex, &pcu->cmd_mutex) { + error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); + if (error) + return error; - error = ims_pcu_read_ofn_config(pcu, attr->addr, &data); - if (!error) { if (value) data |= 1U << attr->nr; else data &= ~(1U << attr->nr); error = ims_pcu_write_ofn_config(pcu, attr->addr, data); + if (error) + return error; } - mutex_unlock(&pcu->cmd_mutex); - - return error ?: count; + return count; } #define IMS_PCU_OFN_BIT_ATTR(_field, _addr, _nr) \ @@ -1466,9 +1454,27 @@ static struct attribute *ims_pcu_ofn_attrs[] = { NULL }; +static umode_t ims_pcu_ofn_is_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_interface *intf = to_usb_interface(dev); + struct ims_pcu *pcu = usb_get_intfdata(intf); + umode_t mode = attr->mode; + + /* + * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor. + */ + if (pcu->bootloader_mode || pcu->device_id == IMS_PCU_PCU_B_DEVICE_ID) + mode = 0; + + return mode; +} + static const struct attribute_group ims_pcu_ofn_attr_group = { - .name = "ofn", - .attrs = ims_pcu_ofn_attrs, + .name = "ofn", + .is_visible = ims_pcu_ofn_is_attr_visible, + .attrs = ims_pcu_ofn_attrs, }; static void ims_pcu_irq(struct urb *urb) @@ -1890,16 +1896,6 @@ static int ims_pcu_init_application_mode(struct ims_pcu *pcu) /* Device appears to be operable, complete initialization */ pcu->device_no = atomic_inc_return(&device_no); - /* - * PCU-B devices, both GEN_1 and GEN_2 do not have OFN sensor - */ - if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) { - error = sysfs_create_group(&pcu->dev->kobj, - &ims_pcu_ofn_attr_group); - if (error) - return error; - } - error = ims_pcu_setup_backlight(pcu); if (error) return error; @@ -1936,10 +1932,6 @@ static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu) ims_pcu_destroy_gamepad(pcu); ims_pcu_destroy_buttons(pcu); ims_pcu_destroy_backlight(pcu); - - if (pcu->device_id != IMS_PCU_PCU_B_DEVICE_ID) - sysfs_remove_group(&pcu->dev->kobj, - &ims_pcu_ofn_attr_group); } } @@ -1993,7 +1985,7 @@ static int ims_pcu_probe(struct usb_interface *intf, struct ims_pcu *pcu; int error; - pcu = kzalloc(sizeof(struct ims_pcu), GFP_KERNEL); + pcu = kzalloc(sizeof(*pcu), GFP_KERNEL); if (!pcu) return -ENOMEM; @@ -2031,20 +2023,14 @@ static int ims_pcu_probe(struct usb_interface *intf, if (error) goto err_stop_io; - error = sysfs_create_group(&intf->dev.kobj, &ims_pcu_attr_group); - if (error) - goto err_stop_io; - error = pcu->bootloader_mode ? ims_pcu_init_bootloader_mode(pcu) : ims_pcu_init_application_mode(pcu); if (error) - goto err_remove_sysfs; + goto err_stop_io; return 0; -err_remove_sysfs: - sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group); err_stop_io: ims_pcu_stop_io(pcu); err_free_buffers: @@ -2070,8 +2056,6 @@ static void ims_pcu_disconnect(struct usb_interface *intf) if (alt->desc.bInterfaceClass != USB_CLASS_COMM) return; - sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group); - ims_pcu_stop_io(pcu); if (pcu->bootloader_mode) @@ -2130,9 +2114,16 @@ static const struct usb_device_id ims_pcu_id_table[] = { { } }; +static const struct attribute_group *ims_pcu_sysfs_groups[] = { + &ims_pcu_attr_group, + &ims_pcu_ofn_attr_group, + NULL +}; + static struct usb_driver ims_pcu_driver = { .name = "ims_pcu", .id_table = ims_pcu_id_table, + .dev_groups = ims_pcu_sysfs_groups, .probe = ims_pcu_probe, .disconnect = ims_pcu_disconnect, #ifdef CONFIG_PM diff --git a/drivers/input/misc/iqs269a.c b/drivers/input/misc/iqs269a.c index cd14ff9f57cf..1851848e2cd3 100644 --- a/drivers/input/misc/iqs269a.c +++ b/drivers/input/misc/iqs269a.c @@ -365,7 +365,7 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269, if (mode > IQS269_CHx_ENG_A_ATI_MODE_MAX) return -EINVAL; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); engine_a = be16_to_cpu(ch_reg[ch_num].engine_a); @@ -375,8 +375,6 @@ static int iqs269_ati_mode_set(struct iqs269_private *iqs269, ch_reg[ch_num].engine_a = cpu_to_be16(engine_a); iqs269->ati_current = false; - mutex_unlock(&iqs269->lock); - return 0; } @@ -389,9 +387,9 @@ static int iqs269_ati_mode_get(struct iqs269_private *iqs269, if (ch_num >= IQS269_NUM_CH) return -EINVAL; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); + engine_a = be16_to_cpu(ch_reg[ch_num].engine_a); - mutex_unlock(&iqs269->lock); engine_a &= IQS269_CHx_ENG_A_ATI_MODE_MASK; *mode = (engine_a >> IQS269_CHx_ENG_A_ATI_MODE_SHIFT); @@ -429,7 +427,7 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269, return -EINVAL; } - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); engine_b = be16_to_cpu(ch_reg[ch_num].engine_b); @@ -439,8 +437,6 @@ static int iqs269_ati_base_set(struct iqs269_private *iqs269, ch_reg[ch_num].engine_b = cpu_to_be16(engine_b); iqs269->ati_current = false; - mutex_unlock(&iqs269->lock); - return 0; } @@ -453,9 +449,9 @@ static int iqs269_ati_base_get(struct iqs269_private *iqs269, if (ch_num >= IQS269_NUM_CH) return -EINVAL; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); + engine_b = be16_to_cpu(ch_reg[ch_num].engine_b); - mutex_unlock(&iqs269->lock); switch (engine_b & IQS269_CHx_ENG_B_ATI_BASE_MASK) { case IQS269_CHx_ENG_B_ATI_BASE_75: @@ -491,7 +487,7 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269, if (target > IQS269_CHx_ENG_B_ATI_TARGET_MAX) return -EINVAL; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); engine_b = be16_to_cpu(ch_reg[ch_num].engine_b); @@ -501,8 +497,6 @@ static int iqs269_ati_target_set(struct iqs269_private *iqs269, ch_reg[ch_num].engine_b = cpu_to_be16(engine_b); iqs269->ati_current = false; - mutex_unlock(&iqs269->lock); - return 0; } @@ -515,10 +509,9 @@ static int iqs269_ati_target_get(struct iqs269_private *iqs269, if (ch_num >= IQS269_NUM_CH) return -EINVAL; - mutex_lock(&iqs269->lock); - engine_b = be16_to_cpu(ch_reg[ch_num].engine_b); - mutex_unlock(&iqs269->lock); + guard(mutex)(&iqs269->lock); + engine_b = be16_to_cpu(ch_reg[ch_num].engine_b); *target = (engine_b & IQS269_CHx_ENG_B_ATI_TARGET_MASK) * 32; return 0; @@ -557,7 +550,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, const struct fwnode_handle *ch_node) { struct i2c_client *client = iqs269->client; - struct fwnode_handle *ev_node; struct iqs269_ch_reg *ch_reg; u16 engine_a, engine_b; unsigned int reg, val; @@ -734,8 +726,9 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, } for (i = 0; i < ARRAY_SIZE(iqs269_events); i++) { - ev_node = fwnode_get_named_child_node(ch_node, - iqs269_events[i].name); + struct fwnode_handle *ev_node __free(fwnode_handle) = + fwnode_get_named_child_node(ch_node, + iqs269_events[i].name); if (!ev_node) continue; @@ -744,7 +737,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, dev_err(&client->dev, "Invalid channel %u threshold: %u\n", reg, val); - fwnode_handle_put(ev_node); return -EINVAL; } @@ -758,7 +750,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, dev_err(&client->dev, "Invalid channel %u hysteresis: %u\n", reg, val); - fwnode_handle_put(ev_node); return -EINVAL; } @@ -774,7 +765,6 @@ static int iqs269_parse_chan(struct iqs269_private *iqs269, } error = fwnode_property_read_u32(ev_node, "linux,code", &val); - fwnode_handle_put(ev_node); if (error == -EINVAL) { continue; } else if (error) { @@ -811,7 +801,6 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269) { struct iqs269_sys_reg *sys_reg = &iqs269->sys_reg; struct i2c_client *client = iqs269->client; - struct fwnode_handle *ch_node; u16 general, misc_a, misc_b; unsigned int val; int error; @@ -1049,12 +1038,10 @@ static int iqs269_parse_prop(struct iqs269_private *iqs269) sys_reg->event_mask = ~((u8)IQS269_EVENT_MASK_SYS); - device_for_each_child_node(&client->dev, ch_node) { + device_for_each_child_node_scoped(&client->dev, ch_node) { error = iqs269_parse_chan(iqs269, ch_node); - if (error) { - fwnode_handle_put(ch_node); + if (error) return error; - } } /* @@ -1202,7 +1189,7 @@ static int iqs269_dev_init(struct iqs269_private *iqs269) { int error; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); /* * Early revisions of silicon require the following workaround in order @@ -1213,19 +1200,19 @@ static int iqs269_dev_init(struct iqs269_private *iqs269) error = regmap_multi_reg_write(iqs269->regmap, iqs269_tws_init, ARRAY_SIZE(iqs269_tws_init)); if (error) - goto err_mutex; + return error; } error = regmap_update_bits(iqs269->regmap, IQS269_HALL_UI, IQS269_HALL_UI_ENABLE, iqs269->hall_enable ? ~0 : 0); if (error) - goto err_mutex; + return error; error = regmap_raw_write(iqs269->regmap, IQS269_SYS_SETTINGS, &iqs269->sys_reg, sizeof(iqs269->sys_reg)); if (error) - goto err_mutex; + return error; /* * The following delay gives the device time to deassert its RDY output @@ -1235,10 +1222,7 @@ static int iqs269_dev_init(struct iqs269_private *iqs269) iqs269->ati_current = true; -err_mutex: - mutex_unlock(&iqs269->lock); - - return error; + return 0; } static int iqs269_input_init(struct iqs269_private *iqs269) @@ -1583,13 +1567,11 @@ static ssize_t hall_enable_store(struct device *dev, if (error) return error; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); iqs269->hall_enable = val; iqs269->ati_current = false; - mutex_unlock(&iqs269->lock); - return count; } @@ -1646,13 +1628,11 @@ static ssize_t rx_enable_store(struct device *dev, if (val > 0xFF) return -EINVAL; - mutex_lock(&iqs269->lock); + guard(mutex)(&iqs269->lock); ch_reg[iqs269->ch_num].rx_enable = val; iqs269->ati_current = false; - mutex_unlock(&iqs269->lock); - return count; } diff --git a/drivers/input/misc/iqs626a.c b/drivers/input/misc/iqs626a.c index 0dab54d3a060..7a6e6927f331 100644 --- a/drivers/input/misc/iqs626a.c +++ b/drivers/input/misc/iqs626a.c @@ -462,7 +462,6 @@ iqs626_parse_events(struct iqs626_private *iqs626, { struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; struct i2c_client *client = iqs626->client; - struct fwnode_handle *ev_node; const char *ev_name; u8 *thresh, *hyst; unsigned int val; @@ -501,6 +500,7 @@ iqs626_parse_events(struct iqs626_private *iqs626, if (!iqs626_channels[ch_id].events[i]) continue; + struct fwnode_handle *ev_node __free(fwnode_handle) = NULL; if (ch_id == IQS626_CH_TP_2 || ch_id == IQS626_CH_TP_3) { /* * Trackpad touch events are simply described under the @@ -530,7 +530,6 @@ iqs626_parse_events(struct iqs626_private *iqs626, dev_err(&client->dev, "Invalid input type: %u\n", val); - fwnode_handle_put(ev_node); return -EINVAL; } @@ -545,7 +544,6 @@ iqs626_parse_events(struct iqs626_private *iqs626, dev_err(&client->dev, "Invalid %s channel hysteresis: %u\n", fwnode_get_name(ch_node), val); - fwnode_handle_put(ev_node); return -EINVAL; } @@ -566,7 +564,6 @@ iqs626_parse_events(struct iqs626_private *iqs626, dev_err(&client->dev, "Invalid %s channel threshold: %u\n", fwnode_get_name(ch_node), val); - fwnode_handle_put(ev_node); return -EINVAL; } @@ -575,8 +572,6 @@ iqs626_parse_events(struct iqs626_private *iqs626, else *(thresh + iqs626_events[i].th_offs) = val; } - - fwnode_handle_put(ev_node); } return 0; @@ -774,12 +769,12 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626, for (i = 0; i < iqs626_channels[ch_id].num_ch; i++) { u8 *ati_base = &sys_reg->tp_grp_reg.ch_reg_tp[i].ati_base; u8 *thresh = &sys_reg->tp_grp_reg.ch_reg_tp[i].thresh; - struct fwnode_handle *tc_node; char tc_name[10]; snprintf(tc_name, sizeof(tc_name), "channel-%d", i); - tc_node = fwnode_get_named_child_node(ch_node, tc_name); + struct fwnode_handle *tc_node __free(fwnode_handle) = + fwnode_get_named_child_node(ch_node, tc_name); if (!tc_node) continue; @@ -790,7 +785,6 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626, dev_err(&client->dev, "Invalid %s %s ATI base: %u\n", fwnode_get_name(ch_node), tc_name, val); - fwnode_handle_put(tc_node); return -EINVAL; } @@ -803,14 +797,11 @@ static int iqs626_parse_trackpad(struct iqs626_private *iqs626, dev_err(&client->dev, "Invalid %s %s threshold: %u\n", fwnode_get_name(ch_node), tc_name, val); - fwnode_handle_put(tc_node); return -EINVAL; } *thresh = val; } - - fwnode_handle_put(tc_node); } if (!fwnode_property_present(ch_node, "linux,keycodes")) @@ -1233,7 +1224,6 @@ static int iqs626_parse_prop(struct iqs626_private *iqs626) { struct iqs626_sys_reg *sys_reg = &iqs626->sys_reg; struct i2c_client *client = iqs626->client; - struct fwnode_handle *ch_node; unsigned int val; int error, i; u16 general; @@ -1375,13 +1365,13 @@ static int iqs626_parse_prop(struct iqs626_private *iqs626) sys_reg->active = 0; for (i = 0; i < ARRAY_SIZE(iqs626_channels); i++) { - ch_node = device_get_named_child_node(&client->dev, - iqs626_channels[i].name); + struct fwnode_handle *ch_node __free(fwnode_handle) = + device_get_named_child_node(&client->dev, + iqs626_channels[i].name); if (!ch_node) continue; error = iqs626_parse_channel(iqs626, ch_node, i); - fwnode_handle_put(ch_node); if (error) return error; diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c index 9ca5a743f19f..80b917944b51 100644 --- a/drivers/input/misc/iqs7222.c +++ b/drivers/input/misc/iqs7222.c @@ -20,7 +20,7 @@ #include <linux/module.h> #include <linux/property.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define IQS7222_PROD_NUM 0x00 #define IQS7222_PROD_NUM_A 840 @@ -100,11 +100,11 @@ enum iqs7222_reg_key_id { enum iqs7222_reg_grp_id { IQS7222_REG_GRP_STAT, - IQS7222_REG_GRP_FILT, IQS7222_REG_GRP_CYCLE, IQS7222_REG_GRP_GLBL, IQS7222_REG_GRP_BTN, IQS7222_REG_GRP_CHAN, + IQS7222_REG_GRP_FILT, IQS7222_REG_GRP_SLDR, IQS7222_REG_GRP_TPAD, IQS7222_REG_GRP_GPIO, @@ -286,6 +286,7 @@ static const struct iqs7222_event_desc iqs7222_tp_events[] = { struct iqs7222_reg_grp_desc { u16 base; + u16 val_len; int num_row; int num_col; }; @@ -342,6 +343,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAC00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -400,6 +402,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAC00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -454,6 +457,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xC400, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -496,6 +500,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xC400, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -543,6 +548,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAA00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -600,6 +606,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAA00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -656,6 +663,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -712,6 +720,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -768,6 +777,7 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = { }, [IQS7222_REG_GRP_FILT] = { .base = 0xAE00, + .val_len = 3, .num_row = 1, .num_col = 2, }, @@ -1604,7 +1614,7 @@ static int iqs7222_force_comms(struct iqs7222_private *iqs7222) } static int iqs7222_read_burst(struct iqs7222_private *iqs7222, - u16 reg, void *val, u16 num_val) + u16 reg, void *val, u16 val_len) { u8 reg_buf[sizeof(__be16)]; int ret, i; @@ -1619,7 +1629,7 @@ static int iqs7222_read_burst(struct iqs7222_private *iqs7222, { .addr = client->addr, .flags = I2C_M_RD, - .len = num_val * sizeof(__le16), + .len = val_len, .buf = (u8 *)val, }, }; @@ -1675,7 +1685,7 @@ static int iqs7222_read_word(struct iqs7222_private *iqs7222, u16 reg, u16 *val) __le16 val_buf; int error; - error = iqs7222_read_burst(iqs7222, reg, &val_buf, 1); + error = iqs7222_read_burst(iqs7222, reg, &val_buf, sizeof(val_buf)); if (error) return error; @@ -1685,10 +1695,9 @@ static int iqs7222_read_word(struct iqs7222_private *iqs7222, u16 reg, u16 *val) } static int iqs7222_write_burst(struct iqs7222_private *iqs7222, - u16 reg, const void *val, u16 num_val) + u16 reg, const void *val, u16 val_len) { int reg_len = reg > U8_MAX ? sizeof(reg) : sizeof(u8); - int val_len = num_val * sizeof(__le16); int msg_len = reg_len + val_len; int ret, i; struct i2c_client *client = iqs7222->client; @@ -1747,7 +1756,7 @@ static int iqs7222_write_word(struct iqs7222_private *iqs7222, u16 reg, u16 val) { __le16 val_buf = cpu_to_le16(val); - return iqs7222_write_burst(iqs7222, reg, &val_buf, 1); + return iqs7222_write_burst(iqs7222, reg, &val_buf, sizeof(val_buf)); } static int iqs7222_ati_trigger(struct iqs7222_private *iqs7222) @@ -1831,30 +1840,14 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) /* * Acknowledge reset before writing any registers in case the device - * suffers a spurious reset during initialization. Because this step - * may change the reserved fields of the second filter beta register, - * its cache must be updated. - * - * Writing the second filter beta register, in turn, may clobber the - * system status register. As such, the filter beta register pair is - * written first to protect against this hazard. + * suffers a spurious reset during initialization. */ if (dir == WRITE) { - u16 reg = dev_desc->reg_grps[IQS7222_REG_GRP_FILT].base + 1; - u16 filt_setup; - error = iqs7222_write_word(iqs7222, IQS7222_SYS_SETUP, iqs7222->sys_setup[0] | IQS7222_SYS_SETUP_ACK_RESET); if (error) return error; - - error = iqs7222_read_word(iqs7222, reg, &filt_setup); - if (error) - return error; - - iqs7222->filt_setup[1] &= GENMASK(7, 0); - iqs7222->filt_setup[1] |= (filt_setup & ~GENMASK(7, 0)); } /* @@ -1883,6 +1876,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) int num_col = dev_desc->reg_grps[i].num_col; u16 reg = dev_desc->reg_grps[i].base; __le16 *val_buf; + u16 val_len = dev_desc->reg_grps[i].val_len ? : num_col * sizeof(*val_buf); u16 *val; if (!num_col) @@ -1900,7 +1894,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) switch (dir) { case READ: error = iqs7222_read_burst(iqs7222, reg, - val_buf, num_col); + val_buf, val_len); for (k = 0; k < num_col; k++) val[k] = le16_to_cpu(val_buf[k]); break; @@ -1909,7 +1903,7 @@ static int iqs7222_dev_init(struct iqs7222_private *iqs7222, int dir) for (k = 0; k < num_col; k++) val_buf[k] = cpu_to_le16(val[k]); error = iqs7222_write_burst(iqs7222, reg, - val_buf, num_col); + val_buf, val_len); break; default: @@ -1962,7 +1956,7 @@ static int iqs7222_dev_info(struct iqs7222_private *iqs7222) int error, i; error = iqs7222_read_burst(iqs7222, IQS7222_PROD_NUM, dev_id, - ARRAY_SIZE(dev_id)); + sizeof(dev_id)); if (error) return error; @@ -2385,9 +2379,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, for (i = 0; i < ARRAY_SIZE(iqs7222_kp_events); i++) { const char *event_name = iqs7222_kp_events[i].name; u16 event_enable = iqs7222_kp_events[i].enable; - struct fwnode_handle *event_node; - event_node = fwnode_get_named_child_node(chan_node, event_name); + struct fwnode_handle *event_node __free(fwnode_handle) = + fwnode_get_named_child_node(chan_node, event_name); if (!event_node) continue; @@ -2408,7 +2402,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, dev_err(&client->dev, "Invalid %s press timeout: %u\n", fwnode_get_name(event_node), val); - fwnode_handle_put(event_node); return -EINVAL; } @@ -2418,7 +2411,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, dev_err(&client->dev, "Failed to read %s press timeout: %d\n", fwnode_get_name(event_node), error); - fwnode_handle_put(event_node); return error; } @@ -2429,7 +2421,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, dev_desc->touch_link - (i ? 0 : 2), &iqs7222->kp_type[chan_index][i], &iqs7222->kp_code[chan_index][i]); - fwnode_handle_put(event_node); if (error) return error; @@ -2604,10 +2595,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) { const char *event_name = iqs7222_sl_events[i].name; - struct fwnode_handle *event_node; enum iqs7222_reg_key_id reg_key; - event_node = fwnode_get_named_child_node(sldr_node, event_name); + struct fwnode_handle *event_node __free(fwnode_handle) = + fwnode_get_named_child_node(sldr_node, event_name); if (!event_node) continue; @@ -2639,7 +2630,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, : sldr_setup[4 + reg_offset], NULL, &iqs7222->sl_code[sldr_index][i]); - fwnode_handle_put(event_node); if (error) return error; @@ -2742,9 +2732,9 @@ static int iqs7222_parse_tpad(struct iqs7222_private *iqs7222, for (i = 0; i < ARRAY_SIZE(iqs7222_tp_events); i++) { const char *event_name = iqs7222_tp_events[i].name; - struct fwnode_handle *event_node; - event_node = fwnode_get_named_child_node(tpad_node, event_name); + struct fwnode_handle *event_node __free(fwnode_handle) = + fwnode_get_named_child_node(tpad_node, event_name); if (!event_node) continue; @@ -2760,7 +2750,6 @@ static int iqs7222_parse_tpad(struct iqs7222_private *iqs7222, iqs7222_tp_events[i].link, 1566, NULL, &iqs7222->tp_code[i]); - fwnode_handle_put(event_node); if (error) return error; @@ -2818,9 +2807,9 @@ static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, int reg_grp_index) { struct i2c_client *client = iqs7222->client; - struct fwnode_handle *reg_grp_node; int error; + struct fwnode_handle *reg_grp_node __free(fwnode_handle) = NULL; if (iqs7222_reg_grp_names[reg_grp]) { char reg_grp_name[16]; @@ -2838,14 +2827,17 @@ static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222, error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index, reg_grp, IQS7222_REG_KEY_NONE); + if (error) + return error; - if (!error && iqs7222_parse_extra[reg_grp]) + if (iqs7222_parse_extra[reg_grp]) { error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node, reg_grp_index); + if (error) + return error; + } - fwnode_handle_put(reg_grp_node); - - return error; + return 0; } static int iqs7222_parse_all(struct iqs7222_private *iqs7222) @@ -2917,7 +2909,7 @@ static int iqs7222_report(struct iqs7222_private *iqs7222) __le16 status[IQS7222_MAX_COLS_STAT]; error = iqs7222_read_burst(iqs7222, IQS7222_SYS_STATUS, status, - num_stat); + num_stat * sizeof(*status)); if (error) return error; diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index d47269b10e9a..eb9788ea5215 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -25,7 +25,7 @@ /* CONTROL REGISTER 1 BITS */ #define PC1_OFF 0x7F #define PC1_ON (1 << 7) -/* Data ready funtion enable bit: set during probe if using irq mode */ +/* Data ready function enable bit: set during probe if using irq mode */ #define DRDYE (1 << 5) /* DATA CONTROL REGISTER BITS */ #define ODR12_5F 0 @@ -314,9 +314,8 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr, return error; /* Lock the device to prevent races with open/close (and itself) */ - mutex_lock(&input_dev->mutex); - - disable_irq(client->irq); + guard(mutex)(&input_dev->mutex); + guard(disable_irq)(&client->irq); /* * Set current interval to the greater of the minimum interval or @@ -326,9 +325,6 @@ static ssize_t kxtj9_set_poll(struct device *dev, struct device_attribute *attr, kxtj9_update_odr(tj9, tj9->last_poll_interval); - enable_irq(client->irq); - mutex_unlock(&input_dev->mutex); - return count; } @@ -504,12 +500,11 @@ static int kxtj9_suspend(struct device *dev) struct kxtj9_data *tj9 = i2c_get_clientdata(client); struct input_dev *input_dev = tj9->input_dev; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) kxtj9_disable(tj9); - mutex_unlock(&input_dev->mutex); return 0; } @@ -519,20 +514,19 @@ static int kxtj9_resume(struct device *dev) struct kxtj9_data *tj9 = i2c_get_clientdata(client); struct input_dev *input_dev = tj9->input_dev; - mutex_lock(&input_dev->mutex); + guard(mutex)(&input_dev->mutex); if (input_device_enabled(input_dev)) kxtj9_enable(tj9); - mutex_unlock(&input_dev->mutex); return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(kxtj9_pm_ops, kxtj9_suspend, kxtj9_resume); static const struct i2c_device_id kxtj9_id[] = { - { NAME, 0 }, - { }, + { NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, kxtj9_id); diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index 3fe0a85c45e0..0542334df624 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c @@ -95,7 +95,7 @@ static struct platform_driver m68kspkr_platform_driver = { .name = "m68kspkr", }, .probe = m68kspkr_probe, - .remove_new = m68kspkr_remove, + .remove = m68kspkr_remove, .shutdown = m68kspkr_shutdown, }; diff --git a/drivers/input/misc/max77693-haptic.c b/drivers/input/misc/max77693-haptic.c index 0e646f1b257b..1dfd7b95a4ce 100644 --- a/drivers/input/misc/max77693-haptic.c +++ b/drivers/input/misc/max77693-haptic.c @@ -18,11 +18,13 @@ #include <linux/platform_device.h> #include <linux/pwm.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/workqueue.h> #include <linux/regulator/consumer.h> #include <linux/mfd/max77693.h> #include <linux/mfd/max77693-common.h> #include <linux/mfd/max77693-private.h> +#include <linux/mfd/max77705-private.h> #include <linux/mfd/max77843-private.h> #define MAX_MAGNITUDE_SHIFT 16 @@ -94,7 +96,7 @@ static int max77843_haptic_bias(struct max77693_haptic *haptic, bool on) on << MAINCTRL1_BIASEN_SHIFT); if (error) { dev_err(haptic->dev, "failed to %s bias: %d\n", - on ? "enable" : "disable", error); + str_enable_disable(on), error); return error; } @@ -115,6 +117,13 @@ static int max77693_haptic_configure(struct max77693_haptic *haptic, MAX77693_HAPTIC_PWM_DIVISOR_128); config_reg = MAX77693_HAPTIC_REG_CONFIG2; break; + case TYPE_MAX77705: + value = ((haptic->type << MAX77693_CONFIG2_MODE) | + (enable << MAX77693_CONFIG2_MEN) | + (haptic->mode << MAX77693_CONFIG2_HTYP) | + MAX77693_HAPTIC_PWM_DIVISOR_128); + config_reg = MAX77705_PMIC_REG_MCONFIG; + break; case TYPE_MAX77843: value = (haptic->type << MCONFIG_MODE_SHIFT) | (enable << MCONFIG_MEN_SHIFT) | @@ -312,6 +321,7 @@ static int max77693_haptic_probe(struct platform_device *pdev) case TYPE_MAX77693: haptic->regmap_haptic = max77693->regmap_haptic; break; + case TYPE_MAX77705: case TYPE_MAX77843: haptic->regmap_haptic = max77693->regmap; break; @@ -407,6 +417,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(max77693_haptic_pm_ops, static const struct platform_device_id max77693_haptic_id[] = { { "max77693-haptic", }, + { "max77705-haptic", }, { "max77843-haptic", }, {}, }; @@ -414,6 +425,7 @@ MODULE_DEVICE_TABLE(platform, max77693_haptic_id); static const struct of_device_id of_max77693_haptic_dt_match[] = { { .compatible = "maxim,max77693-haptic", }, + { .compatible = "maxim,max77705-haptic", }, { .compatible = "maxim,max77843-haptic", }, { /* sentinel */ }, }; @@ -432,5 +444,5 @@ module_platform_driver(max77693_haptic_driver); MODULE_AUTHOR("Jaewon Kim <jaewon02.kim@samsung.com>"); MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>"); -MODULE_DESCRIPTION("MAXIM 77693/77843 Haptic driver"); +MODULE_DESCRIPTION("MAXIM 77693/77705/77843 Haptic driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index 8861a67be575..f97f341ee0bb 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -153,19 +153,19 @@ static void max8997_haptic_enable(struct max8997_haptic *chip) { int error; - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); error = max8997_haptic_set_duty_cycle(chip); if (error) { dev_err(chip->dev, "set_pwm_cycle failed, error: %d\n", error); - goto out; + return; } if (!chip->enabled) { error = regulator_enable(chip->regulator); if (error) { dev_err(chip->dev, "Failed to enable regulator\n"); - goto out; + return; } max8997_haptic_configure(chip); if (chip->mode == MAX8997_EXTERNAL_MODE) { @@ -173,19 +173,16 @@ static void max8997_haptic_enable(struct max8997_haptic *chip) if (error) { dev_err(chip->dev, "Failed to enable PWM\n"); regulator_disable(chip->regulator); - goto out; + return; } } chip->enabled = true; } - -out: - mutex_unlock(&chip->mutex); } static void max8997_haptic_disable(struct max8997_haptic *chip) { - mutex_lock(&chip->mutex); + guard(mutex)(&chip->mutex); if (chip->enabled) { chip->enabled = false; @@ -194,8 +191,6 @@ static void max8997_haptic_disable(struct max8997_haptic *chip) pwm_disable(chip->pwm); regulator_disable(chip->regulator); } - - mutex_unlock(&chip->mutex); } static void max8997_haptic_play_effect_work(struct work_struct *work) @@ -249,7 +244,7 @@ static int max8997_haptic_probe(struct platform_device *pdev) return -EINVAL; } - chip = kzalloc(sizeof(struct max8997_haptic), GFP_KERNEL); + chip = kzalloc(sizeof(*chip), GFP_KERNEL); input_dev = input_allocate_device(); if (!chip || !input_dev) { dev_err(&pdev->dev, "unable to allocate memory\n"); @@ -389,7 +384,7 @@ static struct platform_driver max8997_haptic_driver = { .pm = pm_sleep_ptr(&max8997_haptic_pm_ops), }, .probe = max8997_haptic_probe, - .remove_new = max8997_haptic_remove, + .remove = max8997_haptic_remove, .id_table = max8997_haptic_id, }; module_platform_driver(max8997_haptic_driver); diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c index 1c8c939638f6..1c7faa9b7afe 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -253,7 +253,7 @@ static void mc13783_pwrbutton_remove(struct platform_device *pdev) static struct platform_driver mc13783_pwrbutton_driver = { .probe = mc13783_pwrbutton_probe, - .remove_new = mc13783_pwrbutton_remove, + .remove = mc13783_pwrbutton_remove, .driver = { .name = "mc13783-pwrbutton", }, diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 662b436d765b..0c661140fb88 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -38,6 +38,8 @@ #define MMA8450_CTRL_REG1 0x38 #define MMA8450_CTRL_REG2 0x39 +#define MMA8450_ID 0xc6 +#define MMA8450_WHO_AM_I 0x0f static int mma8450_read(struct i2c_client *c, unsigned int off) { @@ -148,8 +150,20 @@ static void mma8450_close(struct input_dev *input) */ static int mma8450_probe(struct i2c_client *c) { + struct i2c_adapter *adapter = c->adapter; struct input_dev *input; - int err; + int err, client_id; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA)) + return dev_err_probe(&c->dev, -EINVAL, + "I2C adapter doesn't support SMBUS BYTE"); + + client_id = i2c_smbus_read_byte_data(c, MMA8450_WHO_AM_I); + if (client_id != MMA8450_ID) + return dev_err_probe(&c->dev, -EINVAL, + "unexpected chip ID 0x%x (vs 0x%x)\n", + client_id, MMA8450_ID); input = devm_input_allocate_device(&c->dev); if (!input) @@ -186,8 +200,8 @@ static int mma8450_probe(struct i2c_client *c) } static const struct i2c_device_id mma8450_id[] = { - { MMA8450_DRV_NAME, 0 }, - { }, + { MMA8450_DRV_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, mma8450_id); diff --git a/drivers/input/misc/nxp-bbnsm-pwrkey.c b/drivers/input/misc/nxp-bbnsm-pwrkey.c index 1d99206dd3a8..7ba8d166d68c 100644 --- a/drivers/input/misc/nxp-bbnsm-pwrkey.c +++ b/drivers/input/misc/nxp-bbnsm-pwrkey.c @@ -38,6 +38,7 @@ struct bbnsm_pwrkey { int irq; int keycode; int keystate; /* 1:pressed */ + bool suspended; struct timer_list check_timer; struct input_dev *input; }; @@ -70,6 +71,7 @@ static irqreturn_t bbnsm_pwrkey_interrupt(int irq, void *dev_id) { struct platform_device *pdev = dev_id; struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev); + struct input_dev *input = bbnsm->input; u32 event; regmap_read(bbnsm->regmap, BBNSM_EVENTS, &event); @@ -78,6 +80,18 @@ static irqreturn_t bbnsm_pwrkey_interrupt(int irq, void *dev_id) pm_wakeup_event(bbnsm->input->dev.parent, 0); + /* + * Directly report key event after resume to make sure key press + * event is never missed. + */ + if (bbnsm->suspended) { + bbnsm->keystate = 1; + input_event(input, EV_KEY, bbnsm->keycode, 1); + input_sync(input); + /* Fire at most once per suspend/resume cycle */ + bbnsm->suspended = false; + } + mod_timer(&bbnsm->check_timer, jiffies + msecs_to_jiffies(DEBOUNCE_TIME)); @@ -173,6 +187,35 @@ static int bbnsm_pwrkey_probe(struct platform_device *pdev) return 0; } +static void bbnsm_pwrkey_remove(struct platform_device *pdev) +{ + dev_pm_clear_wake_irq(&pdev->dev); + device_init_wakeup(&pdev->dev, false); +} + +static int __maybe_unused bbnsm_pwrkey_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev); + + bbnsm->suspended = true; + + return 0; +} + +static int __maybe_unused bbnsm_pwrkey_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct bbnsm_pwrkey *bbnsm = platform_get_drvdata(pdev); + + bbnsm->suspended = false; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(bbnsm_pwrkey_pm_ops, bbnsm_pwrkey_suspend, + bbnsm_pwrkey_resume); + static const struct of_device_id bbnsm_pwrkey_ids[] = { { .compatible = "nxp,imx93-bbnsm-pwrkey" }, { /* sentinel */ } @@ -182,9 +225,12 @@ MODULE_DEVICE_TABLE(of, bbnsm_pwrkey_ids); static struct platform_driver bbnsm_pwrkey_driver = { .driver = { .name = "bbnsm_pwrkey", + .pm = &bbnsm_pwrkey_pm_ops, .of_match_table = bbnsm_pwrkey_ids, }, .probe = bbnsm_pwrkey_probe, + .remove = bbnsm_pwrkey_remove, + }; module_platform_driver(bbnsm_pwrkey_driver); diff --git a/drivers/input/misc/palmas-pwrbutton.c b/drivers/input/misc/palmas-pwrbutton.c index 06d5972e8e84..39fc451c56e9 100644 --- a/drivers/input/misc/palmas-pwrbutton.c +++ b/drivers/input/misc/palmas-pwrbutton.c @@ -310,7 +310,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_pwr_match); static struct platform_driver palmas_pwron_driver = { .probe = palmas_pwron_probe, - .remove_new = palmas_pwron_remove, + .remove = palmas_pwron_remove, .driver = { .name = "palmas_pwrbutton", .of_match_table = of_match_ptr(of_palmas_pwr_match), diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 8a7e9ada5952..fe43fd72ba7b 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -49,7 +49,7 @@ static int pcap_keys_probe(struct platform_device *pdev) struct pcap_keys *pcap_keys; struct input_dev *input_dev; - pcap_keys = kmalloc(sizeof(struct pcap_keys), GFP_KERNEL); + pcap_keys = kmalloc(sizeof(*pcap_keys), GFP_KERNEL); if (!pcap_keys) return err; @@ -112,7 +112,7 @@ static void pcap_keys_remove(struct platform_device *pdev) static struct platform_driver pcap_keys_device_driver = { .probe = pcap_keys_probe, - .remove_new = pcap_keys_remove, + .remove = pcap_keys_remove, .driver = { .name = "pcap-keys", } diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index c5c5fe236c18..6d046e236ba6 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -103,7 +103,7 @@ static struct platform_driver pcf50633_input_driver = { .name = "pcf50633-input", }, .probe = pcf50633_input_probe, - .remove_new = pcf50633_input_remove, + .remove = pcf50633_input_remove, }; module_platform_driver(pcf50633_input_driver); diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 536cedeb38e6..3632cb206e34 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -189,7 +189,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(pcf8574_kp_pm_ops, pcf8574_kp_suspend, pcf8574_kp_resume); static const struct i2c_device_id pcf8574_kp_id[] = { - { DRV_NAME, 0 }, + { DRV_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, pcf8574_kp_id); diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 897854fd245f..0467808402f2 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -127,7 +127,7 @@ static struct platform_driver pcspkr_platform_driver = { .pm = &pcspkr_pm_ops, }, .probe = pcspkr_probe, - .remove_new = pcspkr_remove, + .remove = pcspkr_remove, .shutdown = pcspkr_shutdown, }; module_platform_driver(pcspkr_platform_driver); diff --git a/drivers/input/misc/pm8941-pwrkey.c b/drivers/input/misc/pm8941-pwrkey.c index bab710023d8f..d952c16f2458 100644 --- a/drivers/input/misc/pm8941-pwrkey.c +++ b/drivers/input/misc/pm8941-pwrkey.c @@ -154,8 +154,8 @@ static irqreturn_t pm8941_pwrkey_irq(int irq, void *_data) if (pwrkey->sw_debounce_time_us) { if (ktime_before(ktime_get(), pwrkey->sw_debounce_end_time)) { dev_dbg(pwrkey->dev, - "ignoring key event received before debounce end %llu us\n", - pwrkey->sw_debounce_end_time); + "ignoring key event received before debounce end %lld us\n", + ktime_to_us(pwrkey->sw_debounce_end_time)); return IRQ_HANDLED; } } @@ -465,7 +465,7 @@ MODULE_DEVICE_TABLE(of, pm8941_pwr_key_id_table); static struct platform_driver pm8941_pwrkey_driver = { .probe = pm8941_pwrkey_probe, - .remove_new = pm8941_pwrkey_remove, + .remove = pm8941_pwrkey_remove, .driver = { .name = "pm8941-pwrkey", .pm = pm_sleep_ptr(&pm8941_pwr_key_pm_ops), diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index 5c288fe7accf..381b06473279 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -11,36 +11,57 @@ #include <linux/regmap.h> #include <linux/slab.h> -#define VIB_MAX_LEVEL_mV (3100) -#define VIB_MIN_LEVEL_mV (1200) -#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV) +#define VIB_MAX_LEVEL_mV(vib) (vib->drv2_addr ? 3544 : 3100) +#define VIB_MIN_LEVEL_mV(vib) (vib->drv2_addr ? 1504 : 1200) +#define VIB_PER_STEP_mV(vib) (vib->drv2_addr ? 8 : 100) +#define VIB_MAX_LEVELS(vib) \ + (VIB_MAX_LEVEL_mV(vib) - VIB_MIN_LEVEL_mV(vib) + VIB_PER_STEP_mV(vib)) #define MAX_FF_SPEED 0xff struct pm8xxx_regs { - unsigned int enable_addr; + unsigned int enable_offset; unsigned int enable_mask; - unsigned int drv_addr; + unsigned int drv_offset; unsigned int drv_mask; unsigned int drv_shift; + unsigned int drv2_offset; + unsigned int drv2_mask; + unsigned int drv2_shift; unsigned int drv_en_manual_mask; + bool drv_in_step; }; static const struct pm8xxx_regs pm8058_regs = { - .drv_addr = 0x4A, - .drv_mask = 0xf8, + .drv_offset = 0, + .drv_mask = GENMASK(7, 3), .drv_shift = 3, .drv_en_manual_mask = 0xfc, + .drv_in_step = true, }; static struct pm8xxx_regs pm8916_regs = { - .enable_addr = 0xc046, + .enable_offset = 0x46, .enable_mask = BIT(7), - .drv_addr = 0xc041, - .drv_mask = 0x1F, + .drv_offset = 0x41, + .drv_mask = GENMASK(4, 0), .drv_shift = 0, .drv_en_manual_mask = 0, + .drv_in_step = true, +}; + +static struct pm8xxx_regs pmi632_regs = { + .enable_offset = 0x46, + .enable_mask = BIT(7), + .drv_offset = 0x40, + .drv_mask = GENMASK(7, 0), + .drv_shift = 0, + .drv2_offset = 0x41, + .drv2_mask = GENMASK(3, 0), + .drv2_shift = 8, + .drv_en_manual_mask = 0, + .drv_in_step = false, }; /** @@ -49,6 +70,9 @@ static struct pm8xxx_regs pm8916_regs = { * @work: work structure to set the vibration parameters * @regmap: regmap for register read/write * @regs: registers' info + * @enable_addr: vibrator enable register + * @drv_addr: vibrator drive strength register + * @drv2_addr: vibrator drive strength upper byte register * @speed: speed of vibration set from userland * @active: state of vibrator * @level: level of vibration to set in the chip @@ -59,6 +83,9 @@ struct pm8xxx_vib { struct work_struct work; struct regmap *regmap; const struct pm8xxx_regs *regs; + unsigned int enable_addr; + unsigned int drv_addr; + unsigned int drv2_addr; int speed; int level; bool active; @@ -76,20 +103,31 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) unsigned int val = vib->reg_vib_drv; const struct pm8xxx_regs *regs = vib->regs; + if (regs->drv_in_step) + vib->level /= VIB_PER_STEP_mV(vib); + if (on) val |= (vib->level << regs->drv_shift) & regs->drv_mask; else val &= ~regs->drv_mask; - rc = regmap_write(vib->regmap, regs->drv_addr, val); + rc = regmap_write(vib->regmap, vib->drv_addr, val); if (rc < 0) return rc; vib->reg_vib_drv = val; + if (regs->drv2_mask) { + val = vib->level << regs->drv2_shift; + rc = regmap_write_bits(vib->regmap, vib->drv2_addr, + regs->drv2_mask, on ? val : 0); + if (rc < 0) + return rc; + } + if (regs->enable_mask) - rc = regmap_update_bits(vib->regmap, regs->enable_addr, - regs->enable_mask, on ? ~0 : 0); + rc = regmap_update_bits(vib->regmap, vib->enable_addr, + regs->enable_mask, on ? regs->enable_mask : 0); return rc; } @@ -101,26 +139,24 @@ static int pm8xxx_vib_set(struct pm8xxx_vib *vib, bool on) static void pm8xxx_work_handler(struct work_struct *work) { struct pm8xxx_vib *vib = container_of(work, struct pm8xxx_vib, work); - const struct pm8xxx_regs *regs = vib->regs; - int rc; unsigned int val; + int rc; - rc = regmap_read(vib->regmap, regs->drv_addr, &val); + rc = regmap_read(vib->regmap, vib->drv_addr, &val); if (rc < 0) return; /* - * pmic vibrator supports voltage ranges from 1.2 to 3.1V, so + * pmic vibrator supports voltage ranges from MIN_LEVEL to MAX_LEVEL, so * scale the level to fit into these ranges. */ if (vib->speed) { vib->active = true; - vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) + - VIB_MIN_LEVEL_mV; - vib->level /= 100; + vib->level = VIB_MIN_LEVEL_mV(vib); + vib->level += mult_frac(VIB_MAX_LEVELS(vib), vib->speed, MAX_FF_SPEED); } else { vib->active = false; - vib->level = VIB_MIN_LEVEL_mV / 100; + vib->level = VIB_MIN_LEVEL_mV(vib); } pm8xxx_vib_set(vib, vib->active); @@ -168,7 +204,7 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) struct pm8xxx_vib *vib; struct input_dev *input_dev; int error; - unsigned int val; + unsigned int val, reg_base = 0; const struct pm8xxx_regs *regs; vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL); @@ -186,15 +222,22 @@ static int pm8xxx_vib_probe(struct platform_device *pdev) INIT_WORK(&vib->work, pm8xxx_work_handler); vib->vib_input_dev = input_dev; + error = fwnode_property_read_u32(pdev->dev.fwnode, "reg", ®_base); + if (error < 0) + return dev_err_probe(&pdev->dev, error, "Failed to read reg address\n"); + regs = of_device_get_match_data(&pdev->dev); + vib->enable_addr = reg_base + regs->enable_offset; + vib->drv_addr = reg_base + regs->drv_offset; + vib->drv2_addr = reg_base + regs->drv2_offset; /* operate in manual mode */ - error = regmap_read(vib->regmap, regs->drv_addr, &val); + error = regmap_read(vib->regmap, vib->drv_addr, &val); if (error < 0) return error; val &= regs->drv_en_manual_mask; - error = regmap_write(vib->regmap, regs->drv_addr, val); + error = regmap_write(vib->regmap, vib->drv_addr, val); if (error < 0) return error; @@ -241,6 +284,7 @@ static const struct of_device_id pm8xxx_vib_id_table[] = { { .compatible = "qcom,pm8058-vib", .data = &pm8058_regs }, { .compatible = "qcom,pm8921-vib", .data = &pm8058_regs }, { .compatible = "qcom,pm8916-vib", .data = &pm8916_regs }, + { .compatible = "qcom,pmi632-vib", .data = &pmi632_regs }, { } }; MODULE_DEVICE_TABLE(of, pm8xxx_vib_id_table); diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index db2ba89adaef..ecb92ee5ebbc 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c @@ -194,22 +194,18 @@ static void powermate_sync_state(struct powermate_device *pm) static void powermate_config_complete(struct urb *urb) { struct powermate_device *pm = urb->context; - unsigned long flags; if (urb->status) printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); - spin_lock_irqsave(&pm->lock, flags); + guard(spinlock_irqsave)(&pm->lock); powermate_sync_state(pm); - spin_unlock_irqrestore(&pm->lock, flags); } /* Set the LED up as described and begin the sync with the hardware if required */ static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, int pulse_table, int pulse_asleep, int pulse_awake) { - unsigned long flags; - if (pulse_speed < 0) pulse_speed = 0; if (pulse_table < 0) @@ -222,8 +218,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne pulse_asleep = !!pulse_asleep; pulse_awake = !!pulse_awake; - - spin_lock_irqsave(&pm->lock, flags); + guard(spinlock_irqsave)(&pm->lock); /* mark state updates which are required */ if (static_brightness != pm->static_brightness) { @@ -245,8 +240,6 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne } powermate_sync_state(pm); - - spin_unlock_irqrestore(&pm->lock, flags); } /* Callback from the Input layer when an event arrives from userspace to configure the LED */ @@ -320,7 +313,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i 0, interface->desc.bInterfaceNumber, NULL, 0, USB_CTRL_SET_TIMEOUT); - pm = kzalloc(sizeof(struct powermate_device), GFP_KERNEL); + pm = kzalloc(sizeof(*pm), GFP_KERNEL); input_dev = input_allocate_device(); if (!pm || !input_dev) goto fail1; diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index 5b9aedf4362f..0e19e97d98ec 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -203,9 +203,9 @@ static int pwm_beeper_suspend(struct device *dev) * beeper->suspended, but to ensure that pwm_beeper_event * does not re-submit work once flag is set. */ - spin_lock_irq(&beeper->input->event_lock); - beeper->suspended = true; - spin_unlock_irq(&beeper->input->event_lock); + scoped_guard(spinlock_irq, &beeper->input->event_lock) { + beeper->suspended = true; + } pwm_beeper_stop(beeper); @@ -216,9 +216,9 @@ static int pwm_beeper_resume(struct device *dev) { struct pwm_beeper *beeper = dev_get_drvdata(dev); - spin_lock_irq(&beeper->input->event_lock); - beeper->suspended = false; - spin_unlock_irq(&beeper->input->event_lock); + scoped_guard(spinlock_irq, &beeper->input->event_lock) { + beeper->suspended = false; + } /* Let worker figure out if we should resume beeping */ schedule_work(&beeper->work); diff --git a/drivers/input/misc/qnap-mcu-input.c b/drivers/input/misc/qnap-mcu-input.c new file mode 100644 index 000000000000..76e62f0816c1 --- /dev/null +++ b/drivers/input/misc/qnap-mcu-input.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* + * Driver for input events on QNAP-MCUs + * + * Copyright (C) 2024 Heiko Stuebner <heiko@sntech.de> + */ + +#include <linux/input.h> +#include <linux/mfd/qnap-mcu.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <uapi/linux/input-event-codes.h> + +/* + * The power-key needs to be pressed for a while to create an event, + * so there is no use for overly frequent polling. + */ +#define POLL_INTERVAL 500 + +struct qnap_mcu_input_dev { + struct input_dev *input; + struct qnap_mcu *mcu; + struct device *dev; + + struct work_struct beep_work; + int beep_type; +}; + +static void qnap_mcu_input_poll(struct input_dev *input) +{ + struct qnap_mcu_input_dev *idev = input_get_drvdata(input); + static const u8 cmd[] = { '@', 'C', 'V' }; + u8 reply[4]; + int state, ret; + + /* poll the power button */ + ret = qnap_mcu_exec(idev->mcu, cmd, sizeof(cmd), reply, sizeof(reply)); + if (ret) + return; + + /* First bytes must mirror the sent command */ + if (memcmp(cmd, reply, sizeof(cmd))) { + dev_err(idev->dev, "malformed data received\n"); + return; + } + + state = reply[3] - 0x30; + input_event(input, EV_KEY, KEY_POWER, state); + input_sync(input); +} + +static void qnap_mcu_input_beeper_work(struct work_struct *work) +{ + struct qnap_mcu_input_dev *idev = + container_of(work, struct qnap_mcu_input_dev, beep_work); + const u8 cmd[] = { '@', 'C', (idev->beep_type == SND_TONE) ? '3' : '2' }; + + qnap_mcu_exec_with_ack(idev->mcu, cmd, sizeof(cmd)); +} + +static int qnap_mcu_input_event(struct input_dev *input, unsigned int type, + unsigned int code, int value) +{ + struct qnap_mcu_input_dev *idev = input_get_drvdata(input); + + if (type != EV_SND || (code != SND_BELL && code != SND_TONE)) + return -EOPNOTSUPP; + + if (value < 0) + return -EINVAL; + + /* beep runtime is determined by the MCU */ + if (value == 0) + return 0; + + /* Schedule work to actually turn the beeper on */ + idev->beep_type = code; + schedule_work(&idev->beep_work); + + return 0; +} + +static void qnap_mcu_input_close(struct input_dev *input) +{ + struct qnap_mcu_input_dev *idev = input_get_drvdata(input); + + cancel_work_sync(&idev->beep_work); +} + +static int qnap_mcu_input_probe(struct platform_device *pdev) +{ + struct qnap_mcu *mcu = dev_get_drvdata(pdev->dev.parent); + struct qnap_mcu_input_dev *idev; + struct device *dev = &pdev->dev; + struct input_dev *input; + int ret; + + idev = devm_kzalloc(dev, sizeof(*idev), GFP_KERNEL); + if (!idev) + return -ENOMEM; + + input = devm_input_allocate_device(dev); + if (!input) + return dev_err_probe(dev, -ENOMEM, "no memory for input device\n"); + + idev->input = input; + idev->dev = dev; + idev->mcu = mcu; + + input_set_drvdata(input, idev); + + input->name = "qnap-mcu"; + input->phys = "qnap-mcu-input/input0"; + input->id.bustype = BUS_HOST; + input->id.vendor = 0x0001; + input->id.product = 0x0001; + input->id.version = 0x0100; + input->event = qnap_mcu_input_event; + input->close = qnap_mcu_input_close; + + input_set_capability(input, EV_KEY, KEY_POWER); + input_set_capability(input, EV_SND, SND_BELL); + input_set_capability(input, EV_SND, SND_TONE); + + INIT_WORK(&idev->beep_work, qnap_mcu_input_beeper_work); + + ret = input_setup_polling(input, qnap_mcu_input_poll); + if (ret) + return dev_err_probe(dev, ret, "unable to set up polling\n"); + + input_set_poll_interval(input, POLL_INTERVAL); + + ret = input_register_device(input); + if (ret) + return dev_err_probe(dev, ret, "unable to register input device\n"); + + return 0; +} + +static struct platform_driver qnap_mcu_input_driver = { + .probe = qnap_mcu_input_probe, + .driver = { + .name = "qnap-mcu-input", + }, +}; +module_platform_driver(qnap_mcu_input_driver); + +MODULE_ALIAS("platform:qnap-mcu-input"); +MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); +MODULE_DESCRIPTION("QNAP MCU input driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/regulator-haptic.c b/drivers/input/misc/regulator-haptic.c index 02f73b7c0462..9711f5c7c78a 100644 --- a/drivers/input/misc/regulator-haptic.c +++ b/drivers/input/misc/regulator-haptic.c @@ -14,6 +14,7 @@ #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/string_choices.h> #define MAX_MAGNITUDE_SHIFT 16 @@ -44,7 +45,7 @@ static int regulator_haptic_toggle(struct regulator_haptic *haptic, bool on) if (error) { dev_err(haptic->dev, "failed to switch regulator %s: %d\n", - on ? "on" : "off", error); + str_on_off(on), error); return error; } @@ -83,12 +84,10 @@ static void regulator_haptic_work(struct work_struct *work) struct regulator_haptic *haptic = container_of(work, struct regulator_haptic, work); - mutex_lock(&haptic->mutex); + guard(mutex)(&haptic->mutex); if (!haptic->suspended) regulator_haptic_set_voltage(haptic, haptic->magnitude); - - mutex_unlock(&haptic->mutex); } static int regulator_haptic_play_effect(struct input_dev *input, void *data, @@ -205,19 +204,15 @@ static int regulator_haptic_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct regulator_haptic *haptic = platform_get_drvdata(pdev); - int error; - error = mutex_lock_interruptible(&haptic->mutex); - if (error) - return error; - - regulator_haptic_set_voltage(haptic, 0); + scoped_guard(mutex_intr, &haptic->mutex) { + regulator_haptic_set_voltage(haptic, 0); + haptic->suspended = true; - haptic->suspended = true; - - mutex_unlock(&haptic->mutex); + return 0; + } - return 0; + return -EINTR; } static int regulator_haptic_resume(struct device *dev) @@ -226,7 +221,7 @@ static int regulator_haptic_resume(struct device *dev) struct regulator_haptic *haptic = platform_get_drvdata(pdev); unsigned int magnitude; - mutex_lock(&haptic->mutex); + guard(mutex)(&haptic->mutex); haptic->suspended = false; @@ -234,8 +229,6 @@ static int regulator_haptic_resume(struct device *dev) if (magnitude) regulator_haptic_set_voltage(haptic, magnitude); - mutex_unlock(&haptic->mutex); - return 0; } diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index e94cab8133be..f706e1997417 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -106,7 +106,7 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) struct rotary_encoder *encoder = dev_id; unsigned int state; - mutex_lock(&encoder->access_mutex); + guard(mutex)(&encoder->access_mutex); state = rotary_encoder_get_state(encoder); @@ -129,8 +129,6 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) break; } - mutex_unlock(&encoder->access_mutex); - return IRQ_HANDLED; } @@ -139,7 +137,7 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) struct rotary_encoder *encoder = dev_id; unsigned int state; - mutex_lock(&encoder->access_mutex); + guard(mutex)(&encoder->access_mutex); state = rotary_encoder_get_state(encoder); @@ -152,8 +150,6 @@ static irqreturn_t rotary_encoder_half_period_irq(int irq, void *dev_id) } } - mutex_unlock(&encoder->access_mutex); - return IRQ_HANDLED; } @@ -162,22 +158,19 @@ static irqreturn_t rotary_encoder_quarter_period_irq(int irq, void *dev_id) struct rotary_encoder *encoder = dev_id; unsigned int state; - mutex_lock(&encoder->access_mutex); + guard(mutex)(&encoder->access_mutex); state = rotary_encoder_get_state(encoder); - if ((encoder->last_stable + 1) % 4 == state) + if ((encoder->last_stable + 1) % 4 == state) { encoder->dir = 1; - else if (encoder->last_stable == (state + 1) % 4) + rotary_encoder_report_event(encoder); + } else if (encoder->last_stable == (state + 1) % 4) { encoder->dir = -1; - else - goto out; - - rotary_encoder_report_event(encoder); + rotary_encoder_report_event(encoder); + } -out: encoder->last_stable = state; - mutex_unlock(&encoder->access_mutex); return IRQ_HANDLED; } diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 0657d785b3cc..39c2882b8e1a 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -128,4 +128,5 @@ static struct platform_driver sgi_buttons_driver = { }; module_platform_driver(sgi_buttons_driver); +MODULE_DESCRIPTION("SGI Indy/O2 volume button interface driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index f6d060377d18..b8cad415c62c 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -515,7 +515,7 @@ static const struct soc_device_data soc_device_INT33D3 = { }; /* - * Button info for Microsoft Surface 3 (non pro), this is indentical to + * Button info for Microsoft Surface 3 (non pro), this is identical to * the PNP0C40 info except that the home button is active-high. * * The Surface 3 Pro also has a MSHW0028 ACPI device, but that uses a custom @@ -612,7 +612,7 @@ MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match); static struct platform_driver soc_button_driver = { .probe = soc_button_probe, - .remove_new = soc_button_remove, + .remove = soc_button_remove, .driver = { .name = KBUILD_MODNAME, .acpi_match_table = ACPI_PTR(soc_button_acpi_match), @@ -620,4 +620,5 @@ static struct platform_driver soc_button_driver = { }; module_platform_driver(soc_button_driver); +MODULE_DESCRIPTION("Windows-compatible SoC Button Array driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 20020cbc0752..1cfadd73829f 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -69,15 +69,19 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent); struct bbc_beep_info *info = &state->u.bbc; unsigned int count = 0; - unsigned long flags; if (type != EV_SND) return -1; switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; + case SND_BELL: + if (value) + value = 1000; + break; + case SND_TONE: + break; + default: + return -1; } if (value > 20 && value < 32767) @@ -85,7 +89,7 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int count = bbc_count_to_reg(info, count); - spin_lock_irqsave(&state->lock, flags); + guard(spinlock_irqsave)(&state->lock); if (count) { sbus_writeb(0x01, info->regs + 0); @@ -97,8 +101,6 @@ static int bbc_spkr_event(struct input_dev *dev, unsigned int type, unsigned int sbus_writeb(0x00, info->regs + 0); } - spin_unlock_irqrestore(&state->lock, flags); - return 0; } @@ -107,21 +109,25 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned struct sparcspkr_state *state = dev_get_drvdata(dev->dev.parent); struct grover_beep_info *info = &state->u.grover; unsigned int count = 0; - unsigned long flags; if (type != EV_SND) return -1; switch (code) { - case SND_BELL: if (value) value = 1000; - case SND_TONE: break; - default: return -1; + case SND_BELL: + if (value) + value = 1000; + break; + case SND_TONE: + break; + default: + return -1; } if (value > 20 && value < 32767) count = 1193182 / value; - spin_lock_irqsave(&state->lock, flags); + guard(spinlock_irqsave)(&state->lock); if (count) { /* enable counter 2 */ @@ -136,8 +142,6 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned sbus_writeb(sbus_readb(info->enable_reg) & 0xFC, info->enable_reg); } - spin_unlock_irqrestore(&state->lock, flags); - return 0; } @@ -188,47 +192,38 @@ static int bbc_beep_probe(struct platform_device *op) { struct sparcspkr_state *state; struct bbc_beep_info *info; - struct device_node *dp; - int err = -ENOMEM; + int err; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = devm_kzalloc(&op->dev, sizeof(*state), GFP_KERNEL); if (!state) - goto out_err; + return -ENOMEM; state->name = "Sparc BBC Speaker"; state->event = bbc_spkr_event; spin_lock_init(&state->lock); - dp = of_find_node_by_path("/"); - err = -ENODEV; + struct device_node *dp __free(device_node) = of_find_node_by_path("/"); if (!dp) - goto out_free; + return -ENODEV; info = &state->u.bbc; info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0); - of_node_put(dp); if (!info->clock_freq) - goto out_free; + return -ENODEV; info->regs = of_ioremap(&op->resource[0], 0, 6, "bbc beep"); if (!info->regs) - goto out_free; + return -ENODEV; platform_set_drvdata(op, state); err = sparcspkr_probe(&op->dev); - if (err) - goto out_clear_drvdata; + if (err) { + of_iounmap(&op->resource[0], info->regs, 6); + return err; + } return 0; - -out_clear_drvdata: - of_iounmap(&op->resource[0], info->regs, 6); - -out_free: - kfree(state); -out_err: - return err; } static void bbc_remove(struct platform_device *op) @@ -243,8 +238,6 @@ static void bbc_remove(struct platform_device *op) input_unregister_device(input_dev); of_iounmap(&op->resource[0], info->regs, 6); - - kfree(state); } static const struct of_device_id bbc_beep_match[] = { @@ -262,7 +255,7 @@ static struct platform_driver bbc_beep_driver = { .of_match_table = bbc_beep_match, }, .probe = bbc_beep_probe, - .remove_new = bbc_remove, + .remove = bbc_remove, .shutdown = sparcspkr_shutdown, }; @@ -272,9 +265,9 @@ static int grover_beep_probe(struct platform_device *op) struct grover_beep_info *info; int err = -ENOMEM; - state = kzalloc(sizeof(*state), GFP_KERNEL); + state = devm_kzalloc(&op->dev, sizeof(*state), GFP_KERNEL); if (!state) - goto out_err; + return err; state->name = "Sparc Grover Speaker"; state->event = grover_spkr_event; @@ -283,7 +276,7 @@ static int grover_beep_probe(struct platform_device *op) info = &state->u.grover; info->freq_regs = of_ioremap(&op->resource[2], 0, 2, "grover beep freq"); if (!info->freq_regs) - goto out_free; + return err; info->enable_reg = of_ioremap(&op->resource[3], 0, 1, "grover beep enable"); if (!info->enable_reg) @@ -302,9 +295,7 @@ out_clear_drvdata: out_unmap_freq_regs: of_iounmap(&op->resource[2], info->freq_regs, 2); -out_free: - kfree(state); -out_err: + return err; } @@ -321,8 +312,6 @@ static void grover_remove(struct platform_device *op) of_iounmap(&op->resource[3], info->enable_reg, 1); of_iounmap(&op->resource[2], info->freq_regs, 2); - - kfree(state); } static const struct of_device_id grover_beep_match[] = { @@ -340,7 +329,7 @@ static struct platform_driver grover_beep_driver = { .of_match_table = grover_beep_match, }, .probe = grover_beep_probe, - .remove_new = grover_remove, + .remove = grover_remove, .shutdown = sparcspkr_shutdown, }; diff --git a/drivers/input/misc/tps65219-pwrbutton.c b/drivers/input/misc/tps65219-pwrbutton.c index eeb9f2334ab4..7a58bae4f1a0 100644 --- a/drivers/input/misc/tps65219-pwrbutton.c +++ b/drivers/input/misc/tps65219-pwrbutton.c @@ -137,7 +137,7 @@ MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table); static struct platform_driver tps65219_pb_driver = { .probe = tps65219_pb_probe, - .remove_new = tps65219_pb_remove, + .remove = tps65219_pb_remove, .driver = { .name = "tps65219_pwrbutton", }, diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index e3ee0638ffba..f85cc289c053 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -1,5 +1,5 @@ -/** - * twl4030-pwrbutton.c - TWL4030 Power Button Input Driver +/* + * TWL4030 Power Button Input Driver * * Copyright (C) 2008-2009 Nokia Corporation * diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 101548b35ee3..5fa7d4a7da36 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -165,15 +165,10 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, static bool twl4030_vibra_check_coexist(struct device_node *parent) { - struct device_node *node; + struct device_node *node __free(device_node) = + of_get_child_by_name(parent, "codec"); - node = of_get_child_by_name(parent, "codec"); - if (node) { - of_node_put(node); - return true; - } - - return false; + return node != NULL; } static int twl4030_vibra_probe(struct platform_device *pdev) diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index 78f0b63e5c20..afed9af65bf9 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -229,14 +229,13 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, static int twl6040_vibra_probe(struct platform_device *pdev) { struct device *twl6040_core_dev = pdev->dev.parent; - struct device_node *twl6040_core_node; struct vibra_info *info; int vddvibl_uV = 0; int vddvibr_uV = 0; int error; - twl6040_core_node = of_get_child_by_name(twl6040_core_dev->of_node, - "vibra"); + struct device_node *twl6040_core_node __free(device_node) = + of_get_child_by_name(twl6040_core_dev->of_node, "vibra"); if (!twl6040_core_node) { dev_err(&pdev->dev, "parent of node is missing?\n"); return -EINVAL; @@ -244,7 +243,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev) info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { - of_node_put(twl6040_core_node); dev_err(&pdev->dev, "couldn't allocate memory\n"); return -ENOMEM; } @@ -264,8 +262,6 @@ static int twl6040_vibra_probe(struct platform_device *pdev) of_property_read_u32(twl6040_core_node, "ti,vddvibl-uV", &vddvibl_uV); of_property_read_u32(twl6040_core_node, "ti,vddvibr-uV", &vddvibr_uV); - of_node_put(twl6040_core_node); - if ((!info->vibldrv_res && !info->viblmotor_res) || (!info->vibrdrv_res && !info->vibrmotor_res)) { dev_err(info->dev, "invalid vibra driver/motor resistance\n"); diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d98212d55108..2c51ea9d01d7 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -379,7 +379,7 @@ static int uinput_open(struct inode *inode, struct file *file) { struct uinput_device *newdev; - newdev = kzalloc(sizeof(struct uinput_device), GFP_KERNEL); + newdev = kzalloc(sizeof(*newdev), GFP_KERNEL); if (!newdev) return -ENOMEM; @@ -417,6 +417,20 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code, return -EINVAL; } + /* + * Limit number of contacts to a reasonable value (100). This + * ensures that we need less than 2 pages for struct input_mt + * (we are not using in-kernel slot assignment so not going to + * allocate memory for the "red" table), and we should have no + * trouble getting this much memory. + */ + if (code == ABS_MT_SLOT && max > 99) { + printk(KERN_DEBUG + "%s: unreasonably large number of slots requested: %d\n", + UINPUT_NAME, max); + return -EINVAL; + } + return 0; } @@ -1118,7 +1132,6 @@ static const struct file_operations uinput_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = uinput_compat_ioctl, #endif - .llseek = no_llseek, }; static struct miscdevice uinput_misc = { diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index 5c4956678cd0..1b2bd2139aaa 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -271,7 +271,7 @@ static struct key_entry keymap_fs_amilo_pro_v8210[] __initdata = { { KE_BLUETOOTH, 0x30 }, /* Fn+F10 */ { KE_KEY, 0x31, {KEY_MAIL} }, /* mail button */ { KE_KEY, 0x36, {KEY_WWW} }, /* www button */ - { KE_WIFI, 0x78 }, /* satelite dish button */ + { KE_WIFI, 0x78 }, /* satellite dish button */ { KE_END, FE_WIFI_LED } }; @@ -990,8 +990,8 @@ static int __init copy_keymap(void) for (key = keymap; key->type != KE_END; key++) length++; - new_keymap = kmemdup(keymap, length * sizeof(struct key_entry), - GFP_KERNEL); + new_keymap = kmemdup_array(keymap, length, sizeof(struct key_entry), + GFP_KERNEL); if (!new_keymap) return -ENOMEM; @@ -1075,7 +1075,7 @@ static void wistron_led_init(struct device *parent) } if (leds_present & FE_MAIL_LED) { - /* bios_get_default_setting(MAIL) always retuns 0, so just turn the led off */ + /* bios_get_default_setting(MAIL) always returns 0, so just turn the led off */ wistron_mail_led.brightness = LED_OFF; if (led_classdev_register(parent, &wistron_mail_led)) leds_present &= ~FE_MAIL_LED; @@ -1334,7 +1334,7 @@ static struct platform_driver wistron_driver = { .pm = pm_sleep_ptr(&wistron_pm_ops), }, .probe = wistron_probe, - .remove_new = wistron_remove, + .remove = wistron_remove, }; static int __init wb_module_init(void) diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index e4a06c73b72d..18eb319bc6f7 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -134,7 +134,7 @@ static void wm831x_on_remove(struct platform_device *pdev) static struct platform_driver wm831x_on_driver = { .probe = wm831x_on_probe, - .remove_new = wm831x_on_remove, + .remove = wm831x_on_remove, .driver = { .name = "wm831x-on", }, diff --git a/drivers/input/misc/yealink.c b/drivers/input/misc/yealink.c index 69420781db30..08dc53ae1b3c 100644 --- a/drivers/input/misc/yealink.c +++ b/drivers/input/misc/yealink.c @@ -36,7 +36,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/rwsem.h> +#include <linux/mutex.h> #include <linux/usb/input.h> #include <linux/map_to_7segment.h> @@ -103,6 +103,8 @@ struct yealink_dev { u8 lcdMap[ARRAY_SIZE(lcdMap)]; /* state of LCD, LED ... */ int key_code; /* last reported key */ + struct mutex sysfs_mutex; + unsigned int shutdown:1; int stat_ix; @@ -375,7 +377,7 @@ send_update: if (len > sizeof(yld->ctl_data->data)) len = sizeof(yld->ctl_data->data); - /* Combine up to <len> consecutive LCD bytes in a singe request + /* Combine up to <len> consecutive LCD bytes in a single request */ yld->ctl_data->cmd = CMD_LCD; yld->ctl_data->offset = cpu_to_be16(ix); @@ -548,8 +550,6 @@ static void input_close(struct input_dev *dev) * sysfs interface ******************************************************************************/ -static DECLARE_RWSEM(sysfs_rwsema); - /* Interface to the 7-segments translation table aka. char set. */ static ssize_t show_map(struct device *dev, struct device_attribute *attr, @@ -580,15 +580,10 @@ static ssize_t store_map(struct device *dev, struct device_attribute *attr, */ static ssize_t show_line(struct device *dev, char *buf, int a, int b) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = a; i < b; i++) *buf++ = lcdMap[i].type; @@ -598,7 +593,6 @@ static ssize_t show_line(struct device *dev, char *buf, int a, int b) *buf++ = '\n'; *buf = 0; - up_read(&sysfs_rwsema); return 3 + ((b - a) << 1); } @@ -620,7 +614,7 @@ static ssize_t show_line3(struct device *dev, struct device_attribute *attr, return show_line(dev, buf, LCD_LINE3_OFFSET, LCD_LINE4_OFFSET); } -/* Writing to /sys/../lineX will set the coresponding LCD line. +/* Writing to /sys/../lineX will set the corresponding LCD line. * - Excess characters are ignored. * - If less characters are written than allowed, the remaining digits are * unchanged. @@ -630,22 +624,16 @@ static ssize_t show_line3(struct device *dev, struct device_attribute *attr, static ssize_t store_line(struct device *dev, const char *buf, size_t count, int el, size_t len) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); if (len > count) len = count; for (i = 0; i < len; i++) setChar(yld, el++, buf[i]); - up_write(&sysfs_rwsema); return count; } @@ -675,15 +663,10 @@ static ssize_t store_line3(struct device *dev, struct device_attribute *attr, static ssize_t get_icons(struct device *dev, struct device_attribute *attr, char *buf) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i, ret = 1; - down_read(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_read(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { if (lcdMap[i].type != '.') @@ -692,7 +675,7 @@ static ssize_t get_icons(struct device *dev, struct device_attribute *attr, yld->lcdMap[i] == ' ' ? " " : "on", lcdMap[i].u.p.name); } - up_read(&sysfs_rwsema); + return ret; } @@ -700,15 +683,10 @@ static ssize_t get_icons(struct device *dev, struct device_attribute *attr, static ssize_t set_icon(struct device *dev, const char *buf, size_t count, int chr) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); int i; - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); for (i = 0; i < ARRAY_SIZE(lcdMap); i++) { if (lcdMap[i].type != '.') @@ -719,7 +697,6 @@ static ssize_t set_icon(struct device *dev, const char *buf, size_t count, } } - up_write(&sysfs_rwsema); return count; } @@ -739,22 +716,16 @@ static ssize_t hide_icon(struct device *dev, struct device_attribute *attr, */ /* Stores raw ringtone data in the phone */ -static ssize_t store_ringtone(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t store_ringtone(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct yealink_dev *yld; + struct yealink_dev *yld = dev_get_drvdata(dev); - down_write(&sysfs_rwsema); - yld = dev_get_drvdata(dev); - if (yld == NULL) { - up_write(&sysfs_rwsema); - return -ENODEV; - } + guard(mutex)(&yld->sysfs_mutex); /* TODO locking with async usb control interface??? */ yealink_set_ringtone(yld, (char *)buf, count); - up_write(&sysfs_rwsema); + return count; } @@ -771,7 +742,7 @@ static DEVICE_ATTR(show_icon , _M220, NULL , show_icon ); static DEVICE_ATTR(hide_icon , _M220, NULL , hide_icon ); static DEVICE_ATTR(ringtone , _M220, NULL , store_ringtone); -static struct attribute *yld_attributes[] = { +static struct attribute *yld_attrs[] = { &dev_attr_line1.attr, &dev_attr_line2.attr, &dev_attr_line3.attr, @@ -782,10 +753,7 @@ static struct attribute *yld_attributes[] = { &dev_attr_ringtone.attr, NULL }; - -static const struct attribute_group yld_attr_group = { - .attrs = yld_attributes -}; +ATTRIBUTE_GROUPS(yld); /******************************************************************************* * Linux interface and usb initialisation @@ -838,15 +806,10 @@ static int usb_cleanup(struct yealink_dev *yld, int err) static void usb_disconnect(struct usb_interface *intf) { - struct yealink_dev *yld; - - down_write(&sysfs_rwsema); - yld = usb_get_intfdata(intf); - sysfs_remove_group(&intf->dev.kobj, &yld_attr_group); - usb_set_intfdata(intf, NULL); - up_write(&sysfs_rwsema); + struct yealink_dev *yld = usb_get_intfdata(intf); usb_cleanup(yld, 0); + usb_set_intfdata(intf, NULL); } static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) @@ -868,12 +831,13 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; - yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); + yld = kzalloc(sizeof(*yld), GFP_KERNEL); if (!yld) return -ENOMEM; yld->udev = udev; yld->intf = intf; + mutex_init(&yld->sysfs_mutex); yld->idev = input_dev = input_allocate_device(); if (!input_dev) @@ -975,8 +939,6 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) store_line3(&intf->dev, NULL, DRIVER_VERSION, sizeof(DRIVER_VERSION)); - /* Register sysfs hooks (don't care about failure) */ - ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group); return 0; } @@ -985,6 +947,7 @@ static struct usb_driver yealink_driver = { .probe = usb_probe, .disconnect = usb_disconnect, .id_table = usb_table, + .dev_groups = yld_groups, }; module_usb_driver(yealink_driver); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index e2c11d9f3868..0bd7b09b0aa3 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -1396,24 +1396,16 @@ static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) static DEFINE_MUTEX(alps_mutex); -static void alps_register_bare_ps2_mouse(struct work_struct *work) +static int alps_do_register_bare_ps2_mouse(struct alps_data *priv) { - struct alps_data *priv = - container_of(work, struct alps_data, dev3_register_work.work); struct psmouse *psmouse = priv->psmouse; struct input_dev *dev3; - int error = 0; - - mutex_lock(&alps_mutex); - - if (priv->dev3) - goto out; + int error; dev3 = input_allocate_device(); if (!dev3) { psmouse_err(psmouse, "failed to allocate secondary device\n"); - error = -ENOMEM; - goto out; + return -ENOMEM; } snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s", @@ -1446,21 +1438,35 @@ static void alps_register_bare_ps2_mouse(struct work_struct *work) psmouse_err(psmouse, "failed to register secondary device: %d\n", error); - input_free_device(dev3); - goto out; + goto err_free_input; } priv->dev3 = dev3; + return 0; -out: - /* - * Save the error code so that we can detect that we - * already tried to create the device. - */ - if (error) - priv->dev3 = ERR_PTR(error); +err_free_input: + input_free_device(dev3); + return error; +} - mutex_unlock(&alps_mutex); +static void alps_register_bare_ps2_mouse(struct work_struct *work) +{ + struct alps_data *priv = container_of(work, struct alps_data, + dev3_register_work.work); + int error; + + guard(mutex)(&alps_mutex); + + if (!priv->dev3) { + error = alps_do_register_bare_ps2_mouse(priv); + if (error) { + /* + * Save the error code so that we can detect that we + * already tried to create the device. + */ + priv->dev3 = ERR_PTR(error); + } + } } static void alps_report_bare_ps2_packet(struct psmouse *psmouse, @@ -1513,7 +1519,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) return PSMOUSE_GOOD_DATA; } - del_timer(&priv->timer); + timer_delete(&priv->timer); if (psmouse->packet[6] & 0x80) { @@ -1579,7 +1585,7 @@ static void alps_flush_packet(struct timer_list *t) struct alps_data *priv = from_timer(priv, t, timer); struct psmouse *psmouse = priv->psmouse; - serio_pause_rx(psmouse->ps2dev.serio); + guard(serio_pause_rx)(psmouse->ps2dev.serio); if (psmouse->pktcnt == psmouse->pktsize) { @@ -1599,8 +1605,6 @@ static void alps_flush_packet(struct timer_list *t) } psmouse->pktcnt = 0; } - - serio_continue_rx(psmouse->ps2dev.serio); } static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) @@ -3201,7 +3205,7 @@ int alps_detect(struct psmouse *psmouse, bool set_properties) */ psmouse_reset(psmouse); - priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index cda0c3ff5a28..d203c2a6c438 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c @@ -132,8 +132,14 @@ static void __exit amimouse_remove(struct platform_device *pdev) input_unregister_device(dev); } -static struct platform_driver amimouse_driver = { - .remove_new = __exit_p(amimouse_remove), +/* + * amimouse_remove() lives in .exit.text. For drivers registered via + * module_platform_driver_probe() this is ok because they cannot get unbound at + * runtime. So mark the driver struct with __refdata to prevent modpost + * triggering a section mismatch warning. + */ +static struct platform_driver amimouse_driver __refdata = { + .remove = __exit_p(amimouse_remove), .driver = { .name = "amiga-mouse", }, diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 627048bc6a12..e669f86f1882 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -855,7 +855,7 @@ static int atp_probe(struct usb_interface *iface, } /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct atp), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); input_dev = input_allocate_device(); if (!dev || !input_dev) { dev_err(&iface->dev, "Out of memory\n"); diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index ca150618d32f..dfdfb59cc8b5 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -834,13 +834,11 @@ static int bcm5974_open(struct input_dev *input) if (error) return error; - mutex_lock(&dev->pm_mutex); - - error = bcm5974_start_traffic(dev); - if (!error) - dev->opened = 1; - - mutex_unlock(&dev->pm_mutex); + scoped_guard(mutex, &dev->pm_mutex) { + error = bcm5974_start_traffic(dev); + if (!error) + dev->opened = 1; + } if (error) usb_autopm_put_interface(dev->intf); @@ -852,12 +850,10 @@ static void bcm5974_close(struct input_dev *input) { struct bcm5974 *dev = input_get_drvdata(input); - mutex_lock(&dev->pm_mutex); - - bcm5974_pause_traffic(dev); - dev->opened = 0; - - mutex_unlock(&dev->pm_mutex); + scoped_guard(mutex, &dev->pm_mutex) { + bcm5974_pause_traffic(dev); + dev->opened = 0; + } usb_autopm_put_interface(dev->intf); } @@ -866,29 +862,24 @@ static int bcm5974_suspend(struct usb_interface *iface, pm_message_t message) { struct bcm5974 *dev = usb_get_intfdata(iface); - mutex_lock(&dev->pm_mutex); + guard(mutex)(&dev->pm_mutex); if (dev->opened) bcm5974_pause_traffic(dev); - mutex_unlock(&dev->pm_mutex); - return 0; } static int bcm5974_resume(struct usb_interface *iface) { struct bcm5974 *dev = usb_get_intfdata(iface); - int error = 0; - mutex_lock(&dev->pm_mutex); + guard(mutex)(&dev->pm_mutex); if (dev->opened) - error = bcm5974_start_traffic(dev); + return bcm5974_start_traffic(dev); - mutex_unlock(&dev->pm_mutex); - - return error; + return 0; } static int bcm5974_probe(struct usb_interface *iface, @@ -904,7 +895,7 @@ static int bcm5974_probe(struct usb_interface *iface, cfg = bcm5974_get_config(udev); /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(struct bcm5974), GFP_KERNEL); + dev = kzalloc(sizeof(*dev), GFP_KERNEL); input_dev = input_allocate_device(); if (!dev || !input_dev) { dev_err(&iface->dev, "out of memory\n"); diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c index 221a553f45cd..4ee084e00a7c 100644 --- a/drivers/input/mouse/byd.c +++ b/drivers/input/mouse/byd.c @@ -254,13 +254,12 @@ static void byd_clear_touch(struct timer_list *t) struct byd_data *priv = from_timer(priv, t, timer); struct psmouse *psmouse = priv->psmouse; - serio_pause_rx(psmouse->ps2dev.serio); + guard(serio_pause_rx)(psmouse->ps2dev.serio); + priv->touch = false; byd_report_input(psmouse); - serio_continue_rx(psmouse->ps2dev.serio); - /* * Move cursor back to center of pad when we lose touch - this * specifically improves user experience when moving cursor with one @@ -426,7 +425,7 @@ static void byd_disconnect(struct psmouse *psmouse) struct byd_data *priv = psmouse->private; if (priv) { - del_timer(&priv->timer); + timer_delete(&priv->timer); kfree(psmouse->private); psmouse->private = NULL; } diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c index 5979deabe23d..00c87c0532a6 100644 --- a/drivers/input/mouse/cyapa.c +++ b/drivers/input/mouse/cyapa.c @@ -1080,8 +1080,8 @@ static ssize_t cyapa_update_fw_store(struct device *dev, char fw_name[NAME_MAX]; int ret, error; - if (count >= NAME_MAX) { - dev_err(dev, "File name too long\n"); + if (!count || count >= NAME_MAX) { + dev_err(dev, "Bad file name size\n"); return -EINVAL; } @@ -1347,10 +1347,16 @@ static int cyapa_suspend(struct device *dev) u8 power_mode; int error; - error = mutex_lock_interruptible(&cyapa->state_sync_lock); + error = mutex_lock_interruptible(&cyapa->input->mutex); if (error) return error; + error = mutex_lock_interruptible(&cyapa->state_sync_lock); + if (error) { + mutex_unlock(&cyapa->input->mutex); + return error; + } + /* * Runtime PM is enable only when device is in operational mode and * users in use, so need check it before disable it to @@ -1385,6 +1391,8 @@ static int cyapa_suspend(struct device *dev) cyapa->irq_wake = (enable_irq_wake(client->irq) == 0); mutex_unlock(&cyapa->state_sync_lock); + mutex_unlock(&cyapa->input->mutex); + return 0; } @@ -1394,6 +1402,7 @@ static int cyapa_resume(struct device *dev) struct cyapa *cyapa = i2c_get_clientdata(client); int error; + mutex_lock(&cyapa->input->mutex); mutex_lock(&cyapa->state_sync_lock); if (device_may_wakeup(dev) && cyapa->irq_wake) { @@ -1412,6 +1421,7 @@ static int cyapa_resume(struct device *dev) enable_irq(client->irq); mutex_unlock(&cyapa->state_sync_lock); + mutex_unlock(&cyapa->input->mutex); return 0; } @@ -1449,8 +1459,8 @@ static const struct dev_pm_ops cyapa_pm_ops = { }; static const struct i2c_device_id cyapa_id_table[] = { - { "cyapa", 0 }, - { }, + { "cyapa" }, + { } }; MODULE_DEVICE_TABLE(i2c, cyapa_id_table); diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c index 60c83bc71d84..fc3fb954523b 100644 --- a/drivers/input/mouse/cyapa_gen3.c +++ b/drivers/input/mouse/cyapa_gen3.c @@ -20,7 +20,7 @@ #include <linux/input/mt.h> #include <linux/module.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "cyapa.h" diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c index 2e6bcb07257e..3b4439f10635 100644 --- a/drivers/input/mouse/cyapa_gen5.c +++ b/drivers/input/mouse/cyapa_gen5.c @@ -17,7 +17,7 @@ #include <linux/mutex.h> #include <linux/completion.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/crc-itu-t.h> #include <linux/pm_runtime.h> #include "cyapa.h" diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index 4ffe08fee10c..570c06dcef78 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -17,7 +17,7 @@ #include <linux/mutex.h> #include <linux/completion.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/crc-itu-t.h> #include "cyapa.h" diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index d272f1ec27ba..9446657a5f35 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c @@ -32,33 +32,30 @@ static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) cytp->pkt_size = n; } -static const unsigned char cytp_rate[] = {10, 20, 40, 60, 100, 200}; -static const unsigned char cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; +static const u8 cytp_rate[] = {10, 20, 40, 60, 100, 200}; +static const u8 cytp_resolution[] = {0x00, 0x01, 0x02, 0x03}; -static int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) +static int cypress_ps2_sendbyte(struct psmouse *psmouse, u8 cmd) { struct ps2dev *ps2dev = &psmouse->ps2dev; + int error; - if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { + error = ps2_sendbyte(ps2dev, cmd, CYTP_CMD_TIMEOUT); + if (error) { psmouse_dbg(psmouse, - "sending command 0x%02x failed, resp 0x%02x\n", - value & 0xff, ps2dev->nak); - if (ps2dev->nak == CYTP_PS2_RETRY) - return CYTP_PS2_RETRY; - else - return CYTP_PS2_ERROR; + "sending command 0x%02x failed, resp 0x%02x, error %d\n", + cmd, ps2dev->nak, error); + return error; } #ifdef CYTP_DEBUG_VERBOSE - psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", - value & 0xff); + psmouse_dbg(psmouse, "sending command 0x%02x succeeded\n", cmd); #endif return 0; } -static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, - unsigned char data) +static int cypress_ps2_ext_cmd(struct psmouse *psmouse, u8 prefix, u8 nibble) { struct ps2dev *ps2dev = &psmouse->ps2dev; int tries = CYTP_PS2_CMD_TRIES; @@ -72,71 +69,29 @@ static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, * If sending the command fails, send recovery command * to make the device return to the ready state. */ - rc = cypress_ps2_sendbyte(psmouse, cmd & 0xff); - if (rc == CYTP_PS2_RETRY) { + rc = cypress_ps2_sendbyte(psmouse, prefix); + if (rc == -EAGAIN) { rc = cypress_ps2_sendbyte(psmouse, 0x00); - if (rc == CYTP_PS2_RETRY) + if (rc == -EAGAIN) rc = cypress_ps2_sendbyte(psmouse, 0x0a); } - if (rc == CYTP_PS2_ERROR) - continue; - - rc = cypress_ps2_sendbyte(psmouse, data); - if (rc == CYTP_PS2_RETRY) - rc = cypress_ps2_sendbyte(psmouse, data); - if (rc == CYTP_PS2_ERROR) - continue; - else - break; - } while (--tries > 0); - - ps2_end_command(ps2dev); - - return rc; -} - -static int cypress_ps2_read_cmd_status(struct psmouse *psmouse, - unsigned char cmd, - unsigned char *param) -{ - int rc; - struct ps2dev *ps2dev = &psmouse->ps2dev; - enum psmouse_state old_state; - int pktsize; - - ps2_begin_command(ps2dev); - old_state = psmouse->state; - psmouse->state = PSMOUSE_CMD_MODE; - psmouse->pktcnt = 0; + if (!rc) { + rc = cypress_ps2_sendbyte(psmouse, nibble); + if (rc == -EAGAIN) + rc = cypress_ps2_sendbyte(psmouse, nibble); - pktsize = (cmd == CYTP_CMD_READ_TP_METRICS) ? 8 : 3; - memset(param, 0, pktsize); - - rc = cypress_ps2_sendbyte(psmouse, 0xe9); - if (rc < 0) - goto out; - - wait_event_timeout(ps2dev->wait, - (psmouse->pktcnt >= pktsize), - msecs_to_jiffies(CYTP_CMD_TIMEOUT)); - - memcpy(param, psmouse->packet, pktsize); - - psmouse_dbg(psmouse, "Command 0x%02x response data (0x): %*ph\n", - cmd, pktsize, param); - -out: - psmouse->state = old_state; - psmouse->pktcnt = 0; + if (!rc) + break; + } + } while (--tries > 0); ps2_end_command(ps2dev); return rc; } -static bool cypress_verify_cmd_state(struct psmouse *psmouse, - unsigned char cmd, unsigned char *param) +static bool cypress_verify_cmd_state(struct psmouse *psmouse, u8 cmd, u8* param) { bool rate_match = false; bool resolution_match = false; @@ -166,33 +121,36 @@ static bool cypress_verify_cmd_state(struct psmouse *psmouse, return false; } -static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, - unsigned char *param) +static int cypress_send_ext_cmd(struct psmouse *psmouse, u8 cmd, u8 *param) { + u8 cmd_prefix = PSMOUSE_CMD_SETRES & 0xff; + unsigned int resp_size = cmd == CYTP_CMD_READ_TP_METRICS ? 8 : 3; + unsigned int ps2_cmd = (PSMOUSE_CMD_GETINFO & 0xff) | (resp_size << 8); int tries = CYTP_PS2_CMD_TRIES; - int rc; + int error; psmouse_dbg(psmouse, "send extension cmd 0x%02x, [%d %d %d %d]\n", cmd, DECODE_CMD_AA(cmd), DECODE_CMD_BB(cmd), DECODE_CMD_CC(cmd), DECODE_CMD_DD(cmd)); do { - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_DD(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_CC(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_BB(cmd)); - cypress_ps2_ext_cmd(psmouse, - PSMOUSE_CMD_SETRES, DECODE_CMD_AA(cmd)); - - rc = cypress_ps2_read_cmd_status(psmouse, cmd, param); - if (rc) - continue; - - if (cypress_verify_cmd_state(psmouse, cmd, param)) - return 0; - + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_DD(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_CC(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_BB(cmd)); + cypress_ps2_ext_cmd(psmouse, cmd_prefix, DECODE_CMD_AA(cmd)); + + error = ps2_command(&psmouse->ps2dev, param, ps2_cmd); + if (error) { + psmouse_dbg(psmouse, "Command 0x%02x failed: %d\n", + cmd, error); + } else { + psmouse_dbg(psmouse, + "Command 0x%02x response data (0x): %*ph\n", + cmd, resp_size, param); + + if (cypress_verify_cmd_state(psmouse, cmd, param)) + return 0; + } } while (--tries > 0); return -EIO; @@ -200,7 +158,7 @@ static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, int cypress_detect(struct psmouse *psmouse, bool set_properties) { - unsigned char param[3]; + u8 param[3]; if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) return -ENODEV; @@ -220,7 +178,7 @@ int cypress_detect(struct psmouse *psmouse, bool set_properties) static int cypress_read_fw_version(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[3]; + u8 param[3]; if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) return -ENODEV; @@ -249,7 +207,7 @@ static int cypress_read_fw_version(struct psmouse *psmouse) static int cypress_read_tp_metrics(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[8]; + u8 param[8]; /* set default values for tp metrics. */ cytp->tp_width = CYTP_DEFAULT_WIDTH; @@ -321,15 +279,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) static int cypress_query_hardware(struct psmouse *psmouse) { - int ret; + int error; - ret = cypress_read_fw_version(psmouse); - if (ret) - return ret; + error = cypress_read_fw_version(psmouse); + if (error) + return error; - ret = cypress_read_tp_metrics(psmouse); - if (ret) - return ret; + error = cypress_read_tp_metrics(psmouse); + if (error) + return error; return 0; } @@ -337,10 +295,13 @@ static int cypress_query_hardware(struct psmouse *psmouse) static int cypress_set_absolute_mode(struct psmouse *psmouse) { struct cytp_data *cytp = psmouse->private; - unsigned char param[3]; + u8 param[3]; + int error; - if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) - return -1; + error = cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, + param); + if (error) + return error; cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) | CYTP_BIT_ABS_PRESSURE; @@ -365,7 +326,7 @@ static void cypress_reset(struct psmouse *psmouse) static int cypress_set_input_params(struct input_dev *input, struct cytp_data *cytp) { - int ret; + int error; if (!cytp->tp_res_x || !cytp->tp_res_y) return -EINVAL; @@ -382,10 +343,10 @@ static int cypress_set_input_params(struct input_dev *input, input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cytp->tp_max_abs_y, 0, 0); input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); - ret = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, - INPUT_MT_DROP_UNUSED|INPUT_MT_TRACK); - if (ret < 0) - return ret; + error = input_mt_init_slots(input, CYTP_MAX_MT_SLOTS, + INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); + if (error) + return error; __set_bit(INPUT_PROP_SEMI_MT, input->propbit); @@ -414,9 +375,9 @@ static int cypress_set_input_params(struct input_dev *input, return 0; } -static int cypress_get_finger_count(unsigned char header_byte) +static int cypress_get_finger_count(u8 header_byte) { - unsigned char bits6_7; + u8 bits6_7; int finger_count; bits6_7 = header_byte >> 6; @@ -441,10 +402,11 @@ static int cypress_get_finger_count(unsigned char header_byte) static int cypress_parse_packet(struct psmouse *psmouse, - struct cytp_data *cytp, struct cytp_report_data *report_data) + struct cytp_data *cytp, + struct cytp_report_data *report_data) { - unsigned char *packet = psmouse->packet; - unsigned char header_byte = packet[0]; + u8 *packet = psmouse->packet; + u8 header_byte = packet[0]; memset(report_data, 0, sizeof(struct cytp_report_data)); @@ -559,7 +521,7 @@ static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) { int contact_cnt; int index = psmouse->pktcnt - 1; - unsigned char *packet = psmouse->packet; + u8 *packet = psmouse->packet; struct cytp_data *cytp = psmouse->private; if (index < 0 || index > cytp->pkt_size) @@ -612,6 +574,7 @@ static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) { struct cytp_data *cytp = psmouse->private; + u8 rate_param; if (rate >= 80) { psmouse->rate = 80; @@ -621,8 +584,8 @@ static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) cytp->mode &= ~CYTP_BIT_HIGH_RATE; } - ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, - PSMOUSE_CMD_SETRATE); + rate_param = (u8)rate; + ps2_command(&psmouse->ps2dev, &rate_param, PSMOUSE_CMD_SETRATE); } static void cypress_disconnect(struct psmouse *psmouse) @@ -635,21 +598,22 @@ static void cypress_disconnect(struct psmouse *psmouse) static int cypress_reconnect(struct psmouse *psmouse) { int tries = CYTP_PS2_CMD_TRIES; - int rc; + int error; do { cypress_reset(psmouse); - rc = cypress_detect(psmouse, false); - } while (rc && (--tries > 0)); + error = cypress_detect(psmouse, false); + } while (error && (--tries > 0)); - if (rc) { + if (error) { psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); - return -1; + return error; } - if (cypress_set_absolute_mode(psmouse)) { + error = cypress_set_absolute_mode(psmouse); + if (error) { psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); - return -1; + return error; } return 0; @@ -658,8 +622,9 @@ static int cypress_reconnect(struct psmouse *psmouse) int cypress_init(struct psmouse *psmouse) { struct cytp_data *cytp; + int error; - cytp = kzalloc(sizeof(struct cytp_data), GFP_KERNEL); + cytp = kzalloc(sizeof(*cytp), GFP_KERNEL); if (!cytp) return -ENOMEM; @@ -668,17 +633,20 @@ int cypress_init(struct psmouse *psmouse) cypress_reset(psmouse); - if (cypress_query_hardware(psmouse)) { + error = cypress_query_hardware(psmouse); + if (error) { psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); goto err_exit; } - if (cypress_set_absolute_mode(psmouse)) { + error = cypress_set_absolute_mode(psmouse); + if (error) { psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); goto err_exit; } - if (cypress_set_input_params(psmouse->dev, cytp) < 0) { + error = cypress_set_input_params(psmouse->dev, cytp); + if (error) { psmouse_err(psmouse, "init: Unable to set input params.\n"); goto err_exit; } @@ -703,5 +671,5 @@ err_exit: psmouse->private = NULL; kfree(cytp); - return -1; + return error; } diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h index bb4979d06bf9..47d538a49089 100644 --- a/drivers/input/mouse/cypress_ps2.h +++ b/drivers/input/mouse/cypress_ps2.h @@ -72,12 +72,6 @@ #define CYTP_DATA_TIMEOUT 30 #define CYTP_EXT_CMD 0xe8 -#define CYTP_PS2_RETRY 0xfe -#define CYTP_PS2_ERROR 0xfc - -#define CYTP_RESP_RETRY 0x01 -#define CYTP_RESP_ERROR 0xfe - #define CYTP_105001_WIDTH 97 /* Dell XPS 13 */ #define CYTP_105001_HIGH 59 diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 8a72c200ccb5..fee1796da3d0 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -28,6 +28,7 @@ #include <linux/slab.h> #include <linux/kernel.h> #include <linux/sched.h> +#include <linux/string_choices.h> #include <linux/input.h> #include <linux/uaccess.h> #include <linux/jiffies.h> @@ -36,7 +37,7 @@ #include <linux/pm_wakeirq.h> #include <linux/property.h> #include <linux/regulator/consumer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "elan_i2c.h" @@ -199,7 +200,7 @@ static int elan_set_power(struct elan_tp_data *data, bool on) } while (--repeat > 0); dev_err(&data->client->dev, "failed to set power %s: %d\n", - on ? "on" : "off", error); + str_on_off(on), error); return error; } @@ -541,7 +542,8 @@ static int elan_update_firmware(struct elan_tp_data *data, dev_dbg(&client->dev, "Starting firmware update....\n"); - disable_irq(client->irq); + guard(disable_irq)(&client->irq); + data->in_fw_update = true; retval = __elan_update_firmware(data, fw); @@ -555,7 +557,6 @@ static int elan_update_firmware(struct elan_tp_data *data, } data->in_fw_update = false; - enable_irq(client->irq); return retval; } @@ -621,8 +622,6 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, const char *buf, size_t count) { struct elan_tp_data *data = dev_get_drvdata(dev); - const struct firmware *fw; - char *fw_name; int error; const u8 *fw_signature; static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF}; @@ -631,15 +630,16 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, return -EINVAL; /* Look for a firmware with the product id appended. */ - fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id); + const char *fw_name __free(kfree) = + kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id); if (!fw_name) { dev_err(dev, "failed to allocate memory for firmware name\n"); return -ENOMEM; } dev_info(dev, "requesting fw '%s'\n", fw_name); + const struct firmware *fw __free(firmware) = NULL; error = request_firmware(&fw, fw_name, dev); - kfree(fw_name); if (error) { dev_err(dev, "failed to request firmware: %d\n", error); return error; @@ -651,46 +651,36 @@ static ssize_t elan_sysfs_update_fw(struct device *dev, dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n", (int)sizeof(signature), signature, (int)sizeof(signature), fw_signature); - error = -EBADF; - goto out_release_fw; + return -EBADF; } - error = mutex_lock_interruptible(&data->sysfs_mutex); - if (error) - goto out_release_fw; - - error = elan_update_firmware(data, fw); - - mutex_unlock(&data->sysfs_mutex); + scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) { + error = elan_update_firmware(data, fw); + if (error) + return error; + } -out_release_fw: - release_firmware(fw); - return error ?: count; + return count; } -static ssize_t calibrate_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int elan_calibrate(struct elan_tp_data *data) { - struct i2c_client *client = to_i2c_client(dev); - struct elan_tp_data *data = i2c_get_clientdata(client); + struct i2c_client *client = data->client; + struct device *dev = &client->dev; int tries = 20; int retval; int error; u8 val[ETP_CALIBRATE_MAX_LEN]; - retval = mutex_lock_interruptible(&data->sysfs_mutex); - if (retval) - return retval; - - disable_irq(client->irq); + guard(disable_irq)(&client->irq); data->mode |= ETP_ENABLE_CALIBRATE; retval = data->ops->set_mode(client, data->mode); if (retval) { + data->mode &= ~ETP_ENABLE_CALIBRATE; dev_err(dev, "failed to enable calibration mode: %d\n", retval); - goto out; + return retval; } retval = data->ops->calibrate(client); @@ -728,10 +718,24 @@ out_disable_calibrate: if (!retval) retval = error; } -out: - enable_irq(client->irq); - mutex_unlock(&data->sysfs_mutex); - return retval ?: count; + return retval; +} + +static ssize_t calibrate_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct elan_tp_data *data = i2c_get_clientdata(client); + int error; + + scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) { + error = elan_calibrate(data); + if (error) + return error; + } + + return count; } static ssize_t elan_sysfs_read_mode(struct device *dev, @@ -743,16 +747,11 @@ static ssize_t elan_sysfs_read_mode(struct device *dev, int error; enum tp_mode mode; - error = mutex_lock_interruptible(&data->sysfs_mutex); - if (error) - return error; - - error = data->ops->iap_get_mode(data->client, &mode); - - mutex_unlock(&data->sysfs_mutex); - - if (error) - return error; + scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) { + error = data->ops->iap_get_mode(data->client, &mode); + if (error) + return error; + } return sysfs_emit(buf, "%d\n", (int)mode); } @@ -783,44 +782,40 @@ static const struct attribute_group elan_sysfs_group = { .attrs = elan_sysfs_entries, }; -static ssize_t acquire_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static int elan_acquire_baseline(struct elan_tp_data *data) { - struct i2c_client *client = to_i2c_client(dev); - struct elan_tp_data *data = i2c_get_clientdata(client); - int error; + struct i2c_client *client = data->client; + struct device *dev = &client->dev; int retval; + int error; - retval = mutex_lock_interruptible(&data->sysfs_mutex); - if (retval) - return retval; - - disable_irq(client->irq); + guard(disable_irq)(&client->irq); data->baseline_ready = false; data->mode |= ETP_ENABLE_CALIBRATE; - retval = data->ops->set_mode(data->client, data->mode); + retval = data->ops->set_mode(client, data->mode); if (retval) { + data->mode &= ~ETP_ENABLE_CALIBRATE; dev_err(dev, "Failed to enable calibration mode to get baseline: %d\n", retval); - goto out; + return retval; } msleep(250); - retval = data->ops->get_baseline_data(data->client, true, + retval = data->ops->get_baseline_data(client, true, &data->max_baseline); if (retval) { - dev_err(dev, "Failed to read max baseline form device: %d\n", + dev_err(dev, "Failed to read max baseline from device: %d\n", retval); goto out_disable_calibrate; } - retval = data->ops->get_baseline_data(data->client, false, + retval = data->ops->get_baseline_data(client, false, &data->min_baseline); if (retval) { - dev_err(dev, "Failed to read min baseline form device: %d\n", + dev_err(dev, "Failed to read min baseline from device: %d\n", retval); goto out_disable_calibrate; } @@ -829,17 +824,31 @@ static ssize_t acquire_store(struct device *dev, struct device_attribute *attr, out_disable_calibrate: data->mode &= ~ETP_ENABLE_CALIBRATE; - error = data->ops->set_mode(data->client, data->mode); + error = data->ops->set_mode(client, data->mode); if (error) { dev_err(dev, "Failed to disable calibration mode after acquiring baseline: %d\n", error); if (!retval) retval = error; } -out: - enable_irq(client->irq); - mutex_unlock(&data->sysfs_mutex); - return retval ?: count; + + return retval; +} + +static ssize_t acquire_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct elan_tp_data *data = i2c_get_clientdata(client); + int error; + + scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) { + error = elan_acquire_baseline(data); + if (error) + return error; + } + + return count; } static ssize_t min_show(struct device *dev, @@ -847,22 +856,15 @@ static ssize_t min_show(struct device *dev, { struct i2c_client *client = to_i2c_client(dev); struct elan_tp_data *data = i2c_get_clientdata(client); - int retval; - retval = mutex_lock_interruptible(&data->sysfs_mutex); - if (retval) - return retval; + scoped_guard(mutex_intr, &data->sysfs_mutex) { + if (!data->baseline_ready) + return -ENODATA; - if (!data->baseline_ready) { - retval = -ENODATA; - goto out; + return sysfs_emit(buf, "%d", data->min_baseline); } - retval = sysfs_emit(buf, "%d", data->min_baseline); - -out: - mutex_unlock(&data->sysfs_mutex); - return retval; + return -EINTR; } static ssize_t max_show(struct device *dev, @@ -870,25 +872,17 @@ static ssize_t max_show(struct device *dev, { struct i2c_client *client = to_i2c_client(dev); struct elan_tp_data *data = i2c_get_clientdata(client); - int retval; - retval = mutex_lock_interruptible(&data->sysfs_mutex); - if (retval) - return retval; + scoped_guard(mutex_intr, &data->sysfs_mutex) { + if (!data->baseline_ready) + return -ENODATA; - if (!data->baseline_ready) { - retval = -ENODATA; - goto out; + return sysfs_emit(buf, "%d", data->max_baseline); } - retval = sysfs_emit(buf, "%d", data->max_baseline); - -out: - mutex_unlock(&data->sysfs_mutex); - return retval; + return -EINTR; } - static DEVICE_ATTR_WO(acquire); static DEVICE_ATTR_RO(min); static DEVICE_ATTR_RO(max); @@ -1323,41 +1317,54 @@ static int elan_probe(struct i2c_client *client) return 0; } +static int __elan_suspend(struct elan_tp_data *data) +{ + struct i2c_client *client = data->client; + int error; + + if (device_may_wakeup(&client->dev)) + return elan_sleep(data); + + /* Touchpad is not a wakeup source */ + error = elan_set_power(data, false); + if (error) + return error; + + error = regulator_disable(data->vcc); + if (error) { + dev_err(&client->dev, + "failed to disable regulator when suspending: %d\n", + error); + /* Attempt to power the chip back up */ + elan_set_power(data, true); + return error; + } + + return 0; +} + static int elan_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); struct elan_tp_data *data = i2c_get_clientdata(client); - int ret; + int error; /* * We are taking the mutex to make sure sysfs operations are * complete before we attempt to bring the device into low[er] * power mode. */ - ret = mutex_lock_interruptible(&data->sysfs_mutex); - if (ret) - return ret; - - disable_irq(client->irq); + scoped_cond_guard(mutex_intr, return -EINTR, &data->sysfs_mutex) { + disable_irq(client->irq); - if (device_may_wakeup(dev)) { - ret = elan_sleep(data); - } else { - ret = elan_set_power(data, false); - if (ret) - goto err; - - ret = regulator_disable(data->vcc); - if (ret) { - dev_err(dev, "error %d disabling regulator\n", ret); - /* Attempt to power the chip back up */ - elan_set_power(data, true); + error = __elan_suspend(data); + if (error) { + enable_irq(client->irq); + return error; } } -err: - mutex_unlock(&data->sysfs_mutex); - return ret; + return 0; } static int elan_resume(struct device *dev) @@ -1392,8 +1399,8 @@ err: static DEFINE_SIMPLE_DEV_PM_OPS(elan_pm_ops, elan_suspend, elan_resume); static const struct i2c_device_id elan_id[] = { - { DRIVER_NAME, 0 }, - { }, + { DRIVER_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, elan_id); diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c index 13dc097eb6c6..a9057d124a88 100644 --- a/drivers/input/mouse/elan_i2c_i2c.c +++ b/drivers/input/mouse/elan_i2c_i2c.c @@ -21,7 +21,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/sched.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "elan_i2c.h" @@ -628,12 +628,11 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size, const u8 *page, u16 checksum, int idx) { struct device *dev = &client->dev; - u8 *page_store; u8 val[3]; u16 result; int ret, error; - page_store = kmalloc(fw_page_size + 4, GFP_KERNEL); + u8 *page_store __free(kfree) = kmalloc(fw_page_size + 4, GFP_KERNEL); if (!page_store) return -ENOMEM; @@ -647,7 +646,7 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size, if (ret != fw_page_size + 4) { error = ret < 0 ? ret : -EIO; dev_err(dev, "Failed to write page %d: %d\n", idx, error); - goto exit; + return error; } /* Wait for F/W to update one page ROM data. */ @@ -656,20 +655,17 @@ static int elan_i2c_write_fw_block(struct i2c_client *client, u16 fw_page_size, error = elan_i2c_read_cmd(client, ETP_I2C_IAP_CTRL_CMD, val); if (error) { dev_err(dev, "Failed to read IAP write result: %d\n", error); - goto exit; + return error; } result = le16_to_cpup((__le16 *)val); if (result & (ETP_FW_IAP_PAGE_ERR | ETP_FW_IAP_INTF_ERR)) { dev_err(dev, "IAP reports failed write: %04hx\n", result); - error = -EIO; - goto exit; + return -EIO; } -exit: - kfree(page_store); - return error; + return 0; } static int elan_i2c_finish_fw_update(struct i2c_client *client, diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 4e38229404b4..79ad98cc1e79 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -17,7 +17,7 @@ #include <linux/platform_device.h> #include <linux/serio.h> #include <linux/libps2.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "psmouse.h" #include "elantech.h" #include "elan_i2c.h" @@ -1477,15 +1477,46 @@ static void elantech_disconnect(struct psmouse *psmouse) } /* + * Some hw_version 4 models fail to properly activate absolute mode on + * resume without going through disable/enable cycle. + */ +static const struct dmi_system_id elantech_needs_reenable[] = { +#if defined(CONFIG_DMI) && defined(CONFIG_X86) + { + /* Lenovo N24 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "81AF"), + }, + }, +#endif + { } +}; + +/* * Put the touchpad back into absolute mode when reconnecting */ static int elantech_reconnect(struct psmouse *psmouse) { + int err; + psmouse_reset(psmouse); if (elantech_detect(psmouse, 0)) return -1; + if (dmi_check_system(elantech_needs_reenable)) { + err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE); + if (err) + psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n", + psmouse->ps2dev.serio->phys, err); + + err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE); + if (err) + psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n", + psmouse->ps2dev.serio->phys, err); + } + if (elantech_set_absolute_mode(psmouse)) { psmouse_err(psmouse, "failed to put touchpad back into absolute mode.\n"); diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index c74b99077d16..356b99d48544 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c @@ -408,8 +408,7 @@ int focaltech_init(struct psmouse *psmouse) struct focaltech_data *priv; int error; - psmouse->private = priv = kzalloc(sizeof(struct focaltech_data), - GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index 3c8310da0b05..6125652e5ad8 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -981,7 +981,7 @@ int hgpk_init(struct psmouse *psmouse) struct hgpk_data *priv; int err; - priv = kzalloc(sizeof(struct hgpk_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { err = -ENOMEM; goto alloc_fail; diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index bd9955730176..7147dacc404f 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c @@ -273,7 +273,7 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) struct lifebook_data *priv; int error = -ENOMEM; - priv = kzalloc(sizeof(struct lifebook_data), GFP_KERNEL); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); dev2 = input_allocate_device(); if (!priv || !dev2) goto err_out; diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 2de64d6a04d1..baef4be14b54 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c @@ -73,7 +73,7 @@ static int probe_maple_mouse(struct device *dev) struct input_dev *input_dev; struct dc_mouse *mse; - mse = kzalloc(sizeof(struct dc_mouse), GFP_KERNEL); + mse = kzalloc(sizeof(*mse), GFP_KERNEL); if (!mse) { error = -ENOMEM; goto fail; diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index a0aac76b1e41..a2c9f7144864 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1591,7 +1591,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) psmouse_deactivate(parent); } - psmouse = kzalloc(sizeof(struct psmouse), GFP_KERNEL); + psmouse = kzalloc(sizeof(*psmouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!psmouse || !input_dev) goto err_free; diff --git a/drivers/input/mouse/psmouse-smbus.c b/drivers/input/mouse/psmouse-smbus.c index 2a2459b1b4f2..93420f07b7d0 100644 --- a/drivers/input/mouse/psmouse-smbus.c +++ b/drivers/input/mouse/psmouse-smbus.c @@ -35,7 +35,7 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HOST_NOTIFY)) return; - mutex_lock(&psmouse_smbus_mutex); + guard(mutex)(&psmouse_smbus_mutex); list_for_each_entry(smbdev, &psmouse_smbus_list, node) { if (smbdev->dead) @@ -55,15 +55,13 @@ static void psmouse_smbus_check_adapter(struct i2c_adapter *adapter) "SMBus candidate adapter appeared, triggering rescan\n"); serio_rescan(smbdev->psmouse->ps2dev.serio); } - - mutex_unlock(&psmouse_smbus_mutex); } static void psmouse_smbus_detach_i2c_client(struct i2c_client *client) { struct psmouse_smbus_dev *smbdev, *tmp; - mutex_lock(&psmouse_smbus_mutex); + guard(mutex)(&psmouse_smbus_mutex); list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) { if (smbdev->client != client) @@ -85,8 +83,6 @@ static void psmouse_smbus_detach_i2c_client(struct i2c_client *client) kfree(smbdev); } } - - mutex_unlock(&psmouse_smbus_mutex); } static int psmouse_smbus_notifier_call(struct notifier_block *nb, @@ -171,7 +167,7 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse) { struct psmouse_smbus_dev *smbdev = psmouse->private; - mutex_lock(&psmouse_smbus_mutex); + guard(mutex)(&psmouse_smbus_mutex); if (smbdev->dead) { list_del(&smbdev->node); @@ -186,8 +182,6 @@ static void psmouse_smbus_disconnect(struct psmouse *psmouse) psmouse_smbus_schedule_remove(smbdev->client); } - mutex_unlock(&psmouse_smbus_mutex); - psmouse->private = NULL; } @@ -219,7 +213,7 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse) { struct psmouse_smbus_dev *smbdev, *tmp; - mutex_lock(&psmouse_smbus_mutex); + guard(mutex)(&psmouse_smbus_mutex); list_for_each_entry_safe(smbdev, tmp, &psmouse_smbus_list, node) { if (psmouse == smbdev->psmouse) { @@ -227,8 +221,6 @@ void psmouse_smbus_cleanup(struct psmouse *psmouse) kfree(smbdev); } } - - mutex_unlock(&psmouse_smbus_mutex); } int psmouse_smbus_init(struct psmouse *psmouse, @@ -267,9 +259,9 @@ int psmouse_smbus_init(struct psmouse *psmouse, psmouse->disconnect = psmouse_smbus_disconnect; psmouse->resync_time = 0; - mutex_lock(&psmouse_smbus_mutex); - list_add_tail(&smbdev->node, &psmouse_smbus_list); - mutex_unlock(&psmouse_smbus_mutex); + scoped_guard(mutex, &psmouse_smbus_mutex) { + list_add_tail(&smbdev->node, &psmouse_smbus_list); + } /* Bind to already existing adapters right away */ error = i2c_for_each_dev(smbdev, psmouse_smbus_create_companion); @@ -293,9 +285,9 @@ int psmouse_smbus_init(struct psmouse *psmouse, smbdev->board.platform_data = NULL; if (error < 0 || !leave_breadcrumbs) { - mutex_lock(&psmouse_smbus_mutex); - list_del(&smbdev->node); - mutex_unlock(&psmouse_smbus_mutex); + scoped_guard(mutex, &psmouse_smbus_mutex) { + list_del(&smbdev->node); + } kfree(smbdev); } diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 2716d2ba386a..44b136fc29aa 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -1028,7 +1028,7 @@ int fsp_init(struct psmouse *psmouse) "Finger Sensing Pad, hw: %d.%d.%d, sn: %x, sw: %s\n", ver >> 4, ver & 0x0F, rev, sn, fsp_drv_ver); - psmouse->private = priv = kzalloc(sizeof(struct fsp_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c index 993f90333380..218c8432a13b 100644 --- a/drivers/input/mouse/sermouse.c +++ b/drivers/input/mouse/sermouse.c @@ -231,7 +231,7 @@ static int sermouse_connect(struct serio *serio, struct serio_driver *drv) unsigned char c = serio->id.extra; int err = -ENOMEM; - sermouse = kzalloc(sizeof(struct sermouse), GFP_KERNEL); + sermouse = kzalloc(sizeof(*sermouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!sermouse || !input_dev) goto fail1; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 7a303a9d6bf7..c5c88a75a019 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -161,8 +161,10 @@ static const char * const topbuttonpad_pnp_ids[] = { NULL }; +#ifdef CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS static const char * const smbus_pnp_ids[] = { /* all of the topbuttonpad_pnp_ids are valid, we just add some extras */ + "DLL060d", /* Dell Precision M3800 */ "LEN0048", /* X1 Carbon 3 */ "LEN0046", /* X250 */ "LEN0049", /* Yoga 11e */ @@ -189,12 +191,18 @@ static const char * const smbus_pnp_ids[] = { "LEN2054", /* E480 */ "LEN2055", /* E580 */ "LEN2068", /* T14 Gen 1 */ + "SYN1221", /* TUXEDO InfinityBook Pro 14 v5 */ + "SYN3003", /* HP EliteBook 850 G1 */ + "SYN3015", /* HP EliteBook 840 G2 */ "SYN3052", /* HP EliteBook 840 G4 */ "SYN3221", /* HP 15-ay000 */ "SYN323d", /* HP Spectre X360 13-w013dx */ "SYN3257", /* HP Envy 13-ad105ng */ + "TOS01f6", /* Dynabook Portege X30L-G */ + "TOS0213", /* Dynabook Portege X30-D */ NULL }; +#endif static const char * const forcepad_pnp_ids[] = { "SYN300D", @@ -649,9 +657,8 @@ static int synaptics_pt_start(struct serio *serio) struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; - serio_pause_rx(parent->ps2dev.serio); + guard(serio_pause_rx)(parent->ps2dev.serio); priv->pt_port = serio; - serio_continue_rx(parent->ps2dev.serio); return 0; } @@ -661,9 +668,28 @@ static void synaptics_pt_stop(struct serio *serio) struct psmouse *parent = psmouse_from_serio(serio->parent); struct synaptics_data *priv = parent->private; - serio_pause_rx(parent->ps2dev.serio); + guard(serio_pause_rx)(parent->ps2dev.serio); priv->pt_port = NULL; - serio_continue_rx(parent->ps2dev.serio); +} + +static int synaptics_pt_open(struct serio *serio) +{ + struct psmouse *parent = psmouse_from_serio(serio->parent); + struct synaptics_data *priv = parent->private; + + guard(serio_pause_rx)(parent->ps2dev.serio); + priv->pt_port_open = true; + + return 0; +} + +static void synaptics_pt_close(struct serio *serio) +{ + struct psmouse *parent = psmouse_from_serio(serio->parent); + struct synaptics_data *priv = parent->private; + + guard(serio_pause_rx)(parent->ps2dev.serio); + priv->pt_port_open = false; } static int synaptics_is_pt_packet(u8 *buf) @@ -671,18 +697,25 @@ static int synaptics_is_pt_packet(u8 *buf) return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; } -static void synaptics_pass_pt_packet(struct serio *ptport, u8 *packet) +static void synaptics_pass_pt_packet(struct synaptics_data *priv, u8 *packet) { - struct psmouse *child = psmouse_from_serio(ptport); + struct serio *ptport; - if (child && child->state == PSMOUSE_ACTIVATED) { - serio_interrupt(ptport, packet[1], 0); - serio_interrupt(ptport, packet[4], 0); - serio_interrupt(ptport, packet[5], 0); - if (child->pktsize == 4) - serio_interrupt(ptport, packet[2], 0); - } else { - serio_interrupt(ptport, packet[1], 0); + ptport = priv->pt_port; + if (!ptport) + return; + + serio_interrupt(ptport, packet[1], 0); + + if (priv->pt_port_open) { + struct psmouse *child = psmouse_from_serio(ptport); + + if (child->state == PSMOUSE_ACTIVATED) { + serio_interrupt(ptport, packet[4], 0); + serio_interrupt(ptport, packet[5], 0); + if (child->pktsize == 4) + serio_interrupt(ptport, packet[2], 0); + } } } @@ -708,7 +741,7 @@ static void synaptics_pt_create(struct psmouse *psmouse) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) { psmouse_err(psmouse, "not enough memory for pass-through port\n"); @@ -721,6 +754,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) serio->write = synaptics_pt_write; serio->start = synaptics_pt_start; serio->stop = synaptics_pt_stop; + serio->open = synaptics_pt_open; + serio->close = synaptics_pt_close; serio->parent = psmouse->ps2dev.serio; psmouse->pt_activate = synaptics_pt_activate; @@ -1217,11 +1252,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) if (SYN_CAP_PASS_THROUGH(priv->info.capabilities) && synaptics_is_pt_packet(psmouse->packet)) { - if (priv->pt_port) - synaptics_pass_pt_packet(priv->pt_port, - psmouse->packet); - } else + synaptics_pass_pt_packet(priv, psmouse->packet); + } else { synaptics_process_packet(psmouse); + } return PSMOUSE_FULL_PACKET; } @@ -1563,7 +1597,7 @@ static int synaptics_init_ps2(struct psmouse *psmouse, synaptics_apply_quirks(psmouse, info); - psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); + psmouse->private = priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 08533d1b1b16..3853165b6b3a 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h @@ -21,7 +21,7 @@ #define SYN_QUE_EXT_MIN_COORDS 0x0f #define SYN_QUE_MEXT_CAPAB_10 0x10 -/* synatics modes */ +/* synaptics modes */ #define SYN_BIT_ABSOLUTE_MODE BIT(7) #define SYN_BIT_HIGH_RATE BIT(6) #define SYN_BIT_SLEEP_MODE BIT(3) @@ -188,6 +188,7 @@ struct synaptics_data { bool disable_gesture; /* disable gestures */ struct serio *pt_port; /* Pass-through serio port */ + bool pt_port_open; /* * Last received Advanced Gesture Mode (AGM) packet. An AGM packet diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index af5cc64c622d..a0d707e47d93 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -508,7 +508,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien { struct synaptics_i2c *touch; - touch = kzalloc(sizeof(struct synaptics_i2c), GFP_KERNEL); + touch = kzalloc(sizeof(*touch), GFP_KERNEL); if (!touch) return NULL; @@ -630,8 +630,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend, synaptics_i2c_resume); static const struct i2c_device_id synaptics_i2c_id_table[] = { - { "synaptics_i2c", 0 }, - { }, + { "synaptics_i2c" }, + { } }; MODULE_DEVICE_TABLE(i2c, synaptics_i2c_id_table); diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c index ea9eff7c8099..fb1d986a6895 100644 --- a/drivers/input/mouse/vmmouse.c +++ b/drivers/input/mouse/vmmouse.c @@ -21,19 +21,16 @@ #include "psmouse.h" #include "vmmouse.h" -#define VMMOUSE_PROTO_MAGIC 0x564D5868U - /* * Main commands supported by the vmmouse hypervisor port. */ -#define VMMOUSE_PROTO_CMD_GETVERSION 10 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA 39 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS 40 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND 41 -#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT 86 +#define VMWARE_CMD_ABSPOINTER_DATA 39 +#define VMWARE_CMD_ABSPOINTER_STATUS 40 +#define VMWARE_CMD_ABSPOINTER_COMMAND 41 +#define VMWARE_CMD_ABSPOINTER_RESTRICT 86 /* - * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND + * Subcommands for VMWARE_CMD_ABSPOINTER_COMMAND */ #define VMMOUSE_CMD_ENABLE 0x45414552U #define VMMOUSE_CMD_DISABLE 0x000000f5U @@ -76,28 +73,6 @@ struct vmmouse_data { char dev_name[128]; }; -/* - * Hypervisor-specific bi-directional communication channel - * implementing the vmmouse protocol. Should never execute on - * bare metal hardware. - */ -#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4) \ -({ \ - unsigned long __dummy1, __dummy2; \ - __asm__ __volatile__ (VMWARE_HYPERCALL : \ - "=a"(out1), \ - "=b"(out2), \ - "=c"(out3), \ - "=d"(out4), \ - "=S"(__dummy1), \ - "=D"(__dummy2) : \ - "a"(VMMOUSE_PROTO_MAGIC), \ - "b"(in1), \ - "c"(VMMOUSE_PROTO_CMD_##cmd), \ - "d"(0) : \ - "memory"); \ -}) - /** * vmmouse_report_button - report button state on the correct input device * @@ -145,14 +120,12 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) struct input_dev *abs_dev = priv->abs_dev; struct input_dev *pref_dev; u32 status, x, y, z; - u32 dummy1, dummy2, dummy3; unsigned int queue_length; unsigned int count = 255; while (count--) { /* See if we have motion data. */ - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) { psmouse_err(psmouse, "failed to fetch status data\n"); /* @@ -172,7 +145,8 @@ static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse) } /* Now get it */ - VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z); + status = vmware_hypercall4(VMWARE_CMD_ABSPOINTER_DATA, 4, + &x, &y, &z); /* * And report what we've got. Prefer to report button @@ -247,14 +221,10 @@ static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse) static void vmmouse_disable(struct psmouse *psmouse) { u32 status; - u32 dummy1, dummy2, dummy3, dummy4; - - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE, - dummy1, dummy2, dummy3, dummy4); - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, - status, dummy1, dummy2, dummy3); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR) psmouse_warn(psmouse, "failed to disable vmmouse device\n"); } @@ -271,26 +241,24 @@ static void vmmouse_disable(struct psmouse *psmouse) static int vmmouse_enable(struct psmouse *psmouse) { u32 status, version; - u32 dummy1, dummy2, dummy3, dummy4; /* * Try enabling the device. If successful, we should be able to * read valid version ID back from it. */ - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE, - dummy1, dummy2, dummy3, dummy4); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE); /* * See if version ID can be retrieved. */ - VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3); + status = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_STATUS, 0); if ((status & 0x0000ffff) == 0) { psmouse_dbg(psmouse, "empty flags - assuming no device\n"); return -ENXIO; } - VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */, - version, dummy1, dummy2, dummy3); + version = vmware_hypercall1(VMWARE_CMD_ABSPOINTER_DATA, + 1 /* single item */); if (version != VMMOUSE_VERSION_ID) { psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n", (unsigned) version, VMMOUSE_VERSION_ID); @@ -301,11 +269,11 @@ static int vmmouse_enable(struct psmouse *psmouse) /* * Restrict ioport access, if possible. */ - VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0, - dummy1, dummy2, dummy3, dummy4); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_RESTRICT, + VMMOUSE_RESTRICT_CPL0); - VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE, - dummy1, dummy2, dummy3, dummy4); + vmware_hypercall1(VMWARE_CMD_ABSPOINTER_COMMAND, + VMMOUSE_CMD_REQUEST_ABSOLUTE); return 0; } @@ -342,7 +310,7 @@ static bool vmmouse_check_hypervisor(void) */ int vmmouse_detect(struct psmouse *psmouse, bool set_properties) { - u32 response, version, dummy1, dummy2; + u32 response, version, type; if (!vmmouse_check_hypervisor()) { psmouse_dbg(psmouse, @@ -351,9 +319,9 @@ int vmmouse_detect(struct psmouse *psmouse, bool set_properties) } /* Check if the device is present */ - response = ~VMMOUSE_PROTO_MAGIC; - VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2); - if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) + response = ~VMWARE_HYPERVISOR_MAGIC; + version = vmware_hypercall3(VMWARE_CMD_GETVERSION, 0, &response, &type); + if (response != VMWARE_HYPERVISOR_MAGIC || version == 0xffffffffU) return -ENXIO; if (set_properties) { diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 8af8e4a15f95..707cd28f4ba6 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c @@ -456,7 +456,7 @@ static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL); + mouse = kzalloc(sizeof(*mouse), GFP_KERNEL); input_dev = input_allocate_device(); if (!mouse || !input_dev) goto fail1; diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c index 343030290d78..3aee04837205 100644 --- a/drivers/input/rmi4/rmi_bus.c +++ b/drivers/input/rmi4/rmi_bus.c @@ -144,9 +144,9 @@ bool rmi_is_function_device(struct device *dev) return dev->type == &rmi_function_type; } -static int rmi_function_match(struct device *dev, struct device_driver *drv) +static int rmi_function_match(struct device *dev, const struct device_driver *drv) { - struct rmi_function_handler *handler = to_rmi_function_handler(drv); + const struct rmi_function_handler *handler = to_rmi_function_handler(drv); struct rmi_function *fn = to_rmi_function(dev); return fn->fd.function_number == handler->func; @@ -333,7 +333,7 @@ EXPORT_SYMBOL_GPL(rmi_unregister_function_handler); /* Bus specific stuff */ -static int rmi_bus_match(struct device *dev, struct device_driver *drv) +static int rmi_bus_match(struct device *dev, const struct device_driver *drv) { bool physical = rmi_is_physical_device(dev); diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h index ea46ad9447ec..d4d0d82c69aa 100644 --- a/drivers/input/rmi4/rmi_bus.h +++ b/drivers/input/rmi4/rmi_bus.h @@ -87,7 +87,7 @@ struct rmi_function_handler { }; #define to_rmi_function_handler(d) \ - container_of(d, struct rmi_function_handler, driver) + container_of_const(d, struct rmi_function_handler, driver) int __must_check __rmi_register_function_handler(struct rmi_function_handler *, struct module *, const char *); diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c index ef9ea295f9e0..2168b6cd7167 100644 --- a/drivers/input/rmi4/rmi_driver.c +++ b/drivers/input/rmi4/rmi_driver.c @@ -1258,7 +1258,7 @@ static struct rmi_driver rmi_physical_driver = { .set_input_params = rmi_driver_set_input_params, }; -bool rmi_is_physical_driver(struct device_driver *drv) +bool rmi_is_physical_driver(const struct device_driver *drv) { return drv == &rmi_physical_driver.driver; } diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h index 1c6c6086c0e5..3bfe9013043e 100644 --- a/drivers/input/rmi4/rmi_driver.h +++ b/drivers/input/rmi4/rmi_driver.h @@ -84,7 +84,7 @@ int rmi_register_desc_calc_reg_offset( bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item, u8 subpacket); -bool rmi_is_physical_driver(struct device_driver *); +bool rmi_is_physical_driver(const struct device_driver *); int rmi_register_physical_driver(void); void rmi_unregister_physical_driver(void); void rmi_free_function_list(struct rmi_device *rmi_dev); diff --git a/drivers/input/rmi4/rmi_f01.c b/drivers/input/rmi4/rmi_f01.c index cc1d4b424640..47be64284b25 100644 --- a/drivers/input/rmi4/rmi_f01.c +++ b/drivers/input/rmi4/rmi_f01.c @@ -9,7 +9,7 @@ #include <linux/slab.h> #include <linux/uaccess.h> #include <linux/of.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "rmi_driver.h" #define RMI_PRODUCT_ID_LENGTH 10 diff --git a/drivers/input/rmi4/rmi_f03.c b/drivers/input/rmi4/rmi_f03.c index 1e11ea30d7bd..e1157ff0f00a 100644 --- a/drivers/input/rmi4/rmi_f03.c +++ b/drivers/input/rmi4/rmi_f03.c @@ -61,14 +61,14 @@ void rmi_f03_commit_buttons(struct rmi_function *fn) struct f03_data *f03 = dev_get_drvdata(&fn->dev); struct serio *serio = f03->serio; - serio_pause_rx(serio); + guard(serio_pause_rx)(serio); + if (serio->drv) { serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS, SERIO_OOB_DATA); serio->drv->interrupt(serio, f03->overwrite_buttons, SERIO_OOB_DATA); } - serio_continue_rx(serio); } static int rmi_f03_pt_write(struct serio *id, unsigned char val) diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c index 7e97944f7616..8246fe77114b 100644 --- a/drivers/input/rmi4/rmi_f12.c +++ b/drivers/input/rmi4/rmi_f12.c @@ -24,6 +24,7 @@ enum rmi_f12_object_type { }; #define F12_DATA1_BYTES_PER_OBJ 8 +#define RMI_F12_QUERY_RESOLUTION 29 struct f12_data { struct rmi_2d_sensor sensor; @@ -73,6 +74,8 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12) int pitch_y = 0; int rx_receivers = 0; int tx_receivers = 0; + u16 query_dpm_addr = 0; + int dpm_resolution = 0; item = rmi_get_register_desc_item(&f12->control_reg_desc, 8); if (!item) { @@ -122,18 +125,38 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12) offset += 4; } - if (rmi_register_desc_has_subpacket(item, 3)) { - rx_receivers = buf[offset]; - tx_receivers = buf[offset + 1]; - offset += 2; - } + /* + * Use the Query DPM feature when the resolution query register + * exists. + */ + if (rmi_get_register_desc_item(&f12->query_reg_desc, + RMI_F12_QUERY_RESOLUTION)) { + offset = rmi_register_desc_calc_reg_offset(&f12->query_reg_desc, + RMI_F12_QUERY_RESOLUTION); + query_dpm_addr = fn->fd.query_base_addr + offset; + ret = rmi_read(fn->rmi_dev, query_dpm_addr, buf); + if (ret < 0) { + dev_err(&fn->dev, "Failed to read DPM value: %d\n", ret); + return -ENODEV; + } + dpm_resolution = buf[0]; - /* Skip over sensor flags */ - if (rmi_register_desc_has_subpacket(item, 4)) - offset += 1; + sensor->x_mm = sensor->max_x / dpm_resolution; + sensor->y_mm = sensor->max_y / dpm_resolution; + } else { + if (rmi_register_desc_has_subpacket(item, 3)) { + rx_receivers = buf[offset]; + tx_receivers = buf[offset + 1]; + offset += 2; + } - sensor->x_mm = (pitch_x * rx_receivers) >> 12; - sensor->y_mm = (pitch_y * tx_receivers) >> 12; + /* Skip over sensor flags */ + if (rmi_register_desc_has_subpacket(item, 4)) + offset += 1; + + sensor->x_mm = (pitch_x * rx_receivers) >> 12; + sensor->y_mm = (pitch_y * tx_receivers) >> 12; + } rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: x_mm: %d y_mm: %d\n", __func__, sensor->x_mm, sensor->y_mm); diff --git a/drivers/input/rmi4/rmi_f34.c b/drivers/input/rmi4/rmi_f34.c index 3b3ac71e53dc..f1947f03b06a 100644 --- a/drivers/input/rmi4/rmi_f34.c +++ b/drivers/input/rmi4/rmi_f34.c @@ -4,10 +4,11 @@ * Copyright (C) 2016 Zodiac Inflight Innovations */ +#include "linux/device.h" #include <linux/kernel.h> #include <linux/rmi.h> #include <linux/firmware.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/bitops.h> #include "rmi_driver.h" @@ -246,7 +247,6 @@ static int rmi_f34_update_firmware(struct f34_data *f34, (const struct rmi_f34_firmware *)fw->data; u32 image_size = le32_to_cpu(syn_fw->image_size); u32 config_size = le32_to_cpu(syn_fw->config_size); - int ret; BUILD_BUG_ON(offsetof(struct rmi_f34_firmware, data) != F34_FW_IMAGE_OFFSET); @@ -267,8 +267,7 @@ static int rmi_f34_update_firmware(struct f34_data *f34, dev_err(&f34->fn->dev, "Bad firmware image: fw size %d, expected %d\n", image_size, f34->v5.fw_blocks * f34->v5.block_size); - ret = -EILSEQ; - goto out; + return -EILSEQ; } if (config_size && @@ -277,36 +276,18 @@ static int rmi_f34_update_firmware(struct f34_data *f34, "Bad firmware image: config size %d, expected %d\n", config_size, f34->v5.config_blocks * f34->v5.block_size); - ret = -EILSEQ; - goto out; + return -EILSEQ; } if (image_size && !config_size) { dev_err(&f34->fn->dev, "Bad firmware image: no config data\n"); - ret = -EILSEQ; - goto out; + return -EILSEQ; } dev_info(&f34->fn->dev, "Firmware image OK\n"); - mutex_lock(&f34->v5.flash_mutex); - - ret = rmi_f34_flash_firmware(f34, syn_fw); - - mutex_unlock(&f34->v5.flash_mutex); -out: - return ret; -} - -static int rmi_f34_status(struct rmi_function *fn) -{ - struct f34_data *f34 = dev_get_drvdata(&fn->dev); - - /* - * The status is the percentage complete, or once complete, - * zero for success or a negative return code. - */ - return f34->update_status; + guard(mutex)(&f34->v5.flash_mutex); + return rmi_f34_flash_firmware(f34, syn_fw); } static ssize_t rmi_driver_bootloader_id_show(struct device *dev, @@ -314,23 +295,25 @@ static ssize_t rmi_driver_bootloader_id_show(struct device *dev, char *buf) { struct rmi_driver_data *data = dev_get_drvdata(dev); - struct rmi_function *fn = data->f34_container; + struct rmi_function *fn; struct f34_data *f34; - if (fn) { - f34 = dev_get_drvdata(&fn->dev); - - if (f34->bl_version == 5) - return sysfs_emit(buf, "%c%c\n", - f34->bootloader_id[0], - f34->bootloader_id[1]); - else - return sysfs_emit(buf, "V%d.%d\n", - f34->bootloader_id[1], - f34->bootloader_id[0]); - } + fn = data->f34_container; + if (!fn) + return -ENODEV; - return 0; + f34 = dev_get_drvdata(&fn->dev); + if (!f34) + return -ENODEV; + + if (f34->bl_version == 5) + return sysfs_emit(buf, "%c%c\n", + f34->bootloader_id[0], + f34->bootloader_id[1]); + else + return sysfs_emit(buf, "V%d.%d\n", + f34->bootloader_id[1], + f34->bootloader_id[0]); } static DEVICE_ATTR(bootloader_id, 0444, rmi_driver_bootloader_id_show, NULL); @@ -343,13 +326,16 @@ static ssize_t rmi_driver_configuration_id_show(struct device *dev, struct rmi_function *fn = data->f34_container; struct f34_data *f34; - if (fn) { - f34 = dev_get_drvdata(&fn->dev); + fn = data->f34_container; + if (!fn) + return -ENODEV; - return sysfs_emit(buf, "%s\n", f34->configuration_id); - } + f34 = dev_get_drvdata(&fn->dev); + if (!f34) + return -ENODEV; - return 0; + + return sysfs_emit(buf, "%s\n", f34->configuration_id); } static DEVICE_ATTR(configuration_id, 0444, @@ -365,10 +351,14 @@ static int rmi_firmware_update(struct rmi_driver_data *data, if (!data->f34_container) { dev_warn(dev, "%s: No F34 present!\n", __func__); - return -EINVAL; + return -ENODEV; } f34 = dev_get_drvdata(&data->f34_container->dev); + if (!f34) { + dev_warn(dev, "%s: No valid F34 present!\n", __func__); + return -ENODEV; + } if (f34->bl_version >= 7) { if (data->pdt_props & HAS_BSR) { @@ -461,9 +451,8 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev, { struct rmi_driver_data *data = dev_get_drvdata(dev); char fw_name[NAME_MAX]; - const struct firmware *fw; size_t copy_count = count; - int ret; + int error; if (count == 0 || count >= NAME_MAX) return -EINVAL; @@ -474,17 +463,18 @@ static ssize_t rmi_driver_update_fw_store(struct device *dev, memcpy(fw_name, buf, copy_count); fw_name[copy_count] = '\0'; - ret = request_firmware(&fw, fw_name, dev); - if (ret) - return ret; + const struct firmware *fw __free(firmware) = NULL; + error = request_firmware(&fw, fw_name, dev); + if (error) + return error; dev_info(dev, "Flashing %s\n", fw_name); - ret = rmi_firmware_update(data, fw); + error = rmi_firmware_update(data, fw); + if (error) + return error; - release_firmware(fw); - - return ret ?: count; + return count; } static DEVICE_ATTR(update_fw, 0200, NULL, rmi_driver_update_fw_store); @@ -494,10 +484,18 @@ static ssize_t rmi_driver_update_fw_status_show(struct device *dev, char *buf) { struct rmi_driver_data *data = dev_get_drvdata(dev); - int update_status = 0; + struct f34_data *f34; + int update_status = -ENODEV; - if (data->f34_container) - update_status = rmi_f34_status(data->f34_container); + /* + * The status is the percentage complete, or once complete, + * zero for success or a negative return code. + */ + if (data->f34_container) { + f34 = dev_get_drvdata(&data->f34_container->dev); + if (f34) + update_status = f34->update_status; + } return sysfs_emit(buf, "%d\n", update_status); } @@ -517,33 +515,21 @@ static const struct attribute_group rmi_firmware_attr_group = { .attrs = rmi_firmware_attrs, }; -static int rmi_f34_probe(struct rmi_function *fn) +static int rmi_f34v5_probe(struct f34_data *f34) { - struct f34_data *f34; - unsigned char f34_queries[9]; + struct rmi_function *fn = f34->fn; + u8 f34_queries[9]; bool has_config_id; - u8 version = fn->fd.function_version; - int ret; - - f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL); - if (!f34) - return -ENOMEM; - - f34->fn = fn; - dev_set_drvdata(&fn->dev, f34); - - /* v5 code only supported version 0, try V7 probe */ - if (version > 0) - return rmi_f34v7_probe(f34); + int error; f34->bl_version = 5; - ret = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, - f34_queries, sizeof(f34_queries)); - if (ret) { + error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr, + f34_queries, sizeof(f34_queries)); + if (error) { dev_err(&fn->dev, "%s: Failed to query properties\n", __func__); - return ret; + return error; } snprintf(f34->bootloader_id, sizeof(f34->bootloader_id), @@ -569,11 +555,11 @@ static int rmi_f34_probe(struct rmi_function *fn) f34->v5.config_blocks); if (has_config_id) { - ret = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr, - f34_queries, sizeof(f34_queries)); - if (ret) { + error = rmi_read_block(fn->rmi_dev, fn->fd.control_base_addr, + f34_queries, sizeof(f34_queries)); + if (error) { dev_err(&fn->dev, "Failed to read F34 config ID\n"); - return ret; + return error; } snprintf(f34->configuration_id, sizeof(f34->configuration_id), @@ -582,12 +568,34 @@ static int rmi_f34_probe(struct rmi_function *fn) f34_queries[2], f34_queries[3]); rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Configuration ID: %s\n", - f34->configuration_id); + f34->configuration_id); } return 0; } +static int rmi_f34_probe(struct rmi_function *fn) +{ + struct f34_data *f34; + u8 version = fn->fd.function_version; + int error; + + f34 = devm_kzalloc(&fn->dev, sizeof(struct f34_data), GFP_KERNEL); + if (!f34) + return -ENOMEM; + + f34->fn = fn; + + /* v5 code only supported version 0 */ + error = version == 0 ? rmi_f34v5_probe(f34) : rmi_f34v7_probe(f34); + if (error) + return error; + + dev_set_drvdata(&fn->dev, f34); + + return 0; +} + int rmi_f34_create_sysfs(struct rmi_device *rmi_dev) { return sysfs_create_group(&rmi_dev->dev.kobj, &rmi_firmware_attr_group); diff --git a/drivers/input/rmi4/rmi_f34v7.c b/drivers/input/rmi4/rmi_f34v7.c index 886557b01eba..fd49acc02071 100644 --- a/drivers/input/rmi4/rmi_f34v7.c +++ b/drivers/input/rmi4/rmi_f34v7.c @@ -13,7 +13,7 @@ #include <linux/delay.h> #include <linux/slab.h> #include <linux/jiffies.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "rmi_driver.h" #include "rmi_f34.h" diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c index 5c3da910b5b2..ac4041a69fcd 100644 --- a/drivers/input/rmi4/rmi_f54.c +++ b/drivers/input/rmi4/rmi_f54.c @@ -372,8 +372,6 @@ static const struct vb2_ops rmi_f54_queue_ops = { .queue_setup = rmi_f54_queue_setup, .buf_queue = rmi_f54_buffer_queue, .stop_streaming = rmi_f54_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue rmi_f54_queue = { diff --git a/drivers/input/rmi4/rmi_i2c.c b/drivers/input/rmi4/rmi_i2c.c index 091d4e23b629..3c0c5fd44702 100644 --- a/drivers/input/rmi4/rmi_i2c.c +++ b/drivers/input/rmi4/rmi_i2c.c @@ -365,7 +365,7 @@ static const struct dev_pm_ops rmi_i2c_pm = { }; static const struct i2c_device_id rmi_id[] = { - { "rmi4_i2c", 0 }, + { "rmi4_i2c" }, { } }; MODULE_DEVICE_TABLE(i2c, rmi_id); diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index b0b099b5528a..f3d0b40721df 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -413,7 +413,7 @@ static const struct dev_pm_ops rmi_smb_pm = { }; static const struct i2c_device_id rmi_id[] = { - { "rmi4_smbus", 0 }, + { "rmi4_smbus" }, { } }; MODULE_DEVICE_TABLE(i2c, rmi_id); diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index c5b634940cfc..aa445b1941e9 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -100,7 +100,7 @@ static int altera_ps2_probe(struct platform_device *pdev) return error; } - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -146,7 +146,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match); */ static struct platform_driver altera_ps2_driver = { .probe = altera_ps2_probe, - .remove_new = altera_ps2_remove, + .remove = altera_ps2_remove, .driver = { .name = DRV_NAME, .of_match_table = of_match_ptr(altera_ps2_match), diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 8fbfa448be4a..de4b3915c37d 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -114,8 +114,8 @@ static int amba_kmi_probe(struct amba_device *dev, if (ret) return ret; - kmi = kzalloc(sizeof(struct amba_kmi_port), GFP_KERNEL); - io = kzalloc(sizeof(struct serio), GFP_KERNEL); + kmi = kzalloc(sizeof(*kmi), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!kmi || !io) { ret = -ENOMEM; goto out; @@ -195,7 +195,6 @@ MODULE_DEVICE_TABLE(amba, amba_kmi_idtable); static struct amba_driver ambakmi_driver = { .drv = { .name = "kmi-pl050", - .owner = THIS_MODULE, .pm = pm_sleep_ptr(&amba_kmi_dev_pm_ops), }, .id_table = amba_kmi_idtable, diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index 0bd6ae106809..81b3a053df81 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c @@ -182,7 +182,7 @@ static void ams_delta_serio_exit(struct platform_device *pdev) static struct platform_driver ams_delta_serio_driver = { .probe = ams_delta_serio_init, - .remove_new = ams_delta_serio_exit, + .remove = ams_delta_serio_exit, .driver = { .name = DRIVER_NAME }, diff --git a/drivers/input/serio/apbps2.c b/drivers/input/serio/apbps2.c index dbbb10251520..b815337be2f4 100644 --- a/drivers/input/serio/apbps2.c +++ b/drivers/input/serio/apbps2.c @@ -165,7 +165,7 @@ static int apbps2_of_probe(struct platform_device *ofdev) /* Set reload register to core freq in kHz/10 */ iowrite32be(freq_hz / 10000, &priv->regs->reload); - priv->io = kzalloc(sizeof(struct serio), GFP_KERNEL); + priv->io = kzalloc(sizeof(*priv->io), GFP_KERNEL); if (!priv->io) return -ENOMEM; @@ -208,7 +208,7 @@ static struct platform_driver apbps2_of_driver = { .of_match_table = apbps2_of_match, }, .probe = apbps2_of_probe, - .remove_new = apbps2_of_remove, + .remove = apbps2_of_remove, }; module_platform_driver(apbps2_of_driver); diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c index 9d8726830140..e991c72296c9 100644 --- a/drivers/input/serio/arc_ps2.c +++ b/drivers/input/serio/arc_ps2.c @@ -155,7 +155,7 @@ static int arc_ps2_create_port(struct platform_device *pdev, struct arc_ps2_port *port = &arc_ps2->port[index]; struct serio *io; - io = kzalloc(sizeof(struct serio), GFP_KERNEL); + io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) return -ENOMEM; @@ -260,7 +260,7 @@ static struct platform_driver arc_ps2_driver = { .of_match_table = of_match_ptr(arc_ps2_match), }, .probe = arc_ps2_probe, - .remove_new = arc_ps2_remove, + .remove = arc_ps2_remove, }; module_platform_driver(arc_ps2_driver); diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index d5c9bb3d0103..053a15988c45 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -158,7 +158,7 @@ static int __init ct82c710_detect(void) static int ct82c710_probe(struct platform_device *dev) { - ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL); + ct82c710_port = kzalloc(sizeof(*ct82c710_port), GFP_KERNEL); if (!ct82c710_port) return -ENOMEM; @@ -190,7 +190,7 @@ static struct platform_driver ct82c710_driver = { .name = "ct82c710", }, .probe = ct82c710_probe, - .remove_new = ct82c710_remove, + .remove = ct82c710_remove, }; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 633c7de49d67..9c6ff04c46cf 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -145,7 +145,6 @@ static void gscps2_flush(struct gscps2port *ps2port) static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) { - unsigned long flags; char __iomem *addr = ps2port->addr; if (!wait_TBE(addr)) { @@ -156,9 +155,8 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) while (gscps2_readb_status(addr) & GSC_STAT_RBNE) /* wait */; - spin_lock_irqsave(&ps2port->lock, flags); - writeb(data, addr+GSC_XMTDATA); - spin_unlock_irqrestore(&ps2port->lock, flags); + scoped_guard(spinlock_irqsave, &ps2port->lock) + writeb(data, addr+GSC_XMTDATA); /* this is ugly, but due to timing of the port it seems to be necessary. */ mdelay(6); @@ -177,19 +175,19 @@ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data) static void gscps2_enable(struct gscps2port *ps2port, int enable) { - unsigned long flags; u8 data; /* now enable/disable the port */ - spin_lock_irqsave(&ps2port->lock, flags); - gscps2_flush(ps2port); - data = gscps2_readb_control(ps2port->addr); - if (enable) - data |= GSC_CTRL_ENBL; - else - data &= ~GSC_CTRL_ENBL; - gscps2_writeb_control(data, ps2port->addr); - spin_unlock_irqrestore(&ps2port->lock, flags); + scoped_guard(spinlock_irqsave, &ps2port->lock) { + gscps2_flush(ps2port); + data = gscps2_readb_control(ps2port->addr); + if (enable) + data |= GSC_CTRL_ENBL; + else + data &= ~GSC_CTRL_ENBL; + gscps2_writeb_control(data, ps2port->addr); + } + wait_TBE(ps2port->addr); gscps2_flush(ps2port); } @@ -200,20 +198,61 @@ static void gscps2_enable(struct gscps2port *ps2port, int enable) static void gscps2_reset(struct gscps2port *ps2port) { - unsigned long flags; - /* reset the interface */ - spin_lock_irqsave(&ps2port->lock, flags); + guard(spinlock_irqsave)(&ps2port->lock); gscps2_flush(ps2port); writeb(0xff, ps2port->addr + GSC_RESET); gscps2_flush(ps2port); - spin_unlock_irqrestore(&ps2port->lock, flags); } static LIST_HEAD(ps2port_list); +static void gscps2_read_data(struct gscps2port *ps2port) +{ + u8 status; + + do { + status = gscps2_readb_status(ps2port->addr); + if (!(status & GSC_STAT_RBNE)) + break; + + ps2port->buffer[ps2port->append].str = status; + ps2port->buffer[ps2port->append].data = + gscps2_readb_input(ps2port->addr); + } while (true); +} + +static bool gscps2_report_data(struct gscps2port *ps2port) +{ + unsigned int rxflags; + u8 data, status; + + while (ps2port->act != ps2port->append) { + /* + * Did new data arrived while we read existing data ? + * If yes, exit now and let the new irq handler start + * over again. + */ + if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) + return true; + + status = ps2port->buffer[ps2port->act].str; + data = ps2port->buffer[ps2port->act].data; + + ps2port->act = (ps2port->act + 1) & BUFFER_SIZE; + rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | + ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); + + serio_interrupt(ps2port->port, data, rxflags); + } + + return false; +} + /** * gscps2_interrupt() - Interruption service routine + * @irq: interrupt number which triggered (unused) + * @dev: device pointer (unused) * * This function reads received PS/2 bytes and processes them on * all interfaces. @@ -229,47 +268,18 @@ static irqreturn_t gscps2_interrupt(int irq, void *dev) struct gscps2port *ps2port; list_for_each_entry(ps2port, &ps2port_list, node) { + guard(spinlock_irqsave)(&ps2port->lock); - unsigned long flags; - spin_lock_irqsave(&ps2port->lock, flags); - - while ( (ps2port->buffer[ps2port->append].str = - gscps2_readb_status(ps2port->addr)) & GSC_STAT_RBNE ) { - ps2port->buffer[ps2port->append].data = - gscps2_readb_input(ps2port->addr); - ps2port->append = ((ps2port->append+1) & BUFFER_SIZE); - } - - spin_unlock_irqrestore(&ps2port->lock, flags); - + gscps2_read_data(ps2port); } /* list_for_each_entry */ /* all data was read from the ports - now report the data to upper layer */ - list_for_each_entry(ps2port, &ps2port_list, node) { - - while (ps2port->act != ps2port->append) { - - unsigned int rxflags; - u8 data, status; - - /* Did new data arrived while we read existing data ? - If yes, exit now and let the new irq handler start over again */ - if (gscps2_readb_status(ps2port->addr) & GSC_STAT_CMPINTR) - return IRQ_HANDLED; - - status = ps2port->buffer[ps2port->act].str; - data = ps2port->buffer[ps2port->act].data; - - ps2port->act = ((ps2port->act+1) & BUFFER_SIZE); - rxflags = ((status & GSC_STAT_TERR) ? SERIO_TIMEOUT : 0 ) | - ((status & GSC_STAT_PERR) ? SERIO_PARITY : 0 ); - - serio_interrupt(ps2port->port, data, rxflags); - - } /* while() */ - - } /* list_for_each_entry */ + if (gscps2_report_data(ps2port)) { + /* More data ready - break early to restart interrupt */ + break; + } + } return IRQ_HANDLED; } @@ -321,6 +331,8 @@ static void gscps2_close(struct serio *port) /** * gscps2_probe() - Probes PS2 devices + * @dev: pointer to parisc_device struct which will be probed + * * @return: success/error report */ @@ -338,8 +350,8 @@ static int __init gscps2_probe(struct parisc_device *dev) if (dev->id.sversion == 0x96) hpa += GSC_DINO_OFFSET; - ps2port = kzalloc(sizeof(struct gscps2port), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2port = kzalloc(sizeof(*ps2port), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2port || !serio) { ret = -ENOMEM; goto fail_nomem; @@ -412,6 +424,8 @@ fail_nomem: /** * gscps2_remove() - Removes PS2 devices + * @dev: pointer to parisc_device which shall be removed + * * @return: success/error report */ diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index d36e89d6fc54..94e8bcbbf94d 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -1017,7 +1017,7 @@ static int __init hil_mlc_init(void) static void __exit hil_mlc_exit(void) { - del_timer_sync(&hil_mlcs_kicker); + timer_delete_sync(&hil_mlcs_kicker); tasklet_kill(&hil_mlcs_tasklet); } diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 13eacf6ab431..0eec4c5585cb 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c @@ -980,7 +980,7 @@ static void hp_sdc_exit(void) free_irq(hp_sdc.irq, &hp_sdc); write_unlock_irq(&hp_sdc.lock); - del_timer_sync(&hp_sdc.kicker); + timer_delete_sync(&hp_sdc.kicker); tasklet_kill(&hp_sdc.task); diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index 31def6ce5157..0ee7505427ac 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -102,7 +102,6 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev, { struct hv_kbd_dev *kbd_dev = hv_get_drvdata(hv_dev); struct synth_kbd_keystroke *ks_msg; - unsigned long flags; u32 msg_type = __le32_to_cpu(msg->header.type); u32 info; u16 scan_code; @@ -147,21 +146,22 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev, /* * Inject the information through the serio interrupt. */ - spin_lock_irqsave(&kbd_dev->lock, flags); - if (kbd_dev->started) { - if (info & IS_E0) - serio_interrupt(kbd_dev->hv_serio, - XTKBD_EMUL0, 0); - if (info & IS_E1) - serio_interrupt(kbd_dev->hv_serio, - XTKBD_EMUL1, 0); - scan_code = __le16_to_cpu(ks_msg->make_code); - if (info & IS_BREAK) - scan_code |= XTKBD_RELEASE; + scoped_guard(spinlock_irqsave, &kbd_dev->lock) { + if (kbd_dev->started) { + if (info & IS_E0) + serio_interrupt(kbd_dev->hv_serio, + XTKBD_EMUL0, 0); + if (info & IS_E1) + serio_interrupt(kbd_dev->hv_serio, + XTKBD_EMUL1, 0); + scan_code = __le16_to_cpu(ks_msg->make_code); + if (info & IS_BREAK) + scan_code |= XTKBD_RELEASE; - serio_interrupt(kbd_dev->hv_serio, scan_code, 0); + serio_interrupt(kbd_dev->hv_serio, + scan_code, 0); + } } - spin_unlock_irqrestore(&kbd_dev->lock, flags); /* * Only trigger a wakeup on key down, otherwise @@ -292,11 +292,10 @@ static int hv_kbd_connect_to_vsp(struct hv_device *hv_dev) static int hv_kbd_start(struct serio *serio) { struct hv_kbd_dev *kbd_dev = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&kbd_dev->lock, flags); + guard(spinlock_irqsave)(&kbd_dev->lock); + kbd_dev->started = true; - spin_unlock_irqrestore(&kbd_dev->lock, flags); return 0; } @@ -304,11 +303,10 @@ static int hv_kbd_start(struct serio *serio) static void hv_kbd_stop(struct serio *serio) { struct hv_kbd_dev *kbd_dev = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&kbd_dev->lock, flags); + guard(spinlock_irqsave)(&kbd_dev->lock); + kbd_dev->started = false; - spin_unlock_irqrestore(&kbd_dev->lock, flags); } static int hv_kbd_probe(struct hv_device *hv_dev, @@ -318,8 +316,8 @@ static int hv_kbd_probe(struct hv_device *hv_dev, struct serio *hv_serio; int error; - kbd_dev = kzalloc(sizeof(struct hv_kbd_dev), GFP_KERNEL); - hv_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + kbd_dev = kzalloc(sizeof(*kbd_dev), GFP_KERNEL); + hv_serio = kzalloc(sizeof(*hv_serio), GFP_KERNEL); if (!kbd_dev || !hv_serio) { error = -ENOMEM; goto err_free_mem; diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h index dfc6c581873b..6ed9fc34948c 100644 --- a/drivers/input/serio/i8042-acpipnpio.h +++ b/drivers/input/serio/i8042-acpipnpio.h @@ -76,20 +76,21 @@ static inline void i8042_write_command(int val) #define SERIO_QUIRK_PROBE_DEFER BIT(5) #define SERIO_QUIRK_RESET_ALWAYS BIT(6) #define SERIO_QUIRK_RESET_NEVER BIT(7) -#define SERIO_QUIRK_DIECT BIT(8) +#define SERIO_QUIRK_DIRECT BIT(8) #define SERIO_QUIRK_DUMBKBD BIT(9) #define SERIO_QUIRK_NOLOOP BIT(10) #define SERIO_QUIRK_NOTIMEOUT BIT(11) #define SERIO_QUIRK_KBDRESET BIT(12) #define SERIO_QUIRK_DRITEK BIT(13) #define SERIO_QUIRK_NOPNP BIT(14) +#define SERIO_QUIRK_FORCENORESTORE BIT(15) /* Quirk table for different mainboards. Options similar or identical to i8042 * module parameters. * ORDERING IS IMPORTANT! The first match will be apllied and the rest ignored. * This allows entries to overwrite vendor wide quirks on a per device basis. * Where this is irrelevant, entries are sorted case sensitive by DMI_SYS_VENDOR - * and/or DMI_BOARD_VENDOR to make it easier to avoid dublicate entries. + * and/or DMI_BOARD_VENDOR to make it easier to avoid duplicate entries. */ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { { @@ -627,6 +628,15 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOMUX) }, { + /* Fujitsu Lifebook E756 */ + /* https://bugzilla.suse.com/show_bug.cgi?id=1229056 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E756"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX) + }, + { /* Fujitsu Lifebook E5411 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU CLIENT COMPUTING LIMITED"), @@ -1070,16 +1080,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), DMI_MATCH(DMI_BOARD_NAME, "AURA1501"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"), DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* Mivvy M310 */ @@ -1111,10 +1119,45 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .driver_data = (void *)(SERIO_QUIRK_NOLOOP) }, /* + * Some TongFang barebones have touchpad and/or keyboard issues after + * suspend fixable with nomux + reset + noloop + nopnp. Luckily, none of + * them have an external PS/2 port so this can safely be set for all of + * them. + * TongFang barebones come with board_vendor and/or system_vendor set to + * a different value for each individual reseller. The only somewhat + * universal way to identify them is by board_name. + */ + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"), + }, + .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | + SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + }, + /* * A lot of modern Clevo barebones have touchpad and/or keyboard issues - * after suspend fixable with nomux + reset + noloop + nopnp. Luckily, - * none of them have an external PS/2 port so this can safely be set for - * all of them. + * after suspend fixable with the forcenorestore quirk. * Clevo barebones come with board_vendor and/or system_vendor set to * either the very generic string "Notebook" and/or a different value * for each individual reseller. The only somewhat universal way to @@ -1124,71 +1167,49 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "LAPQC71A"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "LAPQC71B"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "N140CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "N141CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { - /* - * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes - * the keyboard very laggy for ~5 seconds after boot and - * sometimes also after resume. - * However both are required for the keyboard to not fail - * completely sometimes after boot or resume. - */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "N150CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { - /* - * Setting SERIO_QUIRK_NOMUX or SERIO_QUIRK_RESET_ALWAYS makes - * the keyboard very laggy for ~5 seconds after boot and - * sometimes also after resume. - * However both are required for the keyboard to not fail - * completely sometimes after boot or resume. - */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "NHxxRZQ"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, /* * At least one modern Clevo barebone has the touchpad connected both @@ -1204,17 +1225,15 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NS50MU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | - SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | - SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_NOAUX | + SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NS50_70MU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX | - SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP | - SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_NOAUX | + SERIO_QUIRK_FORCENORESTORE) }, { .matches = { @@ -1226,8 +1245,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "P640RE"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1238,16 +1262,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65xH"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1258,8 +1280,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_P67H"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1270,8 +1291,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1282,8 +1302,7 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P65_67RS"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { /* @@ -1294,22 +1313,43 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "P67xRP"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "PB50_70DFx,DDx"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PB51RF"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PB71RD"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PC70DR"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "PCX0DX_GN20"), + }, + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, /* See comment on TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU above */ { @@ -1322,15 +1362,27 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170SM"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) }, { .matches = { DMI_MATCH(DMI_BOARD_NAME, "X170KM-G"), }, - .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | - SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) + .driver_data = (void *)(SERIO_QUIRK_FORCENORESTORE) + }, + { + /* + * The Ayaneo Kun is a handheld device where some the buttons + * are handled by an AT keyboard. The keyboard is usually + * detected as raw, but sometimes, usually after a cold boot, + * it is detected as translated. Make sure that the keyboard + * is always in raw mode. + */ + .matches = { + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AYANEO"), + DMI_MATCH(DMI_BOARD_NAME, "KUN"), + }, + .driver_data = (void *)(SERIO_QUIRK_DIRECT) }, { } }; @@ -1655,7 +1707,7 @@ static void __init i8042_check_quirks(void) if (quirks & SERIO_QUIRK_RESET_NEVER) i8042_reset = I8042_RESET_NEVER; } - if (quirks & SERIO_QUIRK_DIECT) + if (quirks & SERIO_QUIRK_DIRECT) i8042_direct = true; if (quirks & SERIO_QUIRK_DUMBKBD) i8042_dumbkbd = true; @@ -1671,6 +1723,8 @@ static void __init i8042_check_quirks(void) if (quirks & SERIO_QUIRK_NOPNP) i8042_nopnp = true; #endif + if (quirks & SERIO_QUIRK_FORCENORESTORE) + i8042_forcenorestore = true; } #else static inline void i8042_check_quirks(void) {} @@ -1704,7 +1758,7 @@ static int __init i8042_platform_init(void) i8042_check_quirks(); - pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + pr_debug("Active quirks (empty means none):%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", i8042_nokbd ? " nokbd" : "", i8042_noaux ? " noaux" : "", i8042_nomux ? " nomux" : "", @@ -1724,10 +1778,11 @@ static int __init i8042_platform_init(void) "", #endif #ifdef CONFIG_PNP - i8042_nopnp ? " nopnp" : ""); + i8042_nopnp ? " nopnp" : "", #else - ""); + "", #endif + i8042_forcenorestore ? " forcenorestore" : ""); retval = i8042_pnp_init(); if (retval) diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 64590b86eb37..a8f4b2d70e59 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -15,10 +15,7 @@ * IRQs. */ -#ifdef __alpha__ -# define I8042_KBD_IRQ 1 -# define I8042_AUX_IRQ (RTC_PORT(0) == 0x170 ? 9 : 12) /* Jensen is special */ -#elif defined(__arm__) +#if defined(__arm__) /* defined in include/asm-arm/arch-xxx/irqs.h */ #include <asm/irq.h> #elif defined(CONFIG_PPC) diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index c2fda54dc384..0f97158fd14e 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -101,23 +101,15 @@ static struct platform_driver sparc_i8042_driver = { .of_match_table = sparc_i8042_match, }, .probe = sparc_i8042_probe, - .remove_new = sparc_i8042_remove, + .remove = sparc_i8042_remove, }; static bool i8042_is_mr_coffee(void) { - struct device_node *root; - const char *name; - bool is_mr_coffee; + struct device_node *root __free(device_node) = of_find_node_by_path("/"); + const char *name = of_get_property(root, "name", NULL); - root = of_find_node_by_path("/"); - - name = of_get_property(root, "name", NULL); - is_mr_coffee = name && !strcmp(name, "SUNW,JavaStation-1"); - - of_node_put(root); - - return is_mr_coffee; + return name && !strcmp(name, "SUNW,JavaStation-1"); } static int __init i8042_platform_init(void) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 9fbb8d31575a..cab5a4c5baf5 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -115,6 +115,10 @@ module_param_named(nopnp, i8042_nopnp, bool, 0); MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings"); #endif +static bool i8042_forcenorestore; +module_param_named(forcenorestore, i8042_forcenorestore, bool, 0); +MODULE_PARM_DESC(forcenorestore, "Force no restore on s3 resume, copying s2idle behaviour"); + #define DEBUG #ifdef DEBUG static bool i8042_debug; @@ -174,9 +178,9 @@ static unsigned char i8042_suppress_kbd_ack; static struct platform_device *i8042_platform_device; static struct notifier_block i8042_kbd_bind_notifier_block; -static irqreturn_t i8042_interrupt(int irq, void *dev_id); -static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, - struct serio *serio); +static bool i8042_handle_data(int irq); +static i8042_filter_t i8042_platform_filter; +static void *i8042_platform_filter_context; void i8042_lock_chip(void) { @@ -190,45 +194,29 @@ void i8042_unlock_chip(void) } EXPORT_SYMBOL(i8042_unlock_chip); -int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, - struct serio *serio)) +int i8042_install_filter(i8042_filter_t filter, void *context) { - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&i8042_lock, flags); + guard(spinlock_irqsave)(&i8042_lock); - if (i8042_platform_filter) { - ret = -EBUSY; - goto out; - } + if (i8042_platform_filter) + return -EBUSY; i8042_platform_filter = filter; - -out: - spin_unlock_irqrestore(&i8042_lock, flags); - return ret; + i8042_platform_filter_context = context; + return 0; } EXPORT_SYMBOL(i8042_install_filter); -int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, - struct serio *port)) +int i8042_remove_filter(i8042_filter_t filter) { - unsigned long flags; - int ret = 0; + guard(spinlock_irqsave)(&i8042_lock); - spin_lock_irqsave(&i8042_lock, flags); - - if (i8042_platform_filter != filter) { - ret = -EINVAL; - goto out; - } + if (i8042_platform_filter != filter) + return -EINVAL; i8042_platform_filter = NULL; - -out: - spin_unlock_irqrestore(&i8042_lock, flags); - return ret; + i8042_platform_filter_context = NULL; + return 0; } EXPORT_SYMBOL(i8042_remove_filter); @@ -267,28 +255,22 @@ static int i8042_wait_write(void) static int i8042_flush(void) { - unsigned long flags; unsigned char data, str; int count = 0; - int retval = 0; - spin_lock_irqsave(&i8042_lock, flags); + guard(spinlock_irqsave)(&i8042_lock); while ((str = i8042_read_status()) & I8042_STR_OBF) { - if (count++ < I8042_BUFFER_SIZE) { - udelay(50); - data = i8042_read_data(); - dbg("%02x <- i8042 (flush, %s)\n", - data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); - } else { - retval = -EIO; - break; - } - } + if (count++ >= I8042_BUFFER_SIZE) + return -EIO; - spin_unlock_irqrestore(&i8042_lock, flags); + udelay(50); + data = i8042_read_data(); + dbg("%02x <- i8042 (flush, %s)\n", + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); + } - return retval; + return 0; } /* @@ -345,17 +327,12 @@ static int __i8042_command(unsigned char *param, int command) int i8042_command(unsigned char *param, int command) { - unsigned long flags; - int retval; - if (!i8042_present) return -1; - spin_lock_irqsave(&i8042_lock, flags); - retval = __i8042_command(param, command); - spin_unlock_irqrestore(&i8042_lock, flags); + guard(spinlock_irqsave)(&i8042_lock); - return retval; + return __i8042_command(param, command); } EXPORT_SYMBOL(i8042_command); @@ -365,19 +342,18 @@ EXPORT_SYMBOL(i8042_command); static int i8042_kbd_write(struct serio *port, unsigned char c) { - unsigned long flags; - int retval = 0; + int error; - spin_lock_irqsave(&i8042_lock, flags); + guard(spinlock_irqsave)(&i8042_lock); - if (!(retval = i8042_wait_write())) { - dbg("%02x -> i8042 (kbd-data)\n", c); - i8042_write_data(c); - } + error = i8042_wait_write(); + if (error) + return error; - spin_unlock_irqrestore(&i8042_lock, flags); + dbg("%02x -> i8042 (kbd-data)\n", c); + i8042_write_data(c); - return retval; + return 0; } /* @@ -430,7 +406,7 @@ static void i8042_port_close(struct serio *serio) * See if there is any data appeared while we were messing with * port state. */ - i8042_interrupt(0, NULL); + i8042_handle_data(0); } /* @@ -456,9 +432,8 @@ static int i8042_start(struct serio *serio) device_set_wakeup_enable(&serio->dev, true); } - spin_lock_irq(&i8042_lock); + guard(spinlock_irq)(&i8042_lock); port->exists = true; - spin_unlock_irq(&i8042_lock); return 0; } @@ -472,10 +447,10 @@ static void i8042_stop(struct serio *serio) { struct i8042_port *port = serio->port_data; - spin_lock_irq(&i8042_lock); - port->exists = false; - port->serio = NULL; - spin_unlock_irq(&i8042_lock); + scoped_guard(spinlock_irq, &i8042_lock) { + port->exists = false; + port->serio = NULL; + } /* * We need to make sure that interrupt handler finishes using @@ -505,7 +480,10 @@ static bool i8042_filter(unsigned char data, unsigned char str, } } - if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { + if (!i8042_platform_filter) + return false; + + if (i8042_platform_filter(data, str, serio, i8042_platform_filter_context)) { dbg("Filtered out by platform filter\n"); return true; } @@ -514,44 +492,10 @@ static bool i8042_filter(unsigned char data, unsigned char str, } /* - * i8042_interrupt() is the most important function in this driver - - * it handles the interrupts from the i8042, and sends incoming bytes - * to the upper layers. - */ - -static irqreturn_t i8042_interrupt(int irq, void *dev_id) -{ - struct i8042_port *port; - struct serio *serio; - unsigned long flags; - unsigned char str, data; - unsigned int dfl; - unsigned int port_no; - bool filtered; - int ret = 1; - - spin_lock_irqsave(&i8042_lock, flags); - - str = i8042_read_status(); - if (unlikely(~str & I8042_STR_OBF)) { - spin_unlock_irqrestore(&i8042_lock, flags); - if (irq) - dbg("Interrupt %d, without any data\n", irq); - ret = 0; - goto out; - } - - data = i8042_read_data(); - - if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { - static unsigned long last_transmit; - static unsigned char last_str; - - dfl = 0; - if (str & I8042_STR_MUXERR) { - dbg("MUX error, status is %02x, data is %02x\n", - str, data); -/* + * i8042_handle_mux() handles case when data is coming from one of + * the multiplexed ports. It would be simple if not for quirks with + * handling errors: + * * When MUXERR condition is signalled the data register can only contain * 0xfd, 0xfe or 0xff if implementation follows the spec. Unfortunately * it is not always the case. Some KBCs also report 0xfc when there is @@ -563,50 +507,106 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) * rest assume that the data came from the same serio last byte * was transmitted (if transmission happened not too long ago). */ - - switch (data) { - default: - if (time_before(jiffies, last_transmit + HZ/10)) { - str = last_str; - break; - } - fallthrough; /* report timeout */ - case 0xfc: - case 0xfd: - case 0xfe: dfl = SERIO_TIMEOUT; data = 0xfe; break; - case 0xff: dfl = SERIO_PARITY; data = 0xfe; break; +static int i8042_handle_mux(u8 str, u8 *data, unsigned int *dfl) +{ + static unsigned long last_transmit; + static unsigned long last_port; + unsigned int mux_port; + + mux_port = (str >> 6) & 3; + *dfl = 0; + + if (str & I8042_STR_MUXERR) { + dbg("MUX error, status is %02x, data is %02x\n", + str, *data); + + switch (*data) { + default: + if (time_before(jiffies, last_transmit + HZ/10)) { + mux_port = last_port; + break; } + fallthrough; /* report timeout */ + case 0xfc: + case 0xfd: + case 0xfe: + *dfl = SERIO_TIMEOUT; + *data = 0xfe; + break; + case 0xff: + *dfl = SERIO_PARITY; + *data = 0xfe; + break; } + } - port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3); - last_str = str; - last_transmit = jiffies; - } else { + last_port = mux_port; + last_transmit = jiffies; - dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) | - ((str & I8042_STR_TIMEOUT && !i8042_notimeout) ? SERIO_TIMEOUT : 0); + return I8042_MUX_PORT_NO + mux_port; +} - port_no = (str & I8042_STR_AUXDATA) ? - I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; - } +/* + * i8042_handle_data() is the most important function in this driver - + * it reads the data from the i8042, determines its destination serio + * port, and sends received byte to the upper layers. + * + * Returns true if there was data waiting, false otherwise. + */ +static bool i8042_handle_data(int irq) +{ + struct i8042_port *port; + struct serio *serio; + unsigned char str, data; + unsigned int dfl; + unsigned int port_no; + bool filtered; + + scoped_guard(spinlock_irqsave, &i8042_lock) { + str = i8042_read_status(); + if (unlikely(~str & I8042_STR_OBF)) + return false; - port = &i8042_ports[port_no]; - serio = port->exists ? port->serio : NULL; + data = i8042_read_data(); - filter_dbg(port->driver_bound, data, "<- i8042 (interrupt, %d, %d%s%s)\n", - port_no, irq, - dfl & SERIO_PARITY ? ", bad parity" : "", - dfl & SERIO_TIMEOUT ? ", timeout" : ""); + if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { + port_no = i8042_handle_mux(str, &data, &dfl); + } else { - filtered = i8042_filter(data, str, serio); + dfl = (str & I8042_STR_PARITY) ? SERIO_PARITY : 0; + if ((str & I8042_STR_TIMEOUT) && !i8042_notimeout) + dfl |= SERIO_TIMEOUT; - spin_unlock_irqrestore(&i8042_lock, flags); + port_no = (str & I8042_STR_AUXDATA) ? + I8042_AUX_PORT_NO : I8042_KBD_PORT_NO; + } + + port = &i8042_ports[port_no]; + serio = port->exists ? port->serio : NULL; + + filter_dbg(port->driver_bound, + data, "<- i8042 (interrupt, %d, %d%s%s)\n", + port_no, irq, + dfl & SERIO_PARITY ? ", bad parity" : "", + dfl & SERIO_TIMEOUT ? ", timeout" : ""); + + filtered = i8042_filter(data, str, serio); + } if (likely(serio && !filtered)) serio_interrupt(serio, data, dfl); - out: - return IRQ_RETVAL(ret); + return true; +} + +static irqreturn_t i8042_interrupt(int irq, void *dev_id) +{ + if (unlikely(!i8042_handle_data(irq))) { + dbg("Interrupt %d, without any data\n", irq); + return IRQ_NONE; + } + + return IRQ_HANDLED; } /* @@ -749,24 +749,22 @@ static bool i8042_irq_being_tested; static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id) { - unsigned long flags; unsigned char str, data; - int ret = 0; - spin_lock_irqsave(&i8042_lock, flags); + guard(spinlock_irqsave)(&i8042_lock); + str = i8042_read_status(); - if (str & I8042_STR_OBF) { - data = i8042_read_data(); - dbg("%02x <- i8042 (aux_test_irq, %s)\n", - data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); - if (i8042_irq_being_tested && - data == 0xa5 && (str & I8042_STR_AUXDATA)) - complete(&i8042_aux_irq_delivered); - ret = 1; - } - spin_unlock_irqrestore(&i8042_lock, flags); + if (!(str & I8042_STR_OBF)) + return IRQ_NONE; + + data = i8042_read_data(); + dbg("%02x <- i8042 (aux_test_irq, %s)\n", + data, str & I8042_STR_AUXDATA ? "aux" : "kbd"); + + if (i8042_irq_being_tested && data == 0xa5 && (str & I8042_STR_AUXDATA)) + complete(&i8042_aux_irq_delivered); - return IRQ_RETVAL(ret); + return IRQ_HANDLED; } /* @@ -807,7 +805,6 @@ static int i8042_check_aux(void) int retval = -1; bool irq_registered = false; bool aux_loop_broken = false; - unsigned long flags; unsigned char param; /* @@ -891,18 +888,15 @@ static int i8042_check_aux(void) if (i8042_enable_aux_port()) goto out; - spin_lock_irqsave(&i8042_lock, flags); - - init_completion(&i8042_aux_irq_delivered); - i8042_irq_being_tested = true; + scoped_guard(spinlock_irqsave, &i8042_lock) { + init_completion(&i8042_aux_irq_delivered); + i8042_irq_being_tested = true; - param = 0xa5; - retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); - - spin_unlock_irqrestore(&i8042_lock, flags); - - if (retval) - goto out; + param = 0xa5; + retval = __i8042_command(¶m, I8042_CMD_AUX_LOOP & 0xf0ff); + if (retval) + goto out; + } if (wait_for_completion_timeout(&i8042_aux_irq_delivered, msecs_to_jiffies(250)) == 0) { @@ -990,7 +984,6 @@ static int i8042_controller_selftest(void) static int i8042_controller_init(void) { - unsigned long flags; int n = 0; unsigned char ctr[2]; @@ -1027,14 +1020,14 @@ static int i8042_controller_init(void) * Handle keylock. */ - spin_lock_irqsave(&i8042_lock, flags); - if (~i8042_read_status() & I8042_STR_KEYLOCK) { - if (i8042_unlock) - i8042_ctr |= I8042_CTR_IGNKEYLOCK; - else - pr_warn("Warning: Keylock active\n"); + scoped_guard(spinlock_irqsave, &i8042_lock) { + if (~i8042_read_status() & I8042_STR_KEYLOCK) { + if (i8042_unlock) + i8042_ctr |= I8042_CTR_IGNKEYLOCK; + else + pr_warn("Warning: Keylock active\n"); + } } - spin_unlock_irqrestore(&i8042_lock, flags); /* * If the chip is configured into nontranslated mode by the BIOS, don't @@ -1212,13 +1205,14 @@ static int i8042_controller_resume(bool s2r_wants_reset) if (i8042_mux_present) { if (i8042_set_mux_mode(true, NULL) || i8042_enable_mux_ports()) pr_warn("failed to resume active multiplexor, mouse won't work\n"); - } else if (i8042_ports[I8042_AUX_PORT_NO].serio) + } else if (i8042_ports[I8042_AUX_PORT_NO].serio) { i8042_enable_aux_port(); + } if (i8042_ports[I8042_KBD_PORT_NO].serio) i8042_enable_kbd_port(); - i8042_interrupt(0, NULL); + i8042_handle_data(0); return 0; } @@ -1232,7 +1226,7 @@ static int i8042_pm_suspend(struct device *dev) { int i; - if (pm_suspend_via_firmware()) + if (!i8042_forcenorestore && pm_suspend_via_firmware()) i8042_controller_reset(true); /* Set up serio interrupts for system wakeup. */ @@ -1248,8 +1242,8 @@ static int i8042_pm_suspend(struct device *dev) static int i8042_pm_resume_noirq(struct device *dev) { - if (!pm_resume_via_firmware()) - i8042_interrupt(0, NULL); + if (i8042_forcenorestore || !pm_resume_via_firmware()) + i8042_handle_data(0); return 0; } @@ -1271,7 +1265,7 @@ static int i8042_pm_resume(struct device *dev) * not restore the controller state to whatever it had been at boot * time, so we do not need to do anything. */ - if (!pm_suspend_via_firmware()) + if (i8042_forcenorestore || !pm_suspend_via_firmware()) return 0; /* @@ -1286,7 +1280,7 @@ static int i8042_pm_resume(struct device *dev) static int i8042_pm_thaw(struct device *dev) { - i8042_interrupt(0, NULL); + i8042_handle_data(0); return 0; } @@ -1329,7 +1323,7 @@ static int i8042_create_kbd_port(void) struct serio *serio; struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO]; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -1359,7 +1353,7 @@ static int i8042_create_aux_port(int idx) int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx; struct i8042_port *port = &i8042_ports[port_no]; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -1599,7 +1593,7 @@ static struct platform_driver i8042_driver = { #endif }, .probe = i8042_probe, - .remove_new = i8042_remove, + .remove = i8042_remove, .shutdown = i8042_shutdown, }; diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c index 50552dc7b4f5..d2c7ffb9a946 100644 --- a/drivers/input/serio/ioc3kbd.c +++ b/drivers/input/serio/ioc3kbd.c @@ -200,9 +200,16 @@ static void ioc3kbd_remove(struct platform_device *pdev) serio_unregister_port(d->aux); } +static const struct platform_device_id ioc3kbd_id_table[] = { + { "ioc3-kbd", }, + { } +}; +MODULE_DEVICE_TABLE(platform, ioc3kbd_id_table); + static struct platform_driver ioc3kbd_driver = { .probe = ioc3kbd_probe, - .remove_new = ioc3kbd_remove, + .remove = ioc3kbd_remove, + .id_table = ioc3kbd_id_table, .driver = { .name = "ioc3-kbd", }, diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 6d78a1fe00c1..c22ea532276e 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -108,13 +108,11 @@ int ps2_sendbyte(struct ps2dev *ps2dev, u8 byte, unsigned int timeout) { int retval; - serio_pause_rx(ps2dev->serio); + guard(serio_pause_rx)(ps2dev->serio); retval = ps2_do_sendbyte(ps2dev, byte, timeout, 1); dev_dbg(&ps2dev->serio->dev, "%02x - %x\n", byte, ps2dev->nak); - serio_continue_rx(ps2dev->serio); - return retval; } EXPORT_SYMBOL(ps2_sendbyte); @@ -162,10 +160,10 @@ void ps2_drain(struct ps2dev *ps2dev, size_t maxbytes, unsigned int timeout) ps2_begin_command(ps2dev); - serio_pause_rx(ps2dev->serio); - ps2dev->flags = PS2_FLAG_CMD; - ps2dev->cmdcnt = maxbytes; - serio_continue_rx(ps2dev->serio); + scoped_guard(serio_pause_rx, ps2dev->serio) { + ps2dev->flags = PS2_FLAG_CMD; + ps2dev->cmdcnt = maxbytes; + } wait_event_timeout(ps2dev->wait, !(ps2dev->flags & PS2_FLAG_CMD), @@ -224,9 +222,9 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, * use alternative probe to detect it. */ if (ps2dev->cmdbuf[1] == 0xaa) { - serio_pause_rx(ps2dev->serio); - ps2dev->flags = 0; - serio_continue_rx(ps2dev->serio); + scoped_guard(serio_pause_rx, ps2dev->serio) + ps2dev->flags = 0; + timeout = 0; } @@ -235,9 +233,9 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, * won't be 2nd byte of ID response. */ if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { - serio_pause_rx(ps2dev->serio); - ps2dev->flags = ps2dev->cmdcnt = 0; - serio_continue_rx(ps2dev->serio); + scoped_guard(serio_pause_rx, ps2dev->serio) + ps2dev->flags = ps2dev->cmdcnt = 0; + timeout = 0; } break; @@ -283,6 +281,10 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command) memcpy(send_param, param, send); + /* + * Not using guard notation because we need to break critical + * section below while waiting for the response. + */ serio_pause_rx(ps2dev->serio); ps2dev->cmdcnt = receive; diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c index 5ccfb82759b3..3d28a5cddd61 100644 --- a/drivers/input/serio/maceps2.c +++ b/drivers/input/serio/maceps2.c @@ -117,7 +117,7 @@ static struct serio *maceps2_allocate_port(int idx) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (serio) { serio->id.type = SERIO_8042; serio->write = maceps2_write; @@ -159,7 +159,7 @@ static struct platform_driver maceps2_driver = { .name = "maceps2", }, .probe = maceps2_probe, - .remove_new = maceps2_remove, + .remove = maceps2_remove, }; static int __init maceps2_init(void) diff --git a/drivers/input/serio/olpc_apsp.c b/drivers/input/serio/olpc_apsp.c index 240a714f7081..a24324830021 100644 --- a/drivers/input/serio/olpc_apsp.c +++ b/drivers/input/serio/olpc_apsp.c @@ -188,7 +188,7 @@ static int olpc_apsp_probe(struct platform_device *pdev) return priv->irq; /* KEYBOARD */ - kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + kb_serio = kzalloc(sizeof(*kb_serio), GFP_KERNEL); if (!kb_serio) return -ENOMEM; kb_serio->id.type = SERIO_8042_XL; @@ -203,7 +203,7 @@ static int olpc_apsp_probe(struct platform_device *pdev) serio_register_port(kb_serio); /* TOUCHPAD */ - pad_serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + pad_serio = kzalloc(sizeof(*pad_serio), GFP_KERNEL); if (!pad_serio) { error = -ENOMEM; goto err_pad; @@ -256,7 +256,7 @@ MODULE_DEVICE_TABLE(of, olpc_apsp_dt_ids); static struct platform_driver olpc_apsp_driver = { .probe = olpc_apsp_probe, - .remove_new = olpc_apsp_remove, + .remove = olpc_apsp_remove, .driver = { .name = "olpc-apsp", .of_match_table = olpc_apsp_dt_ids, diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index 0d54895428f5..22fe55490572 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c @@ -165,7 +165,7 @@ static struct serio *parkbd_allocate_serio(void) { struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (serio) { serio->id.type = parkbd_mode; serio->write = parkbd_write; @@ -218,6 +218,5 @@ static struct parport_driver parkbd_parport_driver = { .name = "parkbd", .match_port = parkbd_attach, .detach = parkbd_detach, - .devmodel = true, }; module_parport_driver(parkbd_parport_driver); diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 05878750f2c2..6b9abb2e18c9 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -137,8 +137,8 @@ static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id) if (ret) goto disable; - ps2if = kzalloc(sizeof(struct pcips2_data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2if = kzalloc(sizeof(*ps2if), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2if || !serio) { ret = -ENOMEM; goto release; diff --git a/drivers/input/serio/ps2-gpio.c b/drivers/input/serio/ps2-gpio.c index c3ff60859a03..93769910ce24 100644 --- a/drivers/input/serio/ps2-gpio.c +++ b/drivers/input/serio/ps2-gpio.c @@ -133,12 +133,12 @@ static int ps2_gpio_write(struct serio *serio, unsigned char val) int ret = 0; if (in_task()) { - mutex_lock(&drvdata->tx.mutex); + guard(mutex)(&drvdata->tx.mutex); + __ps2_gpio_write(serio, val); if (!wait_for_completion_timeout(&drvdata->tx.complete, msecs_to_jiffies(10000))) ret = SERIO_TIMEOUT; - mutex_unlock(&drvdata->tx.mutex); } else { __ps2_gpio_write(serio, val); } @@ -404,8 +404,8 @@ static int ps2_gpio_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int error; - drvdata = devm_kzalloc(dev, sizeof(struct ps2_gpio_data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto err_free_serio; @@ -429,16 +429,14 @@ static int ps2_gpio_probe(struct platform_device *pdev) } error = devm_request_irq(dev, drvdata->irq, ps2_gpio_irq, - IRQF_NO_THREAD, DRIVER_NAME, drvdata); + IRQF_NO_THREAD | IRQF_NO_AUTOEN, DRIVER_NAME, + drvdata); if (error) { dev_err(dev, "failed to request irq %d: %d\n", drvdata->irq, error); goto err_free_serio; } - /* Keep irq disabled until serio->open is called. */ - disable_irq(drvdata->irq); - serio->id.type = SERIO_8042; serio->open = ps2_gpio_open; serio->close = ps2_gpio_close; @@ -493,7 +491,7 @@ MODULE_DEVICE_TABLE(of, ps2_gpio_match); static struct platform_driver ps2_gpio_driver = { .probe = ps2_gpio_probe, - .remove_new = ps2_gpio_remove, + .remove = ps2_gpio_remove, .driver = { .name = DRIVER_NAME, .of_match_table = of_match_ptr(ps2_gpio_match), diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c index 902e81826fbf..b96cee52fc52 100644 --- a/drivers/input/serio/ps2mult.c +++ b/drivers/input/serio/ps2mult.c @@ -76,9 +76,8 @@ static int ps2mult_serio_write(struct serio *serio, unsigned char data) struct ps2mult *psm = serio_get_drvdata(mx_port); struct ps2mult_port *port = serio->port_data; bool need_escape; - unsigned long flags; - spin_lock_irqsave(&psm->lock, flags); + guard(spinlock_irqsave)(&psm->lock); if (psm->out_port != port) ps2mult_select_port(psm, port); @@ -93,8 +92,6 @@ static int ps2mult_serio_write(struct serio *serio, unsigned char data) serio_write(mx_port, data); - spin_unlock_irqrestore(&psm->lock, flags); - return 0; } @@ -102,11 +99,10 @@ static int ps2mult_serio_start(struct serio *serio) { struct ps2mult *psm = serio_get_drvdata(serio->parent); struct ps2mult_port *port = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&psm->lock, flags); + guard(spinlock_irqsave)(&psm->lock); + port->registered = true; - spin_unlock_irqrestore(&psm->lock, flags); return 0; } @@ -115,11 +111,10 @@ static void ps2mult_serio_stop(struct serio *serio) { struct ps2mult *psm = serio_get_drvdata(serio->parent); struct ps2mult_port *port = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&psm->lock, flags); + guard(spinlock_irqsave)(&psm->lock); + port->registered = false; - spin_unlock_irqrestore(&psm->lock, flags); } static int ps2mult_create_port(struct ps2mult *psm, int i) @@ -127,7 +122,7 @@ static int ps2mult_create_port(struct ps2mult *psm, int i) struct serio *mx_serio = psm->mx_serio; struct serio *serio; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -148,16 +143,12 @@ static int ps2mult_create_port(struct ps2mult *psm, int i) static void ps2mult_reset(struct ps2mult *psm) { - unsigned long flags; - - spin_lock_irqsave(&psm->lock, flags); + guard(spinlock_irqsave)(&psm->lock); serio_write(psm->mx_serio, PS2MULT_SESSION_END); serio_write(psm->mx_serio, PS2MULT_SESSION_START); ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]); - - spin_unlock_irqrestore(&psm->lock, flags); } static int ps2mult_connect(struct serio *serio, struct serio_driver *drv) @@ -234,11 +225,10 @@ static irqreturn_t ps2mult_interrupt(struct serio *serio, { struct ps2mult *psm = serio_get_drvdata(serio); struct ps2mult_port *in_port; - unsigned long flags; dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl); - spin_lock_irqsave(&psm->lock, flags); + guard(spinlock_irqsave)(&psm->lock); if (psm->escape) { psm->escape = false; @@ -285,7 +275,6 @@ static irqreturn_t ps2mult_interrupt(struct serio *serio, } out: - spin_unlock_irqrestore(&psm->lock, flags); return IRQ_HANDLED; } diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 3f81f8749cd5..ae55c4de092f 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -39,17 +39,14 @@ struct q40kbd { static irqreturn_t q40kbd_interrupt(int irq, void *dev_id) { struct q40kbd *q40kbd = dev_id; - unsigned long flags; - spin_lock_irqsave(&q40kbd->lock, flags); + guard(spinlock_irqsave)(&q40kbd->lock); if (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG)) serio_interrupt(q40kbd->port, master_inb(KEYCODE_REG), 0); master_outb(-1, KEYBOARD_UNLOCK_REG); - spin_unlock_irqrestore(&q40kbd->lock, flags); - return IRQ_HANDLED; } @@ -60,14 +57,11 @@ static irqreturn_t q40kbd_interrupt(int irq, void *dev_id) static void q40kbd_flush(struct q40kbd *q40kbd) { int maxread = 100; - unsigned long flags; - spin_lock_irqsave(&q40kbd->lock, flags); + guard(spinlock_irqsave)(&q40kbd->lock); while (maxread-- && (Q40_IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))) master_inb(KEYCODE_REG); - - spin_unlock_irqrestore(&q40kbd->lock, flags); } static void q40kbd_stop(void) @@ -108,8 +102,8 @@ static int q40kbd_probe(struct platform_device *pdev) struct serio *port; int error; - q40kbd = kzalloc(sizeof(struct q40kbd), GFP_KERNEL); - port = kzalloc(sizeof(struct serio), GFP_KERNEL); + q40kbd = kzalloc(sizeof(*q40kbd), GFP_KERNEL); + port = kzalloc(sizeof(*port), GFP_KERNEL); if (!q40kbd || !port) { error = -ENOMEM; goto err_free_mem; @@ -166,7 +160,7 @@ static struct platform_driver q40kbd_driver = { .driver = { .name = "q40kbd", }, - .remove_new = q40kbd_remove, + .remove = q40kbd_remove, }; module_platform_driver_probe(q40kbd_driver, q40kbd_probe); diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 9bbfefd092c0..c65c552b0c45 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -108,7 +108,7 @@ static int rpckbd_probe(struct platform_device *dev) if (tx_irq < 0) return tx_irq; - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); rpckbd = kzalloc(sizeof(*rpckbd), GFP_KERNEL); if (!serio || !rpckbd) { kfree(rpckbd); @@ -144,7 +144,7 @@ static void rpckbd_remove(struct platform_device *dev) static struct platform_driver rpckbd_driver = { .probe = rpckbd_probe, - .remove_new = rpckbd_remove, + .remove = rpckbd_remove, .driver = { .name = "kart", }, diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 2724c3aa512c..375c6f5f905c 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -92,7 +92,8 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) struct ps2if *ps2if = dev_id; unsigned int status; - spin_lock(&ps2if->lock); + guard(spinlock)(&ps2if->lock); + status = readl_relaxed(ps2if->base + PS2STAT); if (ps2if->head == ps2if->tail) { disable_irq_nosync(irq); @@ -101,7 +102,6 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) writel_relaxed(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA); ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); } - spin_unlock(&ps2if->lock); return IRQ_HANDLED; } @@ -113,10 +113,9 @@ static irqreturn_t ps2_txint(int irq, void *dev_id) static int ps2_write(struct serio *io, unsigned char val) { struct ps2if *ps2if = io->port_data; - unsigned long flags; unsigned int head; - spin_lock_irqsave(&ps2if->lock, flags); + guard(spinlock_irqsave)(&ps2if->lock); /* * If the TX register is empty, we can go straight out. @@ -133,7 +132,6 @@ static int ps2_write(struct serio *io, unsigned char val) } } - spin_unlock_irqrestore(&ps2if->lock, flags); return 0; } @@ -256,8 +254,8 @@ static int ps2_probe(struct sa1111_dev *dev) struct serio *serio; int ret; - ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + ps2if = kzalloc(sizeof(*ps2if), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!ps2if || !serio) { ret = -ENOMEM; goto free; diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index a8838b522627..4468018cef66 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -38,33 +38,27 @@ static void serio_attach_driver(struct serio_driver *drv); static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) { - int retval; - - mutex_lock(&serio->drv_mutex); - retval = drv->connect(serio, drv); - mutex_unlock(&serio->drv_mutex); + guard(mutex)(&serio->drv_mutex); - return retval; + return drv->connect(serio, drv); } static int serio_reconnect_driver(struct serio *serio) { - int retval = -1; + guard(mutex)(&serio->drv_mutex); - mutex_lock(&serio->drv_mutex); if (serio->drv && serio->drv->reconnect) - retval = serio->drv->reconnect(serio); - mutex_unlock(&serio->drv_mutex); + return serio->drv->reconnect(serio); - return retval; + return -1; } static void serio_disconnect_driver(struct serio *serio) { - mutex_lock(&serio->drv_mutex); + guard(mutex)(&serio->drv_mutex); + if (serio->drv) serio->drv->disconnect(serio); - mutex_unlock(&serio->drv_mutex); } static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) @@ -147,9 +141,8 @@ static LIST_HEAD(serio_event_list); static struct serio_event *serio_get_event(void) { struct serio_event *event = NULL; - unsigned long flags; - spin_lock_irqsave(&serio_event_lock, flags); + guard(spinlock_irqsave)(&serio_event_lock); if (!list_empty(&serio_event_list)) { event = list_first_entry(&serio_event_list, @@ -157,7 +150,6 @@ static struct serio_event *serio_get_event(void) list_del_init(&event->node); } - spin_unlock_irqrestore(&serio_event_lock, flags); return event; } @@ -171,9 +163,8 @@ static void serio_remove_duplicate_events(void *object, enum serio_event_type type) { struct serio_event *e, *next; - unsigned long flags; - spin_lock_irqsave(&serio_event_lock, flags); + guard(spinlock_irqsave)(&serio_event_lock); list_for_each_entry_safe(e, next, &serio_event_list, node) { if (object == e->object) { @@ -189,15 +180,13 @@ static void serio_remove_duplicate_events(void *object, serio_free_event(e); } } - - spin_unlock_irqrestore(&serio_event_lock, flags); } static void serio_handle_event(struct work_struct *work) { struct serio_event *event; - mutex_lock(&serio_mutex); + guard(mutex)(&serio_mutex); while ((event = serio_get_event())) { @@ -228,8 +217,6 @@ static void serio_handle_event(struct work_struct *work) serio_remove_duplicate_events(event->object, event->type); serio_free_event(event); } - - mutex_unlock(&serio_mutex); } static DECLARE_WORK(serio_event_work, serio_handle_event); @@ -237,11 +224,9 @@ static DECLARE_WORK(serio_event_work, serio_handle_event); static int serio_queue_event(void *object, struct module *owner, enum serio_event_type event_type) { - unsigned long flags; struct serio_event *event; - int retval = 0; - spin_lock_irqsave(&serio_event_lock, flags); + guard(spinlock_irqsave)(&serio_event_lock); /* * Scan event list for the other events for the same serio port, @@ -253,24 +238,22 @@ static int serio_queue_event(void *object, struct module *owner, list_for_each_entry_reverse(event, &serio_event_list, node) { if (event->object == object) { if (event->type == event_type) - goto out; + return 0; break; } } - event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); + event = kmalloc(sizeof(*event), GFP_ATOMIC); if (!event) { pr_err("Not enough memory to queue event %d\n", event_type); - retval = -ENOMEM; - goto out; + return -ENOMEM; } if (!try_module_get(owner)) { pr_warn("Can't get module reference, dropping event %d\n", event_type); kfree(event); - retval = -EINVAL; - goto out; + return -EINVAL; } event->type = event_type; @@ -280,9 +263,7 @@ static int serio_queue_event(void *object, struct module *owner, list_add_tail(&event->node, &serio_event_list); queue_work(system_long_wq, &serio_event_work); -out: - spin_unlock_irqrestore(&serio_event_lock, flags); - return retval; + return 0; } /* @@ -292,9 +273,8 @@ out: static void serio_remove_pending_events(void *object) { struct serio_event *event, *next; - unsigned long flags; - spin_lock_irqsave(&serio_event_lock, flags); + guard(spinlock_irqsave)(&serio_event_lock); list_for_each_entry_safe(event, next, &serio_event_list, node) { if (event->object == object) { @@ -302,8 +282,6 @@ static void serio_remove_pending_events(void *object) serio_free_event(event); } } - - spin_unlock_irqrestore(&serio_event_lock, flags); } /* @@ -315,23 +293,19 @@ static void serio_remove_pending_events(void *object) static struct serio *serio_get_pending_child(struct serio *parent) { struct serio_event *event; - struct serio *serio, *child = NULL; - unsigned long flags; + struct serio *serio; - spin_lock_irqsave(&serio_event_lock, flags); + guard(spinlock_irqsave)(&serio_event_lock); list_for_each_entry(event, &serio_event_list, node) { if (event->type == SERIO_REGISTER_PORT) { serio = event->object; - if (serio->parent == parent) { - child = serio; - break; - } + if (serio->parent == parent) + return serio; } } - spin_unlock_irqrestore(&serio_event_lock, flags); - return child; + return NULL; } /* @@ -382,29 +356,27 @@ static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, c struct device_driver *drv; int error; - error = mutex_lock_interruptible(&serio_mutex); - if (error) - return error; - - if (!strncmp(buf, "none", count)) { - serio_disconnect_port(serio); - } else if (!strncmp(buf, "reconnect", count)) { - serio_reconnect_subtree(serio); - } else if (!strncmp(buf, "rescan", count)) { - serio_disconnect_port(serio); - serio_find_driver(serio); - serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); - } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { - serio_disconnect_port(serio); - error = serio_bind_driver(serio, to_serio_driver(drv)); - serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); - } else { - error = -EINVAL; + scoped_cond_guard(mutex_intr, return -EINTR, &serio_mutex) { + if (!strncmp(buf, "none", count)) { + serio_disconnect_port(serio); + } else if (!strncmp(buf, "reconnect", count)) { + serio_reconnect_subtree(serio); + } else if (!strncmp(buf, "rescan", count)) { + serio_disconnect_port(serio); + serio_find_driver(serio); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); + } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { + serio_disconnect_port(serio); + error = serio_bind_driver(serio, to_serio_driver(drv)); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); + if (error) + return error; + } else { + return -EINVAL; + } } - mutex_unlock(&serio_mutex); - - return error ? error : count; + return count; } static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf) @@ -526,9 +498,9 @@ static void serio_add_port(struct serio *serio) int error; if (parent) { - serio_pause_rx(parent); + guard(serio_pause_rx)(parent); + list_add_tail(&serio->child_node, &parent->children); - serio_continue_rx(parent); } list_add_tail(&serio->node, &serio_list); @@ -560,9 +532,9 @@ static void serio_destroy_port(struct serio *serio) serio->stop(serio); if (serio->parent) { - serio_pause_rx(serio->parent); + guard(serio_pause_rx)(serio->parent); + list_del_init(&serio->child_node); - serio_continue_rx(serio->parent); serio->parent = NULL; } @@ -701,10 +673,10 @@ EXPORT_SYMBOL(__serio_register_port); */ void serio_unregister_port(struct serio *serio) { - mutex_lock(&serio_mutex); + guard(mutex)(&serio_mutex); + serio_disconnect_port(serio); serio_destroy_port(serio); - mutex_unlock(&serio_mutex); } EXPORT_SYMBOL(serio_unregister_port); @@ -715,12 +687,12 @@ void serio_unregister_child_port(struct serio *serio) { struct serio *s, *next; - mutex_lock(&serio_mutex); + guard(mutex)(&serio_mutex); + list_for_each_entry_safe(s, next, &serio->children, child_node) { serio_disconnect_port(s); serio_destroy_port(s); } - mutex_unlock(&serio_mutex); } EXPORT_SYMBOL(serio_unregister_child_port); @@ -784,10 +756,10 @@ static void serio_driver_remove(struct device *dev) static void serio_cleanup(struct serio *serio) { - mutex_lock(&serio->drv_mutex); + guard(mutex)(&serio->drv_mutex); + if (serio->drv && serio->drv->cleanup) serio->drv->cleanup(serio); - mutex_unlock(&serio->drv_mutex); } static void serio_shutdown(struct device *dev) @@ -850,7 +822,7 @@ void serio_unregister_driver(struct serio_driver *drv) { struct serio *serio; - mutex_lock(&serio_mutex); + guard(mutex)(&serio_mutex); drv->manual_bind = true; /* so serio_find_driver ignores it */ serio_remove_pending_events(drv); @@ -866,21 +838,20 @@ start_over: } driver_unregister(&drv->driver); - mutex_unlock(&serio_mutex); } EXPORT_SYMBOL(serio_unregister_driver); static void serio_set_drv(struct serio *serio, struct serio_driver *drv) { - serio_pause_rx(serio); + guard(serio_pause_rx)(serio); + serio->drv = drv; - serio_continue_rx(serio); } -static int serio_bus_match(struct device *dev, struct device_driver *drv) +static int serio_bus_match(struct device *dev, const struct device_driver *drv) { struct serio *serio = to_serio_port(dev); - struct serio_driver *serio_drv = to_serio_driver(drv); + const struct serio_driver *serio_drv = to_serio_driver(drv); if (serio->manual_bind || serio_drv->manual_bind) return 0; @@ -935,14 +906,14 @@ static int serio_resume(struct device *dev) struct serio *serio = to_serio_port(dev); int error = -ENOENT; - mutex_lock(&serio->drv_mutex); - if (serio->drv && serio->drv->fast_reconnect) { - error = serio->drv->fast_reconnect(serio); - if (error && error != -ENOENT) - dev_warn(dev, "fast reconnect failed with error %d\n", - error); + scoped_guard(mutex, &serio->drv_mutex) { + if (serio->drv && serio->drv->fast_reconnect) { + error = serio->drv->fast_reconnect(serio); + if (error && error != -ENOENT) + dev_warn(dev, "fast reconnect failed with error %d\n", + error); + } } - mutex_unlock(&serio->drv_mutex); if (error) { /* @@ -989,21 +960,17 @@ EXPORT_SYMBOL(serio_close); irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int dfl) { - unsigned long flags; - irqreturn_t ret = IRQ_NONE; + guard(spinlock_irqsave)(&serio->lock); - spin_lock_irqsave(&serio->lock, flags); + if (likely(serio->drv)) + return serio->drv->interrupt(serio, data, dfl); - if (likely(serio->drv)) { - ret = serio->drv->interrupt(serio, data, dfl); - } else if (!dfl && device_is_registered(&serio->dev)) { + if (!dfl && device_is_registered(&serio->dev)) { serio_rescan(serio); - ret = IRQ_HANDLED; + return IRQ_HANDLED; } - spin_unlock_irqrestore(&serio->lock, flags); - - return ret; + return IRQ_NONE; } EXPORT_SYMBOL(serio_interrupt); diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 1e4770094415..4d6395088986 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -29,7 +29,7 @@ struct serio_raw { unsigned char queue[SERIO_RAW_QUEUE_LEN]; unsigned int tail, head; - char name[16]; + char name[20]; struct kref kref; struct serio *serio; struct miscdevice dev; @@ -75,41 +75,31 @@ static int serio_raw_open(struct inode *inode, struct file *file) { struct serio_raw *serio_raw; struct serio_raw_client *client; - int retval; - retval = mutex_lock_interruptible(&serio_raw_mutex); - if (retval) - return retval; + scoped_guard(mutex_intr, &serio_raw_mutex) { + serio_raw = serio_raw_locate(iminor(inode)); + if (!serio_raw) + return -ENODEV; - serio_raw = serio_raw_locate(iminor(inode)); - if (!serio_raw) { - retval = -ENODEV; - goto out; - } + if (serio_raw->dead) + return -ENODEV; - if (serio_raw->dead) { - retval = -ENODEV; - goto out; - } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return -ENOMEM; - client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL); - if (!client) { - retval = -ENOMEM; - goto out; - } + client->serio_raw = serio_raw; + file->private_data = client; - client->serio_raw = serio_raw; - file->private_data = client; + kref_get(&serio_raw->kref); - kref_get(&serio_raw->kref); + scoped_guard(serio_pause_rx, serio_raw->serio) + list_add_tail(&client->node, &serio_raw->client_list); - serio_pause_rx(serio_raw->serio); - list_add_tail(&client->node, &serio_raw->client_list); - serio_continue_rx(serio_raw->serio); + return 0; + } -out: - mutex_unlock(&serio_raw_mutex); - return retval; + return -EINTR; } static void serio_raw_free(struct kref *kref) @@ -126,9 +116,8 @@ static int serio_raw_release(struct inode *inode, struct file *file) struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; - serio_pause_rx(serio_raw->serio); - list_del(&client->node); - serio_continue_rx(serio_raw->serio); + scoped_guard(serio_pause_rx, serio_raw->serio) + list_del(&client->node); kfree(client); @@ -139,19 +128,15 @@ static int serio_raw_release(struct inode *inode, struct file *file) static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) { - bool empty; + guard(serio_pause_rx)(serio_raw->serio); - serio_pause_rx(serio_raw->serio); - - empty = serio_raw->head == serio_raw->tail; - if (!empty) { - *c = serio_raw->queue[serio_raw->tail]; - serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; - } + if (serio_raw->head == serio_raw->tail) + return false; /* queue is empty */ - serio_continue_rx(serio_raw->serio); + *c = serio_raw->queue[serio_raw->tail]; + serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; - return !empty; + return true; } static ssize_t serio_raw_read(struct file *file, char __user *buffer, @@ -200,40 +185,32 @@ static ssize_t serio_raw_write(struct file *file, const char __user *buffer, { struct serio_raw_client *client = file->private_data; struct serio_raw *serio_raw = client->serio_raw; - int retval = 0; + int written = 0; unsigned char c; - retval = mutex_lock_interruptible(&serio_raw_mutex); - if (retval) - return retval; + scoped_guard(mutex_intr, &serio_raw_mutex) { + if (serio_raw->dead) + return -ENODEV; - if (serio_raw->dead) { - retval = -ENODEV; - goto out; - } + if (count > 32) + count = 32; - if (count > 32) - count = 32; + while (count--) { + if (get_user(c, buffer++)) + return -EFAULT; - while (count--) { - if (get_user(c, buffer++)) { - retval = -EFAULT; - goto out; - } + if (serio_write(serio_raw->serio, c)) { + /* Either signal error or partial write */ + return written ?: -EIO; + } - if (serio_write(serio_raw->serio, c)) { - /* Either signal error or partial write */ - if (retval == 0) - retval = -EIO; - goto out; + written++; } - retval++; + return written; } -out: - mutex_unlock(&serio_raw_mutex); - return retval; + return -EINTR; } static __poll_t serio_raw_poll(struct file *file, poll_table *wait) @@ -293,14 +270,14 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) struct serio_raw *serio_raw; int err; - serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL); + serio_raw = kzalloc(sizeof(*serio_raw), GFP_KERNEL); if (!serio_raw) { dev_dbg(&serio->dev, "can't allocate memory for a device\n"); return -ENOMEM; } snprintf(serio_raw->name, sizeof(serio_raw->name), - "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no)); + "serio_raw%u", atomic_inc_return(&serio_raw_no)); kref_init(&serio_raw->kref); INIT_LIST_HEAD(&serio_raw->client_list); init_waitqueue_head(&serio_raw->wait); @@ -379,10 +356,10 @@ static void serio_raw_hangup(struct serio_raw *serio_raw) { struct serio_raw_client *client; - serio_pause_rx(serio_raw->serio); - list_for_each_entry(client, &serio_raw->client_list, node) - kill_fasync(&client->fasync, SIGIO, POLL_HUP); - serio_continue_rx(serio_raw->serio); + scoped_guard(serio_pause_rx, serio_raw->serio) { + list_for_each_entry(client, &serio_raw->client_list, node) + kill_fasync(&client->fasync, SIGIO, POLL_HUP); + } wake_up_interruptible(&serio_raw->wait); } @@ -394,10 +371,10 @@ static void serio_raw_disconnect(struct serio *serio) misc_deregister(&serio_raw->dev); - mutex_lock(&serio_raw_mutex); - serio_raw->dead = true; - list_del_init(&serio_raw->node); - mutex_unlock(&serio_raw_mutex); + scoped_guard(mutex, &serio_raw_mutex) { + serio_raw->dead = true; + list_del_init(&serio_raw->node); + } serio_raw_hangup(serio_raw); diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 1db3f30011c4..74ac88796187 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -50,11 +50,9 @@ static int serport_serio_write(struct serio *serio, unsigned char data) static int serport_serio_open(struct serio *serio) { struct serport *serport = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&serport->lock, flags); + guard(spinlock_irqsave)(&serport->lock); set_bit(SERPORT_ACTIVE, &serport->flags); - spin_unlock_irqrestore(&serport->lock, flags); return 0; } @@ -63,11 +61,9 @@ static int serport_serio_open(struct serio *serio) static void serport_serio_close(struct serio *serio) { struct serport *serport = serio->port_data; - unsigned long flags; - spin_lock_irqsave(&serport->lock, flags); + guard(spinlock_irqsave)(&serport->lock); clear_bit(SERPORT_ACTIVE, &serport->flags); - spin_unlock_irqrestore(&serport->lock, flags); } /* @@ -82,7 +78,7 @@ static int serport_ldisc_open(struct tty_struct *tty) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - serport = kzalloc(sizeof(struct serport), GFP_KERNEL); + serport = kzalloc(sizeof(*serport), GFP_KERNEL); if (!serport) return -ENOMEM; @@ -118,14 +114,13 @@ static void serport_ldisc_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, size_t count) { struct serport *serport = tty->disc_data; - unsigned long flags; unsigned int ch_flags = 0; int i; - spin_lock_irqsave(&serport->lock, flags); + guard(spinlock_irqsave)(&serport->lock); if (!test_bit(SERPORT_ACTIVE, &serport->flags)) - goto out; + return; for (i = 0; i < count; i++) { if (fp) { @@ -146,9 +141,6 @@ static void serport_ldisc_receive(struct tty_struct *tty, const u8 *cp, serio_interrupt(serport->serio, cp[i], ch_flags); } - -out: - spin_unlock_irqrestore(&serport->lock, flags); } /* @@ -167,7 +159,7 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, if (test_and_set_bit(SERPORT_BUSY, &serport->flags)) return -EBUSY; - serport->serio = serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + serport->serio = serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!serio) return -ENOMEM; @@ -246,11 +238,9 @@ static int serport_ldisc_compat_ioctl(struct tty_struct *tty, static void serport_ldisc_hangup(struct tty_struct *tty) { struct serport *serport = tty->disc_data; - unsigned long flags; - spin_lock_irqsave(&serport->lock, flags); - set_bit(SERPORT_DEAD, &serport->flags); - spin_unlock_irqrestore(&serport->lock, flags); + scoped_guard(spinlock_irqsave, &serport->lock) + set_bit(SERPORT_DEAD, &serport->flags); wake_up_interruptible(&serport->wait); } @@ -258,12 +248,11 @@ static void serport_ldisc_hangup(struct tty_struct *tty) static void serport_ldisc_write_wakeup(struct tty_struct * tty) { struct serport *serport = tty->disc_data; - unsigned long flags; - spin_lock_irqsave(&serport->lock, flags); + guard(spinlock_irqsave)(&serport->lock); + if (test_bit(SERPORT_ACTIVE, &serport->flags)) serio_drv_write_wakeup(serport->serio); - spin_unlock_irqrestore(&serport->lock, flags); } /* diff --git a/drivers/input/serio/sun4i-ps2.c b/drivers/input/serio/sun4i-ps2.c index aec66d9f5176..524929ce1cae 100644 --- a/drivers/input/serio/sun4i-ps2.c +++ b/drivers/input/serio/sun4i-ps2.c @@ -101,7 +101,7 @@ static irqreturn_t sun4i_ps2_interrupt(int irq, void *dev_id) unsigned int rxflags = 0; u32 rval; - spin_lock(&drvdata->lock); + guard(spinlock)(&drvdata->lock); /* Get the PS/2 interrupts and clear them */ intr_status = readl(drvdata->reg_base + PS2_REG_LSTS); @@ -134,8 +134,6 @@ static irqreturn_t sun4i_ps2_interrupt(int irq, void *dev_id) writel(intr_status, drvdata->reg_base + PS2_REG_LSTS); writel(fifo_status, drvdata->reg_base + PS2_REG_FSTS); - spin_unlock(&drvdata->lock); - return IRQ_HANDLED; } @@ -146,7 +144,6 @@ static int sun4i_ps2_open(struct serio *serio) u32 clk_scdf; u32 clk_pcdf; u32 rval; - unsigned long flags; /* Set line control and enable interrupt */ rval = PS2_LCTL_STOPERREN | PS2_LCTL_ACKERREN @@ -171,9 +168,8 @@ static int sun4i_ps2_open(struct serio *serio) rval = PS2_GCTL_RESET | PS2_GCTL_INTEN | PS2_GCTL_MASTER | PS2_GCTL_BUSEN; - spin_lock_irqsave(&drvdata->lock, flags); + guard(spinlock_irqsave)(&drvdata->lock); writel(rval, drvdata->reg_base + PS2_REG_GCTL); - spin_unlock_irqrestore(&drvdata->lock, flags); return 0; } @@ -213,8 +209,8 @@ static int sun4i_ps2_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int error; - drvdata = kzalloc(sizeof(struct sun4i_ps2data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto err_free_mem; @@ -322,7 +318,7 @@ MODULE_DEVICE_TABLE(of, sun4i_ps2_match); static struct platform_driver sun4i_ps2_driver = { .probe = sun4i_ps2_probe, - .remove_new = sun4i_ps2_remove, + .remove = sun4i_ps2_remove, .driver = { .name = DRIVER_NAME, .of_match_table = sun4i_ps2_match, diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c index 9ab5c45c3a9f..7f627b08055e 100644 --- a/drivers/input/serio/userio.c +++ b/drivers/input/serio/userio.c @@ -55,18 +55,15 @@ struct userio_device { static int userio_device_write(struct serio *id, unsigned char val) { struct userio_device *userio = id->port_data; - unsigned long flags; - spin_lock_irqsave(&userio->buf_lock, flags); + scoped_guard(spinlock_irqsave, &userio->buf_lock) { + userio->buf[userio->head] = val; + userio->head = (userio->head + 1) % USERIO_BUFSIZE; - userio->buf[userio->head] = val; - userio->head = (userio->head + 1) % USERIO_BUFSIZE; - - if (userio->head == userio->tail) - dev_warn(userio_misc.this_device, - "Buffer overflowed, userio client isn't keeping up"); - - spin_unlock_irqrestore(&userio->buf_lock, flags); + if (userio->head == userio->tail) + dev_warn(userio_misc.this_device, + "Buffer overflowed, userio client isn't keeping up"); + } wake_up_interruptible(&userio->waitq); @@ -75,9 +72,8 @@ static int userio_device_write(struct serio *id, unsigned char val) static int userio_char_open(struct inode *inode, struct file *file) { - struct userio_device *userio; - - userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL); + struct userio_device *userio __free(kfree) = + kzalloc(sizeof(*userio), GFP_KERNEL); if (!userio) return -ENOMEM; @@ -85,16 +81,14 @@ static int userio_char_open(struct inode *inode, struct file *file) spin_lock_init(&userio->buf_lock); init_waitqueue_head(&userio->waitq); - userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL); - if (!userio->serio) { - kfree(userio); + userio->serio = kzalloc(sizeof(*userio->serio), GFP_KERNEL); + if (!userio->serio) return -ENOMEM; - } userio->serio->write = userio_device_write; userio->serio->port_data = userio; - file->private_data = userio; + file->private_data = no_free_ptr(userio); return 0; } @@ -118,14 +112,32 @@ static int userio_char_release(struct inode *inode, struct file *file) return 0; } +static size_t userio_fetch_data(struct userio_device *userio, u8 *buf, + size_t count, size_t *copylen) +{ + size_t available, len; + + guard(spinlock_irqsave)(&userio->buf_lock); + + available = CIRC_CNT_TO_END(userio->head, userio->tail, + USERIO_BUFSIZE); + len = min(available, count); + if (len) { + memcpy(buf, &userio->buf[userio->tail], len); + userio->tail = (userio->tail + len) % USERIO_BUFSIZE; + } + + *copylen = len; + return available; +} + static ssize_t userio_char_read(struct file *file, char __user *user_buffer, size_t count, loff_t *ppos) { struct userio_device *userio = file->private_data; int error; - size_t nonwrap_len, copylen; - unsigned char buf[USERIO_BUFSIZE]; - unsigned long flags; + size_t available, copylen; + u8 buf[USERIO_BUFSIZE]; /* * By the time we get here, the data that was waiting might have @@ -135,21 +147,8 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer, * of course). */ for (;;) { - spin_lock_irqsave(&userio->buf_lock, flags); - - nonwrap_len = CIRC_CNT_TO_END(userio->head, - userio->tail, - USERIO_BUFSIZE); - copylen = min(nonwrap_len, count); - if (copylen) { - memcpy(buf, &userio->buf[userio->tail], copylen); - userio->tail = (userio->tail + copylen) % - USERIO_BUFSIZE; - } - - spin_unlock_irqrestore(&userio->buf_lock, flags); - - if (nonwrap_len) + available = userio_fetch_data(userio, buf, count, ©len); + if (available) break; /* buffer was/is empty */ @@ -176,40 +175,21 @@ static ssize_t userio_char_read(struct file *file, char __user *user_buffer, return copylen; } -static ssize_t userio_char_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static int userio_execute_cmd(struct userio_device *userio, + const struct userio_cmd *cmd) { - struct userio_device *userio = file->private_data; - struct userio_cmd cmd; - int error; - - if (count != sizeof(cmd)) { - dev_warn(userio_misc.this_device, "Invalid payload size\n"); - return -EINVAL; - } - - if (copy_from_user(&cmd, buffer, sizeof(cmd))) - return -EFAULT; - - error = mutex_lock_interruptible(&userio->mutex); - if (error) - return error; - - switch (cmd.type) { + switch (cmd->type) { case USERIO_CMD_REGISTER: if (!userio->serio->id.type) { dev_warn(userio_misc.this_device, "No port type given on /dev/userio\n"); - - error = -EINVAL; - goto out; + return -EINVAL; } if (userio->running) { dev_warn(userio_misc.this_device, "Begin command sent, but we're already running\n"); - error = -EBUSY; - goto out; + return -EBUSY; } userio->running = true; @@ -220,32 +200,51 @@ static ssize_t userio_char_write(struct file *file, const char __user *buffer, if (userio->running) { dev_warn(userio_misc.this_device, "Can't change port type on an already running userio instance\n"); - error = -EBUSY; - goto out; + return -EBUSY; } - userio->serio->id.type = cmd.data; + userio->serio->id.type = cmd->data; break; case USERIO_CMD_SEND_INTERRUPT: if (!userio->running) { dev_warn(userio_misc.this_device, "The device must be registered before sending interrupts\n"); - error = -ENODEV; - goto out; + return -ENODEV; } - serio_interrupt(userio->serio, cmd.data, 0); + serio_interrupt(userio->serio, cmd->data, 0); break; default: - error = -EOPNOTSUPP; - goto out; + return -EOPNOTSUPP; + } + + return 0; +} + +static ssize_t userio_char_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + struct userio_device *userio = file->private_data; + struct userio_cmd cmd; + int error; + + if (count != sizeof(cmd)) { + dev_warn(userio_misc.this_device, "Invalid payload size\n"); + return -EINVAL; + } + + if (copy_from_user(&cmd, buffer, sizeof(cmd))) + return -EFAULT; + + scoped_cond_guard(mutex_intr, return -EINTR, &userio->mutex) { + error = userio_execute_cmd(userio, &cmd); + if (error) + return error; } -out: - mutex_unlock(&userio->mutex); - return error ?: count; + return count; } static __poll_t userio_char_poll(struct file *file, poll_table *wait) @@ -267,7 +266,6 @@ static const struct file_operations userio_fops = { .read = userio_char_read, .write = userio_char_write, .poll = userio_char_poll, - .llseek = no_llseek, }; static struct miscdevice userio_misc = { diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index bb758346a33d..01433f0b48f1 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -155,22 +155,17 @@ static irqreturn_t xps2_interrupt(int irq, void *dev_id) static int sxps2_write(struct serio *pserio, unsigned char c) { struct xps2data *drvdata = pserio->port_data; - unsigned long flags; u32 sr; - int status = -1; - spin_lock_irqsave(&drvdata->lock, flags); + guard(spinlock_irqsave)(&drvdata->lock); /* If the PS/2 transmitter is empty send a byte of data */ sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET); - if (!(sr & XPS2_STATUS_TX_FULL)) { - out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c); - status = 0; - } + if (sr & XPS2_STATUS_TX_FULL) + return -EAGAIN; - spin_unlock_irqrestore(&drvdata->lock, flags); - - return status; + out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c); + return 0; } /** @@ -252,8 +247,8 @@ static int xps2_of_probe(struct platform_device *ofdev) return -ENODEV; } - drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); - serio = kzalloc(sizeof(struct serio), GFP_KERNEL); + drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); + serio = kzalloc(sizeof(*serio), GFP_KERNEL); if (!drvdata || !serio) { error = -ENOMEM; goto failed1; @@ -358,7 +353,7 @@ static struct platform_driver xps2_of_driver = { .of_match_table = xps2_of_match, }, .probe = xps2_of_probe, - .remove_new = xps2_of_remove, + .remove = xps2_of_remove, }; module_platform_driver(xps2_of_driver); diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 25bf8be6e711..96f23ae57d5a 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -176,8 +176,7 @@ int sparse_keymap_setup(struct input_dev *dev, for (e = keymap; e->type != KE_END; e++) map_size++; - map = devm_kmemdup(&dev->dev, keymap, map_size * sizeof(*map), - GFP_KERNEL); + map = devm_kmemdup_array(&dev->dev, keymap, map_size, sizeof(*keymap), GFP_KERNEL); if (!map) return -ENOMEM; diff --git a/drivers/input/tablet/acecad.c b/drivers/input/tablet/acecad.c index b20e5a1afbcc..0ac16f32b31f 100644 --- a/drivers/input/tablet/acecad.c +++ b/drivers/input/tablet/acecad.c @@ -129,7 +129,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_ pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); maxp = usb_maxpacket(dev, pipe); - acecad = kzalloc(sizeof(struct usb_acecad), GFP_KERNEL); + acecad = kzalloc(sizeof(*acecad), GFP_KERNEL); input_dev = input_allocate_device(); if (!acecad || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index baabc51547b8..2b3fbb0455d5 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c @@ -63,7 +63,7 @@ #include <linux/module.h> #include <linux/usb/input.h> #include <linux/uaccess.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* * Aiptek status packet: @@ -1673,7 +1673,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id) */ speeds[0] = programmableDelay; - aiptek = kzalloc(sizeof(struct aiptek), GFP_KERNEL); + aiptek = kzalloc(sizeof(*aiptek), GFP_KERNEL); inputdev = input_allocate_device(); if (!aiptek || !inputdev) { dev_warn(&intf->dev, diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c index 9bc631518b92..42c1e5eaddd5 100644 --- a/drivers/input/tablet/hanwang.c +++ b/drivers/input/tablet/hanwang.c @@ -322,7 +322,7 @@ static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id if (intf->cur_altsetting->desc.bNumEndpoints < 1) return -ENODEV; - hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL); + hanwang = kzalloc(sizeof(*hanwang), GFP_KERNEL); input_dev = input_allocate_device(); if (!hanwang || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/tablet/kbtab.c b/drivers/input/tablet/kbtab.c index aa577898e952..794caa102909 100644 --- a/drivers/input/tablet/kbtab.c +++ b/drivers/input/tablet/kbtab.c @@ -3,7 +3,7 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/usb/input.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* * Pressure-threshold modules param code from Alex Perry <alex.perry@ieee.org> @@ -121,7 +121,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; - kbtab = kzalloc(sizeof(struct kbtab), GFP_KERNEL); + kbtab = kzalloc(sizeof(*kbtab), GFP_KERNEL); input_dev = input_allocate_device(); if (!kbtab || !input_dev) goto fail1; diff --git a/drivers/input/tablet/pegasus_notetaker.c b/drivers/input/tablet/pegasus_notetaker.c index a68da2988f9c..8d6b71d59793 100644 --- a/drivers/input/tablet/pegasus_notetaker.c +++ b/drivers/input/tablet/pegasus_notetaker.c @@ -214,6 +214,28 @@ static void pegasus_init(struct work_struct *work) error); } +static int __pegasus_open(struct pegasus *pegasus) +{ + int error; + + guard(mutex)(&pegasus->pm_mutex); + + pegasus->irq->dev = pegasus->usbdev; + if (usb_submit_urb(pegasus->irq, GFP_KERNEL)) + return -EIO; + + error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE); + if (error) { + usb_kill_urb(pegasus->irq); + cancel_work_sync(&pegasus->init); + return error; + } + + pegasus->is_open = true; + + return 0; +} + static int pegasus_open(struct input_dev *dev) { struct pegasus *pegasus = input_get_drvdata(dev); @@ -223,39 +245,25 @@ static int pegasus_open(struct input_dev *dev) if (error) return error; - mutex_lock(&pegasus->pm_mutex); - pegasus->irq->dev = pegasus->usbdev; - if (usb_submit_urb(pegasus->irq, GFP_KERNEL)) { - error = -EIO; - goto err_autopm_put; + error = __pegasus_open(pegasus); + if (error) { + usb_autopm_put_interface(pegasus->intf); + return error; } - error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE); - if (error) - goto err_kill_urb; - - pegasus->is_open = true; - mutex_unlock(&pegasus->pm_mutex); return 0; - -err_kill_urb: - usb_kill_urb(pegasus->irq); - cancel_work_sync(&pegasus->init); -err_autopm_put: - mutex_unlock(&pegasus->pm_mutex); - usb_autopm_put_interface(pegasus->intf); - return error; } static void pegasus_close(struct input_dev *dev) { struct pegasus *pegasus = input_get_drvdata(dev); - mutex_lock(&pegasus->pm_mutex); - usb_kill_urb(pegasus->irq); - cancel_work_sync(&pegasus->init); - pegasus->is_open = false; - mutex_unlock(&pegasus->pm_mutex); + scoped_guard(mutex, &pegasus->pm_mutex) { + usb_kill_urb(pegasus->irq); + cancel_work_sync(&pegasus->init); + + pegasus->is_open = false; + } usb_autopm_put_interface(pegasus->intf); } @@ -411,10 +419,10 @@ static int pegasus_suspend(struct usb_interface *intf, pm_message_t message) { struct pegasus *pegasus = usb_get_intfdata(intf); - mutex_lock(&pegasus->pm_mutex); + guard(mutex)(&pegasus->pm_mutex); + usb_kill_urb(pegasus->irq); cancel_work_sync(&pegasus->init); - mutex_unlock(&pegasus->pm_mutex); return 0; } @@ -422,31 +430,33 @@ static int pegasus_suspend(struct usb_interface *intf, pm_message_t message) static int pegasus_resume(struct usb_interface *intf) { struct pegasus *pegasus = usb_get_intfdata(intf); - int retval = 0; - mutex_lock(&pegasus->pm_mutex); + guard(mutex)(&pegasus->pm_mutex); + if (pegasus->is_open && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0) - retval = -EIO; - mutex_unlock(&pegasus->pm_mutex); + return -EIO; - return retval; + return 0; } static int pegasus_reset_resume(struct usb_interface *intf) { struct pegasus *pegasus = usb_get_intfdata(intf); - int retval = 0; + int error; + + guard(mutex)(&pegasus->pm_mutex); - mutex_lock(&pegasus->pm_mutex); if (pegasus->is_open) { - retval = pegasus_set_mode(pegasus, PEN_MODE_XY, + error = pegasus_set_mode(pegasus, PEN_MODE_XY, NOTETAKER_LED_MOUSE); - if (!retval && usb_submit_urb(pegasus->irq, GFP_NOIO) < 0) - retval = -EIO; + if (error) + return error; + + if (usb_submit_urb(pegasus->irq, GFP_NOIO) < 0) + return -EIO; } - mutex_unlock(&pegasus->pm_mutex); - return retval; + return 0; } static const struct usb_device_id pegasus_ids[] = { diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c index 1cedb45ba497..cf7cea77dabc 100644 --- a/drivers/input/tablet/wacom_serial4.c +++ b/drivers/input/tablet/wacom_serial4.c @@ -521,7 +521,7 @@ static int wacom_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err = -ENOMEM; - wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); + wacom = kzalloc(sizeof(*wacom), GFP_KERNEL); input_dev = input_allocate_device(); if (!wacom || !input_dev) goto free_device; diff --git a/drivers/input/tests/input_test.c b/drivers/input/tests/input_test.c index 2fa5b725ae0a..e105ce71a920 100644 --- a/drivers/input/tests/input_test.c +++ b/drivers/input/tests/input_test.c @@ -31,7 +31,7 @@ static int input_test_init(struct kunit *test) ret = input_register_device(input_dev); if (ret) { input_free_device(input_dev); - KUNIT_ASSERT_FAILURE(test, "Register device failed: %d", ret); + KUNIT_FAIL_AND_ABORT(test, "Register device failed: %d", ret); } test->priv = input_dev; @@ -179,4 +179,5 @@ static struct kunit_suite input_test_suite = { kunit_test_suite(input_test_suite); MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>"); +MODULE_DESCRIPTION("KUnit test for the input core"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 81a3ea4b9a3d..0468ce2b216f 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -117,13 +117,14 @@ static int 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) + if (!pdev->dev.parent->of_node) return -ENODEV; - np = of_get_child_by_name(np, "touch"); + + struct device_node *np __free(device_node) = + of_get_child_by_name(pdev->dev.parent->of_node, "touch"); if (!np) { dev_err(&pdev->dev, "Can't find touch node\n"); return -EINVAL; @@ -141,13 +142,13 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, if (data) { ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); if (ret < 0) - goto err_put_node; + 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) - goto err_put_node; + return -EINVAL; } /* set prebias & prechg time of pen detect */ data = 0; @@ -158,18 +159,11 @@ static int pm860x_touch_dt_init(struct platform_device *pdev, if (data) { ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); if (ret < 0) - goto err_put_node; + return -EINVAL; } of_property_read_u32(np, "marvell,88pm860x-resistor-X", res_x); - of_node_put(np); - return 0; - -err_put_node: - of_node_put(np); - - return -EINVAL; } #else #define pm860x_touch_dt_init(x, y, z) (-1) diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index c821fe3ee794..91a2b584dab1 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -103,6 +103,19 @@ config TOUCHSCREEN_ADC To compile this driver as a module, choose M here: the module will be called resistive-adc-touch.ko. +config TOUCHSCREEN_APPLE_Z2 + tristate "Apple Z2 touchscreens" + default ARCH_APPLE + depends on SPI && (ARCH_APPLE || COMPILE_TEST) + help + Say Y here if you have an ARM Apple device with + a touchscreen or a touchbar. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called apple_z2. + config TOUCHSCREEN_AR1021_I2C tristate "Microchip AR1020/1021 i2c touchscreen" depends on I2C && OF @@ -254,36 +267,6 @@ config TOUCHSCREEN_CYTTSP_SPI To compile this driver as a module, choose M here: the module will be called cyttsp_spi. -config TOUCHSCREEN_CYTTSP4_CORE - tristate "Cypress TrueTouch Gen4 Touchscreen Driver" - help - Core driver for Cypress TrueTouch(tm) Standard Product - Generation4 touchscreen controllers. - - Say Y here if you have a Cypress Gen4 touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here. - -config TOUCHSCREEN_CYTTSP4_I2C - tristate "support I2C bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && I2C - help - Say Y here if the touchscreen is connected via I2C bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_i2c. - -config TOUCHSCREEN_CYTTSP4_SPI - tristate "support SPI bus connection" - depends on TOUCHSCREEN_CYTTSP4_CORE && SPI_MASTER - help - Say Y here if the touchscreen is connected via SPI bus. - - To compile this driver as a module, choose M here: the - module will be called cyttsp4_spi. - config TOUCHSCREEN_CYTTSP5 tristate "Cypress TrueTouch Gen5 Touchscreen Driver" depends on I2C @@ -450,6 +433,7 @@ config TOUCHSCREEN_GOODIX_BERLIN_SPI config TOUCHSCREEN_HIDEEP tristate "HiDeep Touch IC" depends on I2C + select REGMAP_I2C help Say Y here if you have a touchscreen using HiDeep. @@ -461,6 +445,7 @@ config TOUCHSCREEN_HIDEEP config TOUCHSCREEN_HYCON_HY46XX tristate "Hycon hy46xx touchscreen support" depends on I2C + select REGMAP_I2C help Say Y here if you have a touchscreen using Hycon hy46xx @@ -626,18 +611,6 @@ config TOUCHSCREEN_MAX11801 To compile this driver as a module, choose M here: the module will be called max11801_ts. -config TOUCHSCREEN_MCS5000 - tristate "MELFAS MCS-5000 touchscreen" - depends on I2C - help - Say Y here if you have the MELFAS MCS-5000 touchscreen controller - chip in your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called mcs5000_ts. - config TOUCHSCREEN_MMS114 tristate "MELFAS MMS114 touchscreen" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index a81cb5aa21a5..97a025c6a377 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADC) += resistive-adc-touch.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o +obj-$(CONFIG_TOUCHSCREEN_APPLE_Z2) += apple_z2.o obj-$(CONFIG_TOUCHSCREEN_AR1021_I2C) += ar1021_i2c.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o @@ -25,11 +26,8 @@ obj-$(CONFIG_TOUCHSCREEN_CHIPONE_ICN8505) += chipone_icn8505.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMA140) += cy8ctma140.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o cyttsp_i2c_common.o +obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_CORE) += cyttsp4_core.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_I2C) += cyttsp4_i2c.o cyttsp_i2c_common.o -obj-$(CONFIG_TOUCHSCREEN_CYTTSP4_SPI) += cyttsp4_spi.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP5) += cyttsp5.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o @@ -63,7 +61,6 @@ obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o obj-$(CONFIG_TOUCHSCREEN_MXS_LRADC) += mxs-lradc-ts.o obj-$(CONFIG_TOUCHSCREEN_MX25) += fsl-imx25-tcq.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o -obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MELFAS_MIP4) += melfas_mip4.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o obj-$(CONFIG_TOUCHSCREEN_MMS114) += mms114.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index a0598e9c7aff..8d8392ce7005 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -415,7 +415,7 @@ static void ad7877_disable(void *data) ts->disabled = true; disable_irq(ts->spi->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7877_ts_event_release(ts); } diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 5c094ab74698..e5b99312c3d9 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -42,8 +42,8 @@ static int ad7879_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ad7879_id[] = { - { "ad7879", 0 }, - { "ad7889", 0 }, + { "ad7879" }, + { "ad7889" }, { } }; MODULE_DEVICE_TABLE(i2c, ad7879_id); diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index e5d69bf2276e..f661e199b63c 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -273,7 +273,7 @@ static void __ad7879_disable(struct ad7879 *ts) AD7879_PM(AD7879_PM_SHUTDOWN); disable_irq(ts->irq); - if (del_timer_sync(&ts->timer)) + if (timer_delete_sync(&ts->timer)) ad7879_ts_event_release(ts); ad7879_write(ts, AD7879_REG_CTRL2, reg); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index d2bbb436a77d..67264c5b49cb 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -30,7 +30,7 @@ #include <linux/spi/ads7846.h> #include <linux/regulator/consumer.h> #include <linux/module.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* * This code has been heavily tested on a Nokia 770, and lightly @@ -138,6 +138,7 @@ struct ads7846 { void *filter_data; int (*get_pendown_state)(void); struct gpio_desc *gpio_pendown; + struct gpio_desc *gpio_hsync; void (*wait_for_sync)(void); }; @@ -330,7 +331,7 @@ struct ser_req { u8 ref_off; u16 scratch; struct spi_message msg; - struct spi_transfer xfer[6]; + struct spi_transfer xfer[8]; /* * DMA (thus cache coherency maintenance) requires the * transfer buffers to live in their own cache lines. @@ -404,9 +405,19 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) req->xfer[5].rx_buf = &req->scratch; req->xfer[5].len = 2; - CS_CHANGE(req->xfer[5]); spi_message_add_tail(&req->xfer[5], &req->msg); + /* clear the command register */ + req->scratch = 0; + req->xfer[6].tx_buf = &req->scratch; + req->xfer[6].len = 1; + spi_message_add_tail(&req->xfer[6], &req->msg); + + req->xfer[7].rx_buf = &req->scratch; + req->xfer[7].len = 2; + CS_CHANGE(req->xfer[7]); + spi_message_add_tail(&req->xfer[7], &req->msg); + mutex_lock(&ts->lock); ads7846_stop(ts); status = spi_sync(spi, &req->msg); @@ -634,10 +645,6 @@ ATTRIBUTE_GROUPS(ads784x); /*--------------------------------------------------------------------------*/ -static void null_wait_for_sync(void) -{ -} - static int ads7846_debounce_filter(void *ads, int data_idx, int *val) { struct ads7846 *ts = ads; @@ -790,6 +797,28 @@ static int ads7846_filter(struct ads7846 *ts) return 0; } +static void ads7846_wait_for_hsync(struct ads7846 *ts) +{ + if (ts->wait_for_sync) { + ts->wait_for_sync(); + return; + } + + if (!ts->gpio_hsync) + return; + + /* + * Wait for HSYNC to assert the line should be flagged + * as active low so here we are waiting for it to assert + */ + while (!gpiod_get_value(ts->gpio_hsync)) + cpu_relax(); + + /* Then we wait for it do de-assert */ + while (gpiod_get_value(ts->gpio_hsync)) + cpu_relax(); +} + static void ads7846_read_state(struct ads7846 *ts) { struct ads7846_packet *packet = ts->packet; @@ -800,12 +829,12 @@ static void ads7846_read_state(struct ads7846 *ts) packet->last_cmd_idx = 0; while (true) { - ts->wait_for_sync(); + ads7846_wait_for_hsync(ts); m = &ts->msg[msg_idx]; error = spi_sync(ts->spi, m); if (error) { - dev_err(&ts->spi->dev, "spi_sync --> %d\n", error); + dev_err_ratelimited(&ts->spi->dev, "spi_sync --> %d\n", error); packet->ignore = true; return; } @@ -992,7 +1021,7 @@ static int ads7846_setup_pendown(struct spi_device *spi, if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; } else { - ts->gpio_pendown = gpiod_get(&spi->dev, "pendown", GPIOD_IN); + ts->gpio_pendown = devm_gpiod_get(&spi->dev, "pendown", GPIOD_IN); if (IS_ERR(ts->gpio_pendown)) { dev_err(&spi->dev, "failed to request pendown GPIO\n"); return PTR_ERR(ts->gpio_pendown); @@ -1111,6 +1140,16 @@ static const struct of_device_id ads7846_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, ads7846_dt_ids); +static const struct spi_device_id ads7846_spi_ids[] = { + { "tsc2046", 7846 }, + { "ads7843", 7843 }, + { "ads7845", 7845 }, + { "ads7846", 7846 }, + { "ads7873", 7873 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, ads7846_spi_ids); + static const struct ads7846_platform_data *ads7846_get_props(struct device *dev) { struct ads7846_platform_data *pdata; @@ -1258,7 +1297,11 @@ static int ads7846_probe(struct spi_device *spi) ts->penirq_recheck_delay_usecs = pdata->penirq_recheck_delay_usecs; - ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync; + ts->wait_for_sync = pdata->wait_for_sync; + + ts->gpio_hsync = devm_gpiod_get_optional(dev, "ti,hsync", GPIOD_IN); + if (IS_ERR(ts->gpio_hsync)) + return PTR_ERR(ts->gpio_hsync); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev)); snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model); @@ -1386,10 +1429,10 @@ static struct spi_driver ads7846_driver = { }, .probe = ads7846_probe, .remove = ads7846_remove, + .id_table = ads7846_spi_ids, }; module_spi_driver(ads7846_driver); MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ads7846"); diff --git a/drivers/input/touchscreen/apple_z2.c b/drivers/input/touchscreen/apple_z2.c new file mode 100644 index 000000000000..0de161eae59a --- /dev/null +++ b/drivers/input/touchscreen/apple_z2.c @@ -0,0 +1,477 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Apple Z2 touchscreen driver + * + * Copyright (C) The Asahi Linux Contributors + */ + +#include <linux/delay.h> +#include <linux/firmware.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/input/touchscreen.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spi/spi.h> +#include <linux/unaligned.h> + +#define APPLE_Z2_NUM_FINGERS_OFFSET 16 +#define APPLE_Z2_FINGERS_OFFSET 24 +#define APPLE_Z2_TOUCH_STARTED 3 +#define APPLE_Z2_TOUCH_MOVED 4 +#define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB +#define APPLE_Z2_HBPP_CMD_BLOB 0x3001 +#define APPLE_Z2_FW_MAGIC 0x5746325A +#define LOAD_COMMAND_INIT_PAYLOAD 0 +#define LOAD_COMMAND_SEND_BLOB 1 +#define LOAD_COMMAND_SEND_CALIBRATION 2 +#define CAL_PROP_NAME "apple,z2-cal-blob" + +struct apple_z2 { + struct spi_device *spidev; + struct gpio_desc *reset_gpio; + struct input_dev *input_dev; + struct completion boot_irq; + bool booted; + int index_parity; + struct touchscreen_properties props; + const char *fw_name; + u8 *tx_buf; + u8 *rx_buf; +}; + +struct apple_z2_finger { + u8 finger; + u8 state; + __le16 unknown2; + __le16 abs_x; + __le16 abs_y; + __le16 rel_x; + __le16 rel_y; + __le16 tool_major; + __le16 tool_minor; + __le16 orientation; + __le16 touch_major; + __le16 touch_minor; + __le16 unused[2]; + __le16 pressure; + __le16 multi; +} __packed; + +struct apple_z2_hbpp_blob_hdr { + __le16 cmd; + __le16 len; + __le32 addr; + __le16 checksum; +}; + +struct apple_z2_fw_hdr { + __le32 magic; + __le32 version; +}; + +struct apple_z2_read_interrupt_cmd { + u8 cmd; + u8 counter; + u8 unused[12]; + __le16 checksum; +}; + +static void apple_z2_parse_touches(struct apple_z2 *z2, + const u8 *msg, size_t msg_len) +{ + int i; + int nfingers; + int slot; + int slot_valid; + struct apple_z2_finger *fingers; + + if (msg_len <= APPLE_Z2_NUM_FINGERS_OFFSET) + return; + nfingers = msg[APPLE_Z2_NUM_FINGERS_OFFSET]; + fingers = (struct apple_z2_finger *)(msg + APPLE_Z2_FINGERS_OFFSET); + for (i = 0; i < nfingers; i++) { + slot = input_mt_get_slot_by_key(z2->input_dev, fingers[i].finger); + if (slot < 0) { + dev_warn(&z2->spidev->dev, "unable to get slot for finger\n"); + continue; + } + slot_valid = fingers[i].state == APPLE_Z2_TOUCH_STARTED || + fingers[i].state == APPLE_Z2_TOUCH_MOVED; + input_mt_slot(z2->input_dev, slot); + if (!input_mt_report_slot_state(z2->input_dev, MT_TOOL_FINGER, slot_valid)) + continue; + touchscreen_report_pos(z2->input_dev, &z2->props, + le16_to_cpu(fingers[i].abs_x), + le16_to_cpu(fingers[i].abs_y), + true); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MAJOR, + le16_to_cpu(fingers[i].tool_major)); + input_report_abs(z2->input_dev, ABS_MT_WIDTH_MINOR, + le16_to_cpu(fingers[i].tool_minor)); + input_report_abs(z2->input_dev, ABS_MT_ORIENTATION, + le16_to_cpu(fingers[i].orientation)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MAJOR, + le16_to_cpu(fingers[i].touch_major)); + input_report_abs(z2->input_dev, ABS_MT_TOUCH_MINOR, + le16_to_cpu(fingers[i].touch_minor)); + } + input_mt_sync_frame(z2->input_dev); + input_sync(z2->input_dev); +} + +static int apple_z2_read_packet(struct apple_z2 *z2) +{ + struct apple_z2_read_interrupt_cmd *len_cmd = (void *)z2->tx_buf; + struct spi_transfer xfer; + int error; + size_t pkt_len; + + memset(&xfer, 0, sizeof(xfer)); + len_cmd->cmd = APPLE_Z2_CMD_READ_INTERRUPT_DATA; + len_cmd->counter = z2->index_parity + 1; + len_cmd->checksum = + cpu_to_le16(APPLE_Z2_CMD_READ_INTERRUPT_DATA + len_cmd->counter); + z2->index_parity = !z2->index_parity; + xfer.tx_buf = z2->tx_buf; + xfer.rx_buf = z2->rx_buf; + xfer.len = sizeof(*len_cmd); + + error = spi_sync_transfer(z2->spidev, &xfer, 1); + if (error) + return error; + + pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc; + + error = spi_read(z2->spidev, z2->rx_buf, pkt_len); + if (error) + return error; + + apple_z2_parse_touches(z2, z2->rx_buf + 5, pkt_len - 5); + + return 0; +} + +static irqreturn_t apple_z2_irq(int irq, void *data) +{ + struct apple_z2 *z2 = data; + + if (unlikely(!z2->booted)) + complete(&z2->boot_irq); + else + apple_z2_read_packet(z2); + + return IRQ_HANDLED; +} + +/* Build calibration blob, caller is responsible for freeing the blob data. */ +static const u8 *apple_z2_build_cal_blob(struct apple_z2 *z2, + u32 address, size_t *size) +{ + u8 *cal_data; + int cal_size; + size_t blob_size; + u32 checksum; + u16 checksum_hdr; + int i; + struct apple_z2_hbpp_blob_hdr *hdr; + int error; + + if (!device_property_present(&z2->spidev->dev, CAL_PROP_NAME)) + return NULL; + + cal_size = device_property_count_u8(&z2->spidev->dev, CAL_PROP_NAME); + if (cal_size < 0) + return ERR_PTR(cal_size); + + blob_size = sizeof(struct apple_z2_hbpp_blob_hdr) + cal_size + sizeof(__le32); + u8 *blob_data __free(kfree) = kzalloc(blob_size, GFP_KERNEL); + if (!blob_data) + return ERR_PTR(-ENOMEM); + + hdr = (struct apple_z2_hbpp_blob_hdr *)blob_data; + hdr->cmd = cpu_to_le16(APPLE_Z2_HBPP_CMD_BLOB); + hdr->len = cpu_to_le16(round_up(cal_size, 4) / 4); + hdr->addr = cpu_to_le32(address); + + checksum_hdr = 0; + for (i = 2; i < 8; i++) + checksum_hdr += blob_data[i]; + hdr->checksum = cpu_to_le16(checksum_hdr); + + cal_data = blob_data + sizeof(struct apple_z2_hbpp_blob_hdr); + error = device_property_read_u8_array(&z2->spidev->dev, CAL_PROP_NAME, + cal_data, cal_size); + if (error) + return ERR_PTR(error); + + checksum = 0; + for (i = 0; i < cal_size; i++) + checksum += cal_data[i]; + put_unaligned_le32(checksum, cal_data + cal_size); + + *size = blob_size; + return no_free_ptr(blob_data); +} + +static int apple_z2_send_firmware_blob(struct apple_z2 *z2, const u8 *data, + u32 size, bool init) +{ + struct spi_message msg; + struct spi_transfer blob_xfer, ack_xfer; + int error; + + z2->tx_buf[0] = 0x1a; + z2->tx_buf[1] = 0xa1; + + spi_message_init(&msg); + memset(&blob_xfer, 0, sizeof(blob_xfer)); + memset(&ack_xfer, 0, sizeof(ack_xfer)); + + blob_xfer.tx_buf = data; + blob_xfer.len = size; + blob_xfer.bits_per_word = init ? 8 : 16; + spi_message_add_tail(&blob_xfer, &msg); + + ack_xfer.tx_buf = z2->tx_buf; + ack_xfer.len = 2; + spi_message_add_tail(&ack_xfer, &msg); + + reinit_completion(&z2->boot_irq); + error = spi_sync(z2->spidev, &msg); + if (error) + return error; + + /* Irq only happens sometimes, but the thing boots reliably nonetheless */ + wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20)); + + return 0; +} + +static int apple_z2_upload_firmware(struct apple_z2 *z2) +{ + const struct apple_z2_fw_hdr *fw_hdr; + size_t fw_idx = sizeof(struct apple_z2_fw_hdr); + int error; + u32 load_cmd; + u32 address; + bool init; + size_t size; + + const struct firmware *fw __free(firmware) = NULL; + error = request_firmware(&fw, z2->fw_name, &z2->spidev->dev); + if (error) { + dev_err(&z2->spidev->dev, "unable to load firmware\n"); + return error; + } + + fw_hdr = (const struct apple_z2_fw_hdr *)fw->data; + if (le32_to_cpu(fw_hdr->magic) != APPLE_Z2_FW_MAGIC || le32_to_cpu(fw_hdr->version) != 1) { + dev_err(&z2->spidev->dev, "invalid firmware header\n"); + return -EINVAL; + } + + /* + * This will interrupt the upload half-way if the file is malformed + * As the device has no non-volatile storage to corrupt, and gets reset + * on boot anyway, this is fine. + */ + while (fw_idx < fw->size) { + if (fw->size - fw_idx < 8) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + + load_cmd = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (load_cmd == LOAD_COMMAND_INIT_PAYLOAD || load_cmd == LOAD_COMMAND_SEND_BLOB) { + size = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + if (fw->size - fw_idx < size) { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + init = load_cmd == LOAD_COMMAND_INIT_PAYLOAD; + error = apple_z2_send_firmware_blob(z2, fw->data + fw_idx, + size, init); + if (error) + return error; + fw_idx += size; + } else if (load_cmd == LOAD_COMMAND_SEND_CALIBRATION) { + address = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); + fw_idx += sizeof(u32); + + const u8 *data __free(kfree) = + apple_z2_build_cal_blob(z2, address, &size); + if (IS_ERR(data)) + return PTR_ERR(data); + + if (data) { + error = apple_z2_send_firmware_blob(z2, data, size, false); + if (error) + return error; + } + } else { + dev_err(&z2->spidev->dev, "firmware malformed\n"); + return -EINVAL; + } + fw_idx = round_up(fw_idx, 4); + } + + + z2->booted = true; + apple_z2_read_packet(z2); + return 0; +} + +static int apple_z2_boot(struct apple_z2 *z2) +{ + int error; + + reinit_completion(&z2->boot_irq); + enable_irq(z2->spidev->irq); + gpiod_set_value(z2->reset_gpio, 0); + if (!wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20))) + return -ETIMEDOUT; + + error = apple_z2_upload_firmware(z2); + if (error) { + gpiod_set_value(z2->reset_gpio, 1); + disable_irq(z2->spidev->irq); + return error; + } + + return 0; +} + +static int apple_z2_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct apple_z2 *z2; + int error; + + z2 = devm_kzalloc(dev, sizeof(*z2), GFP_KERNEL); + if (!z2) + return -ENOMEM; + + z2->tx_buf = devm_kzalloc(dev, sizeof(struct apple_z2_read_interrupt_cmd), GFP_KERNEL); + if (!z2->tx_buf) + return -ENOMEM; + /* 4096 will end up being rounded up to 8192 due to devres header */ + z2->rx_buf = devm_kzalloc(dev, 4000, GFP_KERNEL); + if (!z2->rx_buf) + return -ENOMEM; + + z2->spidev = spi; + init_completion(&z2->boot_irq); + spi_set_drvdata(spi, z2); + + /* Reset the device on boot */ + z2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(z2->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(z2->reset_gpio), "unable to get reset\n"); + + error = devm_request_threaded_irq(dev, z2->spidev->irq, NULL, apple_z2_irq, + IRQF_ONESHOT | IRQF_NO_AUTOEN, + "apple-z2-irq", z2); + if (error) + return dev_err_probe(dev, error, "unable to request irq\n"); + + error = device_property_read_string(dev, "firmware-name", &z2->fw_name); + if (error) + return dev_err_probe(dev, error, "unable to get firmware name\n"); + + z2->input_dev = devm_input_allocate_device(dev); + if (!z2->input_dev) + return -ENOMEM; + + z2->input_dev->name = (char *)spi_get_device_id(spi)->driver_data; + z2->input_dev->phys = "apple_z2"; + z2->input_dev->id.bustype = BUS_SPI; + + /* Allocate the axes before setting from DT */ + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_X, 0, 0, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_POSITION_Y, 0, 0, 0, 0); + touchscreen_parse_properties(z2->input_dev, true, &z2->props); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_X, 100); + input_abs_set_res(z2->input_dev, ABS_MT_POSITION_Y, 100); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MAJOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MINOR, 0, 65535, 0, 0); + input_set_abs_params(z2->input_dev, ABS_MT_ORIENTATION, -32768, 32767, 0, 0); + + error = input_mt_init_slots(z2->input_dev, 256, INPUT_MT_DIRECT); + if (error) + return dev_err_probe(dev, error, "unable to initialize multitouch slots\n"); + + error = input_register_device(z2->input_dev); + if (error) + return dev_err_probe(dev, error, "unable to register input device\n"); + + /* Wait for device reset to finish */ + usleep_range(5000, 10000); + error = apple_z2_boot(z2); + if (error) + return error; + + return 0; +} + +static void apple_z2_shutdown(struct spi_device *spi) +{ + struct apple_z2 *z2 = spi_get_drvdata(spi); + + disable_irq(z2->spidev->irq); + gpiod_direction_output(z2->reset_gpio, 1); + z2->booted = false; +} + +static int apple_z2_suspend(struct device *dev) +{ + apple_z2_shutdown(to_spi_device(dev)); + + return 0; +} + +static int apple_z2_resume(struct device *dev) +{ + struct apple_z2 *z2 = spi_get_drvdata(to_spi_device(dev)); + + return apple_z2_boot(z2); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(apple_z2_pm, apple_z2_suspend, apple_z2_resume); + +static const struct of_device_id apple_z2_of_match[] = { + { .compatible = "apple,j293-touchbar" }, + { .compatible = "apple,j493-touchbar" }, + {} +}; +MODULE_DEVICE_TABLE(of, apple_z2_of_match); + +static struct spi_device_id apple_z2_of_id[] = { + { .name = "j293-touchbar", .driver_data = (kernel_ulong_t)"MacBookPro17,1 Touch Bar" }, + { .name = "j493-touchbar", .driver_data = (kernel_ulong_t)"Mac14,7 Touch Bar" }, + {} +}; +MODULE_DEVICE_TABLE(spi, apple_z2_of_id); + +static struct spi_driver apple_z2_driver = { + .driver = { + .name = "apple-z2", + .pm = pm_sleep_ptr(&apple_z2_pm), + .of_match_table = apple_z2_of_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, + .id_table = apple_z2_of_id, + .probe = apple_z2_probe, + .remove = apple_z2_shutdown, +}; + +module_spi_driver(apple_z2_driver); + +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("apple/dfrmtfw-*.bin"); +MODULE_DESCRIPTION("Apple Z2 touchscreens driver"); diff --git a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c index 64dfb749386f..8a588202447d 100644 --- a/drivers/input/touchscreen/ar1021_i2c.c +++ b/drivers/input/touchscreen/ar1021_i2c.c @@ -164,8 +164,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(ar1021_i2c_pm, ar1021_i2c_suspend, ar1021_i2c_resume); static const struct i2c_device_id ar1021_i2c_id[] = { - { "ar1021", 0 }, - { }, + { "ar1021" }, + { } }; MODULE_DEVICE_TABLE(i2c, ar1021_i2c_id); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 542a31448c8f..322d5a3d40a0 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -26,7 +26,7 @@ #include <linux/slab.h> #include <linux/regulator/consumer.h> #include <linux/gpio/consumer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <media/v4l2-device.h> #include <media/v4l2-ioctl.h> #include <media/videobuf2-v4l2.h> @@ -2535,8 +2535,6 @@ fault: static const struct vb2_ops mxt_queue_ops = { .queue_setup = mxt_queue_setup, .buf_queue = mxt_buffer_queue, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue mxt_queue = { @@ -3069,9 +3067,7 @@ static struct attribute *mxt_attrs[] = { NULL }; -static const struct attribute_group mxt_attr_group = { - .attrs = mxt_attrs, -}; +ATTRIBUTE_GROUPS(mxt); static void mxt_start(struct mxt_data *data) { @@ -3348,18 +3344,8 @@ static int mxt_probe(struct i2c_client *client) if (error) goto err_disable_regulators; - error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group); - if (error) { - dev_err(&client->dev, "Failure %d creating sysfs group\n", - error); - goto err_free_object; - } - return 0; -err_free_object: - mxt_free_input_device(data); - mxt_free_object_table(data); err_disable_regulators: regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); @@ -3371,7 +3357,6 @@ static void mxt_remove(struct i2c_client *client) struct mxt_data *data = i2c_get_clientdata(client); disable_irq(data->irq); - sysfs_remove_group(&client->dev.kobj, &mxt_attr_group); mxt_free_input_device(data); mxt_free_object_table(data); regulator_bulk_disable(ARRAY_SIZE(data->regulators), @@ -3443,11 +3428,11 @@ MODULE_DEVICE_TABLE(acpi, mxt_acpi_id); #endif static const struct i2c_device_id mxt_id[] = { - { "qt602240_ts", 0 }, - { "atmel_mxt_ts", 0 }, - { "atmel_mxt_tp", 0 }, - { "maxtouch", 0 }, - { "mXT224", 0 }, + { "qt602240_ts" }, + { "atmel_mxt_ts" }, + { "atmel_mxt_tp" }, + { "maxtouch" }, + { "mXT224" }, { } }; MODULE_DEVICE_TABLE(i2c, mxt_id); @@ -3455,6 +3440,7 @@ MODULE_DEVICE_TABLE(i2c, mxt_id); static struct i2c_driver mxt_driver = { .driver = { .name = "atmel_mxt_ts", + .dev_groups = mxt_groups, .of_match_table = mxt_of_match, .acpi_match_table = ACPI_PTR(mxt_acpi_id), .pm = pm_sleep_ptr(&mxt_pm_ops), diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index 90c682e7407f..363a4a1f1560 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -72,7 +72,7 @@ /* * Interrupt modes: - * periodical: interrupt is asserted periodicaly + * periodical: interrupt is asserted periodically * compare coordinates: interrupt is asserted when coordinates change * indicate touch: interrupt is asserted during touch */ @@ -617,7 +617,7 @@ static int auo_pixcir_probe(struct i2c_client *client) } static const struct i2c_device_id auo_pixcir_idtable[] = { - { "auo_pixcir_ts", 0 }, + { "auo_pixcir_ts" }, { } }; MODULE_DEVICE_TABLE(i2c, auo_pixcir_idtable); diff --git a/drivers/input/touchscreen/bcm_iproc_tsc.c b/drivers/input/touchscreen/bcm_iproc_tsc.c index 9c84235327bf..e49bde50d77a 100644 --- a/drivers/input/touchscreen/bcm_iproc_tsc.c +++ b/drivers/input/touchscreen/bcm_iproc_tsc.c @@ -217,7 +217,7 @@ static irqreturn_t iproc_touchscreen_interrupt(int irq, void *data) "pen up-down (%d)\n", priv->pen_status); } - /* coordinates in FIFO exceed the theshold */ + /* coordinates in FIFO exceed the threshold */ if (intr_status & TS_FIFO_INTR_MASK) { for (i = 0; i < priv->cfg_params.fifo_threshold; i++) { regmap_read(priv->regmap, FIFO_DATA, &raw_coordinate); diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 652439a79e21..6baebb7ec089 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -597,7 +597,7 @@ static int bu21013_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(bu21013_dev_pm_ops, bu21013_suspend, bu21013_resume); static const struct i2c_device_id bu21013_id[] = { - { DRIVER_TP, 0 }, + { DRIVER_TP }, { } }; MODULE_DEVICE_TABLE(i2c, bu21013_id); diff --git a/drivers/input/touchscreen/bu21029_ts.c b/drivers/input/touchscreen/bu21029_ts.c index e1dfbd92ab64..3c997fba7048 100644 --- a/drivers/input/touchscreen/bu21029_ts.c +++ b/drivers/input/touchscreen/bu21029_ts.c @@ -325,7 +325,7 @@ static void bu21029_stop_chip(struct input_dev *dev) struct bu21029_ts_data *bu21029 = input_get_drvdata(dev); disable_irq(bu21029->client->irq); - del_timer_sync(&bu21029->timer); + timer_delete_sync(&bu21029->timer); bu21029_put_chip_in_reset(bu21029); regulator_disable(bu21029->vdd); @@ -441,7 +441,7 @@ static int bu21029_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(bu21029_pm_ops, bu21029_suspend, bu21029_resume); static const struct i2c_device_id bu21029_ids[] = { - { DRIVER_NAME, 0 }, + { DRIVER_NAME }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, bu21029_ids); diff --git a/drivers/input/touchscreen/chipone_icn8505.c b/drivers/input/touchscreen/chipone_icn8505.c index b56954830b33..cde0e4789503 100644 --- a/drivers/input/touchscreen/chipone_icn8505.c +++ b/drivers/input/touchscreen/chipone_icn8505.c @@ -8,7 +8,7 @@ * Hans de Goede <hdegoede@redhat.com> */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/acpi.h> #include <linux/crc32.h> #include <linux/delay.h> @@ -68,7 +68,6 @@ struct icn8505_touch_data { struct icn8505_data { struct i2c_client *client; struct input_dev *input; - struct gpio_desc *wake_gpio; struct touchscreen_properties prop; char firmware_name[32]; }; diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c index aa829725ded7..98d5b2ba63fb 100644 --- a/drivers/input/touchscreen/colibri-vf50-ts.c +++ b/drivers/input/touchscreen/colibri-vf50-ts.c @@ -239,14 +239,10 @@ static void vf50_ts_close(struct input_dev *dev_input) static int vf50_ts_get_gpiod(struct device *dev, struct gpio_desc **gpio_d, const char *con_id, enum gpiod_flags flags) { - int error; - *gpio_d = devm_gpiod_get(dev, con_id, flags); - if (IS_ERR(*gpio_d)) { - error = PTR_ERR(*gpio_d); - dev_err(dev, "Could not get gpio_%s %d\n", con_id, error); - return error; - } + if (IS_ERR(*gpio_d)) + return dev_err_probe(dev, PTR_ERR(*gpio_d), + "Could not get gpio_%s\n", con_id); return 0; } diff --git a/drivers/input/touchscreen/cy8ctma140.c b/drivers/input/touchscreen/cy8ctma140.c index ea3895167b82..2d4b6e343203 100644 --- a/drivers/input/touchscreen/cy8ctma140.c +++ b/drivers/input/touchscreen/cy8ctma140.c @@ -16,7 +16,7 @@ * same. */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/input.h> @@ -322,7 +322,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(cy8ctma140_pm, cy8ctma140_suspend, cy8ctma140_resume); static const struct i2c_device_id cy8ctma140_idtable[] = { - { CY8CTMA140_NAME, 0 }, + { CY8CTMA140_NAME }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, cy8ctma140_idtable); diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c deleted file mode 100644 index 7cb26929dc73..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ /dev/null @@ -1,2174 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp4_core.c - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" -#include <linux/delay.h> -#include <linux/gpio.h> -#include <linux/input/mt.h> -#include <linux/interrupt.h> -#include <linux/pm_runtime.h> -#include <linux/sched.h> -#include <linux/slab.h> - -/* Timeout in ms. */ -#define CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT 500 -#define CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT 5000 -#define CY_CORE_MODE_CHANGE_TIMEOUT 1000 -#define CY_CORE_RESET_AND_WAIT_TIMEOUT 500 -#define CY_CORE_WAKEUP_TIMEOUT 500 - -#define CY_CORE_STARTUP_RETRY_COUNT 3 - -static const char * const cyttsp4_tch_abs_string[] = { - [CY_TCH_X] = "X", - [CY_TCH_Y] = "Y", - [CY_TCH_P] = "P", - [CY_TCH_T] = "T", - [CY_TCH_E] = "E", - [CY_TCH_O] = "O", - [CY_TCH_W] = "W", - [CY_TCH_MAJ] = "MAJ", - [CY_TCH_MIN] = "MIN", - [CY_TCH_OR] = "OR", - [CY_TCH_NUM_ABS] = "INVALID" -}; - -static const u8 ldr_exit[] = { - 0xFF, 0x01, 0x3B, 0x00, 0x00, 0x4F, 0x6D, 0x17 -}; - -static const u8 ldr_err_app[] = { - 0x01, 0x02, 0x00, 0x00, 0x55, 0xDD, 0x17 -}; - -static inline size_t merge_bytes(u8 high, u8 low) -{ - return (high << 8) + low; -} - -#ifdef VERBOSE_DEBUG -static void cyttsp4_pr_buf(struct device *dev, u8 *pr_buf, u8 *dptr, int size, - const char *data_name) -{ - int i, k; - const char fmt[] = "%02X "; - int max; - - if (!size) - return; - - max = (CY_MAX_PRBUF_SIZE - 1) - sizeof(CY_PR_TRUNCATED); - - pr_buf[0] = 0; - for (i = k = 0; i < size && k < max; i++, k += 3) - scnprintf(pr_buf + k, CY_MAX_PRBUF_SIZE, fmt, dptr[i]); - - dev_vdbg(dev, "%s: %s[0..%d]=%s%s\n", __func__, data_name, size - 1, - pr_buf, size <= max ? "" : CY_PR_TRUNCATED); -} -#else -#define cyttsp4_pr_buf(dev, pr_buf, dptr, size, data_name) do { } while (0) -#endif - -static int cyttsp4_load_status_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct device *dev = cd->dev; - int rc; - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, si->si_ofs.mode_size, - si->xy_mode); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_mode, - si->si_ofs.mode_size, "xy_mode"); - - return rc; -} - -static int cyttsp4_handshake(struct cyttsp4 *cd, u8 mode) -{ - u8 cmd = mode ^ CY_HST_TOGGLE; - int rc; - - /* - * Mode change issued, handshaking now will cause endless mode change - * requests, for sync mode modechange will do same with handshake - * */ - if (mode & CY_HST_MODE_CHANGE) - return 0; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) - dev_err(cd->dev, "%s: bus write fail on handshake (ret=%d)\n", - __func__, rc); - - return rc; -} - -static int cyttsp4_hw_soft_reset(struct cyttsp4 *cd) -{ - u8 cmd = CY_HST_RESET; - int rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(cmd), &cmd); - if (rc < 0) { - dev_err(cd->dev, "%s: FAILED to execute SOFT reset\n", - __func__); - return rc; - } - return 0; -} - -static int cyttsp4_hw_hard_reset(struct cyttsp4 *cd) -{ - if (cd->cpdata->xres) { - cd->cpdata->xres(cd->cpdata, cd->dev); - dev_dbg(cd->dev, "%s: execute HARD reset\n", __func__); - return 0; - } - dev_err(cd->dev, "%s: FAILED to execute HARD reset\n", __func__); - return -ENOSYS; -} - -static int cyttsp4_hw_reset(struct cyttsp4 *cd) -{ - int rc = cyttsp4_hw_hard_reset(cd); - if (rc == -ENOSYS) - rc = cyttsp4_hw_soft_reset(cd); - return rc; -} - -/* - * Gets number of bits for a touch filed as parameter, - * sets maximum value for field which is used as bit mask - * and returns number of bytes required for that field - */ -static int cyttsp4_bits_2_bytes(unsigned int nbits, size_t *max) -{ - *max = 1UL << nbits; - return (nbits + 7) / 8; -} - -static int cyttsp4_si_data_offsets(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(si->si_data), - &si->si_data); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read sysinfo data offsets r=%d\n", - __func__, rc); - return rc; - } - - /* Print sysinfo data offsets */ - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)&si->si_data, - sizeof(si->si_data), "sysinfo_data_offsets"); - - /* convert sysinfo data offset bytes into integers */ - - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.map_sz = merge_bytes(si->si_data.map_szh, - si->si_data.map_szl); - si->si_ofs.cydata_ofs = merge_bytes(si->si_data.cydata_ofsh, - si->si_data.cydata_ofsl); - si->si_ofs.test_ofs = merge_bytes(si->si_data.test_ofsh, - si->si_data.test_ofsl); - si->si_ofs.pcfg_ofs = merge_bytes(si->si_data.pcfg_ofsh, - si->si_data.pcfg_ofsl); - si->si_ofs.opcfg_ofs = merge_bytes(si->si_data.opcfg_ofsh, - si->si_data.opcfg_ofsl); - si->si_ofs.ddata_ofs = merge_bytes(si->si_data.ddata_ofsh, - si->si_data.ddata_ofsl); - si->si_ofs.mdata_ofs = merge_bytes(si->si_data.mdata_ofsh, - si->si_data.mdata_ofsl); - return rc; -} - -static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int read_offset; - int mfgid_sz, calc_mfgid_sz; - void *p; - int rc; - - if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) { - dev_err(cd->dev, - "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n", - __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs); - return -EINVAL; - } - - si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; - dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, - si->si_ofs.cydata_size); - - p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate cydata memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.cydata = p; - - read_offset = si->si_ofs.cydata_ofs; - - /* Read the CYDA registers up to MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, - offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz), - si->si_ptrs.cydata); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - /* Check MFGID size */ - mfgid_sz = si->si_ptrs.cydata->mfgid_sz; - calc_mfgid_sz = si->si_ofs.cydata_size - sizeof(struct cyttsp4_cydata); - if (mfgid_sz != calc_mfgid_sz) { - dev_err(cd->dev, "%s: mismatch in MFGID size, reported:%d calculated:%d\n", - __func__, mfgid_sz, calc_mfgid_sz); - return -EINVAL; - } - - read_offset += offsetof(struct cyttsp4_cydata, mfgid_sz) - + sizeof(si->si_ptrs.cydata->mfgid_sz); - - /* Read the CYDA registers for MFGID field */ - rc = cyttsp4_adap_read(cd, read_offset, si->si_ptrs.cydata->mfgid_sz, - si->si_ptrs.cydata->mfg_id); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - read_offset += si->si_ptrs.cydata->mfgid_sz; - - /* Read the rest of the CYDA registers */ - rc = cyttsp4_adap_read(cd, read_offset, - sizeof(struct cyttsp4_cydata) - - offsetof(struct cyttsp4_cydata, cyito_idh), - &si->si_ptrs.cydata->cyito_idh); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read cydata r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.cydata, - si->si_ofs.cydata_size, "sysinfo_cydata"); - return rc; -} - -static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) { - dev_err(cd->dev, - "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n", - __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs); - return -EINVAL; - } - - si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; - - p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate test memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.test = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.test_ofs, si->si_ofs.test_size, - si->si_ptrs.test); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read test data r=%d\n", - __func__, rc); - return rc; - } - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.test, si->si_ofs.test_size, - "sysinfo_test_data"); - if (si->si_ptrs.test->post_codel & - CY_POST_CODEL_WDG_RST) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "Reset was a WATCHDOG RESET", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_CFG_DATA_CRC_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", __func__, - "Config Data CRC FAIL", - si->si_ptrs.test->post_codel); - - if (!(si->si_ptrs.test->post_codel & - CY_POST_CODEL_PANEL_TEST_FAIL)) - dev_info(cd->dev, "%s: %s codel=%02X\n", - __func__, "PANEL TEST FAIL", - si->si_ptrs.test->post_codel); - - dev_info(cd->dev, "%s: SCANNING is %s codel=%02X\n", - __func__, si->si_ptrs.test->post_codel & 0x08 ? - "ENABLED" : "DISABLED", - si->si_ptrs.test->post_codel); - return rc; -} - -static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n", - __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs); - return -EINVAL; - } - - si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; - - p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate pcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.pcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size, - si->si_ptrs.pcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read pcfg data r=%d\n", - __func__, rc); - return rc; - } - - si->si_ofs.max_x = merge_bytes((si->si_ptrs.pcfg->res_xh - & CY_PCFG_RESOLUTION_X_MASK), si->si_ptrs.pcfg->res_xl); - si->si_ofs.x_origin = !!(si->si_ptrs.pcfg->res_xh - & CY_PCFG_ORIGIN_X_MASK); - si->si_ofs.max_y = merge_bytes((si->si_ptrs.pcfg->res_yh - & CY_PCFG_RESOLUTION_Y_MASK), si->si_ptrs.pcfg->res_yl); - si->si_ofs.y_origin = !!(si->si_ptrs.pcfg->res_yh - & CY_PCFG_ORIGIN_Y_MASK); - si->si_ofs.max_p = merge_bytes(si->si_ptrs.pcfg->max_zh, - si->si_ptrs.pcfg->max_zl); - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.pcfg, - si->si_ofs.pcfg_size, "sysinfo_pcfg_data"); - return rc; -} - -static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - struct cyttsp4_tch_abs_params *tch; - struct cyttsp4_tch_rec_params *tch_old, *tch_new; - enum cyttsp4_tch_abs abs; - int i; - void *p; - int rc; - - if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) { - dev_err(cd->dev, - "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n", - __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs); - return -EINVAL; - } - - si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; - - p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: failed to allocate opcfg memory\n", - __func__); - return -ENOMEM; - } - si->si_ptrs.opcfg = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size, - si->si_ptrs.opcfg); - if (rc < 0) { - dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", - __func__, rc); - return rc; - } - si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; - si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; - si->si_ofs.rep_sz = (si->si_ptrs.opcfg->rep_szh * 256) + - si->si_ptrs.opcfg->rep_szl; - si->si_ofs.num_btns = si->si_ptrs.opcfg->num_btns; - si->si_ofs.num_btn_regs = (si->si_ofs.num_btns + - CY_NUM_BTN_PER_REG - 1) / CY_NUM_BTN_PER_REG; - si->si_ofs.tt_stat_ofs = si->si_ptrs.opcfg->tt_stat_ofs; - si->si_ofs.obj_cfg0 = si->si_ptrs.opcfg->obj_cfg0; - si->si_ofs.max_tchs = si->si_ptrs.opcfg->max_tchs & - CY_BYTE_OFS_MASK; - si->si_ofs.tch_rec_size = si->si_ptrs.opcfg->tch_rec_size & - CY_BYTE_OFS_MASK; - - /* Get the old touch fields */ - for (abs = CY_TCH_X; abs < CY_NUM_TCH_FIELDS; abs++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_old = &si->si_ptrs.opcfg->tch_rec_old[abs]; - - tch->ofs = tch_old->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_old->size, - &tch->max); - tch->bofs = (tch_old->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - - /* button fields */ - si->si_ofs.btn_rec_size = si->si_ptrs.opcfg->btn_rec_size; - si->si_ofs.btn_diff_ofs = si->si_ptrs.opcfg->btn_diff_ofs; - si->si_ofs.btn_diff_size = si->si_ptrs.opcfg->btn_diff_size; - - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* Get the extended touch fields */ - for (i = 0; i < CY_NUM_EXT_TCH_FIELDS; abs++, i++) { - tch = &si->si_ofs.tch_abs[abs]; - tch_new = &si->si_ptrs.opcfg->tch_rec_new[i]; - - tch->ofs = tch_new->loc & CY_BYTE_OFS_MASK; - tch->size = cyttsp4_bits_2_bytes(tch_new->size, - &tch->max); - tch->bofs = (tch_new->loc & CY_BOFS_MASK) >> CY_BOFS_SHIFT; - } - } - - for (abs = 0; abs < CY_TCH_NUM_ABS; abs++) { - dev_dbg(cd->dev, "%s: tch_rec_%s\n", __func__, - cyttsp4_tch_abs_string[abs]); - dev_dbg(cd->dev, "%s: ofs =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].ofs); - dev_dbg(cd->dev, "%s: siz =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].size); - dev_dbg(cd->dev, "%s: max =%2zd\n", __func__, - si->si_ofs.tch_abs[abs].max); - dev_dbg(cd->dev, "%s: bofs=%2zd\n", __func__, - si->si_ofs.tch_abs[abs].bofs); - } - - si->si_ofs.mode_size = si->si_ofs.tt_stat_ofs + 1; - si->si_ofs.data_size = si->si_ofs.max_tchs * - si->si_ptrs.opcfg->tch_rec_size; - - cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, - si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); - - return 0; -} - -static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.ddata_size = si->si_ofs.mdata_ofs - si->si_ofs.ddata_ofs; - - p = krealloc(si->si_ptrs.ddata, si->si_ofs.ddata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc ddata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.ddata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.ddata_ofs, si->si_ofs.ddata_size, - si->si_ptrs.ddata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read ddata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.ddata, - si->si_ofs.ddata_size, "sysinfo_ddata"); - return rc; -} - -static int cyttsp4_si_get_mdata(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - int rc; - - si->si_ofs.mdata_size = si->si_ofs.map_sz - si->si_ofs.mdata_ofs; - - p = krealloc(si->si_ptrs.mdata, si->si_ofs.mdata_size, GFP_KERNEL); - if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc mdata memory\n", __func__); - return -ENOMEM; - } - si->si_ptrs.mdata = p; - - rc = cyttsp4_adap_read(cd, si->si_ofs.mdata_ofs, si->si_ofs.mdata_size, - si->si_ptrs.mdata); - if (rc < 0) - dev_err(cd->dev, "%s: fail read mdata data r=%d\n", - __func__, rc); - else - cyttsp4_pr_buf(cd->dev, cd->pr_buf, - (u8 *)si->si_ptrs.mdata, - si->si_ofs.mdata_size, "sysinfo_mdata"); - return rc; -} - -static int cyttsp4_si_get_btn_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int btn; - int num_defined_keys; - u16 *key_table; - void *p; - int rc = 0; - - if (si->si_ofs.num_btns) { - si->si_ofs.btn_keys_size = si->si_ofs.num_btns * - sizeof(struct cyttsp4_btn); - - p = krealloc(si->btn, si->si_ofs.btn_keys_size, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) { - dev_err(cd->dev, "%s: %s\n", __func__, - "fail alloc btn_keys memory"); - return -ENOMEM; - } - si->btn = p; - - if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS] == NULL) - num_defined_keys = 0; - else if (cd->cpdata->sett[CY_IC_GRPNUM_BTN_KEYS]->data == NULL) - num_defined_keys = 0; - else - num_defined_keys = cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->size; - - for (btn = 0; btn < si->si_ofs.num_btns && - btn < num_defined_keys; btn++) { - key_table = (u16 *)cd->cpdata->sett - [CY_IC_GRPNUM_BTN_KEYS]->data; - si->btn[btn].key_code = key_table[btn]; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - for (; btn < si->si_ofs.num_btns; btn++) { - si->btn[btn].key_code = KEY_RESERVED; - si->btn[btn].state = CY_BTN_RELEASED; - si->btn[btn].enabled = true; - } - - return rc; - } - - si->si_ofs.btn_keys_size = 0; - kfree(si->btn); - si->btn = NULL; - return rc; -} - -static int cyttsp4_si_get_op_data_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - void *p; - - p = krealloc(si->xy_mode, si->si_ofs.mode_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_mode = p; - - p = krealloc(si->xy_data, si->si_ofs.data_size, GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->xy_data = p; - - p = krealloc(si->btn_rec_data, - si->si_ofs.btn_rec_size * si->si_ofs.num_btns, - GFP_KERNEL|__GFP_ZERO); - if (p == NULL) - return -ENOMEM; - si->btn_rec_data = p; - - return 0; -} - -static void cyttsp4_si_put_log_data(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - dev_dbg(cd->dev, "%s: cydata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.cydata_ofs, si->si_ofs.cydata_size); - dev_dbg(cd->dev, "%s: test_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.test_ofs, si->si_ofs.test_size); - dev_dbg(cd->dev, "%s: pcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.pcfg_ofs, si->si_ofs.pcfg_size); - dev_dbg(cd->dev, "%s: opcfg_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.opcfg_ofs, si->si_ofs.opcfg_size); - dev_dbg(cd->dev, "%s: ddata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.ddata_ofs, si->si_ofs.ddata_size); - dev_dbg(cd->dev, "%s: mdata_ofs =%4zd siz=%4zd\n", __func__, - si->si_ofs.mdata_ofs, si->si_ofs.mdata_size); - - dev_dbg(cd->dev, "%s: cmd_ofs =%4zd\n", __func__, - si->si_ofs.cmd_ofs); - dev_dbg(cd->dev, "%s: rep_ofs =%4zd\n", __func__, - si->si_ofs.rep_ofs); - dev_dbg(cd->dev, "%s: rep_sz =%4zd\n", __func__, - si->si_ofs.rep_sz); - dev_dbg(cd->dev, "%s: num_btns =%4zd\n", __func__, - si->si_ofs.num_btns); - dev_dbg(cd->dev, "%s: num_btn_regs =%4zd\n", __func__, - si->si_ofs.num_btn_regs); - dev_dbg(cd->dev, "%s: tt_stat_ofs =%4zd\n", __func__, - si->si_ofs.tt_stat_ofs); - dev_dbg(cd->dev, "%s: tch_rec_size =%4zd\n", __func__, - si->si_ofs.tch_rec_size); - dev_dbg(cd->dev, "%s: max_tchs =%4zd\n", __func__, - si->si_ofs.max_tchs); - dev_dbg(cd->dev, "%s: mode_size =%4zd\n", __func__, - si->si_ofs.mode_size); - dev_dbg(cd->dev, "%s: data_size =%4zd\n", __func__, - si->si_ofs.data_size); - dev_dbg(cd->dev, "%s: map_sz =%4zd\n", __func__, - si->si_ofs.map_sz); - - dev_dbg(cd->dev, "%s: btn_rec_size =%2zd\n", __func__, - si->si_ofs.btn_rec_size); - dev_dbg(cd->dev, "%s: btn_diff_ofs =%2zd\n", __func__, - si->si_ofs.btn_diff_ofs); - dev_dbg(cd->dev, "%s: btn_diff_size =%2zd\n", __func__, - si->si_ofs.btn_diff_size); - - dev_dbg(cd->dev, "%s: max_x = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_x, si->si_ofs.max_x); - dev_dbg(cd->dev, "%s: x_origin = %zd (%s)\n", __func__, - si->si_ofs.x_origin, - si->si_ofs.x_origin == CY_NORMAL_ORIGIN ? - "left corner" : "right corner"); - dev_dbg(cd->dev, "%s: max_y = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_y, si->si_ofs.max_y); - dev_dbg(cd->dev, "%s: y_origin = %zd (%s)\n", __func__, - si->si_ofs.y_origin, - si->si_ofs.y_origin == CY_NORMAL_ORIGIN ? - "upper corner" : "lower corner"); - dev_dbg(cd->dev, "%s: max_p = 0x%04zX (%zd)\n", __func__, - si->si_ofs.max_p, si->si_ofs.max_p); - - dev_dbg(cd->dev, "%s: xy_mode=%p xy_data=%p\n", __func__, - si->xy_mode, si->xy_data); -} - -static int cyttsp4_get_sysinfo_regs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - int rc; - - rc = cyttsp4_si_data_offsets(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_cydata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_test_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_pcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_opcfg_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_ddata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_mdata(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_btn_data(cd); - if (rc < 0) - return rc; - - rc = cyttsp4_si_get_op_data_ptrs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get_op_data\n", - __func__); - return rc; - } - - cyttsp4_si_put_log_data(cd); - - /* provide flow control handshake */ - rc = cyttsp4_handshake(cd, si->si_data.hst_mode); - if (rc < 0) - dev_err(cd->dev, "%s: handshake fail on sysinfo reg\n", - __func__); - - si->ready = true; - return rc; -} - -static void cyttsp4_queue_startup_(struct cyttsp4 *cd) -{ - if (cd->startup_state == STARTUP_NONE) { - cd->startup_state = STARTUP_QUEUED; - schedule_work(&cd->startup_work); - dev_dbg(cd->dev, "%s: cyttsp4_startup queued\n", __func__); - } else { - dev_dbg(cd->dev, "%s: startup_state = %d\n", __func__, - cd->startup_state); - } -} - -static void cyttsp4_report_slot_liftoff(struct cyttsp4_mt_data *md, - int max_slots) -{ - int t; - - if (md->num_prv_tch == 0) - return; - - for (t = 0; t < max_slots; t++) { - input_mt_slot(md->input, t); - input_mt_report_slot_inactive(md->input); - } -} - -static void cyttsp4_lift_all(struct cyttsp4_mt_data *md) -{ - if (!md->si) - return; - - if (md->num_prv_tch != 0) { - cyttsp4_report_slot_liftoff(md, - md->si->si_ofs.tch_abs[CY_TCH_T].max); - input_sync(md->input); - md->num_prv_tch = 0; - } -} - -static void cyttsp4_get_touch_axis(struct cyttsp4_mt_data *md, - int *axis, int size, int max, u8 *xy_data, int bofs) -{ - int nbyte; - int next; - - for (nbyte = 0, *axis = 0, next = 0; nbyte < size; nbyte++) { - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d) bofs=%d\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next], bofs); - *axis = (*axis * 256) + (xy_data[next] >> bofs); - next++; - } - - *axis &= max - 1; - - dev_vdbg(&md->input->dev, - "%s: *axis=%02X(%d) size=%d max=%08X xy_data=%p" - " xy_data[%d]=%02X(%d)\n", - __func__, *axis, *axis, size, max, xy_data, next, - xy_data[next], xy_data[next]); -} - -static void cyttsp4_get_touch(struct cyttsp4_mt_data *md, - struct cyttsp4_touch *touch, u8 *xy_data) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - enum cyttsp4_tch_abs abs; - bool flipped; - - for (abs = CY_TCH_X; abs < CY_TCH_NUM_ABS; abs++) { - cyttsp4_get_touch_axis(md, &touch->abs[abs], - si->si_ofs.tch_abs[abs].size, - si->si_ofs.tch_abs[abs].max, - xy_data + si->si_ofs.tch_abs[abs].ofs, - si->si_ofs.tch_abs[abs].bofs); - dev_vdbg(dev, "%s: get %s=%04X(%d)\n", __func__, - cyttsp4_tch_abs_string[abs], - touch->abs[abs], touch->abs[abs]); - } - - if (md->pdata->flags & CY_FLAG_FLIP) { - swap(touch->abs[CY_TCH_X], touch->abs[CY_TCH_Y]); - flipped = true; - } else - flipped = false; - - if (md->pdata->flags & CY_FLAG_INV_X) { - if (flipped) - touch->abs[CY_TCH_X] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_X]; - else - touch->abs[CY_TCH_X] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_X]; - } - if (md->pdata->flags & CY_FLAG_INV_Y) { - if (flipped) - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_x - - touch->abs[CY_TCH_Y]; - else - touch->abs[CY_TCH_Y] = md->si->si_ofs.max_y - - touch->abs[CY_TCH_Y]; - } - - dev_vdbg(dev, "%s: flip=%s inv-x=%s inv-y=%s x=%04X(%d) y=%04X(%d)\n", - __func__, flipped ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_X ? "true" : "false", - md->pdata->flags & CY_FLAG_INV_Y ? "true" : "false", - touch->abs[CY_TCH_X], touch->abs[CY_TCH_X], - touch->abs[CY_TCH_Y], touch->abs[CY_TCH_Y]); -} - -static void cyttsp4_final_sync(struct input_dev *input, int max_slots, int *ids) -{ - int t; - - for (t = 0; t < max_slots; t++) { - if (ids[t]) - continue; - input_mt_slot(input, t); - input_mt_report_slot_inactive(input); - } - - input_sync(input); -} - -static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch) -{ - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - struct cyttsp4_touch tch; - int sig; - int i, j, t = 0; - int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)]; - - memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int)); - for (i = 0; i < num_cur_tch; i++) { - cyttsp4_get_touch(md, &tch, si->xy_data + - (i * si->si_ofs.tch_rec_size)); - if ((tch.abs[CY_TCH_T] < md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]) || - (tch.abs[CY_TCH_T] > md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MAX_OST])) { - dev_err(dev, "%s: tch=%d -> bad trk_id=%d max_id=%d\n", - __func__, i, tch.abs[CY_TCH_T], - md->pdata->frmwrk->abs[(CY_ABS_ID_OST * - CY_NUM_ABS_SET) + CY_MAX_OST]); - continue; - } - - /* use 0 based track id's */ - sig = md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) { - t = tch.abs[CY_TCH_T] - md->pdata->frmwrk->abs - [(CY_ABS_ID_OST * CY_NUM_ABS_SET) + CY_MIN_OST]; - if (tch.abs[CY_TCH_E] == CY_EV_LIFTOFF) { - dev_dbg(dev, "%s: t=%d e=%d lift-off\n", - __func__, t, tch.abs[CY_TCH_E]); - goto cyttsp4_get_mt_touches_pr_tch; - } - input_mt_slot(md->input, t); - input_mt_report_slot_state(md->input, MT_TOOL_FINGER, - true); - ids[t] = true; - } - - /* all devices: position and pressure fields */ - for (j = 0; j <= CY_ABS_W_OST; j++) { - sig = md->pdata->frmwrk->abs[((CY_ABS_X_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_X + j]); - } - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) { - /* - * TMA400 size and orientation fields: - * if pressure is non-zero and major touch - * signal is zero, then set major and minor touch - * signals to minimum non-zero value - */ - if (tch.abs[CY_TCH_P] > 0 && tch.abs[CY_TCH_MAJ] == 0) - tch.abs[CY_TCH_MAJ] = tch.abs[CY_TCH_MIN] = 1; - - /* Get the extended touch fields */ - for (j = 0; j < CY_NUM_EXT_TCH_FIELDS; j++) { - sig = md->pdata->frmwrk->abs - [((CY_ABS_MAJ_OST + j) * - CY_NUM_ABS_SET) + 0]; - if (sig != CY_IGNORE_VALUE) - input_report_abs(md->input, sig, - tch.abs[CY_TCH_MAJ + j]); - } - } - -cyttsp4_get_mt_touches_pr_tch: - if (si->si_ofs.tch_rec_size > CY_TMA1036_TCH_REC_SIZE) - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d M=%d m=%d o=%d e=%d\n", - __func__, t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_MAJ], - tch.abs[CY_TCH_MIN], - tch.abs[CY_TCH_OR], - tch.abs[CY_TCH_E]); - else - dev_dbg(dev, - "%s: t=%d x=%d y=%d z=%d e=%d\n", __func__, - t, - tch.abs[CY_TCH_X], - tch.abs[CY_TCH_Y], - tch.abs[CY_TCH_P], - tch.abs[CY_TCH_E]); - } - - cyttsp4_final_sync(md->input, si->si_ofs.tch_abs[CY_TCH_T].max, ids); - - md->num_prv_tch = num_cur_tch; - - return; -} - -/* read xy_data for all current touches */ -static int cyttsp4_xy_worker(struct cyttsp4 *cd) -{ - struct cyttsp4_mt_data *md = &cd->md; - struct device *dev = &md->input->dev; - struct cyttsp4_sysinfo *si = md->si; - u8 num_cur_tch; - u8 hst_mode; - u8 rep_len; - u8 rep_stat; - u8 tt_stat; - int rc = 0; - - /* - * Get event data from cyttsp4 device. - * The event data includes all data - * for all active touches. - * Event data also includes button data - */ - /* - * Use 2 reads: - * 1st read to get mode + button bytes + touch count (core) - * 2nd read (optional) to get touch 1 - touch n data - */ - hst_mode = si->xy_mode[CY_REG_BASE]; - rep_len = si->xy_mode[si->si_ofs.rep_ofs]; - rep_stat = si->xy_mode[si->si_ofs.rep_ofs + 1]; - tt_stat = si->xy_mode[si->si_ofs.tt_stat_ofs]; - dev_vdbg(dev, "%s: %s%02X %s%d %s%02X %s%02X\n", __func__, - "hst_mode=", hst_mode, "rep_len=", rep_len, - "rep_stat=", rep_stat, "tt_stat=", tt_stat); - - num_cur_tch = GET_NUM_TOUCHES(tt_stat); - dev_vdbg(dev, "%s: num_cur_tch=%d\n", __func__, num_cur_tch); - - if (rep_len == 0 && num_cur_tch > 0) { - dev_err(dev, "%s: report length error rep_len=%d num_tch=%d\n", - __func__, rep_len, num_cur_tch); - goto cyttsp4_xy_worker_exit; - } - - /* read touches */ - if (num_cur_tch > 0) { - rc = cyttsp4_adap_read(cd, si->si_ofs.tt_stat_ofs + 1, - num_cur_tch * si->si_ofs.tch_rec_size, - si->xy_data); - if (rc < 0) { - dev_err(dev, "%s: read fail on touch regs r=%d\n", - __func__, rc); - goto cyttsp4_xy_worker_exit; - } - } - - /* print xy data */ - cyttsp4_pr_buf(dev, cd->pr_buf, si->xy_data, num_cur_tch * - si->si_ofs.tch_rec_size, "xy_data"); - - /* check any error conditions */ - if (IS_BAD_PKT(rep_stat)) { - dev_dbg(dev, "%s: Invalid buffer detected\n", __func__); - rc = 0; - goto cyttsp4_xy_worker_exit; - } - - if (IS_LARGE_AREA(tt_stat)) - dev_dbg(dev, "%s: Large area detected\n", __func__); - - if (num_cur_tch > si->si_ofs.max_tchs) { - dev_err(dev, "%s: too many tch; set to max tch (n=%d c=%zd)\n", - __func__, num_cur_tch, si->si_ofs.max_tchs); - num_cur_tch = si->si_ofs.max_tchs; - } - - /* extract xy_data for all currently reported touches */ - dev_vdbg(dev, "%s: extract data num_cur_tch=%d\n", __func__, - num_cur_tch); - if (num_cur_tch) - cyttsp4_get_mt_touches(md, num_cur_tch); - else - cyttsp4_lift_all(md); - - rc = 0; - -cyttsp4_xy_worker_exit: - return rc; -} - -static int cyttsp4_mt_attention(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int rc = 0; - - if (!md->si) - return 0; - - mutex_lock(&md->report_lock); - if (!md->is_suspended) { - /* core handles handshake */ - rc = cyttsp4_xy_worker(cd); - } else { - dev_vdbg(dev, "%s: Ignoring report while suspended\n", - __func__); - } - mutex_unlock(&md->report_lock); - if (rc < 0) - dev_err(dev, "%s: xy_worker error r=%d\n", __func__, rc); - - return rc; -} - -static irqreturn_t cyttsp4_irq(int irq, void *handle) -{ - struct cyttsp4 *cd = handle; - struct device *dev = cd->dev; - enum cyttsp4_mode cur_mode; - u8 cmd_ofs = cd->sysinfo.si_ofs.cmd_ofs; - u8 mode[3]; - int rc; - - /* - * Check whether this IRQ should be ignored (external) - * This should be the very first thing to check since - * ignore_irq may be set for a very short period of time - */ - if (atomic_read(&cd->ignore_irq)) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - return IRQ_HANDLED; - } - - dev_dbg(dev, "%s int:0x%x\n", __func__, cd->int_status); - - mutex_lock(&cd->system_lock); - - /* Just to debug */ - if (cd->sleep_state == SS_SLEEP_ON || cd->sleep_state == SS_SLEEPING) - dev_vdbg(dev, "%s: Received IRQ while in sleep\n", __func__); - - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), mode); - if (rc) { - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto cyttsp4_irq_exit; - } - dev_vdbg(dev, "%s mode[0-2]:0x%X 0x%X 0x%X\n", __func__, - mode[0], mode[1], mode[2]); - - if (IS_BOOTLOADER(mode[0], mode[1])) { - cur_mode = CY_MODE_BOOTLOADER; - dev_vdbg(dev, "%s: bl running\n", __func__); - if (cd->mode == CY_MODE_BOOTLOADER) { - /* Signal bootloader heartbeat heard */ - wake_up(&cd->wait_q); - goto cyttsp4_irq_exit; - } - - /* switch to bootloader */ - dev_dbg(dev, "%s: restart switch to bl m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - - /* catch operation->bl glitch */ - if (cd->mode != CY_MODE_UNKNOWN) { - /* Incase startup_state do not let startup_() */ - cd->mode = CY_MODE_UNKNOWN; - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* - * do not wake thread on this switch since - * it is possible to get an early heartbeat - * prior to performing the reset - */ - cd->mode = cur_mode; - - goto cyttsp4_irq_exit; - } - - switch (mode[0] & CY_HST_MODE) { - case CY_HST_OPERATE: - cur_mode = CY_MODE_OPERATIONAL; - dev_vdbg(dev, "%s: operational\n", __func__); - break; - case CY_HST_CAT: - cur_mode = CY_MODE_CAT; - dev_vdbg(dev, "%s: CaT\n", __func__); - break; - case CY_HST_SYSINFO: - cur_mode = CY_MODE_SYSINFO; - dev_vdbg(dev, "%s: sysinfo\n", __func__); - break; - default: - cur_mode = CY_MODE_UNKNOWN; - dev_err(dev, "%s: unknown HST mode 0x%02X\n", __func__, - mode[0]); - break; - } - - /* Check whether this IRQ should be ignored (internal) */ - if (cd->int_status & CY_INT_IGNORE) { - dev_vdbg(dev, "%s: Ignoring IRQ\n", __func__); - goto cyttsp4_irq_exit; - } - - /* Check for wake up interrupt */ - if (cd->int_status & CY_INT_AWAKE) { - cd->int_status &= ~CY_INT_AWAKE; - wake_up(&cd->wait_q); - dev_vdbg(dev, "%s: Received wake up interrupt\n", __func__); - goto cyttsp4_irq_handshake; - } - - /* Expecting mode change interrupt */ - if ((cd->int_status & CY_INT_MODE_CHANGE) - && (mode[0] & CY_HST_MODE_CHANGE) == 0) { - cd->int_status &= ~CY_INT_MODE_CHANGE; - dev_dbg(dev, "%s: finish mode switch m=%d -> m=%d\n", - __func__, cd->mode, cur_mode); - cd->mode = cur_mode; - wake_up(&cd->wait_q); - goto cyttsp4_irq_handshake; - } - - /* compare current core mode to current device mode */ - dev_vdbg(dev, "%s: cd->mode=%d cur_mode=%d\n", - __func__, cd->mode, cur_mode); - if ((mode[0] & CY_HST_MODE_CHANGE) == 0 && cd->mode != cur_mode) { - /* Unexpected mode change occurred */ - dev_err(dev, "%s %d->%d 0x%x\n", __func__, cd->mode, - cur_mode, cd->int_status); - dev_dbg(dev, "%s: Unexpected mode change, startup\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_irq_exit; - } - - /* Expecting command complete interrupt */ - dev_vdbg(dev, "%s: command byte:0x%x\n", __func__, mode[cmd_ofs]); - if ((cd->int_status & CY_INT_EXEC_CMD) - && mode[cmd_ofs] & CY_CMD_COMPLETE) { - cd->int_status &= ~CY_INT_EXEC_CMD; - dev_vdbg(dev, "%s: Received command complete interrupt\n", - __func__); - wake_up(&cd->wait_q); - /* - * It is possible to receive a single interrupt for - * command complete and touch/button status report. - * Continue processing for a possible status report. - */ - } - - /* This should be status report, read status regs */ - if (cd->mode == CY_MODE_OPERATIONAL) { - dev_vdbg(dev, "%s: Read status registers\n", __func__); - rc = cyttsp4_load_status_regs(cd); - if (rc < 0) - dev_err(dev, "%s: fail read mode regs r=%d\n", - __func__, rc); - } - - cyttsp4_mt_attention(cd); - -cyttsp4_irq_handshake: - /* handshake the event */ - dev_vdbg(dev, "%s: Handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - rc = cyttsp4_handshake(cd, mode[0]); - if (rc < 0) - dev_err(dev, "%s: Fail handshake mode=0x%02X r=%d\n", - __func__, mode[0], rc); - - /* - * a non-zero udelay period is required for using - * IRQF_TRIGGER_LOW in order to delay until the - * device completes isr deassert - */ - udelay(cd->cpdata->level_irq_udelay); - -cyttsp4_irq_exit: - mutex_unlock(&cd->system_lock); - return IRQ_HANDLED; -} - -static void cyttsp4_start_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - mod_timer(&cd->watchdog_timer, jiffies + - msecs_to_jiffies(CY_WATCHDOG_TIMEOUT)); -} - -static void cyttsp4_stop_wd_timer(struct cyttsp4 *cd) -{ - if (!CY_WATCHDOG_TIMEOUT) - return; - - /* - * Ensure we wait until the watchdog timer - * running on a different CPU finishes - */ - timer_shutdown_sync(&cd->watchdog_timer); - cancel_work_sync(&cd->watchdog_work); -} - -static void cyttsp4_watchdog_timer(struct timer_list *t) -{ - struct cyttsp4 *cd = from_timer(cd, t, watchdog_timer); - - dev_vdbg(cd->dev, "%s: Watchdog timer triggered\n", __func__); - - schedule_work(&cd->watchdog_work); - - return; -} - -static int cyttsp4_request_exclusive(struct cyttsp4 *cd, void *ownptr, - int timeout_ms) -{ - int t = msecs_to_jiffies(timeout_ms); - bool with_timeout = (timeout_ms != 0); - - mutex_lock(&cd->system_lock); - if (!cd->exclusive_dev && cd->exclusive_waits == 0) { - cd->exclusive_dev = ownptr; - goto exit; - } - - cd->exclusive_waits++; -wait: - mutex_unlock(&cd->system_lock); - if (with_timeout) { - t = wait_event_timeout(cd->wait_q, !cd->exclusive_dev, t); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exclusive access\n", - __func__); - mutex_lock(&cd->system_lock); - cd->exclusive_waits--; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - } else { - wait_event(cd->wait_q, !cd->exclusive_dev); - } - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev) - goto wait; - cd->exclusive_dev = ownptr; - cd->exclusive_waits--; -exit: - mutex_unlock(&cd->system_lock); - - return 0; -} - -/* - * returns error if was not owned - */ -static int cyttsp4_release_exclusive(struct cyttsp4 *cd, void *ownptr) -{ - mutex_lock(&cd->system_lock); - if (cd->exclusive_dev != ownptr) { - mutex_unlock(&cd->system_lock); - return -EINVAL; - } - - dev_vdbg(cd->dev, "%s: exclusive_dev %p freed\n", - __func__, cd->exclusive_dev); - cd->exclusive_dev = NULL; - wake_up(&cd->wait_q); - mutex_unlock(&cd->system_lock); - return 0; -} - -static int cyttsp4_wait_bl_heartbeat(struct cyttsp4 *cd) -{ - long t; - int rc = 0; - - /* wait heartbeat */ - dev_vdbg(cd->dev, "%s: wait heartbeat...\n", __func__); - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_BOOTLOADER, - msecs_to_jiffies(CY_CORE_RESET_AND_WAIT_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting bl heartbeat cd->mode=%d\n", - __func__, cd->mode); - rc = -ETIME; - } - - return rc; -} - -static int cyttsp4_wait_sysinfo_mode(struct cyttsp4 *cd) -{ - long t; - - dev_vdbg(cd->dev, "%s: wait sysinfo...\n", __func__); - - t = wait_event_timeout(cd->wait_q, cd->mode == CY_MODE_SYSINFO, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: tmo waiting exit bl cd->mode=%d\n", - __func__, cd->mode); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - return -ETIME; - } - - return 0; -} - -static int cyttsp4_reset_and_wait(struct cyttsp4 *cd) -{ - int rc; - - /* reset hardware */ - mutex_lock(&cd->system_lock); - dev_dbg(cd->dev, "%s: reset hw...\n", __func__); - rc = cyttsp4_hw_reset(cd); - cd->mode = CY_MODE_UNKNOWN; - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s:Fail hw reset r=%d\n", __func__, rc); - return rc; - } - - return cyttsp4_wait_bl_heartbeat(cd); -} - -/* - * returns err if refused or timeout; block until mode change complete - * bit is set (mode change interrupt) - */ -static int cyttsp4_set_mode(struct cyttsp4 *cd, int new_mode) -{ - u8 new_dev_mode; - u8 mode; - long t; - int rc; - - switch (new_mode) { - case CY_MODE_OPERATIONAL: - new_dev_mode = CY_HST_OPERATE; - break; - case CY_MODE_SYSINFO: - new_dev_mode = CY_HST_SYSINFO; - break; - case CY_MODE_CAT: - new_dev_mode = CY_HST_CAT; - break; - default: - dev_err(cd->dev, "%s: invalid mode: %02X(%d)\n", - __func__, new_mode, new_mode); - return -EINVAL; - } - - /* change mode */ - dev_dbg(cd->dev, "%s: %s=%p new_dev_mode=%02X new_mode=%d\n", - __func__, "have exclusive", cd->exclusive_dev, - new_dev_mode, new_mode); - - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc < 0) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read mode r=%d\n", - __func__, rc); - goto exit; - } - - /* Clear device mode bits and set to new mode */ - mode &= ~CY_HST_MODE; - mode |= new_dev_mode | CY_HST_MODE_CHANGE; - - cd->int_status |= CY_INT_MODE_CHANGE; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode), &mode); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write mode change r=%d\n", - __func__, rc); - goto exit; - } - - /* wait for mode change done interrupt */ - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_MODE_CHANGE) == 0, - msecs_to_jiffies(CY_CORE_MODE_CHANGE_TIMEOUT)); - dev_dbg(cd->dev, "%s: back from wait t=%ld cd->mode=%d\n", - __func__, t, cd->mode); - - if (IS_TMO(t)) { - dev_err(cd->dev, "%s: %s\n", __func__, - "tmo waiting mode change"); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_MODE_CHANGE; - mutex_unlock(&cd->system_lock); - rc = -EINVAL; - } - -exit: - return rc; -} - -static void cyttsp4_watchdog_work(struct work_struct *work) -{ - struct cyttsp4 *cd = - container_of(work, struct cyttsp4, watchdog_work); - u8 *mode; - int retval; - - mutex_lock(&cd->system_lock); - retval = cyttsp4_load_status_regs(cd); - if (retval < 0) { - dev_err(cd->dev, - "%s: failed to access device in watchdog timer r=%d\n", - __func__, retval); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - mode = &cd->sysinfo.xy_mode[CY_REG_BASE]; - if (IS_BOOTLOADER(mode[0], mode[1])) { - dev_err(cd->dev, - "%s: device found in bootloader mode when operational mode\n", - __func__); - cyttsp4_queue_startup_(cd); - goto cyttsp4_timer_watchdog_exit_error; - } - - cyttsp4_start_wd_timer(cd); -cyttsp4_timer_watchdog_exit_error: - mutex_unlock(&cd->system_lock); - return; -} - -static int cyttsp4_core_sleep_(struct cyttsp4 *cd) -{ - enum cyttsp4_sleep_state ss = SS_SLEEP_ON; - enum cyttsp4_int_state int_status = CY_INT_IGNORE; - int rc = 0; - u8 mode[2]; - - /* Already in sleep mode? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->sleep_state = SS_SLEEPING; - mutex_unlock(&cd->system_lock); - - cyttsp4_stop_wd_timer(cd); - - /* Wait until currently running IRQ handler exits and disable IRQ */ - disable_irq(cd->irq); - - dev_vdbg(cd->dev, "%s: write DEEP SLEEP...\n", __func__); - mutex_lock(&cd->system_lock); - rc = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - if (rc) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Fail read adapter r=%d\n", __func__, rc); - goto error; - } - - if (IS_BOOTLOADER(mode[0], mode[1])) { - mutex_unlock(&cd->system_lock); - dev_err(cd->dev, "%s: Device in BOOTLOADER mode.\n", __func__); - rc = -EINVAL; - goto error; - } - - mode[0] |= CY_HST_SLEEP; - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(mode[0]), &mode[0]); - mutex_unlock(&cd->system_lock); - if (rc) { - dev_err(cd->dev, "%s: Fail write adapter r=%d\n", __func__, rc); - goto error; - } - dev_vdbg(cd->dev, "%s: write DEEP SLEEP succeeded\n", __func__); - - if (cd->cpdata->power) { - dev_dbg(cd->dev, "%s: Power down HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 0, cd->dev, &cd->ignore_irq); - } else { - dev_dbg(cd->dev, "%s: No power function\n", __func__); - rc = 0; - } - if (rc < 0) { - dev_err(cd->dev, "%s: HW Power down fails r=%d\n", - __func__, rc); - goto error; - } - - /* Give time to FW to sleep */ - msleep(50); - - goto exit; - -error: - ss = SS_SLEEP_OFF; - int_status = CY_INT_NONE; - cyttsp4_start_wd_timer(cd); - -exit: - mutex_lock(&cd->system_lock); - cd->sleep_state = ss; - cd->int_status |= int_status; - mutex_unlock(&cd->system_lock); - enable_irq(cd->irq); - return rc; -} - -static int cyttsp4_startup_(struct cyttsp4 *cd) -{ - int retry = CY_CORE_STARTUP_RETRY_COUNT; - int rc; - - cyttsp4_stop_wd_timer(cd); - -reset: - if (retry != CY_CORE_STARTUP_RETRY_COUNT) - dev_dbg(cd->dev, "%s: Retry %d\n", __func__, - CY_CORE_STARTUP_RETRY_COUNT - retry); - - /* reset hardware and wait for heartbeat */ - rc = cyttsp4_reset_and_wait(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: Error on h/w reset r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - /* exit bl into sysinfo mode */ - dev_vdbg(cd->dev, "%s: write exit ldr...\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_MODE_CHANGE; - - rc = cyttsp4_adap_write(cd, CY_REG_BASE, sizeof(ldr_exit), - (u8 *)ldr_exit); - mutex_unlock(&cd->system_lock); - if (rc < 0) { - dev_err(cd->dev, "%s: Fail write r=%d\n", __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_wait_sysinfo_mode(cd); - if (rc < 0) { - u8 buf[sizeof(ldr_err_app)]; - int rc1; - - /* Check for invalid/corrupted touch application */ - rc1 = cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(ldr_err_app), - buf); - if (rc1) { - dev_err(cd->dev, "%s: Fail read r=%d\n", __func__, rc1); - } else if (!memcmp(buf, ldr_err_app, sizeof(ldr_err_app))) { - dev_err(cd->dev, "%s: Error launching touch application\n", - __func__); - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = true; - mutex_unlock(&cd->system_lock); - goto exit_no_wd; - } - - if (retry--) - goto reset; - goto exit; - } - - mutex_lock(&cd->system_lock); - cd->invalid_touch_app = false; - mutex_unlock(&cd->system_lock); - - /* read sysinfo data */ - dev_vdbg(cd->dev, "%s: get sysinfo regs..\n", __func__); - rc = cyttsp4_get_sysinfo_regs(cd); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to get sysinfo regs rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - rc = cyttsp4_set_mode(cd, CY_MODE_OPERATIONAL); - if (rc < 0) { - dev_err(cd->dev, "%s: failed to set mode to operational rc=%d\n", - __func__, rc); - if (retry--) - goto reset; - goto exit; - } - - cyttsp4_lift_all(&cd->md); - - /* restore to sleep if was suspended */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_ON) { - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - cyttsp4_core_sleep_(cd); - goto exit_no_wd; - } - mutex_unlock(&cd->system_lock); - -exit: - cyttsp4_start_wd_timer(cd); -exit_no_wd: - return rc; -} - -static int cyttsp4_startup(struct cyttsp4 *cd) -{ - int rc; - - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_RUNNING; - mutex_unlock(&cd->system_lock); - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - goto exit; - } - - rc = cyttsp4_startup_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - /* Don't return fail code, mode is already changed. */ - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - -exit: - mutex_lock(&cd->system_lock); - cd->startup_state = STARTUP_NONE; - mutex_unlock(&cd->system_lock); - - /* Wake the waiters for end of startup */ - wake_up(&cd->wait_q); - - return rc; -} - -static void cyttsp4_startup_work_function(struct work_struct *work) -{ - struct cyttsp4 *cd = container_of(work, struct cyttsp4, startup_work); - int rc; - - rc = cyttsp4_startup(cd); - if (rc < 0) - dev_err(cd->dev, "%s: Fail queued startup r=%d\n", - __func__, rc); -} - -static void cyttsp4_free_si_ptrs(struct cyttsp4 *cd) -{ - struct cyttsp4_sysinfo *si = &cd->sysinfo; - - if (!si) - return; - - kfree(si->si_ptrs.cydata); - kfree(si->si_ptrs.test); - kfree(si->si_ptrs.pcfg); - kfree(si->si_ptrs.opcfg); - kfree(si->si_ptrs.ddata); - kfree(si->si_ptrs.mdata); - kfree(si->btn); - kfree(si->xy_mode); - kfree(si->xy_data); - kfree(si->btn_rec_data); -} - -static int cyttsp4_core_sleep(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_SLEEP_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_sleep_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_wake_(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - int rc; - u8 mode; - int t; - - /* Already woken? */ - mutex_lock(&cd->system_lock); - if (cd->sleep_state == SS_SLEEP_OFF) { - mutex_unlock(&cd->system_lock); - return 0; - } - cd->int_status &= ~CY_INT_IGNORE; - cd->int_status |= CY_INT_AWAKE; - cd->sleep_state = SS_WAKING; - - if (cd->cpdata->power) { - dev_dbg(dev, "%s: Power up HW\n", __func__); - rc = cd->cpdata->power(cd->cpdata, 1, dev, &cd->ignore_irq); - } else { - dev_dbg(dev, "%s: No power function\n", __func__); - rc = -ENOSYS; - } - if (rc < 0) { - dev_err(dev, "%s: HW Power up fails r=%d\n", - __func__, rc); - - /* Initiate a read transaction to wake up */ - cyttsp4_adap_read(cd, CY_REG_BASE, sizeof(mode), &mode); - } else - dev_vdbg(cd->dev, "%s: HW power up succeeds\n", - __func__); - mutex_unlock(&cd->system_lock); - - t = wait_event_timeout(cd->wait_q, - (cd->int_status & CY_INT_AWAKE) == 0, - msecs_to_jiffies(CY_CORE_WAKEUP_TIMEOUT)); - if (IS_TMO(t)) { - dev_err(dev, "%s: TMO waiting for wakeup\n", __func__); - mutex_lock(&cd->system_lock); - cd->int_status &= ~CY_INT_AWAKE; - /* Try starting up */ - cyttsp4_queue_startup_(cd); - mutex_unlock(&cd->system_lock); - } - - mutex_lock(&cd->system_lock); - cd->sleep_state = SS_SLEEP_OFF; - mutex_unlock(&cd->system_lock); - - cyttsp4_start_wd_timer(cd); - - return 0; -} - -static int cyttsp4_core_wake(struct cyttsp4 *cd) -{ - int rc; - - rc = cyttsp4_request_exclusive(cd, cd->dev, - CY_CORE_REQUEST_EXCLUSIVE_TIMEOUT); - if (rc < 0) { - dev_err(cd->dev, "%s: fail get exclusive ex=%p own=%p\n", - __func__, cd->exclusive_dev, cd->dev); - return 0; - } - - rc = cyttsp4_core_wake_(cd); - - if (cyttsp4_release_exclusive(cd, cd->dev) < 0) - dev_err(cd->dev, "%s: fail to release exclusive\n", __func__); - else - dev_vdbg(cd->dev, "%s: pass release exclusive\n", __func__); - - return rc; -} - -static int cyttsp4_core_suspend(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = true; - - rc = cyttsp4_core_sleep(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on sleep\n", __func__); - return -EAGAIN; - } - return 0; -} - -static int cyttsp4_core_resume(struct device *dev) -{ - struct cyttsp4 *cd = dev_get_drvdata(dev); - struct cyttsp4_mt_data *md = &cd->md; - int rc; - - md->is_suspended = false; - - rc = cyttsp4_core_wake(cd); - if (rc < 0) { - dev_err(dev, "%s: Error on wake\n", __func__); - return -EAGAIN; - } - - return 0; -} - -EXPORT_GPL_RUNTIME_DEV_PM_OPS(cyttsp4_pm_ops, - cyttsp4_core_suspend, cyttsp4_core_resume, NULL); - -static int cyttsp4_mt_open(struct input_dev *input) -{ - pm_runtime_get(input->dev.parent); - return 0; -} - -static void cyttsp4_mt_close(struct input_dev *input) -{ - struct cyttsp4_mt_data *md = input_get_drvdata(input); - mutex_lock(&md->report_lock); - if (!md->is_suspended) - pm_runtime_put(input->dev.parent); - mutex_unlock(&md->report_lock); -} - - -static int cyttsp4_setup_input_device(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - int signal = CY_IGNORE_VALUE; - int max_x, max_y, max_p, min, max; - int max_x_tmp, max_y_tmp; - int i; - int rc; - - dev_vdbg(dev, "%s: Initialize event signals\n", __func__); - __set_bit(EV_ABS, md->input->evbit); - __set_bit(EV_REL, md->input->evbit); - __set_bit(EV_KEY, md->input->evbit); - - max_x_tmp = md->si->si_ofs.max_x; - max_y_tmp = md->si->si_ofs.max_y; - - /* get maximum values from the sysinfo data */ - if (md->pdata->flags & CY_FLAG_FLIP) { - max_x = max_y_tmp - 1; - max_y = max_x_tmp - 1; - } else { - max_x = max_x_tmp - 1; - max_y = max_y_tmp - 1; - } - max_p = md->si->si_ofs.max_p; - - /* set event signal capabilities */ - for (i = 0; i < (md->pdata->frmwrk->size / CY_NUM_ABS_SET); i++) { - signal = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_SIGNAL_OST]; - if (signal != CY_IGNORE_VALUE) { - __set_bit(signal, md->input->absbit); - min = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MIN_OST]; - max = md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_MAX_OST]; - if (i == CY_ABS_ID_OST) { - /* shift track ids down to start at 0 */ - max = max - min; - min = min - min; - } else if (i == CY_ABS_X_OST) - max = max_x; - else if (i == CY_ABS_Y_OST) - max = max_y; - else if (i == CY_ABS_P_OST) - max = max_p; - input_set_abs_params(md->input, signal, min, max, - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FUZZ_OST], - md->pdata->frmwrk->abs - [(i * CY_NUM_ABS_SET) + CY_FLAT_OST]); - dev_dbg(dev, "%s: register signal=%02X min=%d max=%d\n", - __func__, signal, min, max); - if ((i == CY_ABS_ID_OST) && - (md->si->si_ofs.tch_rec_size < - CY_TMA4XX_TCH_REC_SIZE)) - break; - } - } - - input_mt_init_slots(md->input, md->si->si_ofs.tch_abs[CY_TCH_T].max, - INPUT_MT_DIRECT); - rc = input_register_device(md->input); - if (rc < 0) - dev_err(dev, "%s: Error, failed register input device r=%d\n", - __func__, rc); - return rc; -} - -static int cyttsp4_mt_probe(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - struct cyttsp4_mt_data *md = &cd->md; - struct cyttsp4_mt_platform_data *pdata = cd->pdata->mt_pdata; - int rc = 0; - - mutex_init(&md->report_lock); - md->pdata = pdata; - /* Create the input device and register it. */ - dev_vdbg(dev, "%s: Create the input device and register it\n", - __func__); - md->input = input_allocate_device(); - if (md->input == NULL) { - dev_err(dev, "%s: Error, failed to allocate input device\n", - __func__); - rc = -ENOSYS; - goto error_alloc_failed; - } - - md->input->name = pdata->inp_dev_name; - scnprintf(md->phys, sizeof(md->phys)-1, "%s", dev_name(dev)); - md->input->phys = md->phys; - md->input->id.bustype = cd->bus_ops->bustype; - md->input->dev.parent = dev; - md->input->open = cyttsp4_mt_open; - md->input->close = cyttsp4_mt_close; - input_set_drvdata(md->input, md); - - /* get sysinfo */ - md->si = &cd->sysinfo; - - rc = cyttsp4_setup_input_device(cd); - if (rc) - goto error_init_input; - - return 0; - -error_init_input: - input_free_device(md->input); -error_alloc_failed: - dev_err(dev, "%s failed.\n", __func__); - return rc; -} - -struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size) -{ - struct cyttsp4 *cd; - struct cyttsp4_platform_data *pdata = dev_get_platdata(dev); - unsigned long irq_flags; - int rc = 0; - - if (!pdata || !pdata->core_pdata || !pdata->mt_pdata) { - dev_err(dev, "%s: Missing platform data\n", __func__); - rc = -ENODEV; - goto error_no_pdata; - } - - cd = kzalloc(sizeof(*cd), GFP_KERNEL); - if (!cd) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_alloc_data; - } - - cd->xfer_buf = kzalloc(xfer_buf_size, GFP_KERNEL); - if (!cd->xfer_buf) { - dev_err(dev, "%s: Error, kzalloc\n", __func__); - rc = -ENOMEM; - goto error_free_cd; - } - - /* Initialize device info */ - cd->dev = dev; - cd->pdata = pdata; - cd->cpdata = pdata->core_pdata; - cd->bus_ops = ops; - - /* Initialize mutexes and spinlocks */ - mutex_init(&cd->system_lock); - mutex_init(&cd->adap_lock); - - /* Initialize wait queue */ - init_waitqueue_head(&cd->wait_q); - - /* Initialize works */ - INIT_WORK(&cd->startup_work, cyttsp4_startup_work_function); - INIT_WORK(&cd->watchdog_work, cyttsp4_watchdog_work); - - /* Initialize IRQ */ - cd->irq = gpio_to_irq(cd->cpdata->irq_gpio); - if (cd->irq < 0) { - rc = -EINVAL; - goto error_free_xfer; - } - - dev_set_drvdata(dev, cd); - - /* Call platform init function */ - if (cd->cpdata->init) { - dev_dbg(cd->dev, "%s: Init HW\n", __func__); - rc = cd->cpdata->init(cd->cpdata, 1, cd->dev); - } else { - dev_dbg(cd->dev, "%s: No HW INIT function\n", __func__); - rc = 0; - } - if (rc < 0) - dev_err(cd->dev, "%s: HW Init fail r=%d\n", __func__, rc); - - dev_dbg(dev, "%s: initialize threaded irq=%d\n", __func__, cd->irq); - if (cd->cpdata->level_irq_udelay > 0) - /* use level triggered interrupts */ - irq_flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT; - else - /* use edge triggered interrupts */ - irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; - - rc = request_threaded_irq(cd->irq, NULL, cyttsp4_irq, irq_flags, - dev_name(dev), cd); - if (rc < 0) { - dev_err(dev, "%s: Error, could not request irq\n", __func__); - goto error_request_irq; - } - - /* Setup watchdog timer */ - timer_setup(&cd->watchdog_timer, cyttsp4_watchdog_timer, 0); - - /* - * call startup directly to ensure that the device - * is tested before leaving the probe - */ - rc = cyttsp4_startup(cd); - - /* Do not fail probe if startup fails but the device is detected */ - if (rc < 0 && cd->mode == CY_MODE_UNKNOWN) { - dev_err(cd->dev, "%s: Fail initial startup r=%d\n", - __func__, rc); - goto error_startup; - } - - rc = cyttsp4_mt_probe(cd); - if (rc < 0) { - dev_err(dev, "%s: Error, fail mt probe\n", __func__); - goto error_startup; - } - - pm_runtime_enable(dev); - - return cd; - -error_startup: - cancel_work_sync(&cd->startup_work); - cyttsp4_stop_wd_timer(cd); - pm_runtime_disable(dev); - cyttsp4_free_si_ptrs(cd); - free_irq(cd->irq, cd); -error_request_irq: - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); -error_free_xfer: - kfree(cd->xfer_buf); -error_free_cd: - kfree(cd); -error_alloc_data: -error_no_pdata: - dev_err(dev, "%s failed.\n", __func__); - return ERR_PTR(rc); -} -EXPORT_SYMBOL_GPL(cyttsp4_probe); - -static void cyttsp4_mt_release(struct cyttsp4_mt_data *md) -{ - input_unregister_device(md->input); - input_set_drvdata(md->input, NULL); -} - -int cyttsp4_remove(struct cyttsp4 *cd) -{ - struct device *dev = cd->dev; - - cyttsp4_mt_release(&cd->md); - - /* - * Suspend the device before freeing the startup_work and stopping - * the watchdog since sleep function restarts watchdog on failure - */ - pm_runtime_suspend(dev); - pm_runtime_disable(dev); - - cancel_work_sync(&cd->startup_work); - - cyttsp4_stop_wd_timer(cd); - - free_irq(cd->irq, cd); - if (cd->cpdata->init) - cd->cpdata->init(cd->cpdata, 0, dev); - cyttsp4_free_si_ptrs(cd); - kfree(cd); - return 0; -} -EXPORT_SYMBOL_GPL(cyttsp4_remove); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen core driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_core.h b/drivers/input/touchscreen/cyttsp4_core.h deleted file mode 100644 index 6262f6e45075..000000000000 --- a/drivers/input/touchscreen/cyttsp4_core.h +++ /dev/null @@ -1,448 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * cyttsp4_core.h - * Cypress TrueTouch(TM) Standard Product V4 Core driver module. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2012 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#ifndef _LINUX_CYTTSP4_CORE_H -#define _LINUX_CYTTSP4_CORE_H - -#include <linux/device.h> -#include <linux/err.h> -#include <linux/input.h> -#include <linux/kernel.h> -#include <linux/limits.h> -#include <linux/module.h> -#include <linux/stringify.h> -#include <linux/types.h> -#include <linux/platform_data/cyttsp4.h> - -#define CY_REG_BASE 0x00 - -#define CY_POST_CODEL_WDG_RST 0x01 -#define CY_POST_CODEL_CFG_DATA_CRC_FAIL 0x02 -#define CY_POST_CODEL_PANEL_TEST_FAIL 0x04 - -#define CY_NUM_BTN_PER_REG 4 - -/* touch record system information offset masks and shifts */ -#define CY_BYTE_OFS_MASK 0x1F -#define CY_BOFS_MASK 0xE0 -#define CY_BOFS_SHIFT 5 - -#define CY_TMA1036_TCH_REC_SIZE 6 -#define CY_TMA4XX_TCH_REC_SIZE 9 -#define CY_TMA1036_MAX_TCH 0x0E -#define CY_TMA4XX_MAX_TCH 0x1E - -#define CY_NORMAL_ORIGIN 0 /* upper, left corner */ -#define CY_INVERT_ORIGIN 1 /* lower, right corner */ - -/* helpers */ -#define GET_NUM_TOUCHES(x) ((x) & 0x1F) -#define IS_LARGE_AREA(x) ((x) & 0x20) -#define IS_BAD_PKT(x) ((x) & 0x20) -#define IS_BOOTLOADER(hst_mode, reset_detect) \ - ((hst_mode) & 0x01 || (reset_detect) != 0) -#define IS_TMO(t) ((t) == 0) - - -enum cyttsp_cmd_bits { - CY_CMD_COMPLETE = (1 << 6), -}; - -/* Timeout in ms. */ -#define CY_WATCHDOG_TIMEOUT 1000 - -#define CY_MAX_PRINT_SIZE 512 -#ifdef VERBOSE_DEBUG -#define CY_MAX_PRBUF_SIZE PIPE_BUF -#define CY_PR_TRUNCATED " truncated..." -#endif - -enum cyttsp4_ic_grpnum { - CY_IC_GRPNUM_RESERVED, - CY_IC_GRPNUM_CMD_REGS, - CY_IC_GRPNUM_TCH_REP, - CY_IC_GRPNUM_DATA_REC, - CY_IC_GRPNUM_TEST_REC, - CY_IC_GRPNUM_PCFG_REC, - CY_IC_GRPNUM_TCH_PARM_VAL, - CY_IC_GRPNUM_TCH_PARM_SIZE, - CY_IC_GRPNUM_RESERVED1, - CY_IC_GRPNUM_RESERVED2, - CY_IC_GRPNUM_OPCFG_REC, - CY_IC_GRPNUM_DDATA_REC, - CY_IC_GRPNUM_MDATA_REC, - CY_IC_GRPNUM_TEST_REGS, - CY_IC_GRPNUM_BTN_KEYS, - CY_IC_GRPNUM_TTHE_REGS, - CY_IC_GRPNUM_NUM -}; - -enum cyttsp4_int_state { - CY_INT_NONE, - CY_INT_IGNORE = (1 << 0), - CY_INT_MODE_CHANGE = (1 << 1), - CY_INT_EXEC_CMD = (1 << 2), - CY_INT_AWAKE = (1 << 3), -}; - -enum cyttsp4_mode { - CY_MODE_UNKNOWN, - CY_MODE_BOOTLOADER = (1 << 1), - CY_MODE_OPERATIONAL = (1 << 2), - CY_MODE_SYSINFO = (1 << 3), - CY_MODE_CAT = (1 << 4), - CY_MODE_STARTUP = (1 << 5), - CY_MODE_LOADER = (1 << 6), - CY_MODE_CHANGE_MODE = (1 << 7), - CY_MODE_CHANGED = (1 << 8), - CY_MODE_CMD_COMPLETE = (1 << 9), -}; - -enum cyttsp4_sleep_state { - SS_SLEEP_OFF, - SS_SLEEP_ON, - SS_SLEEPING, - SS_WAKING, -}; - -enum cyttsp4_startup_state { - STARTUP_NONE, - STARTUP_QUEUED, - STARTUP_RUNNING, -}; - -#define CY_NUM_REVCTRL 8 -struct cyttsp4_cydata { - u8 ttpidh; - u8 ttpidl; - u8 fw_ver_major; - u8 fw_ver_minor; - u8 revctrl[CY_NUM_REVCTRL]; - u8 blver_major; - u8 blver_minor; - u8 jtag_si_id3; - u8 jtag_si_id2; - u8 jtag_si_id1; - u8 jtag_si_id0; - u8 mfgid_sz; - u8 cyito_idh; - u8 cyito_idl; - u8 cyito_verh; - u8 cyito_verl; - u8 ttsp_ver_major; - u8 ttsp_ver_minor; - u8 device_info; - u8 mfg_id[]; -} __packed; - -struct cyttsp4_test { - u8 post_codeh; - u8 post_codel; -} __packed; - -struct cyttsp4_pcfg { - u8 electrodes_x; - u8 electrodes_y; - u8 len_xh; - u8 len_xl; - u8 len_yh; - u8 len_yl; - u8 res_xh; - u8 res_xl; - u8 res_yh; - u8 res_yl; - u8 max_zh; - u8 max_zl; - u8 panel_info0; -} __packed; - -struct cyttsp4_tch_rec_params { - u8 loc; - u8 size; -} __packed; - -#define CY_NUM_TCH_FIELDS 7 -#define CY_NUM_EXT_TCH_FIELDS 3 -struct cyttsp4_opcfg { - u8 cmd_ofs; - u8 rep_ofs; - u8 rep_szh; - u8 rep_szl; - u8 num_btns; - u8 tt_stat_ofs; - u8 obj_cfg0; - u8 max_tchs; - u8 tch_rec_size; - struct cyttsp4_tch_rec_params tch_rec_old[CY_NUM_TCH_FIELDS]; - u8 btn_rec_size; /* btn record size (in bytes) */ - u8 btn_diff_ofs; /* btn data loc, diff counts */ - u8 btn_diff_size; /* btn size of diff counts (in bits) */ - struct cyttsp4_tch_rec_params tch_rec_new[CY_NUM_EXT_TCH_FIELDS]; -} __packed; - -struct cyttsp4_sysinfo_ptr { - struct cyttsp4_cydata *cydata; - struct cyttsp4_test *test; - struct cyttsp4_pcfg *pcfg; - struct cyttsp4_opcfg *opcfg; - struct cyttsp4_ddata *ddata; - struct cyttsp4_mdata *mdata; -} __packed; - -struct cyttsp4_sysinfo_data { - u8 hst_mode; - u8 reserved; - u8 map_szh; - u8 map_szl; - u8 cydata_ofsh; - u8 cydata_ofsl; - u8 test_ofsh; - u8 test_ofsl; - u8 pcfg_ofsh; - u8 pcfg_ofsl; - u8 opcfg_ofsh; - u8 opcfg_ofsl; - u8 ddata_ofsh; - u8 ddata_ofsl; - u8 mdata_ofsh; - u8 mdata_ofsl; -} __packed; - -enum cyttsp4_tch_abs { /* for ordering within the extracted touch data array */ - CY_TCH_X, /* X */ - CY_TCH_Y, /* Y */ - CY_TCH_P, /* P (Z) */ - CY_TCH_T, /* TOUCH ID */ - CY_TCH_E, /* EVENT ID */ - CY_TCH_O, /* OBJECT ID */ - CY_TCH_W, /* SIZE */ - CY_TCH_MAJ, /* TOUCH_MAJOR */ - CY_TCH_MIN, /* TOUCH_MINOR */ - CY_TCH_OR, /* ORIENTATION */ - CY_TCH_NUM_ABS -}; - -struct cyttsp4_touch { - int abs[CY_TCH_NUM_ABS]; -}; - -struct cyttsp4_tch_abs_params { - size_t ofs; /* abs byte offset */ - size_t size; /* size in bits */ - size_t max; /* max value */ - size_t bofs; /* bit offset */ -}; - -struct cyttsp4_sysinfo_ofs { - size_t chip_type; - size_t cmd_ofs; - size_t rep_ofs; - size_t rep_sz; - size_t num_btns; - size_t num_btn_regs; /* ceil(num_btns/4) */ - size_t tt_stat_ofs; - size_t tch_rec_size; - size_t obj_cfg0; - size_t max_tchs; - size_t mode_size; - size_t data_size; - size_t map_sz; - size_t max_x; - size_t x_origin; /* left or right corner */ - size_t max_y; - size_t y_origin; /* upper or lower corner */ - size_t max_p; - size_t cydata_ofs; - size_t test_ofs; - size_t pcfg_ofs; - size_t opcfg_ofs; - size_t ddata_ofs; - size_t mdata_ofs; - size_t cydata_size; - size_t test_size; - size_t pcfg_size; - size_t opcfg_size; - size_t ddata_size; - size_t mdata_size; - size_t btn_keys_size; - struct cyttsp4_tch_abs_params tch_abs[CY_TCH_NUM_ABS]; - size_t btn_rec_size; /* btn record size (in bytes) */ - size_t btn_diff_ofs;/* btn data loc ,diff counts, (Op-Mode byte ofs) */ - size_t btn_diff_size;/* btn size of diff counts (in bits) */ -}; - -enum cyttsp4_btn_state { - CY_BTN_RELEASED, - CY_BTN_PRESSED, - CY_BTN_NUM_STATE -}; - -struct cyttsp4_btn { - bool enabled; - int state; /* CY_BTN_PRESSED, CY_BTN_RELEASED */ - int key_code; -}; - -struct cyttsp4_sysinfo { - bool ready; - struct cyttsp4_sysinfo_data si_data; - struct cyttsp4_sysinfo_ptr si_ptrs; - struct cyttsp4_sysinfo_ofs si_ofs; - struct cyttsp4_btn *btn; /* button states */ - u8 *btn_rec_data; /* button diff count data */ - u8 *xy_mode; /* operational mode and status regs */ - u8 *xy_data; /* operational touch regs */ -}; - -struct cyttsp4_mt_data { - struct cyttsp4_mt_platform_data *pdata; - struct cyttsp4_sysinfo *si; - struct input_dev *input; - struct mutex report_lock; - bool is_suspended; - char phys[NAME_MAX]; - int num_prv_tch; -}; - -struct cyttsp4 { - struct device *dev; - struct mutex system_lock; - struct mutex adap_lock; - enum cyttsp4_mode mode; - enum cyttsp4_sleep_state sleep_state; - enum cyttsp4_startup_state startup_state; - int int_status; - wait_queue_head_t wait_q; - int irq; - struct work_struct startup_work; - struct work_struct watchdog_work; - struct timer_list watchdog_timer; - struct cyttsp4_sysinfo sysinfo; - void *exclusive_dev; - int exclusive_waits; - atomic_t ignore_irq; - bool invalid_touch_app; - struct cyttsp4_mt_data md; - struct cyttsp4_platform_data *pdata; - struct cyttsp4_core_platform_data *cpdata; - const struct cyttsp4_bus_ops *bus_ops; - u8 *xfer_buf; -#ifdef VERBOSE_DEBUG - u8 pr_buf[CY_MAX_PRBUF_SIZE]; -#endif -}; - -struct cyttsp4_bus_ops { - u16 bustype; - int (*write)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - const void *values); - int (*read)(struct device *dev, u8 *xfer_buf, u16 addr, u8 length, - void *values); -}; - -enum cyttsp4_hst_mode_bits { - CY_HST_TOGGLE = (1 << 7), - CY_HST_MODE_CHANGE = (1 << 3), - CY_HST_MODE = (7 << 4), - CY_HST_OPERATE = (0 << 4), - CY_HST_SYSINFO = (1 << 4), - CY_HST_CAT = (2 << 4), - CY_HST_LOWPOW = (1 << 2), - CY_HST_SLEEP = (1 << 1), - CY_HST_RESET = (1 << 0), -}; - -/* abs settings */ -#define CY_IGNORE_VALUE 0xFFFF - -/* abs signal capabilities offsets in the frameworks array */ -enum cyttsp4_sig_caps { - CY_SIGNAL_OST, - CY_MIN_OST, - CY_MAX_OST, - CY_FUZZ_OST, - CY_FLAT_OST, - CY_NUM_ABS_SET /* number of signal capability fields */ -}; - -/* abs axis signal offsets in the framworks array */ -enum cyttsp4_sig_ost { - CY_ABS_X_OST, - CY_ABS_Y_OST, - CY_ABS_P_OST, - CY_ABS_W_OST, - CY_ABS_ID_OST, - CY_ABS_MAJ_OST, - CY_ABS_MIN_OST, - CY_ABS_OR_OST, - CY_NUM_ABS_OST /* number of abs signals */ -}; - -enum cyttsp4_flags { - CY_FLAG_NONE = 0x00, - CY_FLAG_HOVER = 0x04, - CY_FLAG_FLIP = 0x08, - CY_FLAG_INV_X = 0x10, - CY_FLAG_INV_Y = 0x20, - CY_FLAG_VKEYS = 0x40, -}; - -enum cyttsp4_object_id { - CY_OBJ_STANDARD_FINGER, - CY_OBJ_LARGE_OBJECT, - CY_OBJ_STYLUS, - CY_OBJ_HOVER, -}; - -enum cyttsp4_event_id { - CY_EV_NO_EVENT, - CY_EV_TOUCHDOWN, - CY_EV_MOVE, /* significant displacement (> act dist) */ - CY_EV_LIFTOFF, /* record reports last position */ -}; - -/* x-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_X_MASK 0x7F - -/* y-axis resolution of panel in pixels */ -#define CY_PCFG_RESOLUTION_Y_MASK 0x7F - -/* x-axis, 0:origin is on left side of panel, 1: right */ -#define CY_PCFG_ORIGIN_X_MASK 0x80 - -/* y-axis, 0:origin is on top side of panel, 1: bottom */ -#define CY_PCFG_ORIGIN_Y_MASK 0x80 - -static inline int cyttsp4_adap_read(struct cyttsp4 *ts, u16 addr, int size, - void *buf) -{ - return ts->bus_ops->read(ts->dev, ts->xfer_buf, addr, size, buf); -} - -static inline int cyttsp4_adap_write(struct cyttsp4 *ts, u16 addr, int size, - const void *buf) -{ - return ts->bus_ops->write(ts->dev, ts->xfer_buf, addr, size, buf); -} - -extern struct cyttsp4 *cyttsp4_probe(const struct cyttsp4_bus_ops *ops, - struct device *dev, u16 irq, size_t xfer_buf_size); -extern int cyttsp4_remove(struct cyttsp4 *ts); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); -extern const struct dev_pm_ops cyttsp4_pm_ops; - -#endif /* _LINUX_CYTTSP4_CORE_H */ diff --git a/drivers/input/touchscreen/cyttsp4_i2c.c b/drivers/input/touchscreen/cyttsp4_i2c.c deleted file mode 100644 index 80a6890cd45a..000000000000 --- a/drivers/input/touchscreen/cyttsp4_i2c.c +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" - -#include <linux/i2c.h> -#include <linux/input.h> - -#define CYTTSP4_I2C_DATA_SIZE (3 * 256) - -static const struct cyttsp4_bus_ops cyttsp4_i2c_bus_ops = { - .bustype = BUS_I2C, - .write = cyttsp_i2c_write_block_data, - .read = cyttsp_i2c_read_block_data, -}; - -static int cyttsp4_i2c_probe(struct i2c_client *client) -{ - struct cyttsp4 *ts; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "I2C functionality not Supported\n"); - return -EIO; - } - - ts = cyttsp4_probe(&cyttsp4_i2c_bus_ops, &client->dev, client->irq, - CYTTSP4_I2C_DATA_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_i2c_remove(struct i2c_client *client) -{ - struct cyttsp4 *ts = i2c_get_clientdata(client); - - cyttsp4_remove(ts); -} - -static const struct i2c_device_id cyttsp4_i2c_id[] = { - { CYTTSP4_I2C_NAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, cyttsp4_i2c_id); - -static struct i2c_driver cyttsp4_i2c_driver = { - .driver = { - .name = CYTTSP4_I2C_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_i2c_probe, - .remove = cyttsp4_i2c_remove, - .id_table = cyttsp4_i2c_id, -}; - -module_i2c_driver(cyttsp4_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) I2C driver"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c deleted file mode 100644 index 944fbbe9113e..000000000000 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Source for: - * Cypress TrueTouch(TM) Standard Product (TTSP) SPI touchscreen driver. - * For use with Cypress Txx4xx parts. - * Supported parts include: - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * Copyright (C) 2013 Cypress Semiconductor - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include "cyttsp4_core.h" - -#include <linux/delay.h> -#include <linux/input.h> -#include <linux/spi/spi.h> - -#define CY_SPI_WR_OP 0x00 /* r/~w */ -#define CY_SPI_RD_OP 0x01 -#define CY_SPI_BITS_PER_WORD 8 -#define CY_SPI_A8_BIT 0x02 -#define CY_SPI_WR_HEADER_BYTES 2 -#define CY_SPI_RD_HEADER_BYTES 1 -#define CY_SPI_CMD_BYTES 2 -#define CY_SPI_SYNC_BYTE 0 -#define CY_SPI_SYNC_ACK 0x62 /* from TRM *A protocol */ -#define CY_SPI_DATA_SIZE (2 * 256) - -#define CY_SPI_DATA_BUF_SIZE (CY_SPI_CMD_BYTES + CY_SPI_DATA_SIZE) - -static int cyttsp_spi_xfer(struct device *dev, u8 *xfer_buf, - u8 op, u16 reg, u8 *buf, int length) -{ - struct spi_device *spi = to_spi_device(dev); - struct spi_message msg; - struct spi_transfer xfer[2]; - u8 *wr_buf = &xfer_buf[0]; - u8 rd_buf[CY_SPI_CMD_BYTES]; - int retval; - int i; - - if (length > CY_SPI_DATA_SIZE) { - dev_err(dev, "%s: length %d is too big.\n", - __func__, length); - return -EINVAL; - } - - memset(wr_buf, 0, CY_SPI_DATA_BUF_SIZE); - memset(rd_buf, 0, CY_SPI_CMD_BYTES); - - wr_buf[0] = op + (((reg >> 8) & 0x1) ? CY_SPI_A8_BIT : 0); - if (op == CY_SPI_WR_OP) { - wr_buf[1] = reg & 0xFF; - if (length > 0) - memcpy(wr_buf + CY_SPI_CMD_BYTES, buf, length); - } - - memset(xfer, 0, sizeof(xfer)); - spi_message_init(&msg); - - /* - We set both TX and RX buffers because Cypress TTSP - requires full duplex operation. - */ - xfer[0].tx_buf = wr_buf; - xfer[0].rx_buf = rd_buf; - switch (op) { - case CY_SPI_WR_OP: - xfer[0].len = length + CY_SPI_CMD_BYTES; - spi_message_add_tail(&xfer[0], &msg); - break; - - case CY_SPI_RD_OP: - xfer[0].len = CY_SPI_RD_HEADER_BYTES; - spi_message_add_tail(&xfer[0], &msg); - - xfer[1].rx_buf = buf; - xfer[1].len = length; - spi_message_add_tail(&xfer[1], &msg); - break; - - default: - dev_err(dev, "%s: bad operation code=%d\n", __func__, op); - return -EINVAL; - } - - retval = spi_sync(spi, &msg); - if (retval < 0) { - dev_dbg(dev, "%s: spi_sync() error %d, len=%d, op=%d\n", - __func__, retval, xfer[1].len, op); - - /* - * do not return here since was a bad ACK sequence - * let the following ACK check handle any errors and - * allow silent retries - */ - } - - if (rd_buf[CY_SPI_SYNC_BYTE] != CY_SPI_SYNC_ACK) { - dev_dbg(dev, "%s: operation %d failed\n", __func__, op); - - for (i = 0; i < CY_SPI_CMD_BYTES; i++) - dev_dbg(dev, "%s: test rd_buf[%d]:0x%02x\n", - __func__, i, rd_buf[i]); - for (i = 0; i < length; i++) - dev_dbg(dev, "%s: test buf[%d]:0x%02x\n", - __func__, i, buf[i]); - - return -EIO; - } - - return 0; -} - -static int cyttsp_spi_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *data) -{ - int rc; - - rc = cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, NULL, 0); - if (rc) - return rc; - else - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_RD_OP, addr, data, - length); -} - -static int cyttsp_spi_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *data) -{ - return cyttsp_spi_xfer(dev, xfer_buf, CY_SPI_WR_OP, addr, (void *)data, - length); -} - -static const struct cyttsp4_bus_ops cyttsp_spi_bus_ops = { - .bustype = BUS_SPI, - .write = cyttsp_spi_write_block_data, - .read = cyttsp_spi_read_block_data, -}; - -static int cyttsp4_spi_probe(struct spi_device *spi) -{ - struct cyttsp4 *ts; - int error; - - /* Set up SPI*/ - spi->bits_per_word = CY_SPI_BITS_PER_WORD; - spi->mode = SPI_MODE_0; - error = spi_setup(spi); - if (error < 0) { - dev_err(&spi->dev, "%s: SPI setup error %d\n", - __func__, error); - return error; - } - - ts = cyttsp4_probe(&cyttsp_spi_bus_ops, &spi->dev, spi->irq, - CY_SPI_DATA_BUF_SIZE); - - return PTR_ERR_OR_ZERO(ts); -} - -static void cyttsp4_spi_remove(struct spi_device *spi) -{ - struct cyttsp4 *ts = spi_get_drvdata(spi); - cyttsp4_remove(ts); -} - -static struct spi_driver cyttsp4_spi_driver = { - .driver = { - .name = CYTTSP4_SPI_NAME, - .pm = pm_ptr(&cyttsp4_pm_ops), - }, - .probe = cyttsp4_spi_probe, - .remove = cyttsp4_spi_remove, -}; - -module_spi_driver(cyttsp4_spi_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); -MODULE_AUTHOR("Cypress"); -MODULE_ALIAS("spi:cyttsp4"); diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c index 68527ede5c0e..071b7c9bf566 100644 --- a/drivers/input/touchscreen/cyttsp5.c +++ b/drivers/input/touchscreen/cyttsp5.c @@ -21,7 +21,7 @@ #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/regmap.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define CYTTSP5_NAME "cyttsp5" #define CY_I2C_DATA_SIZE (2 * 256) @@ -580,7 +580,7 @@ static int cyttsp5_power_control(struct cyttsp5 *ts, bool on) int rc; SET_CMD_REPORT_TYPE(cmd[0], 0); - SET_CMD_REPORT_ID(cmd[0], HID_POWER_SLEEP); + SET_CMD_REPORT_ID(cmd[0], state); SET_CMD_OPCODE(cmd[1], HID_CMD_SET_POWER); rc = cyttsp5_write(ts, HID_COMMAND_REG, cmd, sizeof(cmd)); @@ -870,13 +870,16 @@ static int cyttsp5_probe(struct device *dev, struct regmap *regmap, int irq, ts->input->phys = ts->phys; input_set_drvdata(ts->input, ts); - /* Reset the gpio to be in a reset state */ + /* Assert gpio to be in a reset state */ ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(ts->reset_gpio)) { error = PTR_ERR(ts->reset_gpio); dev_err(dev, "Failed to request reset gpio, error %d\n", error); return error; } + + fsleep(10); /* Ensure long-enough reset pulse (minimum 10us). */ + gpiod_set_value_cansleep(ts->reset_gpio, 0); /* Need a delay to have device up */ @@ -935,7 +938,7 @@ static const struct of_device_id cyttsp5_of_match[] = { MODULE_DEVICE_TABLE(of, cyttsp5_of_match); static const struct i2c_device_id cyttsp5_i2c_id[] = { - { CYTTSP5_NAME, 0, }, + { CYTTSP5_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, cyttsp5_i2c_id); diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index 132ed5786e84..b8ce6012364c 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -17,7 +17,6 @@ #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/slab.h> #include <linux/property.h> @@ -615,17 +614,14 @@ static int cyttsp_parse_properties(struct cyttsp *ts) return 0; } -static void cyttsp_disable_regulators(void *_ts) -{ - struct cyttsp *ts = _ts; - - regulator_bulk_disable(ARRAY_SIZE(ts->regulators), - ts->regulators); -} - struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size) { + /* + * VCPIN is the analog voltage supply + * VDD is the digital voltage supply + */ + static const char * const supplies[] = { "vcpin", "vdd" }; struct cyttsp *ts; struct input_dev *input_dev; int error; @@ -643,29 +639,10 @@ struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, ts->bus_ops = bus_ops; ts->irq = irq; - /* - * VCPIN is the analog voltage supply - * VDD is the digital voltage supply - */ - ts->regulators[0].supply = "vcpin"; - ts->regulators[1].supply = "vdd"; - error = devm_regulator_bulk_get(dev, ARRAY_SIZE(ts->regulators), - ts->regulators); - if (error) { - dev_err(dev, "Failed to get regulators: %d\n", error); - return ERR_PTR(error); - } - - error = regulator_bulk_enable(ARRAY_SIZE(ts->regulators), - ts->regulators); - if (error) { - dev_err(dev, "Cannot enable regulators: %d\n", error); - return ERR_PTR(error); - } - - error = devm_add_action_or_reset(dev, cyttsp_disable_regulators, ts); + error = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(supplies), + supplies); if (error) { - dev_err(dev, "failed to install chip disable handler\n"); + dev_err(dev, "Failed to enable regulators: %d\n", error); return ERR_PTR(error); } diff --git a/drivers/input/touchscreen/cyttsp_core.h b/drivers/input/touchscreen/cyttsp_core.h index 075509e695a2..40a605d20285 100644 --- a/drivers/input/touchscreen/cyttsp_core.h +++ b/drivers/input/touchscreen/cyttsp_core.h @@ -122,7 +122,6 @@ struct cyttsp { enum cyttsp_state state; bool suspended; - struct regulator_bulk_data regulators[2]; struct gpio_desc *reset_gpio; bool use_hndshk; u8 act_dist; @@ -137,10 +136,6 @@ struct cyttsp { struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops, struct device *dev, int irq, size_t xfer_buf_size); -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, const void *values); -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, u16 addr, - u8 length, void *values); extern const struct dev_pm_ops cyttsp_pm_ops; #endif /* __CYTTSP_CORE_H__ */ diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 127a8fda1da4..cb15600549cd 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -22,6 +22,61 @@ #define CY_I2C_DATA_SIZE 128 +static int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = 1, + .buf = &addr_lo, + }, + { + .addr = client_addr, + .flags = I2C_M_RD, + .len = length, + .buf = values, + }, + }; + int retval; + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + +static int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, + u16 addr, u8 length, const void *values) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 client_addr = client->addr | ((addr >> 8) & 0x1); + u8 addr_lo = addr & 0xFF; + struct i2c_msg msgs[] = { + { + .addr = client_addr, + .flags = 0, + .len = length + 1, + .buf = xfer_buf, + }, + }; + int retval; + + xfer_buf[0] = addr_lo; + memcpy(&xfer_buf[1], values, length); + + retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (retval < 0) + return retval; + + return retval != ARRAY_SIZE(msgs) ? -EIO : 0; +} + static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { .bustype = BUS_I2C, .write = cyttsp_i2c_write_block_data, @@ -48,7 +103,7 @@ static int cyttsp_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id cyttsp_i2c_id[] = { - { CY_I2C_NAME, 0 }, + { CY_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, cyttsp_i2c_id); diff --git a/drivers/input/touchscreen/cyttsp_i2c_common.c b/drivers/input/touchscreen/cyttsp_i2c_common.c deleted file mode 100644 index 1f0b6d6f48e2..000000000000 --- a/drivers/input/touchscreen/cyttsp_i2c_common.c +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * cyttsp_i2c_common.c - * Cypress TrueTouch(TM) Standard Product (TTSP) I2C touchscreen driver. - * For use with Cypress Txx3xx and Txx4xx parts. - * Supported parts include: - * CY8CTST341 - * CY8CTMA340 - * TMA4XX - * TMA1036 - * - * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc. - * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org> - * - * Contact Cypress Semiconductor at www.cypress.com <ttdrivers@cypress.com> - */ - -#include <linux/device.h> -#include <linux/export.h> -#include <linux/i2c.h> -#include <linux/module.h> -#include <linux/types.h> - -#include "cyttsp4_core.h" - -int cyttsp_i2c_read_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = 1, - .buf = &addr_lo, - }, - { - .addr = client_addr, - .flags = I2C_M_RD, - .len = length, - .buf = values, - }, - }; - int retval; - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_read_block_data); - -int cyttsp_i2c_write_block_data(struct device *dev, u8 *xfer_buf, - u16 addr, u8 length, const void *values) -{ - struct i2c_client *client = to_i2c_client(dev); - u8 client_addr = client->addr | ((addr >> 8) & 0x1); - u8 addr_lo = addr & 0xFF; - struct i2c_msg msgs[] = { - { - .addr = client_addr, - .flags = 0, - .len = length + 1, - .buf = xfer_buf, - }, - }; - int retval; - - xfer_buf[0] = addr_lo; - memcpy(&xfer_buf[1], values, length); - - retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); - if (retval < 0) - return retval; - - return retval != ARRAY_SIZE(msgs) ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(cyttsp_i2c_write_block_data); - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index d71690ce6463..c2d3252f8466 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c @@ -232,7 +232,7 @@ static int da9052_ts_probe(struct platform_device *pdev) if (!da9052) return -EINVAL; - tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); + tsi = kzalloc(sizeof(*tsi), GFP_KERNEL); input_dev = input_allocate_device(); if (!tsi || !input_dev) { error = -ENOMEM; @@ -326,7 +326,7 @@ static void da9052_ts_remove(struct platform_device *pdev) static struct platform_driver da9052_tsi_driver = { .probe = da9052_ts_probe, - .remove_new = da9052_ts_remove, + .remove = da9052_ts_remove, .driver = { .name = "da9052-tsi", }, diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index dc07fca7c5ed..fe626a226b85 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c @@ -110,7 +110,7 @@ static int dynapro_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); + pdynapro = kzalloc(sizeof(*pdynapro), GFP_KERNEL); input_dev = input_allocate_device(); if (!pdynapro || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 2a1db1134476..0d7bf18e2508 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -32,7 +32,7 @@ #include <linux/slab.h> #include <linux/uaccess.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define WORK_REGISTER_THRESHOLD 0x00 #define WORK_REGISTER_REPORT_RATE 0x08 @@ -1121,6 +1121,14 @@ static void edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata) } } +static void edt_ft5x06_exit_regmap(void *arg) +{ + struct edt_ft5x06_ts_data *data = arg; + + if (!IS_ERR_OR_NULL(data->regmap)) + regmap_exit(data->regmap); +} + static void edt_ft5x06_disable_regulators(void *arg) { struct edt_ft5x06_ts_data *data = arg; @@ -1154,6 +1162,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client) return PTR_ERR(tsdata->regmap); } + /* + * We are not using devm_regmap_init_i2c() and instead install a + * custom action because we may replace regmap with M06-specific one + * and we need to make sure that it will not be released too early. + */ + error = devm_add_action_or_reset(&client->dev, edt_ft5x06_exit_regmap, + tsdata); + if (error) + return error; + chip_data = device_get_match_data(&client->dev); if (!chip_data) chip_data = (const struct edt_i2c_chip_data *)id->driver_data; @@ -1219,7 +1237,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client) } /* - * Check which sleep modes we can support. Power-off requieres the + * Check which sleep modes we can support. Power-off requires the * reset-pin to ensure correct power-down/power-up behaviour. Start with * the EDT_PMODE_POWEROFF test since this is the deepest possible sleep * mode. @@ -1347,7 +1365,6 @@ static void edt_ft5x06_ts_remove(struct i2c_client *client) struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client); edt_ft5x06_ts_teardown_debugfs(tsdata); - regmap_exit(tsdata->regmap); } static int edt_ft5x06_ts_suspend(struct device *dev) @@ -1462,6 +1479,10 @@ static const struct edt_i2c_chip_data edt_ft5x06_data = { .max_support_points = 5, }; +static const struct edt_i2c_chip_data edt_ft5452_data = { + .max_support_points = 5, +}; + static const struct edt_i2c_chip_data edt_ft5506_data = { .max_support_points = 10, }; @@ -1470,12 +1491,23 @@ static const struct edt_i2c_chip_data edt_ft6236_data = { .max_support_points = 2, }; +static const struct edt_i2c_chip_data edt_ft8201_data = { + .max_support_points = 10, +}; + +static const struct edt_i2c_chip_data edt_ft8719_data = { + .max_support_points = 10, +}; + static const struct i2c_device_id edt_ft5x06_ts_id[] = { { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data }, { .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data }, { .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data }, + { .name = "ft5452", .driver_data = (long)&edt_ft5452_data }, /* Note no edt- prefix for compatibility with the ft6236.c driver */ { .name = "ft6236", .driver_data = (long)&edt_ft6236_data }, + { .name = "ft8201", .driver_data = (long)&edt_ft8201_data }, + { .name = "ft8719", .driver_data = (long)&edt_ft8719_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id); @@ -1486,8 +1518,12 @@ static const struct of_device_id edt_ft5x06_of_match[] = { { .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data }, { .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data }, { .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data }, + { .compatible = "focaltech,ft5426", .data = &edt_ft5506_data }, + { .compatible = "focaltech,ft5452", .data = &edt_ft5452_data }, /* Note focaltech vendor prefix for compatibility with ft6236.c */ { .compatible = "focaltech,ft6236", .data = &edt_ft6236_data }, + { .compatible = "focaltech,ft8201", .data = &edt_ft8201_data }, + { .compatible = "focaltech,ft8719", .data = &edt_ft8719_data }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match); diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 5e4167f6c63e..87eb18977b71 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -21,7 +21,7 @@ #include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> struct eeti_ts { struct i2c_client *client; @@ -273,7 +273,7 @@ static int eeti_ts_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(eeti_ts_pm, eeti_ts_suspend, eeti_ts_resume); static const struct i2c_device_id eeti_ts_id[] = { - { "eeti_ts", 0 }, + { "eeti_ts" }, { } }; MODULE_DEVICE_TABLE(i2c, eeti_ts_id); diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index a7f7e7308267..eb3cc2befcdf 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -23,6 +23,7 @@ #include <linux/gpio/consumer.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/string_choices.h> #include <linux/bitops.h> #include <linux/input/mt.h> @@ -102,7 +103,7 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down); dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d", - down ? "down" : "up", id, x, y, z); + str_down_up(down), id, x, y, z); if (down) { input_report_abs(input_dev, ABS_MT_POSITION_X, x); @@ -218,7 +219,7 @@ static int egalax_ts_probe(struct i2c_client *client) } static const struct i2c_device_id egalax_ts_id[] = { - { "egalax_ts", 0 }, + { "egalax_ts" }, { } }; MODULE_DEVICE_TABLE(i2c, egalax_ts_id); diff --git a/drivers/input/touchscreen/egalax_ts_serial.c b/drivers/input/touchscreen/egalax_ts_serial.c index 375922d3a6d1..07a4aa1c19bb 100644 --- a/drivers/input/touchscreen/egalax_ts_serial.c +++ b/drivers/input/touchscreen/egalax_ts_serial.c @@ -99,7 +99,7 @@ static int egalax_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int error; - egalax = kzalloc(sizeof(struct egalax), GFP_KERNEL); + egalax = kzalloc(sizeof(*egalax), GFP_KERNEL); input_dev = input_allocate_device(); if (!egalax || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/touchscreen/ektf2127.c b/drivers/input/touchscreen/ektf2127.c index cc3103b9cbfb..46a0611fac82 100644 --- a/drivers/input/touchscreen/ektf2127.c +++ b/drivers/input/touchscreen/ektf2127.c @@ -13,6 +13,7 @@ * Hans de Goede <hdegoede@redhat.com> */ +#include <linux/bits.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/i2c.h> @@ -46,6 +47,11 @@ struct ektf2127_ts { struct input_dev *input; struct gpio_desc *power_gpios; struct touchscreen_properties prop; + int status_shift; +}; + +struct ektf2127_i2c_chip_data { + int status_shift; }; static void ektf2127_parse_coordinates(const u8 *buf, unsigned int touch_count, @@ -112,8 +118,8 @@ static void ektf2127_report2_contact(struct ektf2127_ts *ts, int slot, static void ektf2127_report2_event(struct ektf2127_ts *ts, const u8 *buf) { - ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & 2)); - ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & 4)); + ektf2127_report2_contact(ts, 0, &buf[1], !!(buf[7] & BIT(ts->status_shift))); + ektf2127_report2_contact(ts, 1, &buf[4], !!(buf[7] & BIT(ts->status_shift + 1))); input_mt_sync_frame(ts->input); input_sync(ts->input); @@ -247,6 +253,7 @@ static int ektf2127_query_dimension(struct i2c_client *client, bool width) static int ektf2127_probe(struct i2c_client *client) { struct device *dev = &client->dev; + const struct ektf2127_i2c_chip_data *chip_data; struct ektf2127_ts *ts; struct input_dev *input; u8 buf[4]; @@ -303,6 +310,13 @@ static int ektf2127_probe(struct i2c_client *client) return error; ts->input = input; + + chip_data = i2c_get_match_data(client); + if (!chip_data) + return dev_err_probe(&client->dev, -EINVAL, "missing chip data\n"); + + ts->status_shift = chip_data->status_shift; + input_set_drvdata(input, ts); error = devm_request_threaded_irq(dev, client->irq, @@ -325,18 +339,28 @@ static int ektf2127_probe(struct i2c_client *client) return 0; } +static const struct ektf2127_i2c_chip_data ektf2127_data = { + .status_shift = 1, +}; + +static const struct ektf2127_i2c_chip_data ektf2232_data = { + .status_shift = 0, +}; + #ifdef CONFIG_OF static const struct of_device_id ektf2127_of_match[] = { - { .compatible = "elan,ektf2127" }, - { .compatible = "elan,ektf2132" }, + { .compatible = "elan,ektf2127", .data = &ektf2127_data}, + { .compatible = "elan,ektf2132", .data = &ektf2127_data}, + { .compatible = "elan,ektf2232", .data = &ektf2232_data}, {} }; MODULE_DEVICE_TABLE(of, ektf2127_of_match); #endif static const struct i2c_device_id ektf2127_i2c_id[] = { - { "ektf2127", 0 }, - { "ektf2132", 0 }, + { .name = "ektf2127", .driver_data = (long)&ektf2127_data }, + { .name = "ektf2132", .driver_data = (long)&ektf2127_data }, + { .name = "ektf2232", .driver_data = (long)&ektf2232_data }, {} }; MODULE_DEVICE_TABLE(i2c, ektf2127_i2c_id); diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 365765d40e62..3fd170f75b4a 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -40,7 +40,7 @@ #include <linux/gpio/consumer.h> #include <linux/regulator/consumer.h> #include <linux/uuid.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* Device, Driver information */ #define DEVICE_NAME "elants_i2c" diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 96173232e53f..ad209e6e82a6 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -225,10 +225,10 @@ static int elo_command_10(struct elo *elo, unsigned char *packet) mutex_lock(&elo->cmd_mutex); - serio_pause_rx(elo->serio); - elo->expected_packet = toupper(packet[0]); - init_completion(&elo->cmd_done); - serio_continue_rx(elo->serio); + scoped_guard(serio_pause_rx, elo->serio) { + elo->expected_packet = toupper(packet[0]); + init_completion(&elo->cmd_done); + } if (serio_write(elo->serio, ELO10_LEAD_BYTE)) goto out; @@ -307,7 +307,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - elo = kzalloc(sizeof(struct elo), GFP_KERNEL); + elo = kzalloc(sizeof(*elo), GFP_KERNEL); input_dev = input_allocate_device(); if (!elo || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/exc3000.c b/drivers/input/touchscreen/exc3000.c index a4030cc9ff60..9a5977d8cad2 100644 --- a/drivers/input/touchscreen/exc3000.c +++ b/drivers/input/touchscreen/exc3000.c @@ -22,7 +22,7 @@ #include <linux/regulator/consumer.h> #include <linux/sizes.h> #include <linux/timer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define EXC3000_NUM_SLOTS 10 #define EXC3000_SLOTS_PER_FRAME 5 @@ -53,6 +53,7 @@ enum eeti_dev_id { EETI_EXC3000, EETI_EXC80H60, EETI_EXC80H84, + EETI_EXC81W32, }; static struct eeti_dev_info exc3000_info[] = { @@ -68,6 +69,10 @@ static struct eeti_dev_info exc3000_info[] = { .name = "EETI EXC80H84 Touch Screen", .max_xy = SZ_16K - 1, }, + [EETI_EXC81W32] = { + .name = "EETI EXC81W32 Touch Screen", + .max_xy = SZ_16K - 1, + }, }; struct exc3000_data { @@ -169,7 +174,7 @@ static int exc3000_handle_mt_event(struct exc3000_data *data) /* * We read full state successfully, no contacts will be "stuck". */ - del_timer_sync(&data->timer); + timer_delete_sync(&data->timer); while (total_slots > 0) { int slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); @@ -441,6 +446,7 @@ static const struct i2c_device_id exc3000_id[] = { { "exc3000", EETI_EXC3000 }, { "exc80h60", EETI_EXC80H60 }, { "exc80h84", EETI_EXC80H84 }, + { "exc81w32", EETI_EXC81W32 }, { } }; MODULE_DEVICE_TABLE(i2c, exc3000_id); @@ -450,6 +456,7 @@ static const struct of_device_id exc3000_of_match[] = { { .compatible = "eeti,exc3000", .data = &exc3000_info[EETI_EXC3000] }, { .compatible = "eeti,exc80h60", .data = &exc3000_info[EETI_EXC80H60] }, { .compatible = "eeti,exc80h84", .data = &exc3000_info[EETI_EXC80H84] }, + { .compatible = "eeti,exc81w32", .data = &exc3000_info[EETI_EXC81W32] }, { } }; MODULE_DEVICE_TABLE(of, exc3000_of_match); diff --git a/drivers/input/touchscreen/fsl-imx25-tcq.c b/drivers/input/touchscreen/fsl-imx25-tcq.c index 60a7246c5157..a32708652d10 100644 --- a/drivers/input/touchscreen/fsl-imx25-tcq.c +++ b/drivers/input/touchscreen/fsl-imx25-tcq.c @@ -38,7 +38,7 @@ struct mx25_tcq_priv { struct device *dev; }; -static struct regmap_config mx25_tcq_regconfig = { +static const struct regmap_config mx25_tcq_regconfig = { .fast_io = true, .max_register = 0x5c, .reg_bits = 32, diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 3b0b8fccc3f0..1a3e14ea2e08 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c @@ -99,7 +99,7 @@ static int fujitsu_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - fujitsu = kzalloc(sizeof(struct fujitsu), GFP_KERNEL); + fujitsu = kzalloc(sizeof(*fujitsu), GFP_KERNEL); input_dev = input_allocate_device(); if (!fujitsu || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index b068ff8afbc9..a3e8a51c9144 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -22,7 +22,7 @@ #include <linux/slab.h> #include <linux/acpi.h> #include <linux/of.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "goodix.h" #define GOODIX_GPIO_INT_NAME "irq" @@ -1510,7 +1510,7 @@ static int goodix_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(goodix_pm_ops, goodix_suspend, goodix_resume); static const struct i2c_device_id goodix_ts_id[] = { - { "GDIX1001:00", 0 }, + { "GDIX1001:00" }, { } }; MODULE_DEVICE_TABLE(i2c, goodix_ts_id); diff --git a/drivers/input/touchscreen/goodix_berlin.h b/drivers/input/touchscreen/goodix_berlin.h index 1fd77eb69c9a..d8bbd4853206 100644 --- a/drivers/input/touchscreen/goodix_berlin.h +++ b/drivers/input/touchscreen/goodix_berlin.h @@ -12,13 +12,28 @@ #include <linux/pm.h> +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A 0x1000C +#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D 0x10014 + +#define GOODIX_BERLIN_IC_INFO_ADDR_A 0x10068 +#define GOODIX_BERLIN_IC_INFO_ADDR_D 0x10070 + +struct goodix_berlin_ic_data { + int fw_version_info_addr; + int ic_info_addr; + ssize_t read_dummy_len; + ssize_t read_prefix_len; +}; + struct device; struct input_id; struct regmap; int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap); + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data); extern const struct dev_pm_ops goodix_berlin_pm_ops; +extern const struct attribute_group *goodix_berlin_groups[]; #endif diff --git a/drivers/input/touchscreen/goodix_berlin_core.c b/drivers/input/touchscreen/goodix_berlin_core.c index e7b41a926ef8..02a1d9a465f2 100644 --- a/drivers/input/touchscreen/goodix_berlin_core.c +++ b/drivers/input/touchscreen/goodix_berlin_core.c @@ -12,7 +12,7 @@ * to the previous generations. * * Currently the driver only handles Multitouch events with already - * programmed firmware and "config" for "Revision D" Berlin IC. + * programmed firmware and "config" for "Revision A/D" Berlin IC. * * Support is missing for: * - ESD Management @@ -20,7 +20,7 @@ * - "Config" update/flashing * - Stylus Events * - Gesture Events - * - Support for older revisions (A & B) + * - Support for revision B */ #include <linux/bitfield.h> @@ -28,10 +28,11 @@ #include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> +#include <linux/property.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/sizes.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "goodix_berlin.h" @@ -53,10 +54,8 @@ #define GOODIX_BERLIN_DEV_CONFIRM_VAL 0xAA #define GOODIX_BERLIN_BOOTOPTION_ADDR 0x10000 -#define GOODIX_BERLIN_FW_VERSION_INFO_ADDR 0x10014 #define GOODIX_BERLIN_IC_INFO_MAX_LEN SZ_1K -#define GOODIX_BERLIN_IC_INFO_ADDR 0x10070 #define GOODIX_BERLIN_CHECKSUM_SIZE sizeof(u16) @@ -165,7 +164,7 @@ struct goodix_berlin_core { struct device *dev; struct regmap *regmap; struct regulator *avdd; - struct regulator *iovdd; + struct regulator *vddio; struct gpio_desc *reset_gpio; struct touchscreen_properties props; struct goodix_berlin_fw_version fw_version; @@ -175,6 +174,8 @@ struct goodix_berlin_core { /* Runtime parameters extracted from IC_INFO buffer */ u32 touch_data_addr; + const struct goodix_berlin_ic_data *ic_data; + struct goodix_berlin_event event; }; @@ -248,22 +249,22 @@ static int goodix_berlin_power_on(struct goodix_berlin_core *cd) { int error; - error = regulator_enable(cd->iovdd); + error = regulator_enable(cd->vddio); if (error) { - dev_err(cd->dev, "Failed to enable iovdd: %d\n", error); + dev_err(cd->dev, "Failed to enable vddio: %d\n", error); return error; } - /* Vendor waits 3ms for IOVDD to settle */ + /* Vendor waits 3ms for VDDIO to settle */ usleep_range(3000, 3100); error = regulator_enable(cd->avdd); if (error) { dev_err(cd->dev, "Failed to enable avdd: %d\n", error); - goto err_iovdd_disable; + goto err_vddio_disable; } - /* Vendor waits 15ms for IOVDD to settle */ + /* Vendor waits 15ms for AVDD to settle */ usleep_range(15000, 15100); gpiod_set_value_cansleep(cd->reset_gpio, 0); @@ -283,8 +284,8 @@ static int goodix_berlin_power_on(struct goodix_berlin_core *cd) err_dev_reset: gpiod_set_value_cansleep(cd->reset_gpio, 1); regulator_disable(cd->avdd); -err_iovdd_disable: - regulator_disable(cd->iovdd); +err_vddio_disable: + regulator_disable(cd->vddio); return error; } @@ -292,14 +293,14 @@ static void goodix_berlin_power_off(struct goodix_berlin_core *cd) { gpiod_set_value_cansleep(cd->reset_gpio, 1); regulator_disable(cd->avdd); - regulator_disable(cd->iovdd); + regulator_disable(cd->vddio); } static int goodix_berlin_read_version(struct goodix_berlin_core *cd) { int error; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_FW_VERSION_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->fw_version_info_addr, &cd->fw_version, sizeof(cd->fw_version)); if (error) { dev_err(cd->dev, "error reading fw version, %d\n", error); @@ -367,7 +368,7 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) if (!afe_data) return -ENOMEM; - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, &length_raw, sizeof(length_raw)); if (error) { dev_err(cd->dev, "failed get ic info length, %d\n", error); @@ -380,8 +381,8 @@ static int goodix_berlin_get_ic_info(struct goodix_berlin_core *cd) return -EINVAL; } - error = regmap_raw_read(cd->regmap, GOODIX_BERLIN_IC_INFO_ADDR, - afe_data, length); + error = regmap_raw_read(cd->regmap, cd->ic_data->ic_info_addr, afe_data, + length); if (error) { dev_err(cd->dev, "failed get ic info data, %d\n", error); return error; @@ -672,8 +673,52 @@ static void goodix_berlin_power_off_act(void *data) goodix_berlin_power_off(cd); } +static ssize_t registers_read(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct goodix_berlin_core *cd = dev_get_drvdata(dev); + int error; + + error = regmap_raw_read(cd->regmap, off, buf, count); + + return error ? error : count; +} + +static ssize_t registers_write(struct file *filp, struct kobject *kobj, + const struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct device *dev = kobj_to_dev(kobj); + struct goodix_berlin_core *cd = dev_get_drvdata(dev); + int error; + + error = regmap_raw_write(cd->regmap, off, buf, count); + + return error ? error : count; +} + +static const BIN_ATTR_ADMIN_RW(registers, 0); + +static const struct bin_attribute *const goodix_berlin_bin_attrs[] = { + &bin_attr_registers, + NULL, +}; + +static const struct attribute_group goodix_berlin_attr_group = { + .bin_attrs_new = goodix_berlin_bin_attrs, +}; + +const struct attribute_group *goodix_berlin_groups[] = { + &goodix_berlin_attr_group, + NULL, +}; +EXPORT_SYMBOL_GPL(goodix_berlin_groups); + int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, - struct regmap *regmap) + struct regmap *regmap, + const struct goodix_berlin_ic_data *ic_data) { struct goodix_berlin_core *cd; int error; @@ -690,6 +735,7 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, cd->dev = dev; cd->regmap = regmap; cd->irq = irq; + cd->ic_data = ic_data; cd->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(cd->reset_gpio)) @@ -701,10 +747,10 @@ int goodix_berlin_probe(struct device *dev, int irq, const struct input_id *id, return dev_err_probe(dev, PTR_ERR(cd->avdd), "Failed to request avdd regulator\n"); - cd->iovdd = devm_regulator_get(dev, "iovdd"); - if (IS_ERR(cd->iovdd)) - return dev_err_probe(dev, PTR_ERR(cd->iovdd), - "Failed to request iovdd regulator\n"); + cd->vddio = devm_regulator_get(dev, "vddio"); + if (IS_ERR(cd->vddio)) + return dev_err_probe(dev, PTR_ERR(cd->vddio), + "Failed to request vddio regulator\n"); error = goodix_berlin_power_on(cd); if (error) { diff --git a/drivers/input/touchscreen/goodix_berlin_i2c.c b/drivers/input/touchscreen/goodix_berlin_i2c.c index 6ed9aa8088cb..929090a094bf 100644 --- a/drivers/input/touchscreen/goodix_berlin_i2c.c +++ b/drivers/input/touchscreen/goodix_berlin_i2c.c @@ -31,6 +31,8 @@ static const struct input_id goodix_berlin_i2c_input_id = { static int goodix_berlin_i2c_probe(struct i2c_client *client) { + const struct goodix_berlin_ic_data *ic_data = + i2c_get_match_data(client); struct regmap *regmap; int error; @@ -39,22 +41,28 @@ static int goodix_berlin_i2c_probe(struct i2c_client *client) return PTR_ERR(regmap); error = goodix_berlin_probe(&client->dev, client->irq, - &goodix_berlin_i2c_input_id, regmap); + &goodix_berlin_i2c_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, +}; + static const struct i2c_device_id goodix_berlin_i2c_id[] = { - { "gt9916", 0 }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { } }; MODULE_DEVICE_TABLE(i2c, goodix_berlin_i2c_id); static const struct of_device_id goodix_berlin_i2c_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_i2c_of_match); @@ -64,6 +72,7 @@ static struct i2c_driver goodix_berlin_i2c_driver = { .name = "goodix-berlin-i2c", .of_match_table = goodix_berlin_i2c_of_match, .pm = pm_sleep_ptr(&goodix_berlin_pm_ops), + .dev_groups = goodix_berlin_groups, }, .probe = goodix_berlin_i2c_probe, .id_table = goodix_berlin_i2c_id, diff --git a/drivers/input/touchscreen/goodix_berlin_spi.c b/drivers/input/touchscreen/goodix_berlin_spi.c index 4cc557da048a..01f850f484c2 100644 --- a/drivers/input/touchscreen/goodix_berlin_spi.c +++ b/drivers/input/touchscreen/goodix_berlin_spi.c @@ -7,7 +7,7 @@ * * Based on goodix_ts_berlin driver. */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/regmap.h> @@ -18,10 +18,14 @@ #define GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN 1 #define GOODIX_BERLIN_REGISTER_WIDTH 4 -#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN 3 -#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A 4 +#define GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D 3 +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH + \ - GOODIX_BERLIN_SPI_READ_DUMMY_LEN) + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A) +#define GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ + GOODIX_BERLIN_REGISTER_WIDTH + \ + GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D) #define GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN (GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + \ GOODIX_BERLIN_REGISTER_WIDTH) @@ -33,41 +37,42 @@ static int goodix_berlin_spi_read(void *context, const void *reg_buf, size_t val_size) { struct spi_device *spi = context; + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = reg_buf; /* reg is stored as native u32 at start of buffer */ - u8 *buf; int error; if (reg_size != GOODIX_BERLIN_REGISTER_WIDTH) return -EINVAL; - buf = kzalloc(GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size, GFP_KERNEL); + u8 *buf __free(kfree) = + kzalloc(ic_data->read_prefix_len + val_size, GFP_KERNEL); if (!buf) return -ENOMEM; spi_message_init(&spi_msg); memset(&xfers, 0, sizeof(xfers)); - /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ + /* buffer format: 0xF1 + addr(4bytes) + dummy(3/4bytes) + data */ buf[0] = GOODIX_BERLIN_SPI_READ_FLAG; put_unaligned_be32(*reg, buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN); memset(buf + GOODIX_BERLIN_SPI_TRANS_PREFIX_LEN + GOODIX_BERLIN_REGISTER_WIDTH, - 0xff, GOODIX_BERLIN_SPI_READ_DUMMY_LEN); + 0xff, ic_data->read_dummy_len); xfers.tx_buf = buf; xfers.rx_buf = buf; - xfers.len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN + val_size; + xfers.len = ic_data->read_prefix_len + val_size; xfers.cs_change = 0; spi_message_add_tail(&xfers, &spi_msg); error = spi_sync(spi, &spi_msg); - if (error < 0) + if (error < 0) { dev_err(&spi->dev, "spi transfer error, %d", error); - else - memcpy(val_buf, buf + GOODIX_BERLIN_SPI_READ_PREFIX_LEN, val_size); + return error; + } - kfree(buf); + memcpy(val_buf, buf + ic_data->read_prefix_len, val_size); return error; } @@ -79,10 +84,10 @@ static int goodix_berlin_spi_write(void *context, const void *data, struct spi_transfer xfers; struct spi_message spi_msg; const u32 *reg = data; /* reg is stored as native u32 at start of buffer */ - u8 *buf; int error; - buf = kzalloc(GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL); + u8 *buf __free(kfree) = + kzalloc(GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -100,11 +105,12 @@ static int goodix_berlin_spi_write(void *context, const void *data, spi_message_add_tail(&xfers, &spi_msg); error = spi_sync(spi, &spi_msg); - if (error < 0) + if (error < 0) { dev_err(&spi->dev, "spi transfer error, %d", error); + return error; + } - kfree(buf); - return error; + return 0; } static const struct regmap_config goodix_berlin_spi_regmap_conf = { @@ -121,6 +127,7 @@ static const struct input_id goodix_berlin_spi_input_id = { static int goodix_berlin_spi_probe(struct spi_device *spi) { + const struct goodix_berlin_ic_data *ic_data = spi_get_device_match_data(spi); struct regmap_config regmap_config; struct regmap *regmap; size_t max_size; @@ -135,7 +142,7 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) max_size = spi_max_transfer_size(spi); regmap_config = goodix_berlin_spi_regmap_conf; - regmap_config.max_raw_read = max_size - GOODIX_BERLIN_SPI_READ_PREFIX_LEN; + regmap_config.max_raw_read = max_size - ic_data->read_prefix_len; regmap_config.max_raw_write = max_size - GOODIX_BERLIN_SPI_WRITE_PREFIX_LEN; regmap = devm_regmap_init(&spi->dev, NULL, spi, ®map_config); @@ -143,21 +150,38 @@ static int goodix_berlin_spi_probe(struct spi_device *spi) return PTR_ERR(regmap); error = goodix_berlin_probe(&spi->dev, spi->irq, - &goodix_berlin_spi_input_id, regmap); + &goodix_berlin_spi_input_id, regmap, + ic_data); if (error) return error; return 0; } +static const struct goodix_berlin_ic_data gt9897_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_A, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_A, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_A, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_A, +}; + +static const struct goodix_berlin_ic_data gt9916_data = { + .fw_version_info_addr = GOODIX_BERLIN_FW_VERSION_INFO_ADDR_D, + .ic_info_addr = GOODIX_BERLIN_IC_INFO_ADDR_D, + .read_dummy_len = GOODIX_BERLIN_SPI_READ_DUMMY_LEN_D, + .read_prefix_len = GOODIX_BERLIN_SPI_READ_PREFIX_LEN_D, +}; + static const struct spi_device_id goodix_berlin_spi_ids[] = { - { "gt9916" }, + { .name = "gt9897", .driver_data = (long)>9897_data }, + { .name = "gt9916", .driver_data = (long)>9916_data }, { }, }; MODULE_DEVICE_TABLE(spi, goodix_berlin_spi_ids); static const struct of_device_id goodix_berlin_spi_of_match[] = { - { .compatible = "goodix,gt9916", }, + { .compatible = "goodix,gt9897", .data = >9897_data }, + { .compatible = "goodix,gt9916", .data = >9916_data }, { } }; MODULE_DEVICE_TABLE(of, goodix_berlin_spi_of_match); @@ -167,6 +191,7 @@ static struct spi_driver goodix_berlin_spi_driver = { .name = "goodix-berlin-spi", .of_match_table = goodix_berlin_spi_of_match, .pm = pm_sleep_ptr(&goodix_berlin_pm_ops), + .dev_groups = goodix_berlin_groups, }, .probe = goodix_berlin_spi_probe, .id_table = goodix_berlin_spi_ids, diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index 5a5f9da73fa1..dbf92fb02f80 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -97,7 +97,7 @@ static int gunze_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - gunze = kzalloc(sizeof(struct gunze), GFP_KERNEL); + gunze = kzalloc(sizeof(*gunze), GFP_KERNEL); input_dev = input_allocate_device(); if (!gunze || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 5c4d877564ee..dc0a2482ddd6 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c @@ -109,7 +109,7 @@ static int hampshire_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - phampshire = kzalloc(sizeof(struct hampshire), GFP_KERNEL); + phampshire = kzalloc(sizeof(*phampshire), GFP_KERNEL); input_dev = input_allocate_device(); if (!phampshire || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index eae90676f4e5..a73369e15dda 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -17,7 +17,7 @@ #include <linux/input/mt.h> #include <linux/input/touchscreen.h> #include <linux/regulator/consumer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define HIDEEP_TS_NAME "HiDeep Touchscreen" #define HIDEEP_I2C_NAME "hideep_ts" @@ -1095,7 +1095,7 @@ static int hideep_probe(struct i2c_client *client) } static const struct i2c_device_id hideep_i2c_id[] = { - { HIDEEP_I2C_NAME, 0 }, + { HIDEEP_I2C_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, hideep_i2c_id); diff --git a/drivers/input/touchscreen/himax_hx83112b.c b/drivers/input/touchscreen/himax_hx83112b.c index 4f6609dcdef3..896a145ddb2b 100644 --- a/drivers/input/touchscreen/himax_hx83112b.c +++ b/drivers/input/touchscreen/himax_hx83112b.c @@ -4,6 +4,9 @@ * * Copyright (C) 2022 Job Noorman <job@noorman.info> * + * HX83100A support + * Copyright (C) 2024 Felix Kaechele <felix@kaechele.ca> + * * This code is based on "Himax Android Driver Sample Code for QCT platform": * * Copyright (C) 2017 Himax Corporation. @@ -20,16 +23,22 @@ #include <linux/kernel.h> #include <linux/regmap.h> -#define HIMAX_ID_83112B 0x83112b - #define HIMAX_MAX_POINTS 10 -#define HIMAX_REG_CFG_SET_ADDR 0x00 -#define HIMAX_REG_CFG_INIT_READ 0x0c -#define HIMAX_REG_CFG_READ_VALUE 0x08 -#define HIMAX_REG_READ_EVENT 0x30 +#define HIMAX_AHB_ADDR_BYTE_0 0x00 +#define HIMAX_AHB_ADDR_RDATA_BYTE_0 0x08 +#define HIMAX_AHB_ADDR_ACCESS_DIRECTION 0x0c +#define HIMAX_AHB_ADDR_INCR4 0x0d +#define HIMAX_AHB_ADDR_CONTI 0x13 +#define HIMAX_AHB_ADDR_EVENT_STACK 0x30 + +#define HIMAX_AHB_CMD_ACCESS_DIRECTION_READ 0x00 +#define HIMAX_AHB_CMD_INCR4 0x10 +#define HIMAX_AHB_CMD_CONTI 0x31 -#define HIMAX_CFG_PRODUCT_ID 0x900000d0 +#define HIMAX_REG_ADDR_ICID 0x900000d0 + +#define HX83100A_REG_FW_EVENT_STACK 0x90060000 #define HIMAX_INVALID_COORD 0xffff @@ -49,7 +58,16 @@ struct himax_event { static_assert(sizeof(struct himax_event) == 56); +struct himax_ts_data; +struct himax_chip { + u32 id; + int (*check_id)(struct himax_ts_data *ts); + int (*read_events)(struct himax_ts_data *ts, struct himax_event *event, + size_t length); +}; + struct himax_ts_data { + const struct himax_chip *chip; struct gpio_desc *gpiod_rst; struct input_dev *input_dev; struct i2c_client *client; @@ -63,19 +81,49 @@ static const struct regmap_config himax_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; -static int himax_read_config(struct himax_ts_data *ts, u32 address, u32 *dst) +static int himax_bus_enable_burst(struct himax_ts_data *ts) +{ + int error; + + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_CONTI, + HIMAX_AHB_CMD_CONTI); + if (error) + return error; + + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_INCR4, + HIMAX_AHB_CMD_INCR4); + if (error) + return error; + + return 0; +} + +static int himax_bus_read(struct himax_ts_data *ts, u32 address, void *dst, + size_t length) { int error; - error = regmap_write(ts->regmap, HIMAX_REG_CFG_SET_ADDR, address); + if (length > 4) { + error = himax_bus_enable_burst(ts); + if (error) + return error; + } + + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_BYTE_0, address); if (error) return error; - error = regmap_write(ts->regmap, HIMAX_REG_CFG_INIT_READ, 0x0); + error = regmap_write(ts->regmap, HIMAX_AHB_ADDR_ACCESS_DIRECTION, + HIMAX_AHB_CMD_ACCESS_DIRECTION_READ); if (error) return error; - error = regmap_read(ts->regmap, HIMAX_REG_CFG_READ_VALUE, dst); + if (length > 4) + error = regmap_noinc_read(ts->regmap, HIMAX_AHB_ADDR_RDATA_BYTE_0, + dst, length); + else + error = regmap_read(ts->regmap, HIMAX_AHB_ADDR_RDATA_BYTE_0, + dst); if (error) return error; @@ -101,7 +149,8 @@ static int himax_read_product_id(struct himax_ts_data *ts, u32 *product_id) { int error; - error = himax_read_config(ts, HIMAX_CFG_PRODUCT_ID, product_id); + error = himax_bus_read(ts, HIMAX_REG_ADDR_ICID, product_id, + sizeof(*product_id)); if (error) return error; @@ -120,15 +169,12 @@ static int himax_check_product_id(struct himax_ts_data *ts) dev_dbg(&ts->client->dev, "Product id: %x\n", product_id); - switch (product_id) { - case HIMAX_ID_83112B: + if (product_id == ts->chip->id) return 0; - default: - dev_err(&ts->client->dev, - "Unknown product id: %x\n", product_id); - return -EINVAL; - } + dev_err(&ts->client->dev, "Unknown product id: %x\n", + product_id); + return -EINVAL; } static int himax_input_register(struct himax_ts_data *ts) @@ -230,13 +276,25 @@ static bool himax_verify_checksum(struct himax_ts_data *ts, return true; } +static int himax_read_events(struct himax_ts_data *ts, + struct himax_event *event, size_t length) +{ + return regmap_raw_read(ts->regmap, HIMAX_AHB_ADDR_EVENT_STACK, event, + length); +} + +static int hx83100a_read_events(struct himax_ts_data *ts, + struct himax_event *event, size_t length) +{ + return himax_bus_read(ts, HX83100A_REG_FW_EVENT_STACK, event, length); +}; + static int himax_handle_input(struct himax_ts_data *ts) { int error; struct himax_event event; - error = regmap_raw_read(ts->regmap, HIMAX_REG_READ_EVENT, &event, - sizeof(event)); + error = ts->chip->read_events(ts, &event, sizeof(event)); if (error) { dev_err(&ts->client->dev, "Failed to read input event: %d\n", error); @@ -282,6 +340,7 @@ static int himax_probe(struct i2c_client *client) i2c_set_clientdata(client, ts); ts->client = client; + ts->chip = i2c_get_match_data(client); ts->regmap = devm_regmap_init_i2c(client, &himax_regmap_config); error = PTR_ERR_OR_ZERO(ts->regmap); @@ -299,9 +358,11 @@ static int himax_probe(struct i2c_client *client) himax_reset(ts); - error = himax_check_product_id(ts); - if (error) - return error; + if (ts->chip->check_id) { + error = himax_check_product_id(ts); + if (error) + return error; + } error = himax_input_register(ts); if (error) @@ -334,15 +395,27 @@ static int himax_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(himax_pm_ops, himax_suspend, himax_resume); +static const struct himax_chip hx83100a_chip = { + .read_events = hx83100a_read_events, +}; + +static const struct himax_chip hx83112b_chip = { + .id = 0x83112b, + .check_id = himax_check_product_id, + .read_events = himax_read_events, +}; + static const struct i2c_device_id himax_ts_id[] = { - { "hx83112b", 0 }, + { "hx83100a", (kernel_ulong_t)&hx83100a_chip }, + { "hx83112b", (kernel_ulong_t)&hx83112b_chip }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, himax_ts_id); #ifdef CONFIG_OF static const struct of_device_id himax_of_match[] = { - { .compatible = "himax,hx83112b" }, + { .compatible = "himax,hx83100a", .data = &hx83100a_chip }, + { .compatible = "himax,hx83112b", .data = &hx83112b_chip }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, himax_of_match); diff --git a/drivers/input/touchscreen/hycon-hy46xx.c b/drivers/input/touchscreen/hycon-hy46xx.c index 2e01d87977c1..b2ff7a45b908 100644 --- a/drivers/input/touchscreen/hycon-hy46xx.c +++ b/drivers/input/touchscreen/hycon-hy46xx.c @@ -15,7 +15,7 @@ #include <linux/regulator/consumer.h> #include <linux/regmap.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define HY46XX_CHKSUM_CODE 0x1 #define HY46XX_FINGER_NUM 0x2 diff --git a/drivers/input/touchscreen/hynitron_cstxxx.c b/drivers/input/touchscreen/hynitron_cstxxx.c index 05946fee4fd4..1d8ca90dcda6 100644 --- a/drivers/input/touchscreen/hynitron_cstxxx.c +++ b/drivers/input/touchscreen/hynitron_cstxxx.c @@ -22,7 +22,7 @@ #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/property.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* Per chip data */ struct hynitron_ts_chip_data { @@ -470,7 +470,7 @@ static const struct hynitron_ts_chip_data cst3xx_data = { }; static const struct i2c_device_id hyn_tpd_id[] = { - { .name = "hynitron_ts", 0 }, + { .name = "hynitron_ts" }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(i2c, hyn_tpd_id); diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 31ffdc2a93f3..fa38d70aded7 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -12,7 +12,7 @@ #include <linux/module.h> #include <linux/sizes.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define ILI2XXX_POLL_PERIOD 15 @@ -261,8 +261,8 @@ static int ili251x_read_touch_data(struct i2c_client *client, u8 *data) if (!error && data[0] == 2) { error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1, ILI251X_DATA_SIZE2); - if (error >= 0 && error != ILI251X_DATA_SIZE2) - error = -EIO; + if (error >= 0) + error = error == ILI251X_DATA_SIZE2 ? 0 : -EIO; } return error; @@ -582,14 +582,12 @@ static ssize_t ili210x_calibrate(struct device *dev, } static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate); -static int ili251x_firmware_to_buffer(const struct firmware *fw, - u8 **buf, u16 *ac_end, u16 *df_end) +static const u8 *ili251x_firmware_to_buffer(const struct firmware *fw, + u16 *ac_end, u16 *df_end) { const struct ihex_binrec *rec; u32 fw_addr, fw_last_addr = 0; u16 fw_len; - u8 *fw_buf; - int error; /* * The firmware ihex blob can never be bigger than 64 kiB, so make this @@ -597,9 +595,9 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, * once, copy them all into this buffer at the right locations, and then * do all operations on this linear buffer. */ - fw_buf = kzalloc(SZ_64K, GFP_KERNEL); + u8* fw_buf __free(kvfree) = kvmalloc(SZ_64K, GFP_KERNEL); if (!fw_buf) - return -ENOMEM; + return ERR_PTR(-ENOMEM); rec = (const struct ihex_binrec *)fw->data; while (rec) { @@ -607,10 +605,8 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, fw_len = be16_to_cpu(rec->len); /* The last 32 Byte firmware block can be 0xffe0 */ - if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) { - error = -EFBIG; - goto err_big; - } + if (fw_addr + fw_len > SZ_64K || fw_addr > SZ_64K - 32) + return ERR_PTR(-EFBIG); /* Find the last address before DF start address, that is AC end */ if (fw_addr == 0xf000) @@ -623,12 +619,8 @@ static int ili251x_firmware_to_buffer(const struct firmware *fw, /* DF end address is the last address in the firmware blob */ *df_end = fw_addr + fw_len; - *buf = fw_buf; - return 0; -err_big: - kfree(fw_buf); - return error; + return_ptr(fw_buf); } /* Switch mode between Application and BootLoader */ @@ -691,7 +683,7 @@ static int ili251x_firmware_busy(struct i2c_client *client) return 0; } -static int ili251x_firmware_write_to_ic(struct device *dev, u8 *fwbuf, +static int ili251x_firmware_write_to_ic(struct device *dev, const u8 *fwbuf, u16 start, u16 end, u8 dataflash) { struct i2c_client *client = to_i2c_client(dev); @@ -776,47 +768,17 @@ static void ili210x_hardware_reset(struct gpio_desc *reset_gpio) msleep(300); } -static ssize_t ili210x_firmware_update_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int ili210x_do_firmware_update(struct ili210x *priv, + const u8 *fwbuf, u16 ac_end, u16 df_end) { - struct i2c_client *client = to_i2c_client(dev); - struct ili210x *priv = i2c_get_clientdata(client); - const char *fwname = ILI251X_FW_FILENAME; - const struct firmware *fw; - u16 ac_end, df_end; - u8 *fwbuf; + struct i2c_client *client = priv->client; + struct device *dev = &client->dev; int error; int i; - error = request_ihex_firmware(&fw, fwname, dev); - if (error) { - dev_err(dev, "Failed to request firmware %s, error=%d\n", - fwname, error); - return error; - } - - error = ili251x_firmware_to_buffer(fw, &fwbuf, &ac_end, &df_end); - release_firmware(fw); - if (error) - return error; - - /* - * Disable touchscreen IRQ, so that we would not get spurious touch - * interrupt during firmware update, and so that the IRQ handler won't - * trigger and interfere with the firmware update. There is no bit in - * the touch controller to disable the IRQs during update, so we have - * to do it this way here. - */ - disable_irq(client->irq); - - dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname); - - ili210x_hardware_reset(priv->reset_gpio); - error = ili251x_firmware_reset(client); if (error) - goto exit; + return error; /* This may not succeed on first try, so re-try a few times. */ for (i = 0; i < 5; i++) { @@ -826,7 +788,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, } if (error) - goto exit; + return error; dev_dbg(dev, "IC is now in BootLoader mode\n"); @@ -835,7 +797,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, error = ili251x_firmware_write_to_ic(dev, fwbuf, 0xf000, df_end, 1); if (error) { dev_err(dev, "DF firmware update failed, error=%d\n", error); - goto exit; + return error; } dev_dbg(dev, "DataFlash firmware written\n"); @@ -843,7 +805,7 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, error = ili251x_firmware_write_to_ic(dev, fwbuf, 0x2000, ac_end, 0); if (error) { dev_err(dev, "AC firmware update failed, error=%d\n", error); - goto exit; + return error; } dev_dbg(dev, "Application firmware written\n"); @@ -856,22 +818,61 @@ static ssize_t ili210x_firmware_update_store(struct device *dev, } if (error) - goto exit; + return error; dev_dbg(dev, "IC is now in Application mode\n"); error = ili251x_firmware_update_cached_state(dev); if (error) - goto exit; + return error; - error = count; + return 0; +} -exit: - ili210x_hardware_reset(priv->reset_gpio); - dev_dbg(dev, "Firmware update ended, error=%i\n", error); - enable_irq(client->irq); - kfree(fwbuf); - return error; +static ssize_t ili210x_firmware_update_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct ili210x *priv = i2c_get_clientdata(client); + const char *fwname = ILI251X_FW_FILENAME; + u16 ac_end, df_end; + int error; + + const struct firmware *fw __free(firmware) = NULL; + error = request_ihex_firmware(&fw, fwname, dev); + if (error) { + dev_err(dev, "Failed to request firmware %s, error=%d\n", + fwname, error); + return error; + } + + const u8* fwbuf __free(kvfree) = + ili251x_firmware_to_buffer(fw, &ac_end, &df_end); + error = PTR_ERR_OR_ZERO(fwbuf); + if (error) + return error; + + /* + * Disable touchscreen IRQ, so that we would not get spurious touch + * interrupt during firmware update, and so that the IRQ handler won't + * trigger and interfere with the firmware update. There is no bit in + * the touch controller to disable the IRQs during update, so we have + * to do it this way here. + */ + scoped_guard(disable_irq, &client->irq) { + dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname); + + ili210x_hardware_reset(priv->reset_gpio); + + error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end); + + ili210x_hardware_reset(priv->reset_gpio); + + dev_dbg(dev, "Firmware update ended, error=%i\n", error); + } + + return error ?: count; } static DEVICE_ATTR(firmware_update, 0200, NULL, ili210x_firmware_update_store); @@ -897,7 +898,7 @@ static umode_t ili210x_attributes_visible(struct kobject *kobj, if (attr == &dev_attr_calibrate.attr) return priv->chip->has_calibrate_reg ? attr->mode : 0; - /* Firmware/Kernel/Protocol/BootMode is implememted only for ILI251x */ + /* Firmware/Kernel/Protocol/BootMode is implemented only for ILI251x */ if (!priv->chip->has_firmware_proto) return 0; diff --git a/drivers/input/touchscreen/ilitek_ts_i2c.c b/drivers/input/touchscreen/ilitek_ts_i2c.c index fc4e39b6651a..0dd632724a00 100644 --- a/drivers/input/touchscreen/ilitek_ts_i2c.c +++ b/drivers/input/touchscreen/ilitek_ts_i2c.c @@ -15,12 +15,11 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/errno.h> #include <linux/acpi.h> #include <linux/input/touchscreen.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define ILITEK_TS_NAME "ilitek_ts" @@ -37,6 +36,8 @@ #define ILITEK_TP_CMD_GET_MCU_VER 0x61 #define ILITEK_TP_CMD_GET_IC_MODE 0xC0 +#define ILITEK_TP_I2C_REPORT_ID 0x48 + #define REPORT_COUNT_ADDRESS 61 #define ILITEK_SUPPORT_MAX_POINT 40 @@ -160,15 +161,19 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) error = ilitek_i2c_write_and_read(ts, NULL, 0, 0, buf, 64); if (error) { dev_err(dev, "get touch info failed, err:%d\n", error); - goto err_sync_frame; + return error; + } + + if (buf[0] != ILITEK_TP_I2C_REPORT_ID) { + dev_err(dev, "get touch info failed. Wrong id: 0x%02X\n", buf[0]); + return -EINVAL; } report_max_point = buf[REPORT_COUNT_ADDRESS]; if (report_max_point > ts->max_tp) { dev_err(dev, "FW report max point:%d > panel info. max:%d\n", report_max_point, ts->max_tp); - error = -EINVAL; - goto err_sync_frame; + return -EINVAL; } count = DIV_ROUND_UP(report_max_point, packet_max_point); @@ -178,7 +183,7 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) if (error) { dev_err(dev, "get touch info. failed, cnt:%d, err:%d\n", count, error); - goto err_sync_frame; + return error; } } @@ -203,10 +208,10 @@ static int ilitek_process_and_report_v6(struct ilitek_ts_data *ts) ilitek_touch_down(ts, id, x, y); } -err_sync_frame: input_mt_sync_frame(input); input_sync(input); - return error; + + return 0; } /* APIs of cmds for ILITEK Touch IC */ @@ -634,8 +639,8 @@ static int ilitek_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(ilitek_pm_ops, ilitek_suspend, ilitek_resume); static const struct i2c_device_id ilitek_ts_i2c_id[] = { - { ILITEK_TS_NAME, 0 }, - { }, + { ILITEK_TS_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, ilitek_ts_i2c_id); diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c index 074dd6c342ec..3c8bbe284b73 100644 --- a/drivers/input/touchscreen/imagis.c +++ b/drivers/input/touchscreen/imagis.c @@ -12,9 +12,18 @@ #include <linux/property.h> #include <linux/regulator/consumer.h> +#define IST30XX_REG_STATUS 0x20 +#define IST30XX_REG_CHIPID (0x40000000 | IST3038C_DIRECT_ACCESS) + +#define IST30XX_WHOAMI 0x30003000 +#define IST30XXA_WHOAMI 0x300a300a +#define IST30XXB_WHOAMI 0x300b300b +#define IST3038_WHOAMI 0x30383038 + #define IST3032C_WHOAMI 0x32c +#define IST3038C_WHOAMI 0x38c +#define IST3038H_WHOAMI 0x38d -#define IST3038B_REG_STATUS 0x20 #define IST3038B_REG_CHIPID 0x30 #define IST3038B_WHOAMI 0x30380b @@ -25,7 +34,6 @@ #define IST3038C_REG_TOUCH_STATUS (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS) #define IST3038C_REG_TOUCH_COORD (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x8) #define IST3038C_REG_INTR_MESSAGE (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x4) -#define IST3038C_WHOAMI 0x38c #define IST3038C_CHIP_ON_DELAY_MS 60 #define IST3038C_I2C_RETRY_COUNT 3 #define IST3038C_MAX_FINGER_NUM 10 @@ -121,11 +129,11 @@ static irqreturn_t imagis_interrupt(int irq, void *dev_id) for (i = 0; i < finger_count; i++) { if (ts->tdata->protocol_b) error = imagis_i2c_read_reg(ts, - ts->tdata->touch_coord_cmd, &finger_status); - else - error = imagis_i2c_read_reg(ts, ts->tdata->touch_coord_cmd + (i * 4), &finger_status); + else + error = imagis_i2c_read_reg(ts, + ts->tdata->touch_coord_cmd, &finger_status); if (error) { dev_err(&ts->client->dev, "failed to read coordinates for finger %d: %d\n", @@ -388,20 +396,29 @@ static int imagis_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume); +#ifdef CONFIG_OF static const struct imagis_properties imagis_3032c_data = { .interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE, .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, .whoami_cmd = IST3038C_REG_CHIPID, .whoami_val = IST3032C_WHOAMI, .touch_keys_supported = true, + .protocol_b = true, +}; + +static const struct imagis_properties imagis_3038_data = { + .interrupt_msg_cmd = IST30XX_REG_STATUS, + .touch_coord_cmd = IST30XX_REG_STATUS, + .whoami_cmd = IST30XX_REG_CHIPID, + .whoami_val = IST3038_WHOAMI, + .touch_keys_supported = true, }; static const struct imagis_properties imagis_3038b_data = { - .interrupt_msg_cmd = IST3038B_REG_STATUS, - .touch_coord_cmd = IST3038B_REG_STATUS, + .interrupt_msg_cmd = IST30XX_REG_STATUS, + .touch_coord_cmd = IST30XX_REG_STATUS, .whoami_cmd = IST3038B_REG_CHIPID, .whoami_val = IST3038B_WHOAMI, - .protocol_b = true, }; static const struct imagis_properties imagis_3038c_data = { @@ -409,13 +426,22 @@ static const struct imagis_properties imagis_3038c_data = { .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, .whoami_cmd = IST3038C_REG_CHIPID, .whoami_val = IST3038C_WHOAMI, + .protocol_b = true, +}; + +static const struct imagis_properties imagis_3038h_data = { + .interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE, + .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, + .whoami_cmd = IST3038C_REG_CHIPID, + .whoami_val = IST3038H_WHOAMI, }; -#ifdef CONFIG_OF static const struct of_device_id imagis_of_match[] = { { .compatible = "imagis,ist3032c", .data = &imagis_3032c_data }, + { .compatible = "imagis,ist3038", .data = &imagis_3038_data }, { .compatible = "imagis,ist3038b", .data = &imagis_3038b_data }, { .compatible = "imagis,ist3038c", .data = &imagis_3038c_data }, + { .compatible = "imagis,ist3038h", .data = &imagis_3038h_data }, { }, }; MODULE_DEVICE_TABLE(of, imagis_of_match); diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index 1d7e4c3966ce..82f7ac62a4f2 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c @@ -114,7 +114,7 @@ static int inexio_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - pinexio = kzalloc(sizeof(struct inexio), GFP_KERNEL); + pinexio = kzalloc(sizeof(*pinexio), GFP_KERNEL); input_dev = input_allocate_device(); if (!pinexio || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/iqs5xx.c b/drivers/input/touchscreen/iqs5xx.c index 4d226118f3cc..4ebd7565ae6e 100644 --- a/drivers/input/touchscreen/iqs5xx.c +++ b/drivers/input/touchscreen/iqs5xx.c @@ -26,7 +26,7 @@ #include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define IQS5XX_FW_FILE_LEN 64 #define IQS5XX_NUM_RETRIES 10 diff --git a/drivers/input/touchscreen/iqs7211.c b/drivers/input/touchscreen/iqs7211.c index f0a56cde899e..c5d447ee6f53 100644 --- a/drivers/input/touchscreen/iqs7211.c +++ b/drivers/input/touchscreen/iqs7211.c @@ -22,7 +22,7 @@ #include <linux/of_device.h> #include <linux/property.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define IQS7211_PROD_NUM 0x00 diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index bfbebe245040..5abf164ae14c 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -261,7 +261,7 @@ static void mainstone_wm97xx_remove(struct platform_device *pdev) static struct platform_driver mainstone_wm97xx_driver = { .probe = mainstone_wm97xx_probe, - .remove_new = mainstone_wm97xx_remove, + .remove = mainstone_wm97xx_remove, .driver = { .name = "wm97xx-touch", }, diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 8be6dade118c..f39633fc8dc2 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -213,7 +213,7 @@ static int max11801_ts_probe(struct i2c_client *client) } static const struct i2c_device_id max11801_ts_id[] = { - {"max11801", 0}, + { "max11801" }, { } }; MODULE_DEVICE_TABLE(i2c, max11801_ts_id); diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index cbcd6e34efb7..33635da85079 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c @@ -226,7 +226,7 @@ static void mc13783_ts_remove(struct platform_device *pdev) } static struct platform_driver mc13783_ts_driver = { - .remove_new = mc13783_ts_remove, + .remove = mc13783_ts_remove, .driver = { .name = MC13783_TS_NAME, }, diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c deleted file mode 100644 index ac28019ba4c3..000000000000 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * mcs5000_ts.c - Touchscreen driver for MELFAS MCS-5000 controller - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim <jy0922.shim@samsung.com> - * - * Based on wm97xx-core.c - */ - -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/irq.h> -#include <linux/platform_data/mcs.h> -#include <linux/slab.h> - -/* Registers */ -#define MCS5000_TS_STATUS 0x00 -#define STATUS_OFFSET 0 -#define STATUS_NO (0 << STATUS_OFFSET) -#define STATUS_INIT (1 << STATUS_OFFSET) -#define STATUS_SENSING (2 << STATUS_OFFSET) -#define STATUS_COORD (3 << STATUS_OFFSET) -#define STATUS_GESTURE (4 << STATUS_OFFSET) -#define ERROR_OFFSET 4 -#define ERROR_NO (0 << ERROR_OFFSET) -#define ERROR_POWER_ON_RESET (1 << ERROR_OFFSET) -#define ERROR_INT_RESET (2 << ERROR_OFFSET) -#define ERROR_EXT_RESET (3 << ERROR_OFFSET) -#define ERROR_INVALID_REG_ADDRESS (8 << ERROR_OFFSET) -#define ERROR_INVALID_REG_VALUE (9 << ERROR_OFFSET) - -#define MCS5000_TS_OP_MODE 0x01 -#define RESET_OFFSET 0 -#define RESET_NO (0 << RESET_OFFSET) -#define RESET_EXT_SOFT (1 << RESET_OFFSET) -#define OP_MODE_OFFSET 1 -#define OP_MODE_SLEEP (0 << OP_MODE_OFFSET) -#define OP_MODE_ACTIVE (1 << OP_MODE_OFFSET) -#define GESTURE_OFFSET 4 -#define GESTURE_DISABLE (0 << GESTURE_OFFSET) -#define GESTURE_ENABLE (1 << GESTURE_OFFSET) -#define PROXIMITY_OFFSET 5 -#define PROXIMITY_DISABLE (0 << PROXIMITY_OFFSET) -#define PROXIMITY_ENABLE (1 << PROXIMITY_OFFSET) -#define SCAN_MODE_OFFSET 6 -#define SCAN_MODE_INTERRUPT (0 << SCAN_MODE_OFFSET) -#define SCAN_MODE_POLLING (1 << SCAN_MODE_OFFSET) -#define REPORT_RATE_OFFSET 7 -#define REPORT_RATE_40 (0 << REPORT_RATE_OFFSET) -#define REPORT_RATE_80 (1 << REPORT_RATE_OFFSET) - -#define MCS5000_TS_SENS_CTL 0x02 -#define MCS5000_TS_FILTER_CTL 0x03 -#define PRI_FILTER_OFFSET 0 -#define SEC_FILTER_OFFSET 4 - -#define MCS5000_TS_X_SIZE_UPPER 0x08 -#define MCS5000_TS_X_SIZE_LOWER 0x09 -#define MCS5000_TS_Y_SIZE_UPPER 0x0A -#define MCS5000_TS_Y_SIZE_LOWER 0x0B - -#define MCS5000_TS_INPUT_INFO 0x10 -#define INPUT_TYPE_OFFSET 0 -#define INPUT_TYPE_NONTOUCH (0 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_SINGLE (1 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_DUAL (2 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_PALM (3 << INPUT_TYPE_OFFSET) -#define INPUT_TYPE_PROXIMITY (7 << INPUT_TYPE_OFFSET) -#define GESTURE_CODE_OFFSET 3 -#define GESTURE_CODE_NO (0 << GESTURE_CODE_OFFSET) - -#define MCS5000_TS_X_POS_UPPER 0x11 -#define MCS5000_TS_X_POS_LOWER 0x12 -#define MCS5000_TS_Y_POS_UPPER 0x13 -#define MCS5000_TS_Y_POS_LOWER 0x14 -#define MCS5000_TS_Z_POS 0x15 -#define MCS5000_TS_WIDTH 0x16 -#define MCS5000_TS_GESTURE_VAL 0x17 -#define MCS5000_TS_MODULE_REV 0x20 -#define MCS5000_TS_FIRMWARE_VER 0x21 - -/* Touchscreen absolute values */ -#define MCS5000_MAX_XC 0x3ff -#define MCS5000_MAX_YC 0x3ff - -enum mcs5000_ts_read_offset { - READ_INPUT_INFO, - READ_X_POS_UPPER, - READ_X_POS_LOWER, - READ_Y_POS_UPPER, - READ_Y_POS_LOWER, - READ_BLOCK_SIZE, -}; - -/* Each client has this additional data */ -struct mcs5000_ts_data { - struct i2c_client *client; - struct input_dev *input_dev; - const struct mcs_platform_data *platform_data; -}; - -static irqreturn_t mcs5000_ts_interrupt(int irq, void *dev_id) -{ - struct mcs5000_ts_data *data = dev_id; - struct i2c_client *client = data->client; - u8 buffer[READ_BLOCK_SIZE]; - int err; - int x; - int y; - - err = i2c_smbus_read_i2c_block_data(client, MCS5000_TS_INPUT_INFO, - READ_BLOCK_SIZE, buffer); - if (err < 0) { - dev_err(&client->dev, "%s, err[%d]\n", __func__, err); - goto out; - } - - switch (buffer[READ_INPUT_INFO]) { - case INPUT_TYPE_NONTOUCH: - input_report_key(data->input_dev, BTN_TOUCH, 0); - input_sync(data->input_dev); - break; - - case INPUT_TYPE_SINGLE: - x = (buffer[READ_X_POS_UPPER] << 8) | buffer[READ_X_POS_LOWER]; - y = (buffer[READ_Y_POS_UPPER] << 8) | buffer[READ_Y_POS_LOWER]; - - input_report_key(data->input_dev, BTN_TOUCH, 1); - input_report_abs(data->input_dev, ABS_X, x); - input_report_abs(data->input_dev, ABS_Y, y); - input_sync(data->input_dev); - break; - - case INPUT_TYPE_DUAL: - /* TODO */ - break; - - case INPUT_TYPE_PALM: - /* TODO */ - break; - - case INPUT_TYPE_PROXIMITY: - /* TODO */ - break; - - default: - dev_err(&client->dev, "Unknown ts input type %d\n", - buffer[READ_INPUT_INFO]); - break; - } - - out: - return IRQ_HANDLED; -} - -static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data, - const struct mcs_platform_data *platform_data) -{ - struct i2c_client *client = data->client; - - /* Touch reset & sleep mode */ - i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, - RESET_EXT_SOFT | OP_MODE_SLEEP); - - /* Touch size */ - i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_UPPER, - platform_data->x_size >> 8); - i2c_smbus_write_byte_data(client, MCS5000_TS_X_SIZE_LOWER, - platform_data->x_size & 0xff); - i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_UPPER, - platform_data->y_size >> 8); - i2c_smbus_write_byte_data(client, MCS5000_TS_Y_SIZE_LOWER, - platform_data->y_size & 0xff); - - /* Touch active mode & 80 report rate */ - i2c_smbus_write_byte_data(data->client, MCS5000_TS_OP_MODE, - OP_MODE_ACTIVE | REPORT_RATE_80); -} - -static int mcs5000_ts_probe(struct i2c_client *client) -{ - const struct mcs_platform_data *pdata; - struct mcs5000_ts_data *data; - struct input_dev *input_dev; - int error; - - pdata = dev_get_platdata(&client->dev); - if (!pdata) - return -EINVAL; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "Failed to allocate memory\n"); - return -ENOMEM; - } - - data->client = client; - - input_dev = devm_input_allocate_device(&client->dev); - if (!input_dev) { - dev_err(&client->dev, "Failed to allocate input device\n"); - return -ENOMEM; - } - - input_dev->name = "MELFAS MCS-5000 Touchscreen"; - input_dev->id.bustype = BUS_I2C; - input_dev->dev.parent = &client->dev; - - __set_bit(EV_ABS, input_dev->evbit); - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(BTN_TOUCH, input_dev->keybit); - input_set_abs_params(input_dev, ABS_X, 0, MCS5000_MAX_XC, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, MCS5000_MAX_YC, 0, 0); - - data->input_dev = input_dev; - - if (pdata->cfg_pin) - pdata->cfg_pin(); - - error = devm_request_threaded_irq(&client->dev, client->irq, - NULL, mcs5000_ts_interrupt, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "mcs5000_ts", data); - if (error) { - dev_err(&client->dev, "Failed to register interrupt\n"); - return error; - } - - error = input_register_device(data->input_dev); - if (error) { - dev_err(&client->dev, "Failed to register input device\n"); - return error; - } - - mcs5000_ts_phys_init(data, pdata); - i2c_set_clientdata(client, data); - - return 0; -} - -static int mcs5000_ts_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - - /* Touch sleep mode */ - i2c_smbus_write_byte_data(client, MCS5000_TS_OP_MODE, OP_MODE_SLEEP); - - return 0; -} - -static int mcs5000_ts_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct mcs5000_ts_data *data = i2c_get_clientdata(client); - const struct mcs_platform_data *pdata = dev_get_platdata(dev); - - mcs5000_ts_phys_init(data, pdata); - - return 0; -} - -static DEFINE_SIMPLE_DEV_PM_OPS(mcs5000_ts_pm, - mcs5000_ts_suspend, mcs5000_ts_resume); - -static const struct i2c_device_id mcs5000_ts_id[] = { - { "mcs5000_ts", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); - -static struct i2c_driver mcs5000_ts_driver = { - .probe = mcs5000_ts_probe, - .driver = { - .name = "mcs5000_ts", - .pm = pm_sleep_ptr(&mcs5000_ts_pm), - }, - .id_table = mcs5000_ts_id, -}; - -module_i2c_driver(mcs5000_ts_driver); - -/* Module information */ -MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); -MODULE_DESCRIPTION("Touchscreen driver for MELFAS MCS-5000 controller"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/melfas_mip4.c b/drivers/input/touchscreen/melfas_mip4.c index 78e1c63e530e..a6946e3d8376 100644 --- a/drivers/input/touchscreen/melfas_mip4.c +++ b/drivers/input/touchscreen/melfas_mip4.c @@ -18,7 +18,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define MIP4_DEVICE_NAME "mip4_ts" @@ -1569,8 +1569,8 @@ MODULE_DEVICE_TABLE(acpi, mip4_acpi_match); #endif static const struct i2c_device_id mip4_i2c_ids[] = { - { MIP4_DEVICE_NAME, 0 }, - { }, + { MIP4_DEVICE_NAME }, + { } }; MODULE_DEVICE_TABLE(i2c, mip4_i2c_ids); diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 2384ea69a3f8..7511a134e302 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -211,7 +211,7 @@ static int migor_ts_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(migor_ts_pm, migor_ts_suspend, migor_ts_resume); static const struct i2c_device_id migor_ts_id[] = { - { "migor_ts", 0 }, + { "migor_ts" }, { } }; MODULE_DEVICE_TABLE(i2c, migor_ts_id); diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index af233b6a16d9..9f947044c4d9 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -677,7 +677,7 @@ static int mms114_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume); static const struct i2c_device_id mms114_id[] = { - { "mms114", 0 }, + { "mms114" }, { } }; MODULE_DEVICE_TABLE(i2c, mms114_id); diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 28e449eea318..eefae96a2d40 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -128,7 +128,7 @@ static int mtouch_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - mtouch = kzalloc(sizeof(struct mtouch), GFP_KERNEL); + mtouch = kzalloc(sizeof(*mtouch), GFP_KERNEL); input_dev = input_allocate_device(); if (!mtouch || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/novatek-nvt-ts.c b/drivers/input/touchscreen/novatek-nvt-ts.c index 1a797e410a3f..44b58e0dc1ad 100644 --- a/drivers/input/touchscreen/novatek-nvt-ts.c +++ b/drivers/input/touchscreen/novatek-nvt-ts.c @@ -15,7 +15,7 @@ #include <linux/input/touchscreen.h> #include <linux/module.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define NVT_TS_TOUCH_START 0x00 #define NVT_TS_TOUCH_SIZE 6 @@ -31,9 +31,6 @@ #define NVT_TS_PARAMS_CHIP_ID 0x0e #define NVT_TS_PARAMS_SIZE 0x0f -#define NVT_TS_SUPPORTED_WAKE_TYPE 0x05 -#define NVT_TS_SUPPORTED_CHIP_ID 0x05 - #define NVT_TS_MAX_TOUCHES 10 #define NVT_TS_MAX_SIZE 4096 @@ -51,10 +48,16 @@ static const int nvt_ts_irq_type[4] = { IRQF_TRIGGER_HIGH }; +struct nvt_ts_i2c_chip_data { + u8 wake_type; + u8 chip_id; +}; + struct nvt_ts_data { struct i2c_client *client; struct input_dev *input; struct gpio_desc *reset_gpio; + struct regulator_bulk_data regulators[2]; struct touchscreen_properties prop; int max_touches; u8 buf[NVT_TS_TOUCH_SIZE * NVT_TS_MAX_TOUCHES]; @@ -142,6 +145,13 @@ static irqreturn_t nvt_ts_irq(int irq, void *dev_id) static int nvt_ts_start(struct input_dev *dev) { struct nvt_ts_data *data = input_get_drvdata(dev); + int error; + + error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators); + if (error) { + dev_err(&data->client->dev, "failed to enable regulators\n"); + return error; + } enable_irq(data->client->irq); gpiod_set_value_cansleep(data->reset_gpio, 0); @@ -155,6 +165,7 @@ static void nvt_ts_stop(struct input_dev *dev) disable_irq(data->client->irq); gpiod_set_value_cansleep(data->reset_gpio, 1); + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); } static int nvt_ts_suspend(struct device *dev) @@ -188,6 +199,7 @@ static int nvt_ts_probe(struct i2c_client *client) struct device *dev = &client->dev; int error, width, height, irq_type; struct nvt_ts_data *data; + const struct nvt_ts_i2c_chip_data *chip; struct input_dev *input; if (!client->irq) { @@ -199,12 +211,35 @@ static int nvt_ts_probe(struct i2c_client *client) if (!data) return -ENOMEM; + chip = device_get_match_data(&client->dev); + if (!chip) + return -EINVAL; + data->client = client; i2c_set_clientdata(client, data); + /* + * VCC is the analog voltage supply + * IOVCC is the digital voltage supply + */ + data->regulators[0].supply = "vcc"; + data->regulators[1].supply = "iovcc"; + error = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators), data->regulators); + if (error) { + dev_err(dev, "cannot get regulators: %d\n", error); + return error; + } + + error = regulator_bulk_enable(ARRAY_SIZE(data->regulators), data->regulators); + if (error) { + dev_err(dev, "failed to enable regulators: %d\n", error); + return error; + } + data->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); error = PTR_ERR_OR_ZERO(data->reset_gpio); if (error) { + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); dev_err(dev, "failed to request reset GPIO: %d\n", error); return error; } @@ -214,6 +249,7 @@ static int nvt_ts_probe(struct i2c_client *client) error = nvt_ts_read_data(data->client, NVT_TS_PARAMETERS_START, data->buf, NVT_TS_PARAMS_SIZE); gpiod_set_value_cansleep(data->reset_gpio, 1); /* Put back in reset */ + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); if (error) return error; @@ -225,8 +261,8 @@ static int nvt_ts_probe(struct i2c_client *client) if (width > NVT_TS_MAX_SIZE || height >= NVT_TS_MAX_SIZE || data->max_touches > NVT_TS_MAX_TOUCHES || irq_type >= ARRAY_SIZE(nvt_ts_irq_type) || - data->buf[NVT_TS_PARAMS_WAKE_TYPE] != NVT_TS_SUPPORTED_WAKE_TYPE || - data->buf[NVT_TS_PARAMS_CHIP_ID] != NVT_TS_SUPPORTED_CHIP_ID) { + data->buf[NVT_TS_PARAMS_WAKE_TYPE] != chip->wake_type || + data->buf[NVT_TS_PARAMS_CHIP_ID] != chip->chip_id) { dev_err(dev, "Unsupported touchscreen parameters: %*ph\n", NVT_TS_PARAMS_SIZE, data->buf); return -EIO; @@ -277,8 +313,26 @@ static int nvt_ts_probe(struct i2c_client *client) return 0; } +static const struct nvt_ts_i2c_chip_data nvt_nt11205_ts_data = { + .wake_type = 0x05, + .chip_id = 0x05, +}; + +static const struct nvt_ts_i2c_chip_data nvt_nt36672a_ts_data = { + .wake_type = 0x01, + .chip_id = 0x08, +}; + +static const struct of_device_id nvt_ts_of_match[] = { + { .compatible = "novatek,nt11205-ts", .data = &nvt_nt11205_ts_data }, + { .compatible = "novatek,nt36672a-ts", .data = &nvt_nt36672a_ts_data }, + { } +}; +MODULE_DEVICE_TABLE(of, nvt_ts_of_match); + static const struct i2c_device_id nvt_ts_i2c_id[] = { - { "NVT-ts" }, + { "nt11205-ts", (unsigned long) &nvt_nt11205_ts_data }, + { "nt36672a-ts", (unsigned long) &nvt_nt36672a_ts_data }, { } }; MODULE_DEVICE_TABLE(i2c, nvt_ts_i2c_id); @@ -287,6 +341,7 @@ static struct i2c_driver nvt_ts_driver = { .driver = { .name = "novatek-nvt-ts", .pm = pm_sleep_ptr(&nvt_ts_pm_ops), + .of_match_table = nvt_ts_of_match, }, .probe = nvt_ts_probe, .id_table = nvt_ts_i2c_id, diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index 821245019fea..083206a3457b 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c @@ -238,7 +238,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = { static struct platform_driver pcap_ts_driver = { .probe = pcap_ts_probe, - .remove_new = pcap_ts_remove, + .remove = pcap_ts_remove, .driver = { .name = "pcap-ts", .pm = PCAP_TS_PM_OPS, diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 12abb3b36128..95adede26703 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -199,7 +199,7 @@ static int pm_connect(struct serio *serio, struct serio_driver *drv) int max_x, max_y; int err; - pm = kzalloc(sizeof(struct pm), GFP_KERNEL); + pm = kzalloc(sizeof(*pm), GFP_KERNEL); input_dev = input_allocate_device(); if (!pm || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 4ede0687beb0..dad5786e82a4 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -5,7 +5,7 @@ * Copyright (C) 2010-2011 Pixcir, Inc. */ -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> @@ -44,7 +44,7 @@ enum pixcir_power_mode { /* * Interrupt modes: - * periodical: interrupt is asserted periodicaly + * periodical: interrupt is asserted periodically * diff coordinates: interrupt is asserted when coordinates change * level on touch: interrupt level asserted during touch * pulse on touch: interrupt pulse asserted during touch diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c index 45c575df994e..841d39a449b3 100644 --- a/drivers/input/touchscreen/raspberrypi-ts.c +++ b/drivers/input/touchscreen/raspberrypi-ts.c @@ -122,20 +122,18 @@ static int rpi_ts_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct input_dev *input; - struct device_node *fw_node; struct rpi_firmware *fw; struct rpi_ts *ts; u32 touchbuf; int error; - fw_node = of_get_parent(np); + struct device_node *fw_node __free(device_node) = of_get_parent(np); if (!fw_node) { dev_err(dev, "Missing firmware node\n"); return -ENOENT; } fw = devm_rpi_firmware_get(&pdev->dev, fw_node); - of_node_put(fw_node); if (!fw) return -EPROBE_DEFER; diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 13c500e776f6..f975b53e8825 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -24,7 +24,7 @@ #include <linux/pm_wakeirq.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* Slave I2C mode */ #define RM_BOOT_BLDR 0x02 @@ -1227,8 +1227,8 @@ static DEFINE_SIMPLE_DEV_PM_OPS(raydium_i2c_pm_ops, raydium_i2c_suspend, raydium_i2c_resume); static const struct i2c_device_id raydium_i2c_id[] = { - { "raydium_i2c", 0 }, - { "rm32380", 0 }, + { "raydium_i2c" }, + { "rm32380" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, raydium_i2c_id); diff --git a/drivers/input/touchscreen/rohm_bu21023.c b/drivers/input/touchscreen/rohm_bu21023.c index 4493ad0c9322..295d8d75ba32 100644 --- a/drivers/input/touchscreen/rohm_bu21023.c +++ b/drivers/input/touchscreen/rohm_bu21023.c @@ -388,13 +388,13 @@ static int rohm_ts_manual_calibration(struct rohm_ts_data *ts) err_y = (int)READ_CALIB_BUF(PRM1_Y_H) << 2 | READ_CALIB_BUF(PRM1_Y_L); - /* X axis ajust */ + /* X axis adjust */ if (err_x <= 4) calib_x -= AXIS_ADJUST; else if (err_x >= 60) calib_x += AXIS_ADJUST; - /* Y axis ajust */ + /* Y axis adjust */ if (err_y <= 4) calib_y -= AXIS_ADJUST; else if (err_y >= 60) @@ -643,12 +643,12 @@ static int rohm_ts_load_firmware(struct i2c_client *client, const char *firmware_name) { struct device *dev = &client->dev; - const struct firmware *fw; s32 status; unsigned int offset, len, xfer_len; unsigned int retry = 0; int error, error2; + const struct firmware *fw __free(firmware) = NULL; error = request_firmware(&fw, firmware_name, dev); if (error) { dev_err(dev, "unable to retrieve firmware %s: %d\n", @@ -722,18 +722,39 @@ static int rohm_ts_load_firmware(struct i2c_client *client, out: error2 = i2c_smbus_write_byte_data(client, INT_MASK, INT_ALL); - release_firmware(fw); - return error ? error : error2; } +static int rohm_ts_update_setting(struct rohm_ts_data *ts, + unsigned int setting_bit, bool on) +{ + int error; + + scoped_cond_guard(mutex_intr, return -EINTR, &ts->input->mutex) { + if (on) + ts->setup2 |= setting_bit; + else + ts->setup2 &= ~setting_bit; + + if (ts->initialized) { + error = i2c_smbus_write_byte_data(ts->client, + COMMON_SETUP2, + ts->setup2); + if (error) + return error; + } + } + + return 0; +} + static ssize_t swap_xy_show(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & SWAP_XY)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & SWAP_XY)); } static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr, @@ -748,22 +769,8 @@ static ssize_t swap_xy_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= SWAP_XY; - else - ts->setup2 &= ~SWAP_XY; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, SWAP_XY, val); + return error ?: count; } static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr, @@ -772,7 +779,7 @@ static ssize_t inv_x_show(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & INV_X)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & INV_X)); } static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr, @@ -787,22 +794,8 @@ static ssize_t inv_x_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= INV_X; - else - ts->setup2 &= ~INV_X; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(ts->client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, INV_X, val); + return error ?: count; } static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr, @@ -811,7 +804,7 @@ static ssize_t inv_y_show(struct device *dev, struct device_attribute *attr, struct i2c_client *client = to_i2c_client(dev); struct rohm_ts_data *ts = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", !!(ts->setup2 & INV_Y)); + return sysfs_emit(buf, "%d\n", !!(ts->setup2 & INV_Y)); } static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr, @@ -826,22 +819,8 @@ static ssize_t inv_y_store(struct device *dev, struct device_attribute *attr, if (error) return error; - error = mutex_lock_interruptible(&ts->input->mutex); - if (error) - return error; - - if (val) - ts->setup2 |= INV_Y; - else - ts->setup2 &= ~INV_Y; - - if (ts->initialized) - error = i2c_smbus_write_byte_data(client, COMMON_SETUP2, - ts->setup2); - - mutex_unlock(&ts->input->mutex); - - return error ? error : count; + error = rohm_ts_update_setting(ts, INV_Y, val); + return error ?: count; } static DEVICE_ATTR_RW(swap_xy); @@ -861,7 +840,7 @@ static int rohm_ts_device_init(struct i2c_client *client, u8 setup2) struct device *dev = &client->dev; int error; - disable_irq(client->irq); + guard(disable_irq)(&client->irq); /* * Wait 200usec for reset @@ -1036,10 +1015,10 @@ static int rohm_ts_device_init(struct i2c_client *client, u8 setup2) /* controller CPU power on */ error = i2c_smbus_write_byte_data(client, SYSTEM, ANALOG_POWER_ON | CPU_POWER_ON); + if (error) + return error; - enable_irq(client->irq); - - return error; + return 0; } static int rohm_ts_power_off(struct i2c_client *client) @@ -1165,7 +1144,7 @@ static int rohm_bu21023_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id rohm_bu21023_i2c_id[] = { - { BU21023_NAME, 0 }, + { BU21023_NAME }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, rohm_bu21023_i2c_id); diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c index 149cc2c4925e..e1518a75a51b 100644 --- a/drivers/input/touchscreen/s6sy761.c +++ b/drivers/input/touchscreen/s6sy761.c @@ -4,7 +4,7 @@ // Copyright (c) 2017 Samsung Electronics Co., Ltd. // Copyright (c) 2017 Andi Shyti <andi@etezian.org> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/delay.h> #include <linux/i2c.h> #include <linux/input/mt.h> @@ -520,8 +520,8 @@ MODULE_DEVICE_TABLE(of, s6sy761_of_match); #endif static const struct i2c_device_id s6sy761_id[] = { - { "s6sy761", 0 }, - { }, + { "s6sy761" }, + { } }; MODULE_DEVICE_TABLE(i2c, s6sy761_id); diff --git a/drivers/input/touchscreen/silead.c b/drivers/input/touchscreen/silead.c index 62f562ad5026..5ccc96764742 100644 --- a/drivers/input/touchscreen/silead.c +++ b/drivers/input/touchscreen/silead.c @@ -24,7 +24,7 @@ #include <linux/irq.h> #include <linux/regulator/consumer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define SILEAD_TS_NAME "silead_ts" @@ -71,7 +71,6 @@ struct silead_ts_data { struct regulator_bulk_data regulators[2]; char fw_name[64]; struct touchscreen_properties prop; - u32 max_fingers; u32 chip_id; struct input_mt_pos pos[SILEAD_MAX_FINGERS]; int slots[SILEAD_MAX_FINGERS]; @@ -136,7 +135,7 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data) touchscreen_parse_properties(data->input, true, &data->prop); silead_apply_efi_fw_min_max(data); - input_mt_init_slots(data->input, data->max_fingers, + input_mt_init_slots(data->input, SILEAD_MAX_FINGERS, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); @@ -256,10 +255,10 @@ static void silead_ts_read_data(struct i2c_client *client) return; } - if (buf[0] > data->max_fingers) { + if (buf[0] > SILEAD_MAX_FINGERS) { dev_warn(dev, "More touches reported then supported %d > %d\n", - buf[0], data->max_fingers); - buf[0] = data->max_fingers; + buf[0], SILEAD_MAX_FINGERS); + buf[0] = SILEAD_MAX_FINGERS; } if (silead_ts_handle_pen_data(data, buf)) @@ -315,7 +314,6 @@ sync: static int silead_ts_init(struct i2c_client *client) { - struct silead_ts_data *data = i2c_get_clientdata(client); int error; error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET, @@ -325,7 +323,7 @@ static int silead_ts_init(struct i2c_client *client) usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR, - data->max_fingers); + SILEAD_MAX_FINGERS); if (error) goto i2c_write_err; usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX); @@ -591,13 +589,6 @@ static void silead_ts_read_props(struct i2c_client *client) const char *str; int error; - error = device_property_read_u32(dev, "silead,max-fingers", - &data->max_fingers); - if (error) { - dev_dbg(dev, "Max fingers read error %d\n", error); - data->max_fingers = 5; /* Most devices handle up-to 5 fingers */ - } - error = device_property_read_string(dev, "firmware-name", &str); if (!error) snprintf(data->fw_name, sizeof(data->fw_name), @@ -785,12 +776,12 @@ static int silead_ts_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(silead_ts_pm, silead_ts_suspend, silead_ts_resume); static const struct i2c_device_id silead_ts_id[] = { - { "gsl1680", 0 }, - { "gsl1688", 0 }, - { "gsl3670", 0 }, - { "gsl3675", 0 }, - { "gsl3692", 0 }, - { "mssl1680", 0 }, + { "gsl1680" }, + { "gsl1688" }, + { "gsl3670" }, + { "gsl3675" }, + { "gsl3692" }, + { "mssl1680" }, { } }; MODULE_DEVICE_TABLE(i2c, silead_ts_id); diff --git a/drivers/input/touchscreen/sis_i2c.c b/drivers/input/touchscreen/sis_i2c.c index ed56cb546f39..a625f2ad809d 100644 --- a/drivers/input/touchscreen/sis_i2c.c +++ b/drivers/input/touchscreen/sis_i2c.c @@ -15,7 +15,7 @@ #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/slab.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define SIS_I2C_NAME "sis_i2c_ts" @@ -374,8 +374,8 @@ MODULE_DEVICE_TABLE(of, sis_ts_dt_ids); #endif static const struct i2c_device_id sis_ts_id[] = { - { SIS_I2C_NAME, 0 }, - { "9200-ts", 0 }, + { SIS_I2C_NAME }, + { "9200-ts" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(i2c, sis_ts_id); diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index 85010fa07908..119cd26851cf 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -789,8 +789,8 @@ MODULE_DEVICE_TABLE(of, stmfts_of_match); #endif static const struct i2c_device_id stmfts_id[] = { - { "stmfts", 0 }, - { }, + { "stmfts" }, + { } }; MODULE_DEVICE_TABLE(i2c, stmfts_id); diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index b204fdb2d22c..af0fb38bcfdc 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -107,7 +107,7 @@ static void stmpe_work(struct work_struct *work) /* * touch_det sometimes get desasserted or just get stuck. This appears - * to be a silicon bug, We still have to clearify this with the + * to be a silicon bug, We still have to clarify this with the * manufacture. As a workaround We release the key anyway if the * touch_det keeps coming in after 4ms, while the FIFO contains no value * during the whole time. @@ -140,7 +140,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) /* * The FIFO sometimes just crashes and stops generating interrupts. This - * appears to be a silicon bug. We still have to clearify this with + * appears to be a silicon bug. We still have to clarify this with * the manufacture. As a workaround we disable the TSC while we are * collecting data and flush the FIFO after reading */ @@ -362,16 +362,11 @@ static struct platform_driver stmpe_ts_driver = { .name = STMPE_TS_NAME, }, .probe = stmpe_input_probe, - .remove_new = stmpe_ts_remove, + .remove = stmpe_ts_remove, }; module_platform_driver(stmpe_ts_driver); -static const struct of_device_id stmpe_ts_ids[] = { - { .compatible = "st,stmpe-ts", }, - { }, -}; -MODULE_DEVICE_TABLE(of, stmpe_ts_ids); - +MODULE_ALIAS("platform:stmpe-ts"); MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); MODULE_DESCRIPTION("STMPEXXX touchscreen driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 92b2b840b4b7..e8286060043a 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -396,12 +396,12 @@ static const struct of_device_id sun4i_ts_of_match[] = { MODULE_DEVICE_TABLE(of, sun4i_ts_of_match); static struct platform_driver sun4i_ts_driver = { - .driver = { + .driver = { .name = "sun4i-ts", .of_match_table = sun4i_ts_of_match, }, .probe = sun4i_ts_probe, - .remove_new = sun4i_ts_remove, + .remove = sun4i_ts_remove, }; module_platform_driver(sun4i_ts_driver); diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index ae3aab428337..7b3b10cbfcfc 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -421,7 +421,7 @@ static void sur40_report_blob(struct sur40_blob *blob, struct input_dev *input) if (blob->type != SUR40_TOUCH) return; - slotnum = input_mt_get_slot_by_key(input, blob->blob_id); + slotnum = input_mt_get_slot_by_key(input, le16_to_cpu(blob->blob_id)); if (slotnum < 0 || slotnum >= MAX_CONTACTS) return; @@ -672,7 +672,7 @@ static int sur40_probe(struct usb_interface *interface, return -ENODEV; /* Allocate memory for our device state and initialize it. */ - sur40 = kzalloc(sizeof(struct sur40_state), GFP_KERNEL); + sur40 = kzalloc(sizeof(*sur40), GFP_KERNEL); if (!sur40) return -ENOMEM; @@ -1108,8 +1108,6 @@ static const struct vb2_ops sur40_queue_ops = { .buf_queue = sur40_buffer_queue, .start_streaming = sur40_start_streaming, .stop_streaming = sur40_stop_streaming, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, }; static const struct vb2_queue sur40_queue = { diff --git a/drivers/input/touchscreen/surface3_spi.c b/drivers/input/touchscreen/surface3_spi.c index 7efbcd0fde4f..6074b7730e86 100644 --- a/drivers/input/touchscreen/surface3_spi.c +++ b/drivers/input/touchscreen/surface3_spi.c @@ -18,7 +18,7 @@ #include <linux/spi/spi.h> #include <linux/acpi.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define SURFACE3_PACKET_SIZE 264 diff --git a/drivers/input/touchscreen/sx8654.c b/drivers/input/touchscreen/sx8654.c index f5c5881cef6b..e59b8d0ed19e 100644 --- a/drivers/input/touchscreen/sx8654.c +++ b/drivers/input/touchscreen/sx8654.c @@ -290,7 +290,7 @@ static void sx8654_close(struct input_dev *dev) disable_irq(client->irq); if (!sx8654->data->has_irq_penrelease) - del_timer_sync(&sx8654->timer); + timer_delete_sync(&sx8654->timer); /* enable manual mode mode */ error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 294b7ceded27..93d659ff90aa 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -550,9 +550,9 @@ MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids); static struct platform_driver ti_tsc_driver = { .probe = titsc_probe, - .remove_new = titsc_remove, + .remove = titsc_remove, .driver = { - .name = "TI-am335x-tsc", + .name = "TI-am335x-tsc", .pm = pm_sleep_ptr(&titsc_pm_ops), .of_match_table = ti_tsc_dt_ids, }, diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index fb49687da405..c2718350815c 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c @@ -139,7 +139,7 @@ static int touchit213_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - touchit213 = kzalloc(sizeof(struct touchit213), GFP_KERNEL); + touchit213 = kzalloc(sizeof(*touchit213), GFP_KERNEL); input_dev = input_allocate_device(); if (!touchit213 || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 3cd58a13e44f..30ba97bd00a1 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -102,7 +102,7 @@ static int tr_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - tr = kzalloc(sizeof(struct tr), GFP_KERNEL); + tr = kzalloc(sizeof(*tr), GFP_KERNEL); input_dev = input_allocate_device(); if (!tr || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index bde3c6ee3c60..fbd72789ea80 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -109,7 +109,7 @@ static int tw_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int err; - tw = kzalloc(sizeof(struct tw), GFP_KERNEL); + tw = kzalloc(sizeof(*tw), GFP_KERNEL); input_dev = input_allocate_device(); if (!tw || !input_dev) { err = -ENOMEM; diff --git a/drivers/input/touchscreen/ts4800-ts.c b/drivers/input/touchscreen/ts4800-ts.c index 6cf66aadc10e..98422d1e80d6 100644 --- a/drivers/input/touchscreen/ts4800-ts.c +++ b/drivers/input/touchscreen/ts4800-ts.c @@ -110,18 +110,17 @@ static int ts4800_parse_dt(struct platform_device *pdev, { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct device_node *syscon_np; u32 reg, bit; int error; - syscon_np = of_parse_phandle(np, "syscon", 0); + struct device_node *syscon_np __free(device_node) = + of_parse_phandle(np, "syscon", 0); if (!syscon_np) { dev_err(dev, "no syscon property\n"); return -ENODEV; } ts->regmap = syscon_node_to_regmap(syscon_np); - of_node_put(syscon_np); if (IS_ERR(ts->regmap)) { dev_err(dev, "cannot get parent's regmap\n"); return PTR_ERR(ts->regmap); diff --git a/drivers/input/touchscreen/tsc2004.c b/drivers/input/touchscreen/tsc2004.c index 89c5248f66f6..787f2caf4f73 100644 --- a/drivers/input/touchscreen/tsc2004.c +++ b/drivers/input/touchscreen/tsc2004.c @@ -42,13 +42,8 @@ static int tsc2004_probe(struct i2c_client *i2c) tsc2004_cmd); } -static void tsc2004_remove(struct i2c_client *i2c) -{ - tsc200x_remove(&i2c->dev); -} - static const struct i2c_device_id tsc2004_idtable[] = { - { "tsc2004", 0 }, + { "tsc2004" }, { } }; MODULE_DEVICE_TABLE(i2c, tsc2004_idtable); @@ -70,7 +65,6 @@ static struct i2c_driver tsc2004_driver = { }, .id_table = tsc2004_idtable, .probe = tsc2004_probe, - .remove = tsc2004_remove, }; module_i2c_driver(tsc2004_driver); diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 1b40ce0ca1b9..6fe8b41b3ecc 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -64,11 +64,6 @@ static int tsc2005_probe(struct spi_device *spi) tsc2005_cmd); } -static void tsc2005_remove(struct spi_device *spi) -{ - tsc200x_remove(&spi->dev); -} - #ifdef CONFIG_OF static const struct of_device_id tsc2005_of_match[] = { { .compatible = "ti,tsc2005" }, @@ -85,7 +80,6 @@ static struct spi_driver tsc2005_driver = { .pm = pm_sleep_ptr(&tsc200x_pm_ops), }, .probe = tsc2005_probe, - .remove = tsc2005_remove, }; module_spi_driver(tsc2005_driver); diff --git a/drivers/input/touchscreen/tsc2007.h b/drivers/input/touchscreen/tsc2007.h index 69b08dd6c8df..e346fb4f7552 100644 --- a/drivers/input/touchscreen/tsc2007.h +++ b/drivers/input/touchscreen/tsc2007.h @@ -19,6 +19,7 @@ #ifndef _TSC2007_H #define _TSC2007_H +#include <linux/input/touchscreen.h> struct gpio_desc; #define TSC2007_MEASURE_TEMP0 (0x0 << 4) @@ -63,6 +64,7 @@ struct tsc2007 { struct i2c_client *client; + struct touchscreen_properties prop; u16 model; u16 x_plate_ohms; u16 max_rt; diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c index b3655250d4a7..5252301686ec 100644 --- a/drivers/input/touchscreen/tsc2007_core.c +++ b/drivers/input/touchscreen/tsc2007_core.c @@ -142,8 +142,7 @@ static irqreturn_t tsc2007_soft_irq(int irq, void *handle) rt = ts->max_rt - rt; input_report_key(input, BTN_TOUCH, 1); - input_report_abs(input, ABS_X, tc.x); - input_report_abs(input, ABS_Y, tc.y); + touchscreen_report_pos(input, &ts->prop, tc.x, tc.y, false); input_report_abs(input, ABS_PRESSURE, rt); input_sync(input); @@ -339,9 +338,9 @@ static int tsc2007_probe(struct i2c_client *client) input_set_drvdata(input_dev, ts); input_set_capability(input_dev, EV_KEY, BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0); input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0); + touchscreen_parse_properties(input_dev, false, &ts->prop); input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, ts->fuzzz, 0); @@ -400,7 +399,7 @@ static int tsc2007_probe(struct i2c_client *client) } static const struct i2c_device_id tsc2007_idtable[] = { - { "tsc2007", 0 }, + { "tsc2007" }, { } }; diff --git a/drivers/input/touchscreen/tsc200x-core.c b/drivers/input/touchscreen/tsc200x-core.c index a4c0e9db9bb9..252a93753ee5 100644 --- a/drivers/input/touchscreen/tsc200x-core.c +++ b/drivers/input/touchscreen/tsc200x-core.c @@ -104,11 +104,11 @@ struct tsc200x { bool pen_down; - struct regulator *vio; - struct gpio_desc *reset_gpio; int (*tsc200x_cmd)(struct device *dev, u8 cmd); + int irq; + bool wake_irq_enabled; }; static void tsc200x_update_pen_state(struct tsc200x *ts, @@ -136,7 +136,6 @@ static void tsc200x_update_pen_state(struct tsc200x *ts, static irqreturn_t tsc200x_irq_thread(int irq, void *_ts) { struct tsc200x *ts = _ts; - unsigned long flags; unsigned int pressure; struct tsc200x_data tsdata; int error; @@ -182,13 +181,11 @@ static irqreturn_t tsc200x_irq_thread(int irq, void *_ts) if (unlikely(pressure > MAX_12BIT)) goto out; - spin_lock_irqsave(&ts->lock, flags); - - tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure); - mod_timer(&ts->penup_timer, - jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS)); - - spin_unlock_irqrestore(&ts->lock, flags); + scoped_guard(spinlock_irqsave, &ts->lock) { + tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure); + mod_timer(&ts->penup_timer, + jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS)); + } ts->last_valid_interrupt = jiffies; out: @@ -198,11 +195,9 @@ out: static void tsc200x_penup_timer(struct timer_list *t) { struct tsc200x *ts = from_timer(ts, t, penup_timer); - unsigned long flags; - spin_lock_irqsave(&ts->lock, flags); + guard(spinlock_irqsave)(&ts->lock); tsc200x_update_pen_state(ts, 0, 0, 0); - spin_unlock_irqrestore(&ts->lock, flags); } static void tsc200x_start_scan(struct tsc200x *ts) @@ -232,12 +227,10 @@ static void __tsc200x_disable(struct tsc200x *ts) { tsc200x_stop_scan(ts); - disable_irq(ts->irq); - del_timer_sync(&ts->penup_timer); + guard(disable_irq)(&ts->irq); + timer_delete_sync(&ts->penup_timer); cancel_delayed_work_sync(&ts->esd_work); - - enable_irq(ts->irq); } /* must be called with ts->mutex held */ @@ -253,80 +246,79 @@ static void __tsc200x_enable(struct tsc200x *ts) } } -static ssize_t tsc200x_selftest_show(struct device *dev, - struct device_attribute *attr, - char *buf) +/* + * Test TSC200X communications via temp high register. + */ +static int tsc200x_do_selftest(struct tsc200x *ts) { - struct tsc200x *ts = dev_get_drvdata(dev); - unsigned int temp_high; unsigned int temp_high_orig; unsigned int temp_high_test; - bool success = true; + unsigned int temp_high; int error; - mutex_lock(&ts->mutex); - - /* - * Test TSC200X communications via temp high register. - */ - __tsc200x_disable(ts); - error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high_orig); if (error) { - dev_warn(dev, "selftest failed: read error %d\n", error); - success = false; - goto out; + dev_warn(ts->dev, "selftest failed: read error %d\n", error); + return error; } temp_high_test = (temp_high_orig - 1) & MAX_12BIT; error = regmap_write(ts->regmap, TSC200X_REG_TEMP_HIGH, temp_high_test); if (error) { - dev_warn(dev, "selftest failed: write error %d\n", error); - success = false; - goto out; + dev_warn(ts->dev, "selftest failed: write error %d\n", error); + return error; } error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high); if (error) { - dev_warn(dev, "selftest failed: read error %d after write\n", - error); - success = false; - goto out; - } - - if (temp_high != temp_high_test) { - dev_warn(dev, "selftest failed: %d != %d\n", - temp_high, temp_high_test); - success = false; + dev_warn(ts->dev, + "selftest failed: read error %d after write\n", error); + return error; } /* hardware reset */ tsc200x_reset(ts); - if (!success) - goto out; + if (temp_high != temp_high_test) { + dev_warn(ts->dev, "selftest failed: %d != %d\n", + temp_high, temp_high_test); + return -EINVAL; + } /* test that the reset really happened */ error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high); if (error) { - dev_warn(dev, "selftest failed: read error %d after reset\n", - error); - success = false; - goto out; + dev_warn(ts->dev, + "selftest failed: read error %d after reset\n", error); + return error; } if (temp_high != temp_high_orig) { - dev_warn(dev, "selftest failed after reset: %d != %d\n", + dev_warn(ts->dev, "selftest failed after reset: %d != %d\n", temp_high, temp_high_orig); - success = false; + return -EINVAL; } -out: - __tsc200x_enable(ts); - mutex_unlock(&ts->mutex); + return 0; +} + +static ssize_t tsc200x_selftest_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct tsc200x *ts = dev_get_drvdata(dev); + int error; + + scoped_guard(mutex, &ts->mutex) { + __tsc200x_disable(ts); + + error = tsc200x_do_selftest(ts); - return sprintf(buf, "%d\n", success); + __tsc200x_enable(ts); + } + + return sprintf(buf, "%d\n", !error); } static DEVICE_ATTR(selftest, S_IRUGO, tsc200x_selftest_show, NULL); @@ -368,46 +360,42 @@ static void tsc200x_esd_work(struct work_struct *work) int error; unsigned int r; - if (!mutex_trylock(&ts->mutex)) { - /* - * If the mutex is taken, it means that disable or enable is in - * progress. In that case just reschedule the work. If the work - * is not needed, it will be canceled by disable. - */ - goto reschedule; - } - - if (time_is_after_jiffies(ts->last_valid_interrupt + - msecs_to_jiffies(ts->esd_timeout))) - goto out; - - /* We should be able to read register without disabling interrupts. */ - error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r); - if (!error && - !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) { - goto out; - } - /* - * If we could not read our known value from configuration register 0 - * then we should reset the controller as if from power-up and start - * scanning again. + * If the mutex is taken, it means that disable or enable is in + * progress. In that case just reschedule the work. If the work + * is not needed, it will be canceled by disable. */ - dev_info(ts->dev, "TSC200X not responding - resetting\n"); + scoped_guard(mutex_try, &ts->mutex) { + if (time_is_after_jiffies(ts->last_valid_interrupt + + msecs_to_jiffies(ts->esd_timeout))) + break; - disable_irq(ts->irq); - del_timer_sync(&ts->penup_timer); + /* + * We should be able to read register without disabling + * interrupts. + */ + error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r); + if (!error && + !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) { + break; + } - tsc200x_update_pen_state(ts, 0, 0, 0); + /* + * If we could not read our known value from configuration + * register 0 then we should reset the controller as if from + * power-up and start scanning again. + */ + dev_info(ts->dev, "TSC200X not responding - resetting\n"); - tsc200x_reset(ts); + scoped_guard(disable_irq, &ts->irq) { + timer_delete_sync(&ts->penup_timer); + tsc200x_update_pen_state(ts, 0, 0, 0); + tsc200x_reset(ts); + } - enable_irq(ts->irq); - tsc200x_start_scan(ts); + tsc200x_start_scan(ts); + } -out: - mutex_unlock(&ts->mutex); -reschedule: /* re-arm the watchdog */ schedule_delayed_work(&ts->esd_work, round_jiffies_relative( @@ -418,15 +406,13 @@ static int tsc200x_open(struct input_dev *input) { struct tsc200x *ts = input_get_drvdata(input); - mutex_lock(&ts->mutex); + guard(mutex)(&ts->mutex); if (!ts->suspended) __tsc200x_enable(ts); ts->opened = true; - mutex_unlock(&ts->mutex); - return 0; } @@ -434,14 +420,12 @@ static void tsc200x_close(struct input_dev *input) { struct tsc200x *ts = input_get_drvdata(input); - mutex_lock(&ts->mutex); + guard(mutex)(&ts->mutex); if (!ts->suspended) __tsc200x_disable(ts); ts->opened = false; - - mutex_unlock(&ts->mutex); } int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, @@ -488,20 +472,6 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, &esd_timeout); ts->esd_timeout = error ? 0 : esd_timeout; - ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(ts->reset_gpio)) { - error = PTR_ERR(ts->reset_gpio); - dev_err(dev, "error acquiring reset gpio: %d\n", error); - return error; - } - - ts->vio = devm_regulator_get(dev, "vio"); - if (IS_ERR(ts->vio)) { - error = PTR_ERR(ts->vio); - dev_err(dev, "error acquiring vio regulator: %d", error); - return error; - } - mutex_init(&ts->mutex); spin_lock_init(&ts->lock); @@ -542,60 +512,60 @@ int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, touchscreen_parse_properties(input_dev, false, &ts->prop); + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + error = PTR_ERR_OR_ZERO(ts->reset_gpio); + if (error) { + dev_err(dev, "error acquiring reset gpio: %d\n", error); + return error; + } + + error = devm_regulator_get_enable(dev, "vio"); + if (error) { + dev_err(dev, "error acquiring vio regulator: %d\n", error); + return error; + } + + tsc200x_reset(ts); + /* Ensure the touchscreen is off */ tsc200x_stop_scan(ts); - error = devm_request_threaded_irq(dev, irq, NULL, - tsc200x_irq_thread, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - "tsc200x", ts); + error = devm_request_threaded_irq(dev, irq, NULL, tsc200x_irq_thread, + IRQF_ONESHOT, "tsc200x", ts); if (error) { dev_err(dev, "Failed to request irq, err: %d\n", error); return error; } - error = regulator_enable(ts->vio); - if (error) - return error; - dev_set_drvdata(dev, ts); error = input_register_device(ts->idev); if (error) { dev_err(dev, "Failed to register input device, err: %d\n", error); - goto disable_regulator; + return error; } - irq_set_irq_wake(irq, 1); - return 0; + device_init_wakeup(dev, + device_property_read_bool(dev, "wakeup-source")); -disable_regulator: - regulator_disable(ts->vio); - return error; + return 0; } EXPORT_SYMBOL_GPL(tsc200x_probe); -void tsc200x_remove(struct device *dev) -{ - struct tsc200x *ts = dev_get_drvdata(dev); - - regulator_disable(ts->vio); -} -EXPORT_SYMBOL_GPL(tsc200x_remove); - static int tsc200x_suspend(struct device *dev) { struct tsc200x *ts = dev_get_drvdata(dev); - mutex_lock(&ts->mutex); + guard(mutex)(&ts->mutex); if (!ts->suspended && ts->opened) __tsc200x_disable(ts); ts->suspended = true; - mutex_unlock(&ts->mutex); + if (device_may_wakeup(dev)) + ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0; return 0; } @@ -604,15 +574,18 @@ static int tsc200x_resume(struct device *dev) { struct tsc200x *ts = dev_get_drvdata(dev); - mutex_lock(&ts->mutex); + guard(mutex)(&ts->mutex); + + if (ts->wake_irq_enabled) { + disable_irq_wake(ts->irq); + ts->wake_irq_enabled = false; + } if (ts->suspended && ts->opened) __tsc200x_enable(ts); ts->suspended = false; - mutex_unlock(&ts->mutex); - return 0; } diff --git a/drivers/input/touchscreen/tsc200x-core.h b/drivers/input/touchscreen/tsc200x-core.h index 37de91efd78e..e76ba7a889dd 100644 --- a/drivers/input/touchscreen/tsc200x-core.h +++ b/drivers/input/touchscreen/tsc200x-core.h @@ -75,6 +75,5 @@ extern const struct attribute_group *tsc200x_groups[]; int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, struct regmap *regmap, int (*tsc200x_cmd)(struct device *dev, u8 cmd)); -void tsc200x_remove(struct device *dev); #endif diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 139577021413..9f485cf57a72 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -83,7 +83,7 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) struct input_dev *input_dev; int error; - ptsc = kzalloc(sizeof(struct tsc_ser), GFP_KERNEL); + ptsc = kzalloc(sizeof(*ptsc), GFP_KERNEL); input_dev = input_allocate_device(); if (!ptsc || !input_dev) { error = -ENOMEM; diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 60354ebc7242..7567efabe014 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -68,8 +68,6 @@ struct usbtouch_device_info { */ bool irq_always; - void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); - /* * used to get the packet len. possible return values: * > 0: packet len @@ -94,7 +92,7 @@ struct usbtouch_usb { struct urb *irq; struct usb_interface *interface; struct input_dev *input; - struct usbtouch_device_info *type; + const struct usbtouch_device_info *type; struct mutex pm_mutex; /* serialize access to open/suspend */ bool is_open; char name[128]; @@ -103,141 +101,8 @@ struct usbtouch_usb { int x, y; int touch, press; -}; - - -/* device types */ -enum { - DEVTYPE_IGNORE = -1, - DEVTYPE_EGALAX, - DEVTYPE_PANJIT, - DEVTYPE_3M, - DEVTYPE_ITM, - DEVTYPE_ETURBO, - DEVTYPE_GUNZE, - DEVTYPE_DMC_TSC10, - DEVTYPE_IRTOUCH, - DEVTYPE_IRTOUCH_HIRES, - DEVTYPE_IDEALTEK, - DEVTYPE_GENERAL_TOUCH, - DEVTYPE_GOTOP, - DEVTYPE_JASTEC, - DEVTYPE_E2I, - DEVTYPE_ZYTRONIC, - DEVTYPE_TC45USB, - DEVTYPE_NEXIO, - DEVTYPE_ELO, - DEVTYPE_ETOUCH, -}; - -#define USB_DEVICE_HID_CLASS(vend, prod) \ - .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS \ - | USB_DEVICE_ID_MATCH_DEVICE, \ - .idVendor = (vend), \ - .idProduct = (prod), \ - .bInterfaceClass = USB_INTERFACE_CLASS_HID - -static const struct usb_device_id usbtouch_devices[] = { -#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX - /* ignore the HID capable devices, handled by usbhid */ - {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, - {USB_DEVICE_HID_CLASS(0x0eef, 0x0002), .driver_info = DEVTYPE_IGNORE}, - - /* normal device IDs */ - {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX}, - {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT - {USB_DEVICE(0x134c, 0x0001), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0002), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0003), .driver_info = DEVTYPE_PANJIT}, - {USB_DEVICE(0x134c, 0x0004), .driver_info = DEVTYPE_PANJIT}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_3M - {USB_DEVICE(0x0596, 0x0001), .driver_info = DEVTYPE_3M}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ITM - {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM}, - {USB_DEVICE(0x16e3, 0xf9e9), .driver_info = DEVTYPE_ITM}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO - {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE - {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 - {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH - {USB_DEVICE(0x255e, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, - {USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, - {USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH}, - {USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK - {USB_DEVICE(0x1391, 0x1000), .driver_info = DEVTYPE_IDEALTEK}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH - {USB_DEVICE(0x0dfc, 0x0001), .driver_info = DEVTYPE_GENERAL_TOUCH}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP - {USB_DEVICE(0x08f2, 0x007f), .driver_info = DEVTYPE_GOTOP}, - {USB_DEVICE(0x08f2, 0x00ce), .driver_info = DEVTYPE_GOTOP}, - {USB_DEVICE(0x08f2, 0x00f4), .driver_info = DEVTYPE_GOTOP}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC - {USB_DEVICE(0x0f92, 0x0001), .driver_info = DEVTYPE_JASTEC}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_E2I - {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC - {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB - /* TC5UH */ - {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC45USB}, - /* TC4UM */ - {USB_DEVICE(0x0664, 0x0306), .driver_info = DEVTYPE_TC45USB}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO - /* data interface only */ - {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), - .driver_info = DEVTYPE_NEXIO}, - {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), - .driver_info = DEVTYPE_NEXIO}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ELO - {USB_DEVICE(0x04e7, 0x0020), .driver_info = DEVTYPE_ELO}, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH - {USB_DEVICE(0x7374, 0x0001), .driver_info = DEVTYPE_ETOUCH}, -#endif - {} + void (*process_pkt)(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); }; @@ -273,6 +138,16 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info e2i_dev_info = { + .min_xc = 0x0, + .max_xc = 0x7fff, + .min_yc = 0x0, + .max_yc = 0x7fff, + .rept_size = 6, + .init = e2i_init, + .read_data = e2i_read_data, +}; #endif @@ -292,9 +167,8 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int egalax_init(struct usbtouch_usb *usbtouch) { - int ret, i; - unsigned char *buf; struct usb_device *udev = interface_to_usbdev(usbtouch->interface); + int ret, i; /* * An eGalax diagnostic packet kicks the device into using the right @@ -302,7 +176,7 @@ static int egalax_init(struct usbtouch_usb *usbtouch) * read later and ignored. */ - buf = kmalloc(3, GFP_KERNEL); + u8 *buf __free(kfree) = kmalloc(3, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -316,17 +190,11 @@ static int egalax_init(struct usbtouch_usb *usbtouch) USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, buf, 3, USB_CTRL_SET_TIMEOUT); - if (ret >= 0) { - ret = 0; - break; - } if (ret != -EPIPE) break; } - kfree(buf); - - return ret; + return ret < 0 ? ret : 0; } static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt) @@ -356,6 +224,17 @@ static int egalax_get_pkt_len(unsigned char *buf, int len) return 0; } + +static const struct usbtouch_device_info egalax_dev_info = { + .min_xc = 0x0, + .max_xc = 0x07ff, + .min_yc = 0x0, + .max_yc = 0x07ff, + .rept_size = 16, + .get_pkt_len = egalax_get_pkt_len, + .read_data = egalax_read_data, + .init = egalax_init, +}; #endif /***************************************************************************** @@ -402,6 +281,16 @@ static int etouch_get_pkt_len(unsigned char *buf, int len) return 0; } + +static const struct usbtouch_device_info etouch_dev_info = { + .min_xc = 0x0, + .max_xc = 0x07ff, + .min_yc = 0x0, + .max_yc = 0x07ff, + .rept_size = 16, + .get_pkt_len = etouch_get_pkt_len, + .read_data = etouch_read_data, +}; #endif /***************************************************************************** @@ -416,6 +305,15 @@ static int panjit_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info panjit_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 8, + .read_data = panjit_read_data, +}; #endif @@ -449,35 +347,13 @@ struct mtouch_priv { u8 fw_rev_minor; }; -static ssize_t mtouch_firmware_rev_show(struct device *dev, - struct device_attribute *attr, char *output) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); - struct mtouch_priv *priv = usbtouch->priv; - - return sysfs_emit(output, "%1x.%1x\n", - priv->fw_rev_major, priv->fw_rev_minor); -} -static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL); - -static struct attribute *mtouch_attrs[] = { - &dev_attr_firmware_rev.attr, - NULL -}; - -static const struct attribute_group mtouch_attr_group = { - .attrs = mtouch_attrs, -}; - static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch) { struct usb_device *udev = interface_to_usbdev(usbtouch->interface); struct mtouch_priv *priv = usbtouch->priv; - u8 *buf; int ret; - buf = kzalloc(MTOUCHUSB_REQ_CTRLLR_ID_LEN, GFP_NOIO); + u8 *buf __free(kfree) = kzalloc(MTOUCHUSB_REQ_CTRLLR_ID_LEN, GFP_NOIO); if (!buf) return -ENOMEM; @@ -489,36 +365,24 @@ static int mtouch_get_fw_revision(struct usbtouch_usb *usbtouch) if (ret != MTOUCHUSB_REQ_CTRLLR_ID_LEN) { dev_warn(&usbtouch->interface->dev, "Failed to read FW rev: %d\n", ret); - ret = ret < 0 ? ret : -EIO; - goto free; + return ret < 0 ? ret : -EIO; } priv->fw_rev_major = buf[3]; priv->fw_rev_minor = buf[4]; - ret = 0; - -free: - kfree(buf); - return ret; + return 0; } static int mtouch_alloc(struct usbtouch_usb *usbtouch) { - int ret; + struct mtouch_priv *priv; - usbtouch->priv = kmalloc(sizeof(struct mtouch_priv), GFP_KERNEL); - if (!usbtouch->priv) + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - ret = sysfs_create_group(&usbtouch->interface->dev.kobj, - &mtouch_attr_group); - if (ret) { - kfree(usbtouch->priv); - usbtouch->priv = NULL; - return ret; - } - + usbtouch->priv = priv; return 0; } @@ -569,9 +433,53 @@ static void mtouch_exit(struct usbtouch_usb *usbtouch) { struct mtouch_priv *priv = usbtouch->priv; - sysfs_remove_group(&usbtouch->interface->dev.kobj, &mtouch_attr_group); kfree(priv); } + +static struct usbtouch_device_info mtouch_dev_info = { + .min_xc = 0x0, + .max_xc = 0x4000, + .min_yc = 0x0, + .max_yc = 0x4000, + .rept_size = 11, + .read_data = mtouch_read_data, + .alloc = mtouch_alloc, + .init = mtouch_init, + .exit = mtouch_exit, +}; + +static ssize_t mtouch_firmware_rev_show(struct device *dev, + struct device_attribute *attr, char *output) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); + struct mtouch_priv *priv = usbtouch->priv; + + return sysfs_emit(output, "%1x.%1x\n", + priv->fw_rev_major, priv->fw_rev_minor); +} +static DEVICE_ATTR(firmware_rev, 0444, mtouch_firmware_rev_show, NULL); + +static struct attribute *mtouch_attrs[] = { + &dev_attr_firmware_rev.attr, + NULL +}; + +static bool mtouch_group_visible(struct kobject *kobj) +{ + struct device *dev = kobj_to_dev(kobj); + struct usb_interface *intf = to_usb_interface(dev); + struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); + + return usbtouch->type == &mtouch_dev_info; +} + +DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(mtouch); + +static const struct attribute_group mtouch_attr_group = { + .is_visible = SYSFS_GROUP_VISIBLE(mtouch), + .attrs = mtouch_attrs, +}; #endif @@ -606,6 +514,16 @@ static int itm_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info itm_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .max_press = 0xff, + .rept_size = 8, + .read_data = itm_read_data, +}; #endif @@ -640,6 +558,16 @@ static int eturbo_get_pkt_len(unsigned char *buf, int len) return 3; return 0; } + +static const struct usbtouch_device_info eturbo_dev_info = { + .min_xc = 0x0, + .max_xc = 0x07ff, + .min_yc = 0x0, + .max_yc = 0x07ff, + .rept_size = 8, + .get_pkt_len = eturbo_get_pkt_len, + .read_data = eturbo_read_data, +}; #endif @@ -658,6 +586,15 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info gunze_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 4, + .read_data = gunze_read_data, +}; #endif /***************************************************************************** @@ -686,24 +623,23 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) { struct usb_device *dev = interface_to_usbdev(usbtouch->interface); - int ret = -ENOMEM; - unsigned char *buf; + int ret; - buf = kmalloc(2, GFP_NOIO); + u8 *buf __free(kfree) = kmalloc(2, GFP_NOIO); if (!buf) - goto err_nobuf; + return -ENOMEM; + /* reset */ buf[0] = buf[1] = 0xFF; ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), - TSC10_CMD_RESET, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); + TSC10_CMD_RESET, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); if (ret < 0) - goto err_out; - if (buf[0] != 0x06) { - ret = -ENODEV; - goto err_out; - } + return ret; + + if (buf[0] != 0x06) + return -ENODEV; /* TSC-25 data sheet specifies a delay after the RESET command */ msleep(150); @@ -711,28 +647,22 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) /* set coordinate output rate */ buf[0] = buf[1] = 0xFF; ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), - TSC10_CMD_RATE, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); + TSC10_CMD_RATE, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); if (ret < 0) - goto err_out; - if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) { - ret = -ENODEV; - goto err_out; - } + return ret; + + if (buf[0] != 0x06 && (buf[0] != 0x15 || buf[1] != 0x01)) + return -ENODEV; /* start sending data */ - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - TSC10_CMD_DATA1, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); -err_out: - kfree(buf); -err_nobuf: - return ret; + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + TSC10_CMD_DATA1, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); } - static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) { dev->x = ((pkt[2] & 0x03) << 8) | pkt[1]; @@ -741,6 +671,16 @@ static int dmc_tsc10_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info dmc_tsc10_dev_info = { + .min_xc = 0x0, + .max_xc = 0x03ff, + .min_yc = 0x0, + .max_yc = 0x03ff, + .rept_size = 5, + .init = dmc_tsc10_init, + .read_data = dmc_tsc10_read_data, +}; #endif @@ -756,6 +696,24 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info irtouch_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 8, + .read_data = irtouch_read_data, +}; + +static const struct usbtouch_device_info irtouch_hires_dev_info = { + .min_xc = 0x0, + .max_xc = 0x7fff, + .min_yc = 0x0, + .max_yc = 0x7fff, + .rept_size = 8, + .read_data = irtouch_read_data, +}; #endif /***************************************************************************** @@ -770,6 +728,15 @@ static int tc45usb_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info tc45usb_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 5, + .read_data = tc45usb_read_data, +}; #endif /***************************************************************************** @@ -809,6 +776,16 @@ static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 0; } } + +static const struct usbtouch_device_info idealtek_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 8, + .get_pkt_len = idealtek_get_pkt_len, + .read_data = idealtek_read_data, +}; #endif /***************************************************************************** @@ -824,6 +801,15 @@ static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info general_touch_dev_info = { + .min_xc = 0x0, + .max_xc = 0x7fff, + .min_yc = 0x0, + .max_yc = 0x7fff, + .rept_size = 7, + .read_data = general_touch_read_data, +}; #endif /***************************************************************************** @@ -838,6 +824,15 @@ static int gotop_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info gotop_dev_info = { + .min_xc = 0x0, + .max_xc = 0x03ff, + .min_yc = 0x0, + .max_yc = 0x03ff, + .rept_size = 4, + .read_data = gotop_read_data, +}; #endif /***************************************************************************** @@ -852,6 +847,15 @@ static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } + +static const struct usbtouch_device_info jastec_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .rept_size = 4, + .read_data = jastec_read_data, +}; #endif /***************************************************************************** @@ -888,6 +892,16 @@ static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 0; } + +static const struct usbtouch_device_info zytronic_dev_info = { + .min_xc = 0x0, + .max_xc = 0x03ff, + .min_yc = 0x0, + .max_yc = 0x03ff, + .rept_size = 5, + .read_data = zytronic_read_data, + .irq_always = true, +}; #endif /***************************************************************************** @@ -924,12 +938,11 @@ static int nexio_alloc(struct usbtouch_usb *usbtouch) struct nexio_priv *priv; int ret = -ENOMEM; - usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); - if (!usbtouch->priv) + priv = kmalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) goto out_buf; - priv = usbtouch->priv; - + usbtouch->priv = priv; priv->ack_buf = kmemdup(nexio_ack_pkt, sizeof(nexio_ack_pkt), GFP_KERNEL); if (!priv->ack_buf) @@ -959,7 +972,6 @@ static int nexio_init(struct usbtouch_usb *usbtouch) struct nexio_priv *priv = usbtouch->priv; int ret = -ENOMEM; int actual_len, i; - unsigned char *buf; char *firmware_ver = NULL, *device_name = NULL; int input_ep = 0, output_ep = 0; @@ -975,9 +987,9 @@ static int nexio_init(struct usbtouch_usb *usbtouch) if (!input_ep || !output_ep) return -ENXIO; - buf = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); + u8 *buf __free(kfree) = kmalloc(NEXIO_BUFSIZE, GFP_NOIO); if (!buf) - goto out_buf; + return -ENOMEM; /* two empty reads */ for (i = 0; i < 2; i++) { @@ -985,7 +997,7 @@ static int nexio_init(struct usbtouch_usb *usbtouch) buf, NEXIO_BUFSIZE, &actual_len, NEXIO_TIMEOUT); if (ret < 0) - goto out_buf; + return ret; } /* send init command */ @@ -994,7 +1006,7 @@ static int nexio_init(struct usbtouch_usb *usbtouch) buf, sizeof(nexio_init_pkt), &actual_len, NEXIO_TIMEOUT); if (ret < 0) - goto out_buf; + return ret; /* read replies */ for (i = 0; i < 3; i++) { @@ -1025,11 +1037,8 @@ static int nexio_init(struct usbtouch_usb *usbtouch) usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), priv->ack_buf, sizeof(nexio_ack_pkt), nexio_ack_complete, usbtouch); - ret = 0; -out_buf: - kfree(buf); - return ret; + return 0; } static void nexio_exit(struct usbtouch_usb *usbtouch) @@ -1066,13 +1075,11 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) if (ret) dev_warn(dev, "Failed to submit ACK URB: %d\n", ret); - if (!usbtouch->type->max_xc) { - usbtouch->type->max_xc = 2 * x_len; + if (!input_abs_get_max(usbtouch->input, ABS_X)) { input_set_abs_params(usbtouch->input, ABS_X, - 0, usbtouch->type->max_xc, 0, 0); - usbtouch->type->max_yc = 2 * y_len; + 0, 2 * x_len, 0, 0); input_set_abs_params(usbtouch->input, ABS_Y, - 0, usbtouch->type->max_yc, 0, 0); + 0, 2 * y_len, 0, 0); } /* * The device reports state of IR sensors on X and Y axes. @@ -1127,6 +1134,15 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) } return 0; } + +static const struct usbtouch_device_info nexio_dev_info = { + .rept_size = 1024, + .irq_always = true, + .read_data = nexio_read_data, + .alloc = nexio_alloc, + .init = nexio_init, + .exit = nexio_exit, +}; #endif @@ -1145,241 +1161,17 @@ static int elo_read_data(struct usbtouch_usb *dev, unsigned char *pkt) return 1; } -#endif - - -/***************************************************************************** - * the different device descriptors - */ -#ifdef MULTI_PACKET -static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, - unsigned char *pkt, int len); -#endif - -static struct usbtouch_device_info usbtouch_dev_info[] = { -#ifdef CONFIG_TOUCHSCREEN_USB_ELO - [DEVTYPE_ELO] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .max_press = 0xff, - .rept_size = 8, - .read_data = elo_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX - [DEVTYPE_EGALAX] = { - .min_xc = 0x0, - .max_xc = 0x07ff, - .min_yc = 0x0, - .max_yc = 0x07ff, - .rept_size = 16, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = egalax_get_pkt_len, - .read_data = egalax_read_data, - .init = egalax_init, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT - [DEVTYPE_PANJIT] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 8, - .read_data = panjit_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_3M - [DEVTYPE_3M] = { - .min_xc = 0x0, - .max_xc = 0x4000, - .min_yc = 0x0, - .max_yc = 0x4000, - .rept_size = 11, - .read_data = mtouch_read_data, - .alloc = mtouch_alloc, - .init = mtouch_init, - .exit = mtouch_exit, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ITM - [DEVTYPE_ITM] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .max_press = 0xff, - .rept_size = 8, - .read_data = itm_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO - [DEVTYPE_ETURBO] = { - .min_xc = 0x0, - .max_xc = 0x07ff, - .min_yc = 0x0, - .max_yc = 0x07ff, - .rept_size = 8, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = eturbo_get_pkt_len, - .read_data = eturbo_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE - [DEVTYPE_GUNZE] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 4, - .read_data = gunze_read_data, - }, -#endif -#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 - [DEVTYPE_DMC_TSC10] = { - .min_xc = 0x0, - .max_xc = 0x03ff, - .min_yc = 0x0, - .max_yc = 0x03ff, - .rept_size = 5, - .init = dmc_tsc10_init, - .read_data = dmc_tsc10_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH - [DEVTYPE_IRTOUCH] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 8, - .read_data = irtouch_read_data, - }, - - [DEVTYPE_IRTOUCH_HIRES] = { - .min_xc = 0x0, - .max_xc = 0x7fff, - .min_yc = 0x0, - .max_yc = 0x7fff, - .rept_size = 8, - .read_data = irtouch_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK - [DEVTYPE_IDEALTEK] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 8, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = idealtek_get_pkt_len, - .read_data = idealtek_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH - [DEVTYPE_GENERAL_TOUCH] = { - .min_xc = 0x0, - .max_xc = 0x7fff, - .min_yc = 0x0, - .max_yc = 0x7fff, - .rept_size = 7, - .read_data = general_touch_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP - [DEVTYPE_GOTOP] = { - .min_xc = 0x0, - .max_xc = 0x03ff, - .min_yc = 0x0, - .max_yc = 0x03ff, - .rept_size = 4, - .read_data = gotop_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC - [DEVTYPE_JASTEC] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 4, - .read_data = jastec_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_E2I - [DEVTYPE_E2I] = { - .min_xc = 0x0, - .max_xc = 0x7fff, - .min_yc = 0x0, - .max_yc = 0x7fff, - .rept_size = 6, - .init = e2i_init, - .read_data = e2i_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC - [DEVTYPE_ZYTRONIC] = { - .min_xc = 0x0, - .max_xc = 0x03ff, - .min_yc = 0x0, - .max_yc = 0x03ff, - .rept_size = 5, - .read_data = zytronic_read_data, - .irq_always = true, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB - [DEVTYPE_TC45USB] = { - .min_xc = 0x0, - .max_xc = 0x0fff, - .min_yc = 0x0, - .max_yc = 0x0fff, - .rept_size = 5, - .read_data = tc45usb_read_data, - }, -#endif - -#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO - [DEVTYPE_NEXIO] = { - .rept_size = 1024, - .irq_always = true, - .read_data = nexio_read_data, - .alloc = nexio_alloc, - .init = nexio_init, - .exit = nexio_exit, - }, -#endif -#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH - [DEVTYPE_ETOUCH] = { - .min_xc = 0x0, - .max_xc = 0x07ff, - .min_yc = 0x0, - .max_yc = 0x07ff, - .rept_size = 16, - .process_pkt = usbtouch_process_multi, - .get_pkt_len = etouch_get_pkt_len, - .read_data = etouch_read_data, - }, -#endif +static const struct usbtouch_device_info elo_dev_info = { + .min_xc = 0x0, + .max_xc = 0x0fff, + .min_yc = 0x0, + .max_yc = 0x0fff, + .max_press = 0xff, + .rept_size = 8, + .read_data = elo_read_data, }; +#endif /***************************************************************************** @@ -1388,10 +1180,10 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch, unsigned char *pkt, int len) { - struct usbtouch_device_info *type = usbtouch->type; + const struct usbtouch_device_info *type = usbtouch->type; if (!type->read_data(usbtouch, pkt)) - return; + return; input_report_key(usbtouch->input, BTN_TOUCH, usbtouch->touch); @@ -1484,9 +1276,15 @@ out_flush_buf: usbtouch->buf_len = 0; return; } +#else +static void usbtouch_process_multi(struct usbtouch_usb *usbtouch, + unsigned char *pkt, int len) +{ + dev_WARN_ONCE(&usbtouch->interface->dev, 1, + "Protocol has ->get_pkt_len() without #define MULTI_PACKET"); +} #endif - static void usbtouch_irq(struct urb *urb) { struct usbtouch_usb *usbtouch = urb->context; @@ -1517,7 +1315,7 @@ static void usbtouch_irq(struct urb *urb) goto exit; } - usbtouch->type->process_pkt(usbtouch, usbtouch->data, urb->actual_length); + usbtouch->process_pkt(usbtouch, usbtouch->data, urb->actual_length); exit: usb_mark_last_busy(interface_to_usbdev(usbtouch->interface)); @@ -1527,6 +1325,20 @@ exit: __func__, retval); } +static int usbtouch_start_io(struct usbtouch_usb *usbtouch) +{ + guard(mutex)(&usbtouch->pm_mutex); + + if (!usbtouch->type->irq_always) + if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) + return -EIO; + + usbtouch->interface->needs_remote_wakeup = 1; + usbtouch->is_open = true; + + return 0; +} + static int usbtouch_open(struct input_dev *input) { struct usbtouch_usb *usbtouch = input_get_drvdata(input); @@ -1535,23 +1347,12 @@ static int usbtouch_open(struct input_dev *input) usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); r = usb_autopm_get_interface(usbtouch->interface) ? -EIO : 0; - if (r < 0) - goto out; - - mutex_lock(&usbtouch->pm_mutex); - if (!usbtouch->type->irq_always) { - if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) { - r = -EIO; - goto out_put; - } - } + if (r) + return r; + + r = usbtouch_start_io(usbtouch); - usbtouch->interface->needs_remote_wakeup = 1; - usbtouch->is_open = true; -out_put: - mutex_unlock(&usbtouch->pm_mutex); usb_autopm_put_interface(usbtouch->interface); -out: return r; } @@ -1560,11 +1361,11 @@ static void usbtouch_close(struct input_dev *input) struct usbtouch_usb *usbtouch = input_get_drvdata(input); int r; - mutex_lock(&usbtouch->pm_mutex); - if (!usbtouch->type->irq_always) - usb_kill_urb(usbtouch->irq); - usbtouch->is_open = false; - mutex_unlock(&usbtouch->pm_mutex); + scoped_guard(mutex, &usbtouch->pm_mutex) { + if (!usbtouch->type->irq_always) + usb_kill_urb(usbtouch->irq); + usbtouch->is_open = false; + } r = usb_autopm_get_interface(usbtouch->interface); usbtouch->interface->needs_remote_wakeup = 0; @@ -1572,8 +1373,7 @@ static void usbtouch_close(struct input_dev *input) usb_autopm_put_interface(usbtouch->interface); } -static int usbtouch_suspend -(struct usb_interface *intf, pm_message_t message) +static int usbtouch_suspend(struct usb_interface *intf, pm_message_t message) { struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); @@ -1585,20 +1385,19 @@ static int usbtouch_suspend static int usbtouch_resume(struct usb_interface *intf) { struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); - int result = 0; - mutex_lock(&usbtouch->pm_mutex); + guard(mutex)(&usbtouch->pm_mutex); + if (usbtouch->is_open || usbtouch->type->irq_always) - result = usb_submit_urb(usbtouch->irq, GFP_NOIO); - mutex_unlock(&usbtouch->pm_mutex); + return usb_submit_urb(usbtouch->irq, GFP_NOIO); - return result; + return 0; } static int usbtouch_reset_resume(struct usb_interface *intf) { struct usbtouch_usb *usbtouch = usb_get_intfdata(intf); - int err = 0; + int err; /* reinit the device */ if (usbtouch->type->init) { @@ -1612,12 +1411,12 @@ static int usbtouch_reset_resume(struct usb_interface *intf) } /* restart IO if needed */ - mutex_lock(&usbtouch->pm_mutex); + guard(mutex)(&usbtouch->pm_mutex); + if (usbtouch->is_open) - err = usb_submit_urb(usbtouch->irq, GFP_NOIO); - mutex_unlock(&usbtouch->pm_mutex); + return usb_submit_urb(usbtouch->irq, GFP_NOIO); - return err; + return 0; } static void usbtouch_free_buffers(struct usb_device *udev, @@ -1647,31 +1446,25 @@ static int usbtouch_probe(struct usb_interface *intf, struct input_dev *input_dev; struct usb_endpoint_descriptor *endpoint; struct usb_device *udev = interface_to_usbdev(intf); - struct usbtouch_device_info *type; + const struct usbtouch_device_info *type; int err = -ENOMEM; /* some devices are ignored */ - if (id->driver_info == DEVTYPE_IGNORE) - return -ENODEV; - - if (id->driver_info >= ARRAY_SIZE(usbtouch_dev_info)) + type = (const struct usbtouch_device_info *)id->driver_info; + if (!type) return -ENODEV; endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); if (!endpoint) return -ENXIO; - usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); + usbtouch = kzalloc(sizeof(*usbtouch), GFP_KERNEL); input_dev = input_allocate_device(); if (!usbtouch || !input_dev) goto out_free; mutex_init(&usbtouch->pm_mutex); - - type = &usbtouch_dev_info[id->driver_info]; usbtouch->type = type; - if (!type->process_pkt) - type->process_pkt = usbtouch_process_pkt; usbtouch->data_size = type->rept_size; if (type->get_pkt_len) { @@ -1695,6 +1488,9 @@ static int usbtouch_probe(struct usb_interface *intf, usbtouch->buffer = kmalloc(type->rept_size, GFP_KERNEL); if (!usbtouch->buffer) goto out_free_buffers; + usbtouch->process_pkt = usbtouch_process_multi; + } else { + usbtouch->process_pkt = usbtouch_process_pkt; } usbtouch->irq = usb_alloc_urb(0, GFP_KERNEL); @@ -1841,6 +1637,150 @@ static void usbtouch_disconnect(struct usb_interface *intf) kfree(usbtouch); } +static const struct attribute_group *usbtouch_groups[] = { +#ifdef CONFIG_TOUCHSCREEN_USB_3M + &mtouch_attr_group, +#endif + NULL +}; + +static const struct usb_device_id usbtouch_devices[] = { +#ifdef CONFIG_TOUCHSCREEN_USB_EGALAX + /* ignore the HID capable devices, handled by usbhid */ + { USB_DEVICE_INTERFACE_CLASS(0x0eef, 0x0001, USB_INTERFACE_CLASS_HID), + .driver_info = 0 }, + { USB_DEVICE_INTERFACE_CLASS(0x0eef, 0x0002, USB_INTERFACE_CLASS_HID), + .driver_info = 0 }, + + /* normal device IDs */ + { USB_DEVICE(0x3823, 0x0001), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x3823, 0x0002), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x0123, 0x0001), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x0eef, 0x0001), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x0eef, 0x0002), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x1234, 0x0001), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, + { USB_DEVICE(0x1234, 0x0002), + .driver_info = (kernel_ulong_t)&egalax_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_PANJIT + { USB_DEVICE(0x134c, 0x0001), + .driver_info = (kernel_ulong_t)&panjit_dev_info }, + { USB_DEVICE(0x134c, 0x0002), + .driver_info = (kernel_ulong_t)&panjit_dev_info }, + { USB_DEVICE(0x134c, 0x0003), + .driver_info = (kernel_ulong_t)&panjit_dev_info }, + { USB_DEVICE(0x134c, 0x0004), + .driver_info = (kernel_ulong_t)&panjit_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_3M + { USB_DEVICE(0x0596, 0x0001), + .driver_info = (kernel_ulong_t)&mtouch_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_ITM + { USB_DEVICE(0x0403, 0xf9e9), + .driver_info = (kernel_ulong_t)&itm_dev_info }, + { USB_DEVICE(0x16e3, 0xf9e9), + .driver_info = (kernel_ulong_t)&itm_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_ETURBO + { USB_DEVICE(0x1234, 0x5678), + .driver_info = (kernel_ulong_t)&eturbo_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_GUNZE + { USB_DEVICE(0x0637, 0x0001), + .driver_info = (kernel_ulong_t)&gunze_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_DMC_TSC10 + { USB_DEVICE(0x0afa, 0x03e8), + .driver_info = (kernel_ulong_t)&dmc_tsc10_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH + { USB_DEVICE(0x255e, 0x0001), + .driver_info = (kernel_ulong_t)&irtouch_dev_info }, + { USB_DEVICE(0x595a, 0x0001), + .driver_info = (kernel_ulong_t)&irtouch_dev_info }, + { USB_DEVICE(0x6615, 0x0001), + .driver_info = (kernel_ulong_t)&irtouch_dev_info }, + { USB_DEVICE(0x6615, 0x0012), + .driver_info = (kernel_ulong_t)&irtouch_hires_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_IDEALTEK + { USB_DEVICE(0x1391, 0x1000), + .driver_info = (kernel_ulong_t)&idealtek_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH + { USB_DEVICE(0x0dfc, 0x0001), + .driver_info = (kernel_ulong_t)&general_touch_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_GOTOP + { USB_DEVICE(0x08f2, 0x007f), + .driver_info = (kernel_ulong_t)&gotop_dev_info }, + { USB_DEVICE(0x08f2, 0x00ce), + .driver_info = (kernel_ulong_t)&gotop_dev_info }, + { USB_DEVICE(0x08f2, 0x00f4), + .driver_info = (kernel_ulong_t)&gotop_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_JASTEC + { USB_DEVICE(0x0f92, 0x0001), + .driver_info = (kernel_ulong_t)&jastec_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_E2I + { USB_DEVICE(0x1ac7, 0x0001), + .driver_info = (kernel_ulong_t)&e2i_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC + { USB_DEVICE(0x14c8, 0x0003), + .driver_info = (kernel_ulong_t)&zytronic_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC45USB + /* TC5UH */ + { USB_DEVICE(0x0664, 0x0309), + .driver_info = (kernel_ulong_t)&tc45usb_dev_info }, + /* TC4UM */ + { USB_DEVICE(0x0664, 0x0306), + .driver_info = (kernel_ulong_t)&tc45usb_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_NEXIO + /* data interface only */ + { USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), + .driver_info = (kernel_ulong_t)&nexio_dev_info }, + { USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), + .driver_info = (kernel_ulong_t)&nexio_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_ELO + { USB_DEVICE(0x04e7, 0x0020), + .driver_info = (kernel_ulong_t)&elo_dev_info }, +#endif + +#ifdef CONFIG_TOUCHSCREEN_USB_EASYTOUCH + { USB_DEVICE(0x7374, 0x0001), + .driver_info = (kernel_ulong_t)&etouch_dev_info }, +#endif + + { } +}; MODULE_DEVICE_TABLE(usb, usbtouch_devices); static struct usb_driver usbtouch_driver = { @@ -1851,6 +1791,7 @@ static struct usb_driver usbtouch_driver = { .resume = usbtouch_resume, .reset_resume = usbtouch_reset_resume, .id_table = usbtouch_devices, + .dev_groups = usbtouch_groups, .supports_autosuspend = 1, }; diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index f389f9c004a9..fd97a83f5664 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -13,7 +13,7 @@ #include <linux/slab.h> #include <linux/irq.h> #include <linux/interrupt.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* Bitmasks (for data[3]) */ #define WACOM_TIP_SWITCH BIT(0) @@ -253,8 +253,8 @@ static int wacom_i2c_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); static const struct i2c_device_id wacom_i2c_id[] = { - { "WAC_I2C_EMR", 0 }, - { }, + { "WAC_I2C_EMR" }, + { } }; MODULE_DEVICE_TABLE(i2c, wacom_i2c_id); diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 928c5ee3ac36..ed2ca8a689d5 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -380,30 +380,28 @@ static int w8001_open(struct input_dev *dev) struct w8001 *w8001 = input_get_drvdata(dev); int err; - err = mutex_lock_interruptible(&w8001->mutex); - if (err) - return err; + scoped_guard(mutex_intr, &w8001->mutex) { + if (w8001->open_count == 0) { + err = w8001_command(w8001, W8001_CMD_START, false); + if (err) + return err; + } - if (w8001->open_count++ == 0) { - err = w8001_command(w8001, W8001_CMD_START, false); - if (err) - w8001->open_count--; + w8001->open_count++; + return 0; } - mutex_unlock(&w8001->mutex); - return err; + return -EINTR; } static void w8001_close(struct input_dev *dev) { struct w8001 *w8001 = input_get_drvdata(dev); - mutex_lock(&w8001->mutex); + guard(mutex)(&w8001->mutex); if (--w8001->open_count == 0) w8001_command(w8001, W8001_CMD_STOP, false); - - mutex_unlock(&w8001->mutex); } static int w8001_detect(struct w8001 *w8001) @@ -595,10 +593,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) struct w8001 *w8001; struct input_dev *input_dev_pen; struct input_dev *input_dev_touch; - char basename[64]; + char basename[64] = "Wacom Serial"; int err, err_pen, err_touch; - w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL); + w8001 = kzalloc(sizeof(*w8001), GFP_KERNEL); input_dev_pen = input_allocate_device(); input_dev_touch = input_allocate_device(); if (!w8001 || !input_dev_pen || !input_dev_touch) { @@ -625,8 +623,6 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) /* For backwards-compatibility we compose the basename based on * capabilities and then just append the tool type */ - strscpy(basename, "Wacom Serial", sizeof(basename)); - err_pen = w8001_setup_pen(w8001, basename, sizeof(basename)); err_touch = w8001_setup_touch(w8001, basename, sizeof(basename)); if (err_pen && err_touch) { @@ -635,8 +631,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) } if (!err_pen) { - strscpy(w8001->pen_name, basename, sizeof(w8001->pen_name)); - strlcat(w8001->pen_name, " Pen", sizeof(w8001->pen_name)); + snprintf(w8001->pen_name, sizeof(w8001->pen_name), + "%s Pen", basename); input_dev_pen->name = w8001->pen_name; w8001_set_devdata(input_dev_pen, w8001, serio); @@ -651,9 +647,8 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv) } if (!err_touch) { - strscpy(w8001->touch_name, basename, sizeof(w8001->touch_name)); - strlcat(w8001->touch_name, " Finger", - sizeof(w8001->touch_name)); + snprintf(w8001->touch_name, sizeof(w8001->touch_name), + "%s Finger", basename); input_dev_touch->name = w8001->touch_name; w8001_set_devdata(input_dev_touch, w8001, serio); diff --git a/drivers/input/touchscreen/wdt87xx_i2c.c b/drivers/input/touchscreen/wdt87xx_i2c.c index 32c7be54434c..88d376090e6e 100644 --- a/drivers/input/touchscreen/wdt87xx_i2c.c +++ b/drivers/input/touchscreen/wdt87xx_i2c.c @@ -20,7 +20,7 @@ #include <linux/firmware.h> #include <linux/input/mt.h> #include <linux/acpi.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define WDT87XX_NAME "wdt87xx_i2c" #define WDT87XX_FW_NAME "wdt87xx_fw.bin" @@ -1148,16 +1148,18 @@ static int wdt87xx_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(wdt87xx_pm_ops, wdt87xx_suspend, wdt87xx_resume); static const struct i2c_device_id wdt87xx_dev_id[] = { - { WDT87XX_NAME, 0 }, + { WDT87XX_NAME }, { } }; MODULE_DEVICE_TABLE(i2c, wdt87xx_dev_id); +#ifdef CONFIG_ACPI static const struct acpi_device_id wdt87xx_acpi_id[] = { { "WDHT0001", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, wdt87xx_acpi_id); +#endif static struct i2c_driver wdt87xx_driver = { .probe = wdt87xx_ts_probe, diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 9cee26b63341..98f8ec408cad 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -387,7 +387,7 @@ static struct platform_driver wm831x_ts_driver = { .name = "wm831x-touch", }, .probe = wm831x_ts_probe, - .remove_new = wm831x_ts_remove, + .remove = wm831x_ts_remove, }; module_platform_driver(wm831x_ts_driver); diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index f01f6cc9b59f..b25771a8df2b 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -222,7 +222,7 @@ EXPORT_SYMBOL_GPL(wm97xx_set_gpio); /* * Codec GPIO pin configuration, this sets pin direction, polarity, - * stickyness and wake up. + * stickiness and wake up. */ void wm97xx_config_gpio(struct wm97xx *wm, u32 gpio, enum wm97xx_gpio_dir dir, enum wm97xx_gpio_pol pol, enum wm97xx_gpio_sticky sticky, @@ -403,7 +403,7 @@ static int wm97xx_read_samples(struct wm97xx *wm) * is actively working with the touchscreen we * don't want to lose the quick response. So we * will slowly increase sleep time after the - * pen is up and quicky restore it to ~one task + * pen is up and quickly restore it to ~one task * switch when pen is down again. */ if (wm->ts_reader_interval < HZ / 10) @@ -876,7 +876,7 @@ static struct platform_driver wm97xx_mfd_driver = { .pm = pm_sleep_ptr(&wm97xx_pm_ops), }, .probe = wm97xx_mfd_probe, - .remove_new = wm97xx_mfd_remove, + .remove = wm97xx_mfd_remove, }; static int __init wm97xx_init(void) diff --git a/drivers/input/touchscreen/zet6223.c b/drivers/input/touchscreen/zet6223.c index 1a034471f103..943634ba9cd9 100644 --- a/drivers/input/touchscreen/zet6223.c +++ b/drivers/input/touchscreen/zet6223.c @@ -11,7 +11,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/regulator/consumer.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #define ZET6223_MAX_FINGERS 16 #define ZET6223_MAX_PKT_SIZE (3 + 4 * ZET6223_MAX_FINGERS) @@ -25,8 +25,6 @@ struct zet6223_ts { struct i2c_client *client; struct input_dev *input; - struct regulator *vcc; - struct regulator *vio; struct touchscreen_properties prop; struct regulator_bulk_data supplies[2]; u16 max_x; @@ -238,7 +236,7 @@ static const struct of_device_id zet6223_of_match[] = { MODULE_DEVICE_TABLE(of, zet6223_of_match); static const struct i2c_device_id zet6223_id[] = { - { "zet6223", 0}, + { "zet6223" }, { } }; MODULE_DEVICE_TABLE(i2c, zet6223_id); diff --git a/drivers/input/touchscreen/zforce_ts.c b/drivers/input/touchscreen/zforce_ts.c index 5680075f0bb8..df42fdf36ae3 100644 --- a/drivers/input/touchscreen/zforce_ts.c +++ b/drivers/input/touchscreen/zforce_ts.c @@ -9,21 +9,20 @@ * Author: Pieter Truter<ptruter@intrinsyc.com> */ -#include <linux/module.h> -#include <linux/hrtimer.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> #include <linux/delay.h> -#include <linux/gpio/consumer.h> #include <linux/device.h> -#include <linux/sysfs.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/input.h> #include <linux/input/mt.h> #include <linux/input/touchscreen.h> -#include <linux/platform_data/zforce_ts.h> -#include <linux/regulator/consumer.h> +#include <linux/interrupt.h> +#include <linux/module.h> #include <linux/of.h> +#include <linux/property.h> +#include <linux/regulator/consumer.h> +#include <linux/slab.h> +#include <linux/unaligned.h> #define WAIT_TIMEOUT msecs_to_jiffies(1000) @@ -97,9 +96,7 @@ struct zforce_point { * @suspending in the process of going to suspend (don't emit wakeup * events for commands executed to suspend the device) * @suspended device suspended - * @access_mutex serialize i2c-access, to keep multipart reads together * @command_done completion to wait for the command result - * @command_mutex serialize commands sent to the ic * @command_waiting the id of the command that is currently waiting * for a result * @command_result returned result of the command @@ -108,11 +105,8 @@ struct zforce_ts { struct i2c_client *client; struct input_dev *input; struct touchscreen_properties prop; - const struct zforce_ts_platdata *pdata; char phys[32]; - struct regulator *reg_vdd; - struct gpio_desc *gpio_int; struct gpio_desc *gpio_rst; @@ -126,10 +120,7 @@ struct zforce_ts { u16 version_build; u16 version_rev; - struct mutex access_mutex; - struct completion command_done; - struct mutex command_mutex; int command_waiting; int command_result; }; @@ -146,9 +137,7 @@ static int zforce_command(struct zforce_ts *ts, u8 cmd) buf[1] = 1; /* data size, command only */ buf[2] = cmd; - mutex_lock(&ts->access_mutex); ret = i2c_master_send(client, &buf[0], ARRAY_SIZE(buf)); - mutex_unlock(&ts->access_mutex); if (ret < 0) { dev_err(&client->dev, "i2c send data request error: %d\n", ret); return ret; @@ -157,59 +146,36 @@ static int zforce_command(struct zforce_ts *ts, u8 cmd) return 0; } -static void zforce_reset_assert(struct zforce_ts *ts) -{ - gpiod_set_value_cansleep(ts->gpio_rst, 1); -} - -static void zforce_reset_deassert(struct zforce_ts *ts) -{ - gpiod_set_value_cansleep(ts->gpio_rst, 0); -} - static int zforce_send_wait(struct zforce_ts *ts, const char *buf, int len) { struct i2c_client *client = ts->client; int ret; - ret = mutex_trylock(&ts->command_mutex); - if (!ret) { - dev_err(&client->dev, "already waiting for a command\n"); - return -EBUSY; - } - dev_dbg(&client->dev, "sending %d bytes for command 0x%x\n", buf[1], buf[2]); ts->command_waiting = buf[2]; - mutex_lock(&ts->access_mutex); ret = i2c_master_send(client, buf, len); - mutex_unlock(&ts->access_mutex); if (ret < 0) { dev_err(&client->dev, "i2c send data request error: %d\n", ret); - goto unlock; + return ret; } dev_dbg(&client->dev, "waiting for result for command 0x%x\n", buf[2]); - if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) { - ret = -ETIME; - goto unlock; - } + if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) + return -ETIME; ret = ts->command_result; - -unlock: - mutex_unlock(&ts->command_mutex); - return ret; + return 0; } static int zforce_command_wait(struct zforce_ts *ts, u8 cmd) { struct i2c_client *client = ts->client; char buf[3]; - int ret; + int error; dev_dbg(&client->dev, "%s: 0x%x\n", __func__, cmd); @@ -217,10 +183,11 @@ static int zforce_command_wait(struct zforce_ts *ts, u8 cmd) buf[1] = 1; /* data size, command only */ buf[2] = cmd; - ret = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); - if (ret < 0) { - dev_err(&client->dev, "i2c send data request error: %d\n", ret); - return ret; + error = zforce_send_wait(ts, &buf[0], ARRAY_SIZE(buf)); + if (error) { + dev_err(&client->dev, "i2c send data request error: %d\n", + error); + return error; } return 0; @@ -268,40 +235,40 @@ static int zforce_setconfig(struct zforce_ts *ts, char b1) static int zforce_start(struct zforce_ts *ts) { struct i2c_client *client = ts->client; - int ret; + int error; dev_dbg(&client->dev, "starting device\n"); - ret = zforce_command_wait(ts, COMMAND_INITIALIZE); - if (ret) { - dev_err(&client->dev, "Unable to initialize, %d\n", ret); - return ret; + error = zforce_command_wait(ts, COMMAND_INITIALIZE); + if (error) { + dev_err(&client->dev, "Unable to initialize, %d\n", error); + return error; } - ret = zforce_resolution(ts, ts->prop.max_x, ts->prop.max_y); - if (ret) { - dev_err(&client->dev, "Unable to set resolution, %d\n", ret); - goto error; + error = zforce_resolution(ts, ts->prop.max_x, ts->prop.max_y); + if (error) { + dev_err(&client->dev, "Unable to set resolution, %d\n", error); + goto err_deactivate; } - ret = zforce_scan_frequency(ts, 10, 50, 50); - if (ret) { + error = zforce_scan_frequency(ts, 10, 50, 50); + if (error) { dev_err(&client->dev, "Unable to set scan frequency, %d\n", - ret); - goto error; + error); + goto err_deactivate; } - ret = zforce_setconfig(ts, SETCONFIG_DUALTOUCH); - if (ret) { + error = zforce_setconfig(ts, SETCONFIG_DUALTOUCH); + if (error) { dev_err(&client->dev, "Unable to set config\n"); - goto error; + goto err_deactivate; } /* start sending touch events */ - ret = zforce_command(ts, COMMAND_DATAREQUEST); - if (ret) { + error = zforce_command(ts, COMMAND_DATAREQUEST); + if (error) { dev_err(&client->dev, "Unable to request data\n"); - goto error; + goto err_deactivate; } /* @@ -312,24 +279,24 @@ static int zforce_start(struct zforce_ts *ts) return 0; -error: +err_deactivate: zforce_command_wait(ts, COMMAND_DEACTIVATE); - return ret; + return error; } static int zforce_stop(struct zforce_ts *ts) { struct i2c_client *client = ts->client; - int ret; + int error; dev_dbg(&client->dev, "stopping device\n"); /* Deactivates touch sensing and puts the device into sleep. */ - ret = zforce_command_wait(ts, COMMAND_DEACTIVATE); - if (ret != 0) { + error = zforce_command_wait(ts, COMMAND_DEACTIVATE); + if (error) { dev_err(&client->dev, "could not deactivate device, %d\n", - ret); - return ret; + error); + return error; } return 0; @@ -340,6 +307,7 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) struct i2c_client *client = ts->client; struct zforce_point point; int count, i, num = 0; + u8 *p; count = payload[0]; if (count > ZFORCE_REPORT_POINTS) { @@ -350,10 +318,10 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) } for (i = 0; i < count; i++) { - point.coord_x = - payload[9 * i + 2] << 8 | payload[9 * i + 1]; - point.coord_y = - payload[9 * i + 4] << 8 | payload[9 * i + 3]; + p = &payload[i * 9 + 1]; + + point.coord_x = get_unaligned_le16(&p[0]); + point.coord_y = get_unaligned_le16(&p[2]); if (point.coord_x > ts->prop.max_x || point.coord_y > ts->prop.max_y) { @@ -362,18 +330,16 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) point.coord_x = point.coord_y = 0; } - point.state = payload[9 * i + 5] & 0x0f; - point.id = (payload[9 * i + 5] & 0xf0) >> 4; + point.state = p[4] & 0x0f; + point.id = (p[4] & 0xf0) >> 4; /* determine touch major, minor and orientation */ - point.area_major = max(payload[9 * i + 6], - payload[9 * i + 7]); - point.area_minor = min(payload[9 * i + 6], - payload[9 * i + 7]); - point.orientation = payload[9 * i + 6] > payload[9 * i + 7]; + point.area_major = max(p[5], p[6]); + point.area_minor = min(p[5], p[6]); + point.orientation = p[5] > p[6]; - point.pressure = payload[9 * i + 8]; - point.prblty = payload[9 * i + 9]; + point.pressure = p[7]; + point.prblty = p[8]; dev_dbg(&client->dev, "point %d/%d: state %d, id %d, pressure %d, prblty %d, x %d, y %d, amajor %d, aminor %d, ori %d\n", @@ -386,10 +352,8 @@ static int zforce_touch_event(struct zforce_ts *ts, u8 *payload) /* the zforce id starts with "1", so needs to be decreased */ input_mt_slot(ts->input, point.id - 1); - input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, - point.state != STATE_UP); - - if (point.state != STATE_UP) { + if (input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, + point.state != STATE_UP)) { touchscreen_report_pos(ts->input, &ts->prop, point.coord_x, point.coord_y, true); @@ -417,41 +381,35 @@ static int zforce_read_packet(struct zforce_ts *ts, u8 *buf) struct i2c_client *client = ts->client; int ret; - mutex_lock(&ts->access_mutex); - /* read 2 byte message header */ ret = i2c_master_recv(client, buf, 2); if (ret < 0) { dev_err(&client->dev, "error reading header: %d\n", ret); - goto unlock; + return ret; } if (buf[PAYLOAD_HEADER] != FRAME_START) { dev_err(&client->dev, "invalid frame start: %d\n", buf[0]); - ret = -EIO; - goto unlock; + return -EIO; } if (buf[PAYLOAD_LENGTH] == 0) { dev_err(&client->dev, "invalid payload length: %d\n", buf[PAYLOAD_LENGTH]); - ret = -EIO; - goto unlock; + return -EIO; } /* read the message */ ret = i2c_master_recv(client, &buf[PAYLOAD_BODY], buf[PAYLOAD_LENGTH]); if (ret < 0) { dev_err(&client->dev, "error reading payload: %d\n", ret); - goto unlock; + return ret; } dev_dbg(&client->dev, "read %d bytes for response command 0x%x\n", buf[PAYLOAD_LENGTH], buf[PAYLOAD_BODY]); -unlock: - mutex_unlock(&ts->access_mutex); - return ret; + return 0; } static void zforce_complete(struct zforce_ts *ts, int cmd, int result) @@ -482,9 +440,10 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) { struct zforce_ts *ts = dev_id; struct i2c_client *client = ts->client; - int ret; + int error; u8 payload_buffer[FRAME_MAXSIZE]; u8 *payload; + bool suspending; /* * When still suspended, return. @@ -498,7 +457,8 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) dev_dbg(&client->dev, "handling interrupt\n"); /* Don't emit wakeup events from commands run by zforce_suspend */ - if (!ts->suspending && device_may_wakeup(&client->dev)) + suspending = READ_ONCE(ts->suspending); + if (!suspending && device_may_wakeup(&client->dev)) pm_stay_awake(&client->dev); /* @@ -511,10 +471,10 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) * no IRQ any more) */ do { - ret = zforce_read_packet(ts, payload_buffer); - if (ret < 0) { + error = zforce_read_packet(ts, payload_buffer); + if (error) { dev_err(&client->dev, - "could not read packet, ret: %d\n", ret); + "could not read packet, ret: %d\n", error); break; } @@ -526,7 +486,7 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) * Always report touch-events received while * suspending, when being a wakeup source */ - if (ts->suspending && device_may_wakeup(&client->dev)) + if (suspending && device_may_wakeup(&client->dev)) pm_wakeup_event(&client->dev, 500); zforce_touch_event(ts, &payload[RESPONSE_DATA]); break; @@ -550,14 +510,15 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) * Version Payload Results * [2:major] [2:minor] [2:build] [2:rev] */ - ts->version_major = (payload[RESPONSE_DATA + 1] << 8) | - payload[RESPONSE_DATA]; - ts->version_minor = (payload[RESPONSE_DATA + 3] << 8) | - payload[RESPONSE_DATA + 2]; - ts->version_build = (payload[RESPONSE_DATA + 5] << 8) | - payload[RESPONSE_DATA + 4]; - ts->version_rev = (payload[RESPONSE_DATA + 7] << 8) | - payload[RESPONSE_DATA + 6]; + ts->version_major = + get_unaligned_le16(&payload[RESPONSE_DATA]); + ts->version_minor = + get_unaligned_le16(&payload[RESPONSE_DATA + 2]); + ts->version_build = + get_unaligned_le16(&payload[RESPONSE_DATA + 4]); + ts->version_rev = + get_unaligned_le16(&payload[RESPONSE_DATA + 6]); + dev_dbg(&ts->client->dev, "Firmware Version %04x:%04x %04x:%04x\n", ts->version_major, ts->version_minor, @@ -579,7 +540,7 @@ static irqreturn_t zforce_irq_thread(int irq, void *dev_id) } } while (gpiod_get_value_cansleep(ts->gpio_int)); - if (!ts->suspending && device_may_wakeup(&client->dev)) + if (!suspending && device_may_wakeup(&client->dev)) pm_relax(&client->dev); dev_dbg(&client->dev, "finished interrupt\n"); @@ -598,24 +559,20 @@ static void zforce_input_close(struct input_dev *dev) { struct zforce_ts *ts = input_get_drvdata(dev); struct i2c_client *client = ts->client; - int ret; + int error; - ret = zforce_stop(ts); - if (ret) + error = zforce_stop(ts); + if (error) dev_warn(&client->dev, "stopping zforce failed\n"); - - return; } -static int zforce_suspend(struct device *dev) +static int __zforce_suspend(struct zforce_ts *ts) { - struct i2c_client *client = to_i2c_client(dev); - struct zforce_ts *ts = i2c_get_clientdata(client); + struct i2c_client *client = ts->client; struct input_dev *input = ts->input; - int ret = 0; + int error; - mutex_lock(&input->mutex); - ts->suspending = true; + guard(mutex)(&input->mutex); /* * When configured as a wakeup source device should always wake @@ -626,9 +583,9 @@ static int zforce_suspend(struct device *dev) /* Need to start device, if not open, to be a wakeup source. */ if (!input_device_enabled(input)) { - ret = zforce_start(ts); - if (ret) - goto unlock; + error = zforce_start(ts); + if (error) + return error; } enable_irq_wake(client->irq); @@ -636,18 +593,30 @@ static int zforce_suspend(struct device *dev) dev_dbg(&client->dev, "suspend without being a wakeup source\n"); - ret = zforce_stop(ts); - if (ret) - goto unlock; + error = zforce_stop(ts); + if (error) + return error; disable_irq(client->irq); } ts->suspended = true; + return 0; +} + +static int zforce_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct zforce_ts *ts = i2c_get_clientdata(client); + int ret; + + WRITE_ONCE(ts->suspending, true); + smp_mb(); -unlock: - ts->suspending = false; - mutex_unlock(&input->mutex); + ret = __zforce_suspend(ts); + + smp_mb(); + WRITE_ONCE(ts->suspending, false); return ret; } @@ -657,9 +626,9 @@ static int zforce_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct zforce_ts *ts = i2c_get_clientdata(client); struct input_dev *input = ts->input; - int ret = 0; + int error; - mutex_lock(&input->mutex); + guard(mutex)(&input->mutex); ts->suspended = false; @@ -670,24 +639,21 @@ static int zforce_resume(struct device *dev) /* need to stop device if it was not open on suspend */ if (!input_device_enabled(input)) { - ret = zforce_stop(ts); - if (ret) - goto unlock; + error = zforce_stop(ts); + if (error) + return error; } } else if (input_device_enabled(input)) { dev_dbg(&client->dev, "resume without being a wakeup source\n"); enable_irq(client->irq); - ret = zforce_start(ts); - if (ret < 0) - goto unlock; + error = zforce_start(ts); + if (error) + return error; } -unlock: - mutex_unlock(&input->mutex); - - return ret; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(zforce_pm_ops, zforce_suspend, zforce_resume); @@ -696,46 +662,27 @@ static void zforce_reset(void *data) { struct zforce_ts *ts = data; - zforce_reset_assert(ts); - + gpiod_set_value_cansleep(ts->gpio_rst, 1); udelay(10); - - if (!IS_ERR(ts->reg_vdd)) - regulator_disable(ts->reg_vdd); } -static struct zforce_ts_platdata *zforce_parse_dt(struct device *dev) +static void zforce_ts_parse_legacy_properties(struct zforce_ts *ts) { - struct zforce_ts_platdata *pdata; - struct device_node *np = dev->of_node; + u32 x_max = 0; + u32 y_max = 0; - if (!np) - return ERR_PTR(-ENOENT); + device_property_read_u32(&ts->client->dev, "x-size", &x_max); + input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, x_max, 0, 0); - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "failed to allocate platform data\n"); - return ERR_PTR(-ENOMEM); - } - - of_property_read_u32(np, "x-size", &pdata->x_max); - of_property_read_u32(np, "y-size", &pdata->y_max); - - return pdata; + device_property_read_u32(&ts->client->dev, "y-size", &y_max); + input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, y_max, 0, 0); } static int zforce_probe(struct i2c_client *client) { - const struct zforce_ts_platdata *pdata = dev_get_platdata(&client->dev); struct zforce_ts *ts; struct input_dev *input_dev; - int ret; - - if (!pdata) { - pdata = zforce_parse_dt(&client->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - } + int error; ts = devm_kzalloc(&client->dev, sizeof(struct zforce_ts), GFP_KERNEL); if (!ts) @@ -743,22 +690,18 @@ static int zforce_probe(struct i2c_client *client) ts->gpio_rst = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(ts->gpio_rst)) { - ret = PTR_ERR(ts->gpio_rst); - dev_err(&client->dev, - "failed to request reset GPIO: %d\n", ret); - return ret; - } + error = PTR_ERR_OR_ZERO(ts->gpio_rst); + if (error) + return dev_err_probe(&client->dev, error, + "failed to request reset GPIO\n"); if (ts->gpio_rst) { ts->gpio_int = devm_gpiod_get_optional(&client->dev, "irq", GPIOD_IN); - if (IS_ERR(ts->gpio_int)) { - ret = PTR_ERR(ts->gpio_int); - dev_err(&client->dev, - "failed to request interrupt GPIO: %d\n", ret); - return ret; - } + error = PTR_ERR_OR_ZERO(ts->gpio_int); + if (error) + return dev_err_probe(&client->dev, error, + "failed to request interrupt GPIO\n"); } else { /* * Deprecated GPIO handling for compatibility @@ -768,66 +711,45 @@ static int zforce_probe(struct i2c_client *client) /* INT GPIO */ ts->gpio_int = devm_gpiod_get_index(&client->dev, NULL, 0, GPIOD_IN); - if (IS_ERR(ts->gpio_int)) { - ret = PTR_ERR(ts->gpio_int); - dev_err(&client->dev, - "failed to request interrupt GPIO: %d\n", ret); - return ret; - } + + error = PTR_ERR_OR_ZERO(ts->gpio_int); + if (error) + return dev_err_probe(&client->dev, error, + "failed to request interrupt GPIO\n"); /* RST GPIO */ ts->gpio_rst = devm_gpiod_get_index(&client->dev, NULL, 1, GPIOD_OUT_HIGH); - if (IS_ERR(ts->gpio_rst)) { - ret = PTR_ERR(ts->gpio_rst); - dev_err(&client->dev, - "failed to request reset GPIO: %d\n", ret); - return ret; - } - } - - ts->reg_vdd = devm_regulator_get_optional(&client->dev, "vdd"); - if (IS_ERR(ts->reg_vdd)) { - ret = PTR_ERR(ts->reg_vdd); - if (ret == -EPROBE_DEFER) - return ret; - } else { - ret = regulator_enable(ts->reg_vdd); - if (ret) - return ret; - - /* - * according to datasheet add 100us grace time after regular - * regulator enable delay. - */ - udelay(100); + error = PTR_ERR_OR_ZERO(ts->gpio_rst); + if (error) + return dev_err_probe(&client->dev, error, + "failed to request reset GPIO\n"); } - ret = devm_add_action(&client->dev, zforce_reset, ts); - if (ret) { - dev_err(&client->dev, "failed to register reset action, %d\n", - ret); + error = devm_regulator_get_enable(&client->dev, "vdd"); + if (error) + return dev_err_probe(&client->dev, error, + "failed to request vdd supply\n"); - /* hereafter the regulator will be disabled by the action */ - if (!IS_ERR(ts->reg_vdd)) - regulator_disable(ts->reg_vdd); + /* + * According to datasheet add 100us grace time after regular + * regulator enable delay. + */ + usleep_range(100, 200); - return ret; - } + error = devm_add_action_or_reset(&client->dev, zforce_reset, ts); + if (error) + return dev_err_probe(&client->dev, error, + "failed to register reset action\n"); snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev)); input_dev = devm_input_allocate_device(&client->dev); - if (!input_dev) { - dev_err(&client->dev, "could not allocate input device\n"); - return -ENOMEM; - } - - mutex_init(&ts->access_mutex); - mutex_init(&ts->command_mutex); + if (!input_dev) + return dev_err_probe(&client->dev, -ENOMEM, + "could not allocate input device\n"); - ts->pdata = pdata; ts->client = client; ts->input = input_dev; @@ -838,28 +760,21 @@ static int zforce_probe(struct i2c_client *client) input_dev->open = zforce_input_open; input_dev->close = zforce_input_close; - __set_bit(EV_KEY, input_dev->evbit); - __set_bit(EV_SYN, input_dev->evbit); - __set_bit(EV_ABS, input_dev->evbit); - - /* For multi touch */ - input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, - pdata->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, - pdata->y_max, 0, 0); - + zforce_ts_parse_legacy_properties(ts); touchscreen_parse_properties(input_dev, true, &ts->prop); - if (ts->prop.max_x == 0 || ts->prop.max_y == 0) { - dev_err(&client->dev, "no size specified\n"); - return -EINVAL; - } + if (ts->prop.max_x == 0 || ts->prop.max_y == 0) + return dev_err_probe(&client->dev, -EINVAL, "no size specified"); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, ZFORCE_MAX_AREA, 0, 0); input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, ZFORCE_MAX_AREA, 0, 0); input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); - input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, INPUT_MT_DIRECT); + + error = input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS, + INPUT_MT_DIRECT); + if (error) + return error; input_set_drvdata(ts->input, ts); @@ -872,58 +787,52 @@ static int zforce_probe(struct i2c_client *client) * Therefore we can trigger the interrupt anytime it is low and do * not need to limit it to the interrupt edge. */ - ret = devm_request_threaded_irq(&client->dev, client->irq, - zforce_irq, zforce_irq_thread, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - input_dev->name, ts); - if (ret) { - dev_err(&client->dev, "irq %d request failed\n", client->irq); - return ret; - } + error = devm_request_threaded_irq(&client->dev, client->irq, + zforce_irq, zforce_irq_thread, + IRQF_ONESHOT, input_dev->name, ts); + if (error) + return dev_err_probe(&client->dev, error, + "irq %d request failed\n", client->irq); i2c_set_clientdata(client, ts); /* let the controller boot */ - zforce_reset_deassert(ts); + gpiod_set_value_cansleep(ts->gpio_rst, 0); ts->command_waiting = NOTIFICATION_BOOTCOMPLETE; if (wait_for_completion_timeout(&ts->command_done, WAIT_TIMEOUT) == 0) dev_warn(&client->dev, "bootcomplete timed out\n"); /* need to start device to get version information */ - ret = zforce_command_wait(ts, COMMAND_INITIALIZE); - if (ret) { - dev_err(&client->dev, "unable to initialize, %d\n", ret); - return ret; - } + error = zforce_command_wait(ts, COMMAND_INITIALIZE); + if (error) + return dev_err_probe(&client->dev, error, "unable to initialize\n"); /* this gets the firmware version among other information */ - ret = zforce_command_wait(ts, COMMAND_STATUS); - if (ret < 0) { - dev_err(&client->dev, "couldn't get status, %d\n", ret); + error = zforce_command_wait(ts, COMMAND_STATUS); + if (error) { + dev_err_probe(&client->dev, error, "couldn't get status\n"); zforce_stop(ts); - return ret; + return error; } /* stop device and put it into sleep until it is opened */ - ret = zforce_stop(ts); - if (ret < 0) - return ret; + error = zforce_stop(ts); + if (error) + return error; device_set_wakeup_capable(&client->dev, true); - ret = input_register_device(input_dev); - if (ret) { - dev_err(&client->dev, "could not register input device, %d\n", - ret); - return ret; - } + error = input_register_device(input_dev); + if (error) + return dev_err_probe(&client->dev, error, + "could not register input device\n"); return 0; } -static struct i2c_device_id zforce_idtable[] = { - { "zforce-ts", 0 }, +static const struct i2c_device_id zforce_idtable[] = { + { "zforce-ts" }, { } }; MODULE_DEVICE_TABLE(i2c, zforce_idtable); @@ -941,6 +850,7 @@ static struct i2c_driver zforce_driver = { .name = "zforce-ts", .pm = pm_sleep_ptr(&zforce_pm_ops), .of_match_table = of_match_ptr(zforce_dt_idtable), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = zforce_probe, .id_table = zforce_idtable, diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c index 1b4807ba4624..716d6fa60f86 100644 --- a/drivers/input/touchscreen/zinitix.c +++ b/drivers/input/touchscreen/zinitix.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/property.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> @@ -34,7 +35,13 @@ #define ZINITIX_DEBUG_REG 0x0115 /* 0~7 */ #define ZINITIX_TOUCH_MODE 0x0010 + #define ZINITIX_CHIP_REVISION 0x0011 +#define ZINITIX_CHIP_BTX0X_MASK 0xF0F0 +#define ZINITIX_CHIP_BT4X2 0x4020 +#define ZINITIX_CHIP_BT4X3 0x4030 +#define ZINITIX_CHIP_BT4X4 0x4040 + #define ZINITIX_FIRMWARE_VERSION 0x0012 #define ZINITIX_USB_DETECT 0x116 @@ -62,7 +69,11 @@ #define ZINITIX_Y_RESOLUTION 0x00C1 #define ZINITIX_POINT_STATUS_REG 0x0080 -#define ZINITIX_ICON_STATUS_REG 0x00AA + +#define ZINITIX_BT4X2_ICON_STATUS_REG 0x009A +#define ZINITIX_BT4X3_ICON_STATUS_REG 0x00A0 +#define ZINITIX_BT4X4_ICON_STATUS_REG 0x00A0 +#define ZINITIX_BT5XX_ICON_STATUS_REG 0x00AA #define ZINITIX_POINT_COORD_REG (ZINITIX_POINT_STATUS_REG + 2) @@ -119,6 +130,7 @@ #define DEFAULT_TOUCH_POINT_MODE 2 #define MAX_SUPPORTED_FINGER_NUM 5 +#define MAX_SUPPORTED_BUTTON_NUM 8 #define CHIP_ON_DELAY 15 // ms #define FIRMWARE_ON_DELAY 40 // ms @@ -146,6 +158,13 @@ struct bt541_ts_data { struct touchscreen_properties prop; struct regulator_bulk_data supplies[2]; u32 zinitix_mode; + u32 keycodes[MAX_SUPPORTED_BUTTON_NUM]; + int num_keycodes; + bool have_versioninfo; + u16 chip_revision; + u16 firmware_version; + u16 regdata_version; + u16 icon_status_reg; }; static int zinitix_read_data(struct i2c_client *client, @@ -190,11 +209,25 @@ static int zinitix_write_cmd(struct i2c_client *client, u16 reg) return 0; } +static u16 zinitix_get_u16_reg(struct bt541_ts_data *bt541, u16 vreg) +{ + struct i2c_client *client = bt541->client; + int error; + __le16 val; + + error = zinitix_read_data(client, vreg, (void *)&val, 2); + if (error) + return U8_MAX; + + return le16_to_cpu(val); +} + static int zinitix_init_touch(struct bt541_ts_data *bt541) { struct i2c_client *client = bt541->client; int i; int error; + u16 int_flags; error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); if (error) { @@ -202,6 +235,47 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541) return error; } + /* + * Read and cache the chip revision and firmware version the first time + * we get here. + */ + if (!bt541->have_versioninfo) { + bt541->chip_revision = zinitix_get_u16_reg(bt541, + ZINITIX_CHIP_REVISION); + bt541->firmware_version = zinitix_get_u16_reg(bt541, + ZINITIX_FIRMWARE_VERSION); + bt541->regdata_version = zinitix_get_u16_reg(bt541, + ZINITIX_DATA_VERSION_REG); + bt541->have_versioninfo = true; + + dev_dbg(&client->dev, + "chip revision %04x firmware version %04x regdata version %04x\n", + bt541->chip_revision, bt541->firmware_version, + bt541->regdata_version); + + /* + * Determine the "icon" status register which varies by the + * chip. + */ + switch (bt541->chip_revision & ZINITIX_CHIP_BTX0X_MASK) { + case ZINITIX_CHIP_BT4X2: + bt541->icon_status_reg = ZINITIX_BT4X2_ICON_STATUS_REG; + break; + + case ZINITIX_CHIP_BT4X3: + bt541->icon_status_reg = ZINITIX_BT4X3_ICON_STATUS_REG; + break; + + case ZINITIX_CHIP_BT4X4: + bt541->icon_status_reg = ZINITIX_BT4X4_ICON_STATUS_REG; + break; + + default: + bt541->icon_status_reg = ZINITIX_BT5XX_ICON_STATUS_REG; + break; + } + } + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0); if (error) { dev_err(&client->dev, @@ -225,6 +299,11 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541) if (error) return error; + error = zinitix_write_u16(client, ZINITIX_BUTTON_SUPPORTED_NUM, + bt541->num_keycodes); + if (error) + return error; + error = zinitix_write_u16(client, ZINITIX_INITIAL_TOUCH_MODE, bt541->zinitix_mode); if (error) @@ -235,9 +314,11 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541) if (error) return error; - error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, - BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE | - BIT_UP); + int_flags = BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE | BIT_UP; + if (bt541->num_keycodes) + int_flags |= BIT_ICON_EVENT; + + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, int_flags); if (error) return error; @@ -350,12 +431,22 @@ static void zinitix_report_finger(struct bt541_ts_data *bt541, int slot, } } +static void zinitix_report_keys(struct bt541_ts_data *bt541, u16 icon_events) +{ + int i; + + for (i = 0; i < bt541->num_keycodes; i++) + input_report_key(bt541->input_dev, + bt541->keycodes[i], icon_events & BIT(i)); +} + static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler) { struct bt541_ts_data *bt541 = bt541_handler; struct i2c_client *client = bt541->client; struct touch_event touch_event; unsigned long finger_mask; + __le16 icon_events; int error; int i; @@ -368,6 +459,17 @@ static irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler) goto out; } + if (le16_to_cpu(touch_event.status) & BIT_ICON_EVENT) { + error = zinitix_read_data(bt541->client, bt541->icon_status_reg, + &icon_events, sizeof(icon_events)); + if (error) { + dev_err(&client->dev, "Failed to read icon events\n"); + goto out; + } + + zinitix_report_keys(bt541, le16_to_cpu(icon_events)); + } + finger_mask = touch_event.finger_mask; for_each_set_bit(i, &finger_mask, MAX_SUPPORTED_FINGER_NUM) { const struct point_coord *p = &touch_event.point_coord[i]; @@ -453,6 +555,7 @@ static int zinitix_init_input_dev(struct bt541_ts_data *bt541) { struct input_dev *input_dev; int error; + int i; input_dev = devm_input_allocate_device(&bt541->client->dev); if (!input_dev) { @@ -470,6 +573,14 @@ static int zinitix_init_input_dev(struct bt541_ts_data *bt541) input_dev->open = zinitix_input_open; input_dev->close = zinitix_input_close; + if (bt541->num_keycodes) { + input_dev->keycode = bt541->keycodes; + input_dev->keycodemax = bt541->num_keycodes; + input_dev->keycodesize = sizeof(bt541->keycodes[0]); + for (i = 0; i < bt541->num_keycodes; i++) + input_set_capability(input_dev, EV_KEY, bt541->keycodes[i]); + } + input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); @@ -534,6 +645,31 @@ static int zinitix_ts_probe(struct i2c_client *client) return error; } + if (device_property_present(&client->dev, "linux,keycodes")) { + bt541->num_keycodes = device_property_count_u32(&client->dev, + "linux,keycodes"); + if (bt541->num_keycodes < 0) { + dev_err(&client->dev, "Failed to count keys (%d)\n", + bt541->num_keycodes); + return bt541->num_keycodes; + } else if (bt541->num_keycodes > ARRAY_SIZE(bt541->keycodes)) { + dev_err(&client->dev, "Too many keys defined (%d)\n", + bt541->num_keycodes); + return -EINVAL; + } + + error = device_property_read_u32_array(&client->dev, + "linux,keycodes", + bt541->keycodes, + bt541->num_keycodes); + if (error) { + dev_err(&client->dev, + "Unable to parse \"linux,keycodes\" property: %d\n", + error); + return error; + } + } + error = zinitix_init_input_dev(bt541); if (error) { dev_err(&client->dev, diff --git a/drivers/input/vivaldi-fmap.c b/drivers/input/vivaldi-fmap.c index 0d29ec014e2f..978949eba9eb 100644 --- a/drivers/input/vivaldi-fmap.c +++ b/drivers/input/vivaldi-fmap.c @@ -36,4 +36,5 @@ ssize_t vivaldi_function_row_physmap_show(const struct vivaldi_data *data, } EXPORT_SYMBOL_GPL(vivaldi_function_row_physmap_show); +MODULE_DESCRIPTION("Helpers for ChromeOS Vivaldi keyboard function row mapping"); MODULE_LICENSE("GPL"); |