diff options
Diffstat (limited to 'drivers/input')
183 files changed, 5843 insertions, 3153 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 55f7e57d4e42..38b523a1ece0 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -3,7 +3,7 @@ # menu "Input device support" - depends on !S390 && !UML + depends on !UML config INPUT tristate "Generic input layer (needed for keyboard, mouse, ...)" if EXPERT diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index daceafe7ee7d..fa7a95c1da0e 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c @@ -57,7 +57,7 @@ static const struct pci_device_id emu_tbl[] = { MODULE_DEVICE_TABLE(pci, emu_tbl); -static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct emu *emu; struct gameport *port; @@ -107,7 +107,7 @@ static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id return error; } -static void __devexit emu_remove(struct pci_dev *pdev) +static void emu_remove(struct pci_dev *pdev) { struct emu *emu = pci_get_drvdata(pdev); @@ -122,7 +122,7 @@ static struct pci_driver emu_driver = { .name = "Emu10k1_gameport", .id_table = emu_tbl, .probe = emu_probe, - .remove = __devexit_p(emu_remove), + .remove = emu_remove, }; module_pci_driver(emu_driver); diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 48ad3829ff20..ae912d3aee4e 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -78,7 +78,7 @@ static int fm801_gp_open(struct gameport *gameport, int mode) return 0; } -static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id) +static int fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct fm801_gp *gp; struct gameport *port; @@ -129,7 +129,7 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device return error; } -static void __devexit fm801_gp_remove(struct pci_dev *pci) +static void fm801_gp_remove(struct pci_dev *pci) { struct fm801_gp *gp = pci_get_drvdata(pci); @@ -150,7 +150,7 @@ static struct pci_driver fm801_gp_driver = { .name = "FM801_gameport", .id_table = fm801_gp_id_table, .probe = fm801_gp_probe, - .remove = __devexit_p(fm801_gp_remove), + .remove = fm801_gp_remove, }; module_pci_driver(fm801_gp_driver); diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 8c4b50fd9a79..71db1930573f 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -18,6 +18,7 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) { if (dev->absinfo && test_bit(src, dev->absbit)) { dev->absinfo[dst] = dev->absinfo[src]; + dev->absinfo[dst].fuzz = 0; dev->absbit[BIT_WORD(dst)] |= BIT_MASK(dst); } } @@ -194,7 +195,7 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) if (!mt) return; - oldest = 0; + oldest = NULL; oldid = mt->trkid; count = 0; diff --git a/drivers/input/input.c b/drivers/input/input.c index 53a0ddee7872..c04469928925 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -534,8 +534,11 @@ EXPORT_SYMBOL(input_grab_device); static void __input_release_device(struct input_handle *handle) { struct input_dev *dev = handle->dev; + struct input_handle *grabber; - if (dev->grab == handle) { + grabber = rcu_dereference_protected(dev->grab, + lockdep_is_held(&dev->mutex)); + if (grabber == handle) { rcu_assign_pointer(dev->grab, NULL); /* Make sure input_pass_event() notices that grab is gone */ synchronize_rcu(); @@ -1723,7 +1726,7 @@ EXPORT_SYMBOL_GPL(input_class); /** * input_allocate_device - allocate memory for new input device * - * Returns prepared struct input_dev or NULL. + * Returns prepared struct input_dev or %NULL. * * NOTE: Use input_free_device() to free devices that have not been * registered; input_unregister_device() should be used for already @@ -1750,6 +1753,71 @@ struct input_dev *input_allocate_device(void) } EXPORT_SYMBOL(input_allocate_device); +struct input_devres { + struct input_dev *input; +}; + +static int devm_input_device_match(struct device *dev, void *res, void *data) +{ + struct input_devres *devres = res; + + return devres->input == data; +} + +static void devm_input_device_release(struct device *dev, void *res) +{ + struct input_devres *devres = res; + struct input_dev *input = devres->input; + + dev_dbg(dev, "%s: dropping reference to %s\n", + __func__, dev_name(&input->dev)); + input_put_device(input); +} + +/** + * devm_input_allocate_device - allocate managed input device + * @dev: device owning the input device being created + * + * Returns prepared struct input_dev or %NULL. + * + * Managed input devices do not need to be explicitly unregistered or + * freed as it will be done automatically when owner device unbinds from + * its driver (or binding fails). Once managed input device is allocated, + * it is ready to be set up and registered in the same fashion as regular + * input device. There are no special devm_input_device_[un]register() + * variants, regular ones work with both managed and unmanaged devices, + * should you need them. In most cases however, managed input device need + * not be explicitly unregistered or freed. + * + * NOTE: the owner device is set up as parent of input device and users + * should not override it. + */ +struct input_dev *devm_input_allocate_device(struct device *dev) +{ + struct input_dev *input; + struct input_devres *devres; + + devres = devres_alloc(devm_input_device_release, + sizeof(struct input_devres), GFP_KERNEL); + if (!devres) + return NULL; + + input = input_allocate_device(); + if (!input) { + devres_free(devres); + return NULL; + } + + input->dev.parent = dev; + input->devres_managed = true; + + devres->input = input; + devres_add(dev, devres); + + return input; +} +EXPORT_SYMBOL(devm_input_allocate_device); + /** * input_free_device - free memory occupied by input_dev structure * @dev: input device to free @@ -1766,8 +1834,14 @@ EXPORT_SYMBOL(input_allocate_device); */ void input_free_device(struct input_dev *dev) { - if (dev) + if (dev) { + if (dev->devres_managed) + WARN_ON(devres_destroy(dev->dev.parent, + devm_input_device_release, + devm_input_device_match, + dev)); input_put_device(dev); + } } EXPORT_SYMBOL(input_free_device); @@ -1888,6 +1962,38 @@ static void input_cleanse_bitmasks(struct input_dev *dev) INPUT_CLEANSE_BITMASK(dev, SW, sw); } +static void __input_unregister_device(struct input_dev *dev) +{ + struct input_handle *handle, *next; + + input_disconnect_device(dev); + + mutex_lock(&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)); + + del_timer_sync(&dev->timer); + list_del_init(&dev->node); + + input_wakeup_procfs_readers(); + + mutex_unlock(&input_mutex); + + device_del(&dev->dev); +} + +static void devm_input_device_unregister(struct device *dev, void *res) +{ + struct input_devres *devres = res; + struct input_dev *input = devres->input; + + dev_dbg(dev, "%s: unregistering device %s\n", + __func__, dev_name(&input->dev)); + __input_unregister_device(input); +} + /** * input_register_device - register device with input core * @dev: device to be registered @@ -1899,15 +2005,36 @@ static void input_cleanse_bitmasks(struct input_dev *dev) * Once device has been successfully registered it can be unregistered * with input_unregister_device(); input_free_device() should not be * called in this case. + * + * Note that this function is also used to register managed input devices + * (ones allocated with devm_input_allocate_device()). Such managed input + * devices need not be explicitly unregistered or freed, their tear down + * is controlled by the devres infrastructure. It is also worth noting + * that tear down of managed input devices is internally a 2-step process: + * registered managed input device is first unregistered, but stays in + * memory and can still handle input_event() calls (although events will + * not be delivered anywhere). The freeing of managed input device will + * happen later, when devres stack is unwound to the point where device + * allocation was made. */ int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); + struct input_devres *devres = NULL; struct input_handler *handler; unsigned int packet_size; const char *path; int error; + if (dev->devres_managed) { + devres = devres_alloc(devm_input_device_unregister, + sizeof(struct input_devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; + + devres->input = dev; + } + /* Every input device generates EV_SYN/SYN_REPORT events. */ __set_bit(EV_SYN, dev->evbit); @@ -1923,8 +2050,10 @@ int input_register_device(struct input_dev *dev) dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); - if (!dev->vals) - return -ENOMEM; + if (!dev->vals) { + error = -ENOMEM; + goto err_devres_free; + } /* * If delay and period are pre-set by the driver, then autorepeating @@ -1949,7 +2078,7 @@ int input_register_device(struct input_dev *dev) error = device_add(&dev->dev); if (error) - return error; + goto err_free_vals; path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL); pr_info("%s as %s\n", @@ -1958,10 +2087,8 @@ int input_register_device(struct input_dev *dev) kfree(path); error = mutex_lock_interruptible(&input_mutex); - if (error) { - device_del(&dev->dev); - return error; - } + if (error) + goto err_device_del; list_add_tail(&dev->node, &input_dev_list); @@ -1972,7 +2099,21 @@ int input_register_device(struct input_dev *dev) mutex_unlock(&input_mutex); + if (dev->devres_managed) { + dev_dbg(dev->dev.parent, "%s: registering %s with devres.\n", + __func__, dev_name(&dev->dev)); + devres_add(dev->dev.parent, devres); + } return 0; + +err_device_del: + device_del(&dev->dev); +err_free_vals: + kfree(dev->vals); + dev->vals = NULL; +err_devres_free: + devres_free(devres); + return error; } EXPORT_SYMBOL(input_register_device); @@ -1985,24 +2126,20 @@ EXPORT_SYMBOL(input_register_device); */ void input_unregister_device(struct input_dev *dev) { - struct input_handle *handle, *next; - - input_disconnect_device(dev); - - mutex_lock(&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)); - - del_timer_sync(&dev->timer); - list_del_init(&dev->node); - - input_wakeup_procfs_readers(); - - mutex_unlock(&input_mutex); - - device_unregister(&dev->dev); + if (dev->devres_managed) { + WARN_ON(devres_destroy(dev->dev.parent, + devm_input_device_unregister, + devm_input_device_match, + dev)); + __input_unregister_device(dev); + /* + * We do not do input_put_device() here because it will be done + * when 2nd devres fires up. + */ + } else { + __input_unregister_device(dev); + input_put_device(dev); + } } EXPORT_SYMBOL(input_unregister_device); diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 358cd7ee905b..7cd74e29cbc8 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -162,7 +162,7 @@ static unsigned int get_time_pit(void) #define GET_TIME(x) do { x = get_cycles(); } while (0) #define DELTA(x,y) ((y)-(x)) #define TIME_NAME "PCC" -#elif defined(CONFIG_MN10300) +#elif defined(CONFIG_MN10300) || defined(CONFIG_TILE) #define GET_TIME(x) do { x = get_cycles(); } while (0) #define DELTA(x, y) ((x) - (y)) #define TIME_NAME "TSC" diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c index c96653b58867..121cd63d3334 100644 --- a/drivers/input/joystick/as5011.c +++ b/drivers/input/joystick/as5011.c @@ -85,7 +85,10 @@ static int as5011_i2c_write(struct i2c_client *client, { uint8_t data[2] = { aregaddr, avalue }; struct i2c_msg msg = { - client->addr, I2C_M_IGNORE_NAK, 2, (uint8_t *)data + .addr = client->addr, + .flags = I2C_M_IGNORE_NAK, + .len = 2, + .buf = (uint8_t *)data }; int error; @@ -98,8 +101,18 @@ static int as5011_i2c_read(struct i2c_client *client, { uint8_t data[2] = { aregaddr }; struct i2c_msg msg_set[2] = { - { client->addr, I2C_M_REV_DIR_ADDR, 1, (uint8_t *)data }, - { client->addr, I2C_M_RD | I2C_M_NOSTART, 1, (uint8_t *)data } + { + .addr = client->addr, + .flags = I2C_M_REV_DIR_ADDR, + .len = 1, + .buf = (uint8_t *)data + }, + { + .addr = client->addr, + .flags = I2C_M_RD | I2C_M_NOSTART, + .len = 1, + .buf = (uint8_t *)data + } }; int error; @@ -144,7 +157,7 @@ out: return IRQ_HANDLED; } -static int __devinit as5011_configure_chip(struct as5011_device *as5011, +static int as5011_configure_chip(struct as5011_device *as5011, const struct as5011_platform_data *plat_dat) { struct i2c_client *client = as5011->i2c_client; @@ -212,8 +225,8 @@ static int __devinit as5011_configure_chip(struct as5011_device *as5011, return 0; } -static int __devinit as5011_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int as5011_probe(struct i2c_client *client, + const struct i2c_device_id *id) { const struct as5011_platform_data *plat_data; struct as5011_device *as5011; @@ -328,7 +341,7 @@ err_free_mem: return error; } -static int __devexit as5011_remove(struct i2c_client *client) +static int as5011_remove(struct i2c_client *client) { struct as5011_device *as5011 = i2c_get_clientdata(client); @@ -353,7 +366,7 @@ static struct i2c_driver as5011_driver = { .name = "as5011", }, .probe = as5011_probe, - .remove = __devexit_p(as5011_remove), + .remove = as5011_remove, .id_table = as5011_id, }; diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c index 77cfde571bd9..59c10ec5a2a1 100644 --- a/drivers/input/joystick/maplecontrol.c +++ b/drivers/input/joystick/maplecontrol.c @@ -78,7 +78,7 @@ static void dc_pad_close(struct input_dev *dev) } /* allow the controller to be used */ -static int __devinit probe_maple_controller(struct device *dev) +static int probe_maple_controller(struct device *dev) { static const short btn_bit[32] = { BTN_C, BTN_B, BTN_A, BTN_START, -1, -1, -1, -1, @@ -157,7 +157,7 @@ fail: return error; } -static int __devexit remove_maple_controller(struct device *dev) +static int remove_maple_controller(struct device *dev) { struct maple_device *mdev = to_maple_dev(dev); struct dc_pad *pad = maple_get_drvdata(mdev); @@ -175,7 +175,7 @@ static struct maple_driver dc_pad_driver = { .drv = { .name = "Dreamcast_controller", .probe = probe_maple_controller, - .remove = __devexit_p(remove_maple_controller), + .remove = remove_maple_controller, }, }; diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 4dfa1eed4b7c..b76ac580703c 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -12,7 +12,7 @@ * the Free Software Foundation. */ -/* #define WK0701_DEBUG */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define RESERVE 20000 #define SYNC_PULSE 1306000 @@ -67,6 +67,7 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w) { int i; int val1, val2, val3, val4, val5, val6, val7, val8; + int magic, magic_bit; int crc1, crc2; for (crc1 = crc2 = i = 0; i < 10; i++) { @@ -102,17 +103,12 @@ static inline void walkera0701_parse_frame(struct walkera_dev *w) val8 = (w->buf[18] & 1) << 8 | (w->buf[19] << 4) | w->buf[20]; val8 *= (w->buf[18] & 2) - 1; /*sign */ -#ifdef WK0701_DEBUG - { - int magic, magic_bit; - magic = (w->buf[21] << 4) | w->buf[22]; - magic_bit = (w->buf[24] & 8) >> 3; - printk(KERN_DEBUG - "walkera0701: %4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n", - val1, val2, val3, val4, val5, val6, val7, val8, magic, - magic_bit); - } -#endif + magic = (w->buf[21] << 4) | w->buf[22]; + magic_bit = (w->buf[24] & 8) >> 3; + pr_debug("%4d %4d %4d %4d %4d %4d %4d %4d (magic %2x %d)\n", + val1, val2, val3, val4, val5, val6, val7, val8, + magic, magic_bit); + input_report_abs(w->input_dev, ABS_X, val2); input_report_abs(w->input_dev, ABS_Y, val1); input_report_abs(w->input_dev, ABS_Z, val6); @@ -187,6 +183,9 @@ static int walkera0701_open(struct input_dev *dev) { struct walkera_dev *w = input_get_drvdata(dev); + if (parport_claim(w->pardevice)) + return -EBUSY; + parport_enable_irq(w->parport); return 0; } @@ -196,37 +195,52 @@ static void walkera0701_close(struct input_dev *dev) struct walkera_dev *w = input_get_drvdata(dev); parport_disable_irq(w->parport); + hrtimer_cancel(&w->timer); + + parport_release(w->pardevice); } static int walkera0701_connect(struct walkera_dev *w, int parport) { - int err = -ENODEV; + int error; w->parport = parport_find_number(parport); - if (w->parport == NULL) + if (!w->parport) { + pr_err("parport %d does not exist\n", parport); return -ENODEV; + } if (w->parport->irq == -1) { - printk(KERN_ERR "walkera0701: parport without interrupt\n"); - goto init_err; + pr_err("parport %d does not have interrupt assigned\n", + parport); + error = -EINVAL; + goto err_put_parport; } - err = -EBUSY; w->pardevice = parport_register_device(w->parport, "walkera0701", NULL, NULL, walkera0701_irq_handler, PARPORT_DEV_EXCL, w); - if (!w->pardevice) - goto init_err; + if (!w->pardevice) { + pr_err("failed to register parport device\n"); + error = -EIO; + goto err_put_parport; + } - if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) - goto init_err1; + if (parport_negotiate(w->pardevice->port, IEEE1284_MODE_COMPAT)) { + pr_err("failed to negotiate parport mode\n"); + error = -EIO; + goto err_unregister_device; + } - if (parport_claim(w->pardevice)) - goto init_err1; + hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + w->timer.function = timer_handler; w->input_dev = input_allocate_device(); - if (!w->input_dev) - goto init_err2; + if (!w->input_dev) { + pr_err("failed to allocate input device\n"); + error = -ENOMEM; + goto err_unregister_device; + } input_set_drvdata(w->input_dev, w); w->input_dev->name = "Walkera WK-0701 TX"; @@ -237,6 +251,7 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) w->input_dev->id.vendor = 0x0001; w->input_dev->id.product = 0x0001; w->input_dev->id.version = 0x0100; + w->input_dev->dev.parent = w->parport->dev; w->input_dev->open = walkera0701_open; w->input_dev->close = walkera0701_close; @@ -250,30 +265,26 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) input_set_abs_params(w->input_dev, ABS_RUDDER, -512, 512, 0, 0); input_set_abs_params(w->input_dev, ABS_MISC, -512, 512, 0, 0); - err = input_register_device(w->input_dev); - if (err) - goto init_err3; + error = input_register_device(w->input_dev); + if (error) { + pr_err("failed to register input device\n"); + goto err_free_input_dev; + } - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; return 0; - init_err3: +err_free_input_dev: input_free_device(w->input_dev); - init_err2: - parport_release(w->pardevice); - init_err1: +err_unregister_device: parport_unregister_device(w->pardevice); - init_err: +err_put_parport: parport_put_port(w->parport); - return err; + return error; } static void walkera0701_disconnect(struct walkera_dev *w) { - hrtimer_cancel(&w->timer); input_unregister_device(w->input_dev); - parport_release(w->pardevice); parport_unregister_device(w->pardevice); parport_put_port(w->parport); } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 83811e45d633..d6cbfe9df218 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -118,11 +118,12 @@ static const struct xpad_device { u8 xtype; } xpad_device[] = { { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, - { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, + { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, + { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, - { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, @@ -136,9 +137,12 @@ static const struct xpad_device { { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", XTYPE_XBOX360 }, { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, + { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, @@ -148,24 +152,28 @@ static const struct xpad_device { { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, - { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, + { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 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 }, - { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, - { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, + { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -235,7 +243,7 @@ static const signed short xpad_abs_triggers[] = { { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } -static struct usb_device_id xpad_table [] = { +static struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ @@ -248,10 +256,11 @@ static struct usb_device_id xpad_table [] = { XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ + XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ { } }; -MODULE_DEVICE_TABLE (usb, xpad_table); +MODULE_DEVICE_TABLE(usb, xpad_table); struct usb_xpad { struct input_dev *dev; /* input device interface */ @@ -783,7 +792,7 @@ static int xpad_open(struct input_dev *dev) struct usb_xpad *xpad = input_get_drvdata(dev); /* URB was submitted in probe */ - if(xpad->xtype == XTYPE_XBOX360W) + if (xpad->xtype == XTYPE_XBOX360W) return 0; xpad->irq_in->dev = xpad->udev; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 77629d33f03f..ac0500667000 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -134,7 +134,7 @@ config KEYBOARD_QT1070 config KEYBOARD_QT2160 tristate "Atmel AT42QT2160 Touch Sensor Chip" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for Atmel AT42QT2160 Touch Sensor chip as a keyboard input. @@ -224,7 +224,7 @@ config KEYBOARD_TCA6416 config KEYBOARD_TCA8418 tristate "TCA8418 Keypad Support" - depends on I2C + depends on I2C && GENERIC_HARDIRQS select INPUT_MATRIXKMAP help This driver implements basic keypad functionality @@ -303,7 +303,7 @@ config KEYBOARD_HP7XX config KEYBOARD_LM8323 tristate "LM8323 keypad chip" - depends on I2C + depends on I2C && GENERIC_HARDIRQS depends on LEDS_CLASS help If you say yes here you get support for the National Semiconductor @@ -420,7 +420,7 @@ config KEYBOARD_NOMADIK config KEYBOARD_TEGRA tristate "NVIDIA Tegra internal matrix keyboard controller support" - depends on ARCH_TEGRA + depends on ARCH_TEGRA && OF select INPUT_MATRIXKMAP help Say Y here if you want to use a matrix keyboard connected directly @@ -479,6 +479,16 @@ config KEYBOARD_SAMSUNG To compile this driver as a module, choose M here: the module will be called samsung-keypad. +config KEYBOARD_GOLDFISH_EVENTS + depends on GOLDFISH + tristate "Generic Input Event device for Goldfish" + help + Say Y here to get an input event device for the Goldfish virtual + device emulator. + + To compile this driver as a module, choose M here: the + module will be called goldfish-events. + config KEYBOARD_STOWAWAY tristate "Stowaway keyboard" select SERIO @@ -544,6 +554,7 @@ config KEYBOARD_OMAP config KEYBOARD_OMAP4 tristate "TI OMAP4+ keypad support" + depends on ARCH_OMAP2PLUS select INPUT_MATRIXKMAP help Say Y here if you want to use the OMAP4+ keypad. diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 44e76002f54b..49b16453d00e 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o obj-$(CONFIG_KEYBOARD_TCA6416) += tca6416-keypad.o diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c index e9e8674dfda1..ef26b17fb159 100644 --- a/drivers/input/keyboard/adp5520-keys.c +++ b/drivers/input/keyboard/adp5520-keys.c @@ -69,7 +69,7 @@ static int adp5520_keys_notifier(struct notifier_block *nb, return 0; } -static int __devinit adp5520_keys_probe(struct platform_device *pdev) +static int adp5520_keys_probe(struct platform_device *pdev) { struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input; @@ -182,7 +182,7 @@ err: return ret; } -static int __devexit adp5520_keys_remove(struct platform_device *pdev) +static int adp5520_keys_remove(struct platform_device *pdev) { struct adp5520_keys *dev = platform_get_drvdata(pdev); @@ -200,7 +200,7 @@ static struct platform_driver adp5520_keys_driver = { .owner = THIS_MODULE, }, .probe = adp5520_keys_probe, - .remove = __devexit_p(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 b083bf10f139..dbd2047f1641 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -145,7 +145,7 @@ static int adp5588_gpio_direction_output(struct gpio_chip *chip, return ret; } -static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad, +static int adp5588_build_gpiomap(struct adp5588_kpad *kpad, const struct adp5588_kpad_platform_data *pdata) { bool pin_used[ADP5588_MAXGPIO]; @@ -170,7 +170,7 @@ static int __devinit adp5588_build_gpiomap(struct adp5588_kpad *kpad, return n_unused; } -static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad) +static int adp5588_gpio_add(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; const struct adp5588_kpad_platform_data *pdata = dev->platform_data; @@ -224,7 +224,7 @@ static int __devinit adp5588_gpio_add(struct adp5588_kpad *kpad) return 0; } -static void __devexit adp5588_gpio_remove(struct adp5588_kpad *kpad) +static void adp5588_gpio_remove(struct adp5588_kpad *kpad) { struct device *dev = &kpad->client->dev; const struct adp5588_kpad_platform_data *pdata = dev->platform_data; @@ -319,7 +319,7 @@ static irqreturn_t adp5588_irq(int irq, void *handle) return IRQ_HANDLED; } -static int __devinit adp5588_setup(struct i2c_client *client) +static int adp5588_setup(struct i2c_client *client) { const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; const struct adp5588_gpio_platform_data *gpio_data = pdata->gpio_data; @@ -382,7 +382,7 @@ static int __devinit adp5588_setup(struct i2c_client *client) return 0; } -static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad) +static void adp5588_report_switch_state(struct adp5588_kpad *kpad) { int gpi_stat1 = adp5588_read(kpad->client, GPIO_DAT_STAT1); int gpi_stat2 = adp5588_read(kpad->client, GPIO_DAT_STAT2); @@ -420,8 +420,8 @@ static void __devinit adp5588_report_switch_state(struct adp5588_kpad *kpad) } -static int __devinit adp5588_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5588_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct adp5588_kpad *kpad; const struct adp5588_kpad_platform_data *pdata = client->dev.platform_data; @@ -587,7 +587,7 @@ static int __devinit adp5588_probe(struct i2c_client *client, return error; } -static int __devexit adp5588_remove(struct i2c_client *client) +static int adp5588_remove(struct i2c_client *client) { struct adp5588_kpad *kpad = i2c_get_clientdata(client); @@ -650,7 +650,7 @@ static struct i2c_driver adp5588_driver = { #endif }, .probe = adp5588_probe, - .remove = __devexit_p(adp5588_remove), + .remove = adp5588_remove, .id_table = adp5588_id, }; diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c index 74e603213386..67d12b3427c9 100644 --- a/drivers/input/keyboard/adp5589-keys.c +++ b/drivers/input/keyboard/adp5589-keys.c @@ -464,7 +464,7 @@ static int adp5589_gpio_direction_output(struct gpio_chip *chip, return ret; } -static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad, +static int adp5589_build_gpiomap(struct adp5589_kpad *kpad, const struct adp5589_kpad_platform_data *pdata) { bool pin_used[ADP5589_MAXGPIO]; @@ -496,7 +496,7 @@ static int __devinit adp5589_build_gpiomap(struct adp5589_kpad *kpad, return n_unused; } -static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad) +static int adp5589_gpio_add(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; const struct adp5589_kpad_platform_data *pdata = dev->platform_data; @@ -550,7 +550,7 @@ static int __devinit adp5589_gpio_add(struct adp5589_kpad *kpad) return 0; } -static void __devexit adp5589_gpio_remove(struct adp5589_kpad *kpad) +static void adp5589_gpio_remove(struct adp5589_kpad *kpad) { struct device *dev = &kpad->client->dev; const struct adp5589_kpad_platform_data *pdata = dev->platform_data; @@ -641,8 +641,7 @@ static irqreturn_t adp5589_irq(int irq, void *handle) return IRQ_HANDLED; } -static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, - unsigned short key) +static int adp5589_get_evcode(struct adp5589_kpad *kpad, unsigned short key) { int i; @@ -655,7 +654,7 @@ static int __devinit adp5589_get_evcode(struct adp5589_kpad *kpad, return -EINVAL; } -static int __devinit adp5589_setup(struct adp5589_kpad *kpad) +static int adp5589_setup(struct adp5589_kpad *kpad) { struct i2c_client *client = kpad->client; const struct adp5589_kpad_platform_data *pdata = @@ -820,7 +819,7 @@ static int __devinit adp5589_setup(struct adp5589_kpad *kpad) return 0; } -static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad) +static void adp5589_report_switch_state(struct adp5589_kpad *kpad) { int gpi_stat_tmp, pin_loc; int i; @@ -860,8 +859,8 @@ static void __devinit adp5589_report_switch_state(struct adp5589_kpad *kpad) input_sync(kpad->input); } -static int __devinit adp5589_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int adp5589_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct adp5589_kpad *kpad; const struct adp5589_kpad_platform_data *pdata = @@ -1045,7 +1044,7 @@ err_free_mem: return error; } -static int __devexit adp5589_remove(struct i2c_client *client) +static int adp5589_remove(struct i2c_client *client) { struct adp5589_kpad *kpad = i2c_get_clientdata(client); @@ -1104,7 +1103,7 @@ static struct i2c_driver adp5589_driver = { .pm = &adp5589_dev_pm_ops, }, .probe = adp5589_probe, - .remove = __devexit_p(adp5589_remove), + .remove = adp5589_remove, .id_table = adp5589_id, }; diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index add5ffd9fe26..2626773ff29b 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -676,6 +676,39 @@ static inline void atkbd_disable(struct atkbd *atkbd) serio_continue_rx(atkbd->ps2dev.serio); } +static int atkbd_activate(struct atkbd *atkbd) +{ + struct ps2dev *ps2dev = &atkbd->ps2dev; + +/* + * Enable the keyboard to receive keystrokes. + */ + + if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { + dev_err(&ps2dev->serio->dev, + "Failed to enable keyboard on %s\n", + ps2dev->serio->phys); + return -1; + } + + return 0; +} + +/* + * atkbd_deactivate() resets and disables the keyboard from sending + * keystrokes. + */ + +static void atkbd_deactivate(struct atkbd *atkbd) +{ + struct ps2dev *ps2dev = &atkbd->ps2dev; + + if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_DIS)) + dev_err(&ps2dev->serio->dev, + "Failed to deactivate keyboard on %s\n", + ps2dev->serio->phys); +} + /* * atkbd_probe() probes for an AT keyboard on a serio port. */ @@ -726,11 +759,17 @@ static int atkbd_probe(struct atkbd *atkbd) if (atkbd->id == 0xaca1 && atkbd->translated) { dev_err(&ps2dev->serio->dev, - "NCD terminal keyboards are only supported on non-translating controlelrs. " + "NCD terminal keyboards are only supported on non-translating controllers. " "Use i8042.direct=1 to disable translation.\n"); return -1; } +/* + * Make sure nothing is coming from the keyboard and disturbs our + * internal state. + */ + atkbd_deactivate(atkbd); + return 0; } @@ -825,24 +864,6 @@ static int atkbd_reset_state(struct atkbd *atkbd) return 0; } -static int atkbd_activate(struct atkbd *atkbd) -{ - struct ps2dev *ps2dev = &atkbd->ps2dev; - -/* - * Enable the keyboard to receive keystrokes. - */ - - if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { - dev_err(&ps2dev->serio->dev, - "Failed to enable keyboard on %s\n", - ps2dev->serio->phys); - return -1; - } - - return 0; -} - /* * atkbd_cleanup() restores the keyboard state so that BIOS is happy after a * reboot. @@ -1150,7 +1171,6 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra); atkbd_reset_state(atkbd); - atkbd_activate(atkbd); } else { atkbd->set = 2; @@ -1165,6 +1185,8 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) goto fail3; atkbd_enable(atkbd); + if (serio->write) + atkbd_activate(atkbd); err = input_register_device(atkbd->dev); if (err) @@ -1208,8 +1230,6 @@ static int atkbd_reconnect(struct serio *serio) if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) goto out; - atkbd_activate(atkbd); - /* * Restore LED state and repeat rate. While input core * will do this for us at resume time reconnect may happen @@ -1223,7 +1243,17 @@ static int atkbd_reconnect(struct serio *serio) } + /* + * Reset our state machine in case reconnect happened in the middle + * of multi-byte scancode. + */ + atkbd->xl_bit = 0; + atkbd->emul = 0; + atkbd_enable(atkbd); + if (atkbd->write) + atkbd_activate(atkbd); + retval = 0; out: diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 8eb9116e0a5f..20b9fa91fb9e 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -177,7 +177,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit bfin_kpad_probe(struct platform_device *pdev) +static int bfin_kpad_probe(struct platform_device *pdev) { struct bf54x_kpad *bf54x_kpad; struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; @@ -331,7 +331,7 @@ out: return error; } -static int __devexit bfin_kpad_remove(struct platform_device *pdev) +static int bfin_kpad_remove(struct platform_device *pdev) { struct bfin_kpad_platform_data *pdata = pdev->dev.platform_data; struct bf54x_kpad *bf54x_kpad = platform_get_drvdata(pdev); @@ -390,7 +390,7 @@ static struct platform_driver bfin_kpad_device_driver = { .owner = THIS_MODULE, }, .probe = bfin_kpad_probe, - .remove = __devexit_p(bfin_kpad_remove), + .remove = bfin_kpad_remove, .suspend = bfin_kpad_suspend, .resume = bfin_kpad_resume, }; diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c index d5bacbb479b0..4e4e453ea15e 100644 --- a/drivers/input/keyboard/davinci_keyscan.c +++ b/drivers/input/keyboard/davinci_keyscan.c @@ -303,7 +303,7 @@ fail1: return error; } -static int __devexit davinci_ks_remove(struct platform_device *pdev) +static int davinci_ks_remove(struct platform_device *pdev) { struct davinci_ks *davinci_ks = platform_get_drvdata(pdev); @@ -326,7 +326,7 @@ static struct platform_driver davinci_ks_driver = { .name = "davinci_keyscan", .owner = THIS_MODULE, }, - .remove = __devexit_p(davinci_ks_remove), + .remove = davinci_ks_remove, }; static int __init davinci_ks_init(void) diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 7363402de8d4..9857e8fd0987 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -232,7 +232,7 @@ static int ep93xx_keypad_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops, ep93xx_keypad_suspend, ep93xx_keypad_resume); -static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) +static int ep93xx_keypad_probe(struct platform_device *pdev) { struct ep93xx_keypad *keypad; const struct matrix_keymap_data *keymap_data; @@ -346,7 +346,7 @@ failed_free: return err; } -static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) +static int ep93xx_keypad_remove(struct platform_device *pdev) { struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; @@ -380,7 +380,7 @@ static struct platform_driver ep93xx_keypad_driver = { .pm = &ep93xx_keypad_pm_ops, }, .probe = ep93xx_keypad_probe, - .remove = __devexit_p(ep93xx_keypad_remove), + .remove = ep93xx_keypad_remove, }; module_platform_driver(ep93xx_keypad_driver); diff --git a/drivers/input/keyboard/goldfish_events.c b/drivers/input/keyboard/goldfish_events.c new file mode 100644 index 000000000000..9f60a2ec88db --- /dev/null +++ b/drivers/input/keyboard/goldfish_events.c @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2007 Google, Inc. + * Copyright (C) 2012 Intel, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/types.h> +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/io.h> + +enum { + REG_READ = 0x00, + REG_SET_PAGE = 0x00, + REG_LEN = 0x04, + REG_DATA = 0x08, + + PAGE_NAME = 0x00000, + PAGE_EVBITS = 0x10000, + PAGE_ABSDATA = 0x20000 | EV_ABS, +}; + +struct event_dev { + struct input_dev *input; + int irq; + void __iomem *addr; + char name[0]; +}; + +static irqreturn_t events_interrupt(int irq, void *dev_id) +{ + struct event_dev *edev = dev_id; + unsigned type, code, value; + + type = __raw_readl(edev->addr + REG_READ); + code = __raw_readl(edev->addr + REG_READ); + value = __raw_readl(edev->addr + REG_READ); + + input_event(edev->input, type, code, value); + input_sync(edev->input); + return IRQ_HANDLED; +} + +static void events_import_bits(struct event_dev *edev, + unsigned long bits[], unsigned type, size_t count) +{ + void __iomem *addr = edev->addr; + int i, j; + size_t size; + uint8_t val; + + __raw_writel(PAGE_EVBITS | type, addr + REG_SET_PAGE); + + size = __raw_readl(addr + REG_LEN) * 8; + if (size < count) + count = size; + + addr += REG_DATA; + for (i = 0; i < count; i += 8) { + val = __raw_readb(addr++); + for (j = 0; j < 8; j++) + if (val & 1 << j) + set_bit(i + j, bits); + } +} + +static void events_import_abs_params(struct event_dev *edev) +{ + struct input_dev *input_dev = edev->input; + void __iomem *addr = edev->addr; + u32 val[4]; + int count; + int i, j; + + __raw_writel(PAGE_ABSDATA, addr + REG_SET_PAGE); + + count = __raw_readl(addr + REG_LEN) / sizeof(val); + if (count > ABS_MAX) + count = ABS_MAX; + + for (i = 0; i < count; i++) { + if (!test_bit(i, input_dev->absbit)) + continue; + + for (j = 0; j < ARRAY_SIZE(val); j++) { + int offset = (i * ARRAY_SIZE(val) + j) * sizeof(u32); + val[j] = __raw_readl(edev->addr + REG_DATA + offset); + } + + input_set_abs_params(input_dev, i, + val[0], val[1], val[2], val[3]); + } +} + +static int events_probe(struct platform_device *pdev) +{ + struct input_dev *input_dev; + struct event_dev *edev; + struct resource *res; + unsigned keymapnamelen; + void __iomem *addr; + int irq; + int i; + int error; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -EINVAL; + + addr = devm_ioremap(&pdev->dev, res->start, 4096); + if (!addr) + return -ENOMEM; + + __raw_writel(PAGE_NAME, addr + REG_SET_PAGE); + keymapnamelen = __raw_readl(addr + REG_LEN); + + edev = devm_kzalloc(&pdev->dev, + sizeof(struct event_dev) + keymapnamelen + 1, + GFP_KERNEL); + if (!edev) + return -ENOMEM; + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) + return -ENOMEM; + + edev->input = input_dev; + edev->addr = addr; + edev->irq = irq; + + for (i = 0; i < keymapnamelen; i++) + edev->name[i] = __raw_readb(edev->addr + REG_DATA + i); + + pr_debug("events_probe() keymap=%s\n", edev->name); + + input_dev->name = edev->name; + input_dev->id.bustype = BUS_HOST; + + events_import_bits(edev, input_dev->evbit, EV_SYN, EV_MAX); + events_import_bits(edev, input_dev->keybit, EV_KEY, KEY_MAX); + events_import_bits(edev, input_dev->relbit, EV_REL, REL_MAX); + events_import_bits(edev, input_dev->absbit, EV_ABS, ABS_MAX); + events_import_bits(edev, input_dev->mscbit, EV_MSC, MSC_MAX); + events_import_bits(edev, input_dev->ledbit, EV_LED, LED_MAX); + events_import_bits(edev, input_dev->sndbit, EV_SND, SND_MAX); + events_import_bits(edev, input_dev->ffbit, EV_FF, FF_MAX); + events_import_bits(edev, input_dev->swbit, EV_SW, SW_MAX); + + events_import_abs_params(edev); + + error = devm_request_irq(&pdev->dev, edev->irq, events_interrupt, 0, + "goldfish-events-keypad", edev); + if (error) + return error; + + error = input_register_device(input_dev); + if (error) + return error; + + return 0; +} + +static struct platform_driver events_driver = { + .probe = events_probe, + .driver = { + .owner = THIS_MODULE, + .name = "goldfish_events", + }, +}; + +module_platform_driver(events_driver); + +MODULE_AUTHOR("Brian Swetland"); +MODULE_DESCRIPTION("Goldfish Event Device"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6a68041c261d..b29ca651a395 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -423,10 +423,10 @@ out: return IRQ_HANDLED; } -static int __devinit gpio_keys_setup_key(struct platform_device *pdev, - struct input_dev *input, - struct gpio_button_data *bdata, - const struct gpio_keys_button *button) +static int gpio_keys_setup_key(struct platform_device *pdev, + struct input_dev *input, + struct gpio_button_data *bdata, + const struct gpio_keys_button *button) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; @@ -440,21 +440,13 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, if (gpio_is_valid(button->gpio)) { - error = gpio_request(button->gpio, desc); + error = gpio_request_one(button->gpio, GPIOF_IN, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); return error; } - error = gpio_direction_input(button->gpio); - if (error < 0) { - dev_err(dev, - "Failed to configure direction for GPIO %d, error %d\n", - button->gpio, error); - goto fail; - } - if (button->debounce_interval) { error = gpio_set_debounce(button->gpio, button->debounce_interval * 1000); @@ -526,12 +518,35 @@ fail: return error; } +static void gpio_keys_report_state(struct gpio_keys_drvdata *ddata) +{ + struct input_dev *input = ddata->input; + int i; + + for (i = 0; i < ddata->pdata->nbuttons; i++) { + struct gpio_button_data *bdata = &ddata->data[i]; + if (gpio_is_valid(bdata->button->gpio)) + gpio_keys_gpio_report_event(bdata); + } + input_sync(input); +} + static int gpio_keys_open(struct input_dev *input) { struct gpio_keys_drvdata *ddata = input_get_drvdata(input); const struct gpio_keys_platform_data *pdata = ddata->pdata; + int error; - return pdata->enable ? pdata->enable(input->dev.parent) : 0; + if (pdata->enable) { + error = pdata->enable(input->dev.parent); + if (error) + return error; + } + + /* Report current state of buttons that are connected to GPIOs */ + gpio_keys_report_state(ddata); + + return 0; } static void gpio_keys_close(struct input_dev *input) @@ -551,7 +566,7 @@ static void gpio_keys_close(struct input_dev *input) /* * Translate OpenFirmware node properties into platform_data */ -static struct gpio_keys_platform_data * __devinit +static struct gpio_keys_platform_data * gpio_keys_get_devtree_pdata(struct device *dev) { struct device_node *node, *pp; @@ -587,6 +602,7 @@ gpio_keys_get_devtree_pdata(struct device *dev) i = 0; for_each_child_of_node(node, pp) { + int gpio; enum of_gpio_flags flags; if (!of_find_property(pp, "gpios", NULL)) { @@ -595,9 +611,19 @@ gpio_keys_get_devtree_pdata(struct device *dev) continue; } + gpio = of_get_gpio_flags(pp, 0, &flags); + if (gpio < 0) { + error = gpio; + if (error != -EPROBE_DEFER) + dev_err(dev, + "Failed to get gpio flags, error: %d\n", + error); + goto err_free_pdata; + } + button = &pdata->buttons[i++]; - button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->gpio = gpio; button->active_low = flags & OF_GPIO_ACTIVE_LOW; if (of_property_read_u32(pp, "linux,code", &button->code)) { @@ -658,7 +684,7 @@ static void gpio_remove_key(struct gpio_button_data *bdata) gpio_free(bdata->button->gpio); } -static int __devinit gpio_keys_probe(struct platform_device *pdev) +static int gpio_keys_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); @@ -731,14 +757,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) goto fail3; } - /* get current state of buttons that are connected to GPIOs */ - for (i = 0; i < pdata->nbuttons; i++) { - struct gpio_button_data *bdata = &ddata->data[i]; - if (gpio_is_valid(bdata->button->gpio)) - gpio_keys_gpio_report_event(bdata); - } - input_sync(input); - device_init_wakeup(&pdev->dev, wakeup); return 0; @@ -760,7 +778,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) return error; } -static int __devexit gpio_keys_remove(struct platform_device *pdev) +static int gpio_keys_remove(struct platform_device *pdev) { struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); struct input_dev *input = ddata->input; @@ -788,6 +806,7 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) static int gpio_keys_suspend(struct device *dev) { struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev); + struct input_dev *input = ddata->input; int i; if (device_may_wakeup(dev)) { @@ -796,6 +815,11 @@ static int gpio_keys_suspend(struct device *dev) if (bdata->button->wakeup) enable_irq_wake(bdata->irq); } + } else { + mutex_lock(&input->mutex); + if (input->users) + gpio_keys_close(input); + mutex_unlock(&input->mutex); } return 0; @@ -804,18 +828,27 @@ static int gpio_keys_suspend(struct device *dev) 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 i; - for (i = 0; i < ddata->pdata->nbuttons; i++) { - struct gpio_button_data *bdata = &ddata->data[i]; - if (bdata->button->wakeup && device_may_wakeup(dev)) - disable_irq_wake(bdata->irq); - - if (gpio_is_valid(bdata->button->gpio)) - gpio_keys_gpio_report_event(bdata); + if (device_may_wakeup(dev)) { + for (i = 0; i < ddata->pdata->nbuttons; i++) { + struct gpio_button_data *bdata = &ddata->data[i]; + if (bdata->button->wakeup) + disable_irq_wake(bdata->irq); + } + } else { + mutex_lock(&input->mutex); + if (input->users) + error = gpio_keys_open(input); + mutex_unlock(&input->mutex); } - input_sync(ddata->input); + if (error) + return error; + + gpio_keys_report_state(ddata); return 0; } #endif @@ -824,7 +857,7 @@ static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume); static struct platform_driver gpio_keys_device_driver = { .probe = gpio_keys_probe, - .remove = __devexit_p(gpio_keys_remove), + .remove = gpio_keys_remove, .driver = { .name = "gpio-keys", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c index f2142de789e7..21147164874d 100644 --- a/drivers/input/keyboard/gpio_keys_polled.c +++ b/drivers/input/keyboard/gpio_keys_polled.c @@ -103,8 +103,7 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev) } #ifdef CONFIG_OF -static struct gpio_keys_platform_data * __devinit -gpio_keys_polled_get_devtree_pdata(struct device *dev) +static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev) { struct device_node *node, *pp; struct gpio_keys_platform_data *pdata; @@ -136,6 +135,7 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev) i = 0; for_each_child_of_node(node, pp) { + int gpio; enum of_gpio_flags flags; if (!of_find_property(pp, "gpios", NULL)) { @@ -144,9 +144,19 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev) continue; } + gpio = of_get_gpio_flags(pp, 0, &flags); + if (gpio < 0) { + error = gpio; + if (error != -EPROBE_DEFER) + dev_err(dev, + "Failed to get gpio flags, error: %d\n", + error); + goto err_free_pdata; + } + button = &pdata->buttons[i++]; - button->gpio = of_get_gpio_flags(pp, 0, &flags); + button->gpio = gpio; button->active_low = flags & OF_GPIO_ACTIVE_LOW; if (of_property_read_u32(pp, "linux,code", &button->code)) { @@ -196,7 +206,7 @@ gpio_keys_polled_get_devtree_pdata(struct device *dev) } #endif -static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) +static int gpio_keys_polled_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct gpio_keys_platform_data *pdata = dev_get_platdata(dev); @@ -246,7 +256,6 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) input = poll_dev->input; - input->evbit[0] = BIT(EV_KEY); input->name = pdev->name; input->phys = DRV_NAME"/input0"; input->dev.parent = &pdev->dev; @@ -256,6 +265,10 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) input->id.product = 0x0001; input->id.version = 0x0100; + __set_bit(EV_KEY, input->evbit); + if (pdata->rep) + __set_bit(EV_REP, input->evbit); + for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_keys_button_data *bdata = &bdev->data[i]; @@ -268,22 +281,14 @@ static int __devinit gpio_keys_polled_probe(struct platform_device *pdev) goto err_free_gpio; } - error = gpio_request(gpio, - button->desc ? button->desc : DRV_NAME); + error = gpio_request_one(gpio, GPIOF_IN, + button->desc ?: DRV_NAME); if (error) { dev_err(dev, "unable to claim gpio %u, err=%d\n", gpio, error); goto err_free_gpio; } - error = gpio_direction_input(gpio); - if (error) { - dev_err(dev, - "unable to set direction on gpio %u, err=%d\n", - gpio, error); - goto err_free_gpio; - } - bdata->can_sleep = gpio_cansleep(gpio); bdata->last_state = -1; bdata->threshold = DIV_ROUND_UP(button->debounce_interval, @@ -329,7 +334,7 @@ err_free_pdata: return error; } -static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) +static int gpio_keys_polled_remove(struct platform_device *pdev) { struct gpio_keys_polled_dev *bdev = platform_get_drvdata(pdev); const struct gpio_keys_platform_data *pdata = bdev->pdata; @@ -357,7 +362,7 @@ static int __devexit gpio_keys_polled_remove(struct platform_device *pdev) static struct platform_driver gpio_keys_polled_driver = { .probe = gpio_keys_polled_probe, - .remove = __devexit_p(gpio_keys_polled_remove), + .remove = gpio_keys_polled_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c index 5f72440b50c8..198dc07a1be5 100644 --- a/drivers/input/keyboard/hilkbd.c +++ b/drivers/input/keyboard/hilkbd.c @@ -200,7 +200,7 @@ static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len) /* initialize HIL */ -static int __devinit hil_keyb_init(void) +static int hil_keyb_init(void) { unsigned char c; unsigned int i, kbid; @@ -286,7 +286,7 @@ err1: return err; } -static void __devexit hil_keyb_exit(void) +static void hil_keyb_exit(void) { if (HIL_IRQ) free_irq(HIL_IRQ, hil_dev.dev_id); @@ -299,7 +299,7 @@ static void __devexit hil_keyb_exit(void) } #if defined(CONFIG_PARISC) -static int __devinit hil_probe_chip(struct parisc_device *dev) +static int hil_probe_chip(struct parisc_device *dev) { /* Only allow one HIL keyboard */ if (hil_dev.dev) @@ -320,7 +320,7 @@ static int __devinit hil_probe_chip(struct parisc_device *dev) return hil_keyb_init(); } -static int __devexit hil_remove_chip(struct parisc_device *dev) +static int hil_remove_chip(struct parisc_device *dev) { hil_keyb_exit(); @@ -341,7 +341,7 @@ static struct parisc_driver hil_driver = { .name = "hil", .id_table = hil_tbl, .probe = hil_probe_chip, - .remove = __devexit_p(hil_remove_chip), + .remove = hil_remove_chip, }; static int __init hil_init(void) diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index cdc252612c0b..98f9113251d2 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -20,6 +20,7 @@ #include <linux/jiffies.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/timer.h> @@ -362,7 +363,8 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad) writew(reg_val, keypad->mmio_base + KPSR); /* Colums as open drain and disable all rows */ - writew(0xff00, keypad->mmio_base + KPCR); + reg_val = (keypad->cols_en_mask & 0xff) << 8; + writew(reg_val, keypad->mmio_base + KPCR); } static void imx_keypad_close(struct input_dev *dev) @@ -413,15 +415,23 @@ open_err: return -EIO; } -static int __devinit imx_keypad_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct of_device_id imx_keypad_of_match[] = { + { .compatible = "fsl,imx21-kpp", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imx_keypad_of_match); +#endif + +static int imx_keypad_probe(struct platform_device *pdev) { const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; struct imx_keypad *keypad; struct input_dev *input_dev; struct resource *res; - int irq, error, i; + int irq, error, i, row, col; - if (keymap_data == NULL) { + if (!keymap_data && !pdev->dev.of_node) { dev_err(&pdev->dev, "no keymap defined\n"); return -EINVAL; } @@ -479,22 +489,6 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) goto failed_unmap; } - /* Search for rows and cols enabled */ - for (i = 0; i < keymap_data->keymap_size; i++) { - keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]); - keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]); - } - - if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || - keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { - dev_err(&pdev->dev, - "invalid key data (too many rows or colums)\n"); - error = -EINVAL; - goto failed_clock_put; - } - dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); - dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); - /* Init the Input device */ input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; @@ -511,6 +505,19 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev) goto failed_clock_put; } + /* Search for rows and cols enabled */ + for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) { + for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) { + i = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); + if (keypad->keycodes[i] != KEY_RESERVED) { + keypad->rows_en_mask |= 1 << row; + keypad->cols_en_mask |= 1 << col; + } + } + } + dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); + dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); + __set_bit(EV_REP, input_dev->evbit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); @@ -554,7 +561,7 @@ failed_rel_mem: return error; } -static int __devexit imx_keypad_remove(struct platform_device *pdev) +static int imx_keypad_remove(struct platform_device *pdev) { struct imx_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; @@ -630,9 +637,10 @@ static struct platform_driver imx_keypad_driver = { .name = "imx-keypad", .owner = THIS_MODULE, .pm = &imx_kbd_pm_ops, + .of_match_table = of_match_ptr(imx_keypad_of_match), }, .probe = imx_keypad_probe, - .remove = __devexit_p(imx_keypad_remove), + .remove = imx_keypad_remove, }; module_platform_driver(imx_keypad_driver); diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 24f3ea01c4d5..74e75a6e8deb 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c @@ -179,7 +179,7 @@ static void jornadakbd680_poll(struct input_polled_dev *dev) memcpy(jornadakbd->old_scan, jornadakbd->new_scan, JORNADA_SCAN_SIZE); } -static int __devinit jornada680kbd_probe(struct platform_device *pdev) +static int jornada680kbd_probe(struct platform_device *pdev) { struct jornadakbd *jornadakbd; struct input_polled_dev *poll_dev; @@ -240,7 +240,7 @@ static int __devinit jornada680kbd_probe(struct platform_device *pdev) } -static int __devexit jornada680kbd_remove(struct platform_device *pdev) +static int jornada680kbd_remove(struct platform_device *pdev) { struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); @@ -258,7 +258,7 @@ static struct platform_driver jornada680kbd_driver = { .owner = THIS_MODULE, }, .probe = jornada680kbd_probe, - .remove = __devexit_p(jornada680kbd_remove), + .remove = jornada680kbd_remove, }; module_platform_driver(jornada680kbd_driver); diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 9d639fa1afbd..5ceef636df2f 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c @@ -94,7 +94,7 @@ static irqreturn_t jornada720_kbd_interrupt(int irq, void *dev_id) return IRQ_HANDLED; }; -static int __devinit jornada720_kbd_probe(struct platform_device *pdev) +static int jornada720_kbd_probe(struct platform_device *pdev) { struct jornadakbd *jornadakbd; struct input_dev *input_dev; @@ -152,7 +152,7 @@ static int __devinit jornada720_kbd_probe(struct platform_device *pdev) return err; }; -static int __devexit jornada720_kbd_remove(struct platform_device *pdev) +static int jornada720_kbd_remove(struct platform_device *pdev) { struct jornadakbd *jornadakbd = platform_get_drvdata(pdev); @@ -173,6 +173,6 @@ static struct platform_driver jornada720_kbd_driver = { .owner = THIS_MODULE, }, .probe = jornada720_kbd_probe, - .remove = __devexit_p(jornada720_kbd_remove), + .remove = jornada720_kbd_remove, }; module_platform_driver(jornada720_kbd_driver); diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 39ac2787e275..0de23f41b2d3 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -398,7 +398,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm) lm8323_configure(lm); } for (i = 0; i < LM8323_NUM_PWMS; i++) { - if (ints & (1 << (INT_PWM1 + i))) { + if (ints & (INT_PWM1 << i)) { dev_vdbg(&lm->client->dev, "pwm%d engine completed\n", i); pwm_done(&lm->pwm[i]); @@ -624,7 +624,7 @@ static ssize_t lm8323_set_disable(struct device *dev, } static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable); -static int __devinit lm8323_probe(struct i2c_client *client, +static int lm8323_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct lm8323_platform_data *pdata = client->dev.platform_data; @@ -764,7 +764,7 @@ fail1: return err; } -static int __devexit lm8323_remove(struct i2c_client *client) +static int lm8323_remove(struct i2c_client *client) { struct lm8323_chip *lm = i2c_get_clientdata(client); int i; @@ -846,7 +846,7 @@ static struct i2c_driver lm8323_i2c_driver = { .pm = &lm8323_pm_ops, }, .probe = lm8323_probe, - .remove = __devexit_p(lm8323_remove), + .remove = lm8323_remove, .id_table = lm8323_id, }; MODULE_DEVICE_TABLE(i2c, lm8323_id); diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c index 081fd9effa8c..5a8ca35dc9af 100644 --- a/drivers/input/keyboard/lm8333.c +++ b/drivers/input/keyboard/lm8333.c @@ -128,7 +128,7 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data) return IRQ_HANDLED; } -static int __devinit lm8333_probe(struct i2c_client *client, +static int lm8333_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct lm8333_platform_data *pdata = client->dev.platform_data; @@ -202,7 +202,7 @@ static int __devinit lm8333_probe(struct i2c_client *client, return err; } -static int __devexit lm8333_remove(struct i2c_client *client) +static int lm8333_remove(struct i2c_client *client) { struct lm8333 *lm8333 = i2c_get_clientdata(client); @@ -225,7 +225,7 @@ static struct i2c_driver lm8333_driver = { .owner = THIS_MODULE, }, .probe = lm8333_probe, - .remove = __devexit_p(lm8333_remove), + .remove = lm8333_remove, .id_table = lm8333_id, }; module_i2c_driver(lm8333_driver); diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index b1ab29861e1c..c94d610b9d78 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); #define KEY_CENTER KEY_F15 static const unsigned char -locomokbd_keycode[LOCOMOKBD_NUMKEYS] __devinitconst = { +locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { 0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0, /* 0 - 9 */ 0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT, /* 10 - 19 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 29 */ @@ -236,7 +236,7 @@ static void locomokbd_close(struct input_dev *dev) locomo_writel(r, locomokbd->base + LOCOMO_KIC); } -static int __devinit locomokbd_probe(struct locomo_dev *dev) +static int locomokbd_probe(struct locomo_dev *dev) { struct locomokbd *locomokbd; struct input_dev *input_dev; @@ -321,7 +321,7 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) return err; } -static int __devexit locomokbd_remove(struct locomo_dev *dev) +static int locomokbd_remove(struct locomo_dev *dev) { struct locomokbd *locomokbd = locomo_get_drvdata(dev); @@ -345,7 +345,7 @@ static struct locomo_driver keyboard_driver = { }, .devid = LOCOMO_DEVID_KEYBOARD, .probe = locomokbd_probe, - .remove = __devexit_p(locomokbd_remove), + .remove = locomokbd_remove, }; static int __init locomokbd_init(void) diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c index dd786c8a7584..1b8add6cfb9d 100644 --- a/drivers/input/keyboard/lpc32xx-keys.c +++ b/drivers/input/keyboard/lpc32xx-keys.c @@ -139,7 +139,7 @@ static void lpc32xx_kscan_close(struct input_dev *dev) clk_disable_unprepare(kscandat->clk); } -static int __devinit lpc32xx_parse_dt(struct device *dev, +static int lpc32xx_parse_dt(struct device *dev, struct lpc32xx_kscan_drv *kscandat) { struct device_node *np = dev->of_node; @@ -166,7 +166,7 @@ static int __devinit lpc32xx_parse_dt(struct device *dev, return 0; } -static int __devinit lpc32xx_kscan_probe(struct platform_device *pdev) +static int lpc32xx_kscan_probe(struct platform_device *pdev) { struct lpc32xx_kscan_drv *kscandat; struct input_dev *input; @@ -310,7 +310,7 @@ err_free_mem: return error; } -static int __devexit lpc32xx_kscan_remove(struct platform_device *pdev) +static int lpc32xx_kscan_remove(struct platform_device *pdev) { struct lpc32xx_kscan_drv *kscandat = platform_get_drvdata(pdev); @@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_kscan_match); static struct platform_driver lpc32xx_kscan_driver = { .probe = lpc32xx_kscan_probe, - .remove = __devexit_p(lpc32xx_kscan_remove), + .remove = lpc32xx_kscan_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 18b72372028a..71d77192ac1e 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -23,6 +23,9 @@ #include <linux/gpio.h> #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; @@ -37,8 +40,6 @@ struct matrix_keypad { bool scan_pending; bool stopped; bool gpio_all_disabled; - - unsigned short keycodes[]; }; /* @@ -118,6 +119,7 @@ static void matrix_keypad_scan(struct work_struct *work) struct matrix_keypad *keypad = 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; @@ -153,7 +155,7 @@ static void matrix_keypad_scan(struct work_struct *work) code = MATRIX_SCAN_CODE(row, col, keypad->row_shift); input_event(input_dev, EV_MSC, MSC_SCAN, code); input_report_key(input_dev, - keypad->keycodes[code], + keycodes[code], new_state[col] & (1 << row)); } } @@ -299,8 +301,8 @@ static int matrix_keypad_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, matrix_keypad_suspend, matrix_keypad_resume); -static int __devinit matrix_keypad_init_gpio(struct platform_device *pdev, - struct matrix_keypad *keypad) +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, err; @@ -394,33 +396,95 @@ static void matrix_keypad_free_gpio(struct matrix_keypad *keypad) gpio_free(pdata->col_gpios[i]); } -static int __devinit matrix_keypad_probe(struct platform_device *pdev) +#ifdef CONFIG_OF +static struct matrix_keypad_platform_data * +matrix_keypad_parse_dt(struct device *dev) +{ + struct matrix_keypad_platform_data *pdata; + struct device_node *np = dev->of_node; + unsigned int *gpios; + int 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 = of_gpio_named_count(np, "row-gpios"); + pdata->num_col_gpios = ncol = of_gpio_named_count(np, "col-gpios"); + if (nrow <= 0 || ncol <= 0) { + dev_err(dev, "number of keypad rows/columns not specified\n"); + return ERR_PTR(-EINVAL); + } + + if (of_get_property(np, "linux,no-autorepeat", NULL)) + pdata->no_autorepeat = true; + if (of_get_property(np, "linux,wakeup", NULL)) + pdata->wakeup = true; + if (of_get_property(np, "gpio-activelow", NULL)) + pdata->active_low = true; + + 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); + + gpios = devm_kzalloc(dev, + sizeof(unsigned int) * + (pdata->num_row_gpios + pdata->num_col_gpios), + GFP_KERNEL); + if (!gpios) { + dev_err(dev, "could not allocate memory for gpios\n"); + return ERR_PTR(-ENOMEM); + } + + for (i = 0; i < pdata->num_row_gpios; i++) + gpios[i] = of_get_named_gpio(np, "row-gpios", i); + + for (i = 0; i < pdata->num_col_gpios; i++) + gpios[pdata->num_row_gpios + i] = + of_get_named_gpio(np, "col-gpios", i); + + 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"); + + return ERR_PTR(-EINVAL); +} +#endif + +static int matrix_keypad_probe(struct platform_device *pdev) { const struct matrix_keypad_platform_data *pdata; - const struct matrix_keymap_data *keymap_data; struct matrix_keypad *keypad; struct input_dev *input_dev; - unsigned int row_shift; - size_t keymap_size; int err; - pdata = pdev->dev.platform_data; + pdata = dev_get_platdata(&pdev->dev); if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -EINVAL; - } - - keymap_data = pdata->keymap_data; - if (!keymap_data) { + pdata = matrix_keypad_parse_dt(&pdev->dev); + if (IS_ERR(pdata)) { + dev_err(&pdev->dev, "no platform data defined\n"); + return PTR_ERR(pdata); + } + } else if (!pdata->keymap_data) { dev_err(&pdev->dev, "no keymap data defined\n"); return -EINVAL; } - row_shift = get_count_order(pdata->num_col_gpios); - keymap_size = (pdata->num_row_gpios << row_shift) * - sizeof(keypad->keycodes[0]); - keypad = kzalloc(sizeof(struct matrix_keypad) + keymap_size, - GFP_KERNEL); + keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); input_dev = input_allocate_device(); if (!keypad || !input_dev) { err = -ENOMEM; @@ -429,7 +493,7 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) keypad->input_dev = input_dev; keypad->pdata = pdata; - keypad->row_shift = row_shift; + 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); @@ -440,12 +504,14 @@ static int __devinit matrix_keypad_probe(struct platform_device *pdev) input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; - err = matrix_keypad_build_keymap(keymap_data, NULL, + err = matrix_keypad_build_keymap(pdata->keymap_data, NULL, pdata->num_row_gpios, pdata->num_col_gpios, - keypad->keycodes, input_dev); - if (err) + NULL, input_dev); + if (err) { + dev_err(&pdev->dev, "failed to build keymap\n"); goto err_free_mem; + } if (!pdata->no_autorepeat) __set_bit(EV_REP, input_dev->evbit); @@ -473,7 +539,7 @@ err_free_mem: return err; } -static int __devexit matrix_keypad_remove(struct platform_device *pdev) +static int matrix_keypad_remove(struct platform_device *pdev) { struct matrix_keypad *keypad = platform_get_drvdata(pdev); @@ -488,13 +554,22 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id matrix_keypad_dt_match[] = { + { .compatible = "gpio-matrix-keypad" }, + { } +}; +MODULE_DEVICE_TABLE(of, matrix_keypad_dt_match); +#endif + static struct platform_driver matrix_keypad_driver = { .probe = matrix_keypad_probe, - .remove = __devexit_p(matrix_keypad_remove), + .remove = matrix_keypad_remove, .driver = { .name = "matrix-keypad", .owner = THIS_MODULE, .pm = &matrix_keypad_pm_ops, + .of_match_table = of_match_ptr(matrix_keypad_dt_match), }, }; module_platform_driver(matrix_keypad_driver); diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 8edada8ae712..7c7af2b01e65 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -179,7 +179,7 @@ static void max7359_initialize(struct i2c_client *client) max7359_fall_deepsleep(client); } -static int __devinit max7359_probe(struct i2c_client *client, +static int max7359_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct matrix_keymap_data *keymap_data = client->dev.platform_data; @@ -260,7 +260,7 @@ failed_free_mem: return error; } -static int __devexit max7359_remove(struct i2c_client *client) +static int max7359_remove(struct i2c_client *client) { struct max7359_keypad *keypad = i2c_get_clientdata(client); @@ -312,7 +312,7 @@ static struct i2c_driver max7359_i2c_driver = { .pm = &max7359_pm, }, .probe = max7359_probe, - .remove = __devexit_p(max7359_remove), + .remove = max7359_remove, .id_table = max7359_ids, }; diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c index 0d77f6c84950..7c236f9c6a51 100644 --- a/drivers/input/keyboard/mcs_touchkey.c +++ b/drivers/input/keyboard/mcs_touchkey.c @@ -97,7 +97,7 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit mcs_touchkey_probe(struct i2c_client *client, +static int mcs_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct mcs_platform_data *pdata; @@ -200,7 +200,7 @@ err_free_mem: return error; } -static int __devexit mcs_touchkey_remove(struct i2c_client *client) +static int mcs_touchkey_remove(struct i2c_client *client) { struct mcs_touchkey_data *data = i2c_get_clientdata(client); @@ -270,7 +270,7 @@ static struct i2c_driver mcs_touchkey_driver = { .pm = &mcs_touchkey_pm_ops, }, .probe = mcs_touchkey_probe, - .remove = __devexit_p(mcs_touchkey_remove), + .remove = mcs_touchkey_remove, .shutdown = mcs_touchkey_shutdown, .id_table = mcs_touchkey_id, }; diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c index 7613f1cac951..f7f3e9a9fd3f 100644 --- a/drivers/input/keyboard/mpr121_touchkey.c +++ b/drivers/input/keyboard/mpr121_touchkey.c @@ -71,7 +71,7 @@ struct mpr121_init_register { u8 val; }; -static const struct mpr121_init_register init_reg_table[] __devinitconst = { +static const struct mpr121_init_register init_reg_table[] = { { MHD_RISING_ADDR, 0x1 }, { NHD_RISING_ADDR, 0x1 }, { MHD_FALLING_ADDR, 0x1 }, @@ -123,7 +123,7 @@ out: return IRQ_HANDLED; } -static int __devinit mpr121_phys_init(const struct mpr121_platform_data *pdata, +static int mpr121_phys_init(const struct mpr121_platform_data *pdata, struct mpr121_touchkey *mpr121, struct i2c_client *client) { @@ -185,8 +185,8 @@ err_i2c_write: return ret; } -static int __devinit mpr_touchkey_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int mpr_touchkey_probe(struct i2c_client *client, + const struct i2c_device_id *id) { const struct mpr121_platform_data *pdata = client->dev.platform_data; struct mpr121_touchkey *mpr121; @@ -272,7 +272,7 @@ err_free_mem: return error; } -static int __devexit mpr_touchkey_remove(struct i2c_client *client) +static int mpr_touchkey_remove(struct i2c_client *client) { struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client); @@ -327,7 +327,7 @@ static struct i2c_driver mpr_touchkey_driver = { }, .id_table = mpr121_id, .probe = mpr_touchkey_probe, - .remove = __devexit_p(mpr_touchkey_remove), + .remove = mpr_touchkey_remove, }; module_i2c_driver(mpr_touchkey_driver); diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c index 49f5fa64e0b1..0e6a8151fee3 100644 --- a/drivers/input/keyboard/nomadik-ske-keypad.c +++ b/drivers/input/keyboard/nomadik-ske-keypad.c @@ -67,6 +67,7 @@ struct ske_keypad { 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; }; @@ -271,11 +272,18 @@ static int __init ske_keypad_probe(struct platform_device *pdev) goto err_free_mem_region; } + keypad->pclk = clk_get(&pdev->dev, "apb_pclk"); + if (IS_ERR(keypad->pclk)) { + dev_err(&pdev->dev, "failed to get pclk\n"); + error = PTR_ERR(keypad->pclk); + goto err_iounmap; + } + keypad->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get clk\n"); error = PTR_ERR(keypad->clk); - goto err_iounmap; + goto err_pclk; } input->id.bustype = BUS_HOST; @@ -287,14 +295,25 @@ static int __init ske_keypad_probe(struct platform_device *pdev) keypad->keymap, input); if (error) { dev_err(&pdev->dev, "Failed to build keymap\n"); - goto err_iounmap; + goto err_clk; } input_set_capability(input, EV_MSC, MSC_SCAN); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - clk_enable(keypad->clk); + error = clk_prepare_enable(keypad->pclk); + if (error) { + dev_err(&pdev->dev, "Failed to prepare/enable pclk\n"); + goto err_clk; + } + + error = clk_prepare_enable(keypad->clk); + if (error) { + dev_err(&pdev->dev, "Failed to prepare/enable clk\n"); + goto err_pclk_disable; + } + /* go through board initialization helpers */ if (keypad->board->init) @@ -330,8 +349,13 @@ static int __init ske_keypad_probe(struct platform_device *pdev) err_free_irq: free_irq(keypad->irq, keypad); err_clk_disable: - clk_disable(keypad->clk); + clk_disable_unprepare(keypad->clk); +err_pclk_disable: + clk_disable_unprepare(keypad->pclk); +err_clk: clk_put(keypad->clk); +err_pclk: + clk_put(keypad->pclk); err_iounmap: iounmap(keypad->reg_base); err_free_mem_region: @@ -342,7 +366,7 @@ err_free_mem: return error; } -static int __devexit ske_keypad_remove(struct platform_device *pdev) +static int ske_keypad_remove(struct platform_device *pdev) { struct ske_keypad *keypad = platform_get_drvdata(pdev); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -351,7 +375,7 @@ static int __devexit ske_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input); - clk_disable(keypad->clk); + clk_disable_unprepare(keypad->clk); clk_put(keypad->clk); if (keypad->board->exit) @@ -403,7 +427,7 @@ static struct platform_driver ske_keypad_driver = { .owner = THIS_MODULE, .pm = &ske_keypad_dev_pm_ops, }, - .remove = __devexit_p(ske_keypad_remove), + .remove = ske_keypad_remove, }; static int __init ske_keypad_init(void) diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index 4a5fcc8026f5..d0d5226d9cd4 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c @@ -244,7 +244,7 @@ static int omap_kp_resume(struct platform_device *dev) #define omap_kp_resume NULL #endif -static int __devinit omap_kp_probe(struct platform_device *pdev) +static int omap_kp_probe(struct platform_device *pdev) { struct omap_kp *omap_kp; struct input_dev *input_dev; @@ -357,7 +357,7 @@ err2: return -EINVAL; } -static int __devexit omap_kp_remove(struct platform_device *pdev) +static int omap_kp_remove(struct platform_device *pdev) { struct omap_kp *omap_kp = platform_get_drvdata(pdev); @@ -379,7 +379,7 @@ static int __devexit omap_kp_remove(struct platform_device *pdev) static struct platform_driver omap_kp_driver = { .probe = omap_kp_probe, - .remove = __devexit_p(omap_kp_remove), + .remove = omap_kp_remove, .suspend = omap_kp_suspend, .resume = omap_kp_resume, .driver = { diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index c05f98c41410..e25b022692cd 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -211,8 +211,8 @@ static void omap4_keypad_close(struct input_dev *input) } #ifdef CONFIG_OF -static int __devinit omap4_keypad_parse_dt(struct device *dev, - struct omap4_keypad *keypad_data) +static int omap4_keypad_parse_dt(struct device *dev, + struct omap4_keypad *keypad_data) { struct device_node *np = dev->of_node; @@ -241,7 +241,7 @@ static inline int omap4_keypad_parse_dt(struct device *dev, } #endif -static int __devinit omap4_keypad_probe(struct platform_device *pdev) +static int omap4_keypad_probe(struct platform_device *pdev) { const struct omap4_keypad_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -406,7 +406,7 @@ err_free_keypad: return error; } -static int __devexit omap4_keypad_remove(struct platform_device *pdev) +static int omap4_keypad_remove(struct platform_device *pdev) { struct omap4_keypad *keypad_data = platform_get_drvdata(pdev); struct resource *res; @@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(of, omap_keypad_dt_match); static struct platform_driver omap4_keypad_driver = { .probe = omap4_keypad_probe, - .remove = __devexit_p(omap4_keypad_remove), + .remove = omap4_keypad_remove, .driver = { .name = "omap4-keypad", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index abe728c7b88e..7ac5f174c6f7 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c @@ -37,7 +37,7 @@ static irqreturn_t opencores_kbd_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit opencores_kbd_probe(struct platform_device *pdev) +static int opencores_kbd_probe(struct platform_device *pdev) { struct input_dev *input; struct opencores_kbd *opencores_kbd; @@ -139,7 +139,7 @@ static int __devinit opencores_kbd_probe(struct platform_device *pdev) return error; } -static int __devexit opencores_kbd_remove(struct platform_device *pdev) +static int opencores_kbd_remove(struct platform_device *pdev) { struct opencores_kbd *opencores_kbd = platform_get_drvdata(pdev); @@ -158,7 +158,7 @@ static int __devexit opencores_kbd_remove(struct platform_device *pdev) static struct platform_driver opencores_kbd_device_driver = { .probe = opencores_kbd_probe, - .remove = __devexit_p(opencores_kbd_remove), + .remove = opencores_kbd_remove, .driver = { .name = "opencores-kbd", }, diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c index 52c34657d301..74339e139d43 100644 --- a/drivers/input/keyboard/pmic8xxx-keypad.c +++ b/drivers/input/keyboard/pmic8xxx-keypad.c @@ -397,7 +397,7 @@ static irqreturn_t pmic8xxx_kp_irq(int irq, void *data) return IRQ_HANDLED; } -static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) +static int pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) { int bits, rc, cycles; u8 scan_val = 0, ctrl_val = 0; @@ -447,7 +447,7 @@ static int __devinit pmic8xxx_kpd_init(struct pmic8xxx_kp *kp) } -static int __devinit pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, +static int pmic8xxx_kp_config_gpio(int gpio_start, int num_gpios, struct pmic8xxx_kp *kp, struct pm_gpio *gpio_config) { int rc, i; @@ -518,7 +518,7 @@ static void pmic8xxx_kp_close(struct input_dev *dev) * - set irq edge type. * - enable the keypad controller. */ -static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) +static int pmic8xxx_kp_probe(struct platform_device *pdev) { const struct pm8xxx_keypad_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -712,7 +712,7 @@ err_alloc_device: return rc; } -static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) +static int pmic8xxx_kp_remove(struct platform_device *pdev) { struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); @@ -773,7 +773,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, static struct platform_driver pmic8xxx_kp_driver = { .probe = pmic8xxx_kp_probe, - .remove = __devexit_p(pmic8xxx_kp_remove), + .remove = pmic8xxx_kp_remove, .driver = { .name = PM8XXX_KEYPAD_DEV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index cad9d5dd5973..5330d8fbf6c0 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -482,7 +482,7 @@ static const struct dev_pm_ops pxa27x_keypad_pm_ops = { }; #endif -static int __devinit pxa27x_keypad_probe(struct platform_device *pdev) +static int pxa27x_keypad_probe(struct platform_device *pdev) { struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data; struct pxa27x_keypad *keypad; @@ -595,7 +595,7 @@ failed_free: return error; } -static int __devexit pxa27x_keypad_remove(struct platform_device *pdev) +static int pxa27x_keypad_remove(struct platform_device *pdev) { struct pxa27x_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; @@ -620,7 +620,7 @@ MODULE_ALIAS("platform:pxa27x-keypad"); static struct platform_driver pxa27x_keypad_driver = { .probe = pxa27x_keypad_probe, - .remove = __devexit_p(pxa27x_keypad_remove), + .remove = pxa27x_keypad_remove, .driver = { .name = "pxa27x-keypad", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 41488f9add20..bcad95be73aa 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c @@ -82,7 +82,7 @@ static void pxa930_rotary_close(struct input_dev *dev) clear_sbcr(r); } -static int __devinit pxa930_rotary_probe(struct platform_device *pdev) +static int pxa930_rotary_probe(struct platform_device *pdev) { struct pxa930_rotary_platform_data *pdata = pdev->dev.platform_data; struct pxa930_rotary *r; @@ -174,7 +174,7 @@ failed_free: return err; } -static int __devexit pxa930_rotary_remove(struct platform_device *pdev) +static int pxa930_rotary_remove(struct platform_device *pdev) { struct pxa930_rotary *r = platform_get_drvdata(pdev); @@ -193,7 +193,7 @@ static struct platform_driver pxa930_rotary_driver = { .owner = THIS_MODULE, }, .probe = pxa930_rotary_probe, - .remove = __devexit_p(pxa930_rotary_remove), + .remove = pxa930_rotary_remove, }; module_platform_driver(pxa930_rotary_driver); diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c index ca68f2992d72..42b773b3125a 100644 --- a/drivers/input/keyboard/qt1070.c +++ b/drivers/input/keyboard/qt1070.c @@ -91,7 +91,7 @@ static int qt1070_write(struct i2c_client *client, u8 reg, u8 data) return ret; } -static bool __devinit qt1070_identify(struct i2c_client *client) +static bool qt1070_identify(struct i2c_client *client) { int id, ver; @@ -140,7 +140,7 @@ static irqreturn_t qt1070_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit qt1070_probe(struct i2c_client *client, +static int qt1070_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct qt1070_data *data; @@ -230,7 +230,7 @@ err_free_mem: return err; } -static int __devexit qt1070_remove(struct i2c_client *client) +static int qt1070_remove(struct i2c_client *client) { struct qt1070_data *data = i2c_get_clientdata(client); @@ -256,7 +256,7 @@ static struct i2c_driver qt1070_driver = { }, .id_table = qt1070_id, .probe = qt1070_probe, - .remove = __devexit_p(qt1070_remove), + .remove = qt1070_remove, }; module_i2c_driver(qt1070_driver); diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 76b7d430d03a..1c0ddad0a1cc 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -20,6 +20,7 @@ #include <linux/kernel.h> #include <linux/init.h> +#include <linux/leds.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/jiffies.h> @@ -39,6 +40,11 @@ #define QT2160_CMD_GPIOS 6 #define QT2160_CMD_SUBVER 7 #define QT2160_CMD_CALIBRATE 10 +#define QT2160_CMD_DRIVE_X 70 +#define QT2160_CMD_PWMEN_X 74 +#define QT2160_CMD_PWM_DUTY 76 + +#define QT2160_NUM_LEDS_X 8 #define QT2160_CYCLE_INTERVAL (2*HZ) @@ -49,6 +55,17 @@ static unsigned char qt2160_key2code[] = { KEY_C, KEY_D, KEY_E, KEY_F, }; +#ifdef CONFIG_LEDS_CLASS +struct qt2160_led { + struct qt2160_data *qt2160; + struct led_classdev cdev; + struct work_struct work; + char name[32]; + int id; + enum led_brightness new_brightness; +}; +#endif + struct qt2160_data { struct i2c_client *client; struct input_dev *input; @@ -56,8 +73,61 @@ struct qt2160_data { spinlock_t lock; /* Protects canceling/rescheduling of dwork */ unsigned short keycodes[ARRAY_SIZE(qt2160_key2code)]; u16 key_matrix; +#ifdef CONFIG_LEDS_CLASS + struct qt2160_led leds[QT2160_NUM_LEDS_X]; + struct mutex led_lock; +#endif }; +static int qt2160_read(struct i2c_client *client, u8 reg); +static int qt2160_write(struct i2c_client *client, u8 reg, u8 data); + +#ifdef CONFIG_LEDS_CLASS + +static void qt2160_led_work(struct work_struct *work) +{ + struct qt2160_led *led = container_of(work, struct qt2160_led, work); + struct qt2160_data *qt2160 = led->qt2160; + struct i2c_client *client = qt2160->client; + int value = led->new_brightness; + u32 drive, pwmen; + + mutex_lock(&qt2160->led_lock); + + drive = qt2160_read(client, QT2160_CMD_DRIVE_X); + pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X); + if (value != LED_OFF) { + drive |= (1 << led->id); + pwmen |= (1 << led->id); + + } else { + drive &= ~(1 << led->id); + pwmen &= ~(1 << led->id); + } + qt2160_write(client, QT2160_CMD_DRIVE_X, drive); + qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen); + + /* + * Changing this register will change the brightness + * of every LED in the qt2160. It's a HW limitation. + */ + if (value != LED_OFF) + qt2160_write(client, QT2160_CMD_PWM_DUTY, value); + + mutex_unlock(&qt2160->led_lock); +} + +static void qt2160_led_set(struct led_classdev *cdev, + enum led_brightness value) +{ + struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev); + + led->new_brightness = value; + schedule_work(&led->work); +} + +#endif /* CONFIG_LEDS_CLASS */ + static int qt2160_read_block(struct i2c_client *client, u8 inireg, u8 *buffer, unsigned int count) { @@ -183,7 +253,7 @@ static void qt2160_worker(struct work_struct *work) qt2160_schedule_read(qt2160); } -static int __devinit qt2160_read(struct i2c_client *client, u8 reg) +static int qt2160_read(struct i2c_client *client, u8 reg) { int ret; @@ -204,29 +274,77 @@ static int __devinit qt2160_read(struct i2c_client *client, u8 reg) return ret; } -static int __devinit qt2160_write(struct i2c_client *client, u8 reg, u8 data) +static int qt2160_write(struct i2c_client *client, u8 reg, u8 data) { - int error; + int ret; - error = i2c_smbus_write_byte(client, reg); - if (error) { + ret = i2c_smbus_write_byte_data(client, reg, data); + if (ret < 0) dev_err(&client->dev, - "couldn't send request. Returned %d\n", error); - return error; + "couldn't write data. Returned %d\n", ret); + + return ret; +} + +#ifdef CONFIG_LEDS_CLASS + +static int qt2160_register_leds(struct qt2160_data *qt2160) +{ + struct i2c_client *client = qt2160->client; + int ret; + int i; + + mutex_init(&qt2160->led_lock); + + for (i = 0; i < QT2160_NUM_LEDS_X; i++) { + struct qt2160_led *led = &qt2160->leds[i]; + + snprintf(led->name, sizeof(led->name), "qt2160:x%d", i); + led->cdev.name = led->name; + led->cdev.brightness_set = qt2160_led_set; + led->cdev.brightness = LED_OFF; + led->id = i; + led->qt2160 = qt2160; + + INIT_WORK(&led->work, qt2160_led_work); + + ret = led_classdev_register(&client->dev, &led->cdev); + if (ret < 0) + return ret; } - error = i2c_smbus_write_byte(client, data); - if (error) { - dev_err(&client->dev, - "couldn't write data. Returned %d\n", error); - return error; + /* Tur off LEDs */ + qt2160_write(client, QT2160_CMD_DRIVE_X, 0); + qt2160_write(client, QT2160_CMD_PWMEN_X, 0); + qt2160_write(client, QT2160_CMD_PWM_DUTY, 0); + + return 0; +} + +static void qt2160_unregister_leds(struct qt2160_data *qt2160) +{ + int i; + + for (i = 0; i < QT2160_NUM_LEDS_X; i++) { + led_classdev_unregister(&qt2160->leds[i].cdev); + cancel_work_sync(&qt2160->leds[i].work); } +} - return error; +#else + +static inline int qt2160_register_leds(struct qt2160_data *qt2160) +{ + return 0; +} + +static inline void qt2160_unregister_leds(struct qt2160_data *qt2160) +{ } +#endif -static bool __devinit qt2160_identify(struct i2c_client *client) +static bool qt2160_identify(struct i2c_client *client) { int id, ver, rev; @@ -257,8 +375,8 @@ static bool __devinit qt2160_identify(struct i2c_client *client) return true; } -static int __devinit qt2160_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int qt2160_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct qt2160_data *qt2160; struct input_dev *input; @@ -323,11 +441,17 @@ static int __devinit qt2160_probe(struct i2c_client *client, } } + error = qt2160_register_leds(qt2160); + if (error) { + dev_err(&client->dev, "Failed to register leds\n"); + goto err_free_irq; + } + error = input_register_device(qt2160->input); if (error) { dev_err(&client->dev, "Failed to register input device\n"); - goto err_free_irq; + goto err_unregister_leds; } i2c_set_clientdata(client, qt2160); @@ -335,6 +459,8 @@ static int __devinit qt2160_probe(struct i2c_client *client, return 0; +err_unregister_leds: + qt2160_unregister_leds(qt2160); err_free_irq: if (client->irq) free_irq(client->irq, qt2160); @@ -344,10 +470,12 @@ err_free_mem: return error; } -static int __devexit qt2160_remove(struct i2c_client *client) +static int qt2160_remove(struct i2c_client *client) { struct qt2160_data *qt2160 = i2c_get_clientdata(client); + qt2160_unregister_leds(qt2160); + /* Release IRQ so no queue will be scheduled */ if (client->irq) free_irq(client->irq, qt2160); @@ -375,7 +503,7 @@ static struct i2c_driver qt2160_driver = { .id_table = qt2160_idtable, .probe = qt2160_probe, - .remove = __devexit_p(qt2160_remove), + .remove = qt2160_remove, }; module_i2c_driver(qt2160_driver); diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c index 9d7a111486f7..22e357b51024 100644 --- a/drivers/input/keyboard/samsung-keypad.c +++ b/drivers/input/keyboard/samsung-keypad.c @@ -309,7 +309,7 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, struct samsung_keypad *keypad) { struct device_node *np = dev->of_node; - int gpio, ret, row, col; + int gpio, error, row, col; for (row = 0; row < keypad->rows; row++) { gpio = of_get_named_gpio(np, "row-gpios", row); @@ -320,10 +320,11 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, continue; } - ret = gpio_request(gpio, "keypad-row"); - if (ret) - dev_err(dev, "keypad row[%d] gpio request failed\n", - row); + error = devm_gpio_request(dev, gpio, "keypad-row"); + if (error) + dev_err(dev, + "keypad row[%d] gpio request failed: %d\n", + row, error); } for (col = 0; col < keypad->cols; col++) { @@ -335,38 +336,22 @@ static void samsung_keypad_parse_dt_gpio(struct device *dev, continue; } - ret = gpio_request(gpio, "keypad-col"); - if (ret) - dev_err(dev, "keypad column[%d] gpio request failed\n", - col); + error = devm_gpio_request(dev, gpio, "keypad-col"); + if (error) + dev_err(dev, + "keypad column[%d] gpio request failed: %d\n", + col, error); } } - -static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) -{ - int cnt; - - for (cnt = 0; cnt < keypad->rows; cnt++) - if (gpio_is_valid(keypad->row_gpios[cnt])) - gpio_free(keypad->row_gpios[cnt]); - - for (cnt = 0; cnt < keypad->cols; cnt++) - if (gpio_is_valid(keypad->col_gpios[cnt])) - gpio_free(keypad->col_gpios[cnt]); -} #else static struct samsung_keypad_platdata *samsung_keypad_parse_dt(struct device *dev) { return NULL; } - -static void samsung_keypad_dt_gpio_free(struct samsung_keypad *keypad) -{ -} #endif -static int __devinit samsung_keypad_probe(struct platform_device *pdev) +static int samsung_keypad_probe(struct platform_device *pdev) { const struct samsung_keypad_platdata *pdata; const struct matrix_keymap_data *keymap_data; @@ -405,36 +390,30 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) row_shift = get_count_order(pdata->cols); keymap_size = (pdata->rows << row_shift) * sizeof(keypad->keycodes[0]); - keypad = kzalloc(sizeof(*keypad) + keymap_size, GFP_KERNEL); - input_dev = input_allocate_device(); - if (!keypad || !input_dev) { - error = -ENOMEM; - goto err_free_mem; - } + keypad = devm_kzalloc(&pdev->dev, sizeof(*keypad) + keymap_size, + GFP_KERNEL); + input_dev = devm_input_allocate_device(&pdev->dev); + if (!keypad || !input_dev) + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - error = -ENODEV; - goto err_free_mem; - } + if (!res) + return -ENODEV; - keypad->base = ioremap(res->start, resource_size(res)); - if (!keypad->base) { - error = -EBUSY; - goto err_free_mem; - } + keypad->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!keypad->base) + return -EBUSY; - keypad->clk = clk_get(&pdev->dev, "keypad"); + keypad->clk = devm_clk_get(&pdev->dev, "keypad"); if (IS_ERR(keypad->clk)) { dev_err(&pdev->dev, "failed to get keypad clk\n"); - error = PTR_ERR(keypad->clk); - goto err_unmap_base; + return PTR_ERR(keypad->clk); } error = clk_prepare(keypad->clk); if (error) { dev_err(&pdev->dev, "keypad clock prepare failed\n"); - goto err_put_clk; + return error; } keypad->input_dev = input_dev; @@ -479,14 +458,15 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) keypad->irq = platform_get_irq(pdev, 0); if (keypad->irq < 0) { error = keypad->irq; - goto err_put_clk; + goto err_unprepare_clk; } - error = request_threaded_irq(keypad->irq, NULL, samsung_keypad_irq, - IRQF_ONESHOT, dev_name(&pdev->dev), keypad); + error = devm_request_threaded_irq(&pdev->dev, keypad->irq, NULL, + samsung_keypad_irq, IRQF_ONESHOT, + dev_name(&pdev->dev), keypad); if (error) { dev_err(&pdev->dev, "failed to register keypad interrupt\n"); - goto err_put_clk; + goto err_unprepare_clk; } device_init_wakeup(&pdev->dev, pdata->wakeup); @@ -495,7 +475,7 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) error = input_register_device(keypad->input_dev); if (error) - goto err_free_irq; + goto err_disable_runtime_pm; if (pdev->dev.of_node) { devm_kfree(&pdev->dev, (void *)pdata->keymap_data->keymap); @@ -504,26 +484,16 @@ static int __devinit samsung_keypad_probe(struct platform_device *pdev) } return 0; -err_free_irq: - free_irq(keypad->irq, keypad); +err_disable_runtime_pm: pm_runtime_disable(&pdev->dev); device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); err_unprepare_clk: clk_unprepare(keypad->clk); -err_put_clk: - clk_put(keypad->clk); - samsung_keypad_dt_gpio_free(keypad); -err_unmap_base: - iounmap(keypad->base); -err_free_mem: - input_free_device(input_dev); - kfree(keypad); - return error; } -static int __devexit samsung_keypad_remove(struct platform_device *pdev) +static int samsung_keypad_remove(struct platform_device *pdev) { struct samsung_keypad *keypad = platform_get_drvdata(pdev); @@ -533,18 +503,7 @@ static int __devexit samsung_keypad_remove(struct platform_device *pdev) input_unregister_device(keypad->input_dev); - /* - * It is safe to free IRQ after unregistering device because - * samsung_keypad_close will shut off interrupts. - */ - free_irq(keypad->irq, keypad); - clk_unprepare(keypad->clk); - clk_put(keypad->clk); - samsung_keypad_dt_gpio_free(keypad); - - iounmap(keypad->base); - kfree(keypad); return 0; } @@ -685,7 +644,7 @@ MODULE_DEVICE_TABLE(platform, samsung_keypad_driver_ids); static struct platform_driver samsung_keypad_driver = { .probe = samsung_keypad_probe, - .remove = __devexit_p(samsung_keypad_remove), + .remove = samsung_keypad_remove, .driver = { .name = "samsung-keypad", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index da54ad5db154..fdb9eb2df380 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -162,7 +162,7 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit sh_keysc_probe(struct platform_device *pdev) +static int sh_keysc_probe(struct platform_device *pdev) { struct sh_keysc_priv *priv; struct sh_keysc_info *pdata; @@ -272,7 +272,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) return error; } -static int __devexit sh_keysc_remove(struct platform_device *pdev) +static int sh_keysc_remove(struct platform_device *pdev) { struct sh_keysc_priv *priv = platform_get_drvdata(pdev); @@ -331,7 +331,7 @@ static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops, static struct platform_driver sh_keysc_device_driver = { .probe = sh_keysc_probe, - .remove = __devexit_p(sh_keysc_remove), + .remove = sh_keysc_remove, .driver = { .name = "sh_keysc", .pm = &sh_keysc_dev_pm_ops, diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index c7ca97f44bfb..cb1e8f614631 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -55,15 +55,15 @@ struct spear_kbd { struct input_dev *input; - struct resource *res; void __iomem *io_base; struct clk *clk; unsigned int irq; unsigned int mode; + unsigned int suspended_rate; unsigned short last_key; unsigned short keycodes[NUM_ROWS * NUM_COLS]; bool rep; - unsigned int suspended_rate; + bool irq_wake_enabled; u32 mode_ctl_reg; }; @@ -146,7 +146,7 @@ static void spear_kbd_close(struct input_dev *dev) } #ifdef CONFIG_OF -static int __devinit spear_kbd_parse_dt(struct platform_device *pdev, +static int spear_kbd_parse_dt(struct platform_device *pdev, struct spear_kbd *kbd) { struct device_node *np = pdev->dev.of_node; @@ -181,7 +181,7 @@ static inline int spear_kbd_parse_dt(struct platform_device *pdev, } #endif -static int __devinit spear_kbd_probe(struct platform_device *pdev) +static int spear_kbd_probe(struct platform_device *pdev) { struct kbd_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap = pdata ? pdata->keymap : NULL; @@ -203,12 +203,16 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) return irq; } - kbd = kzalloc(sizeof(*kbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbd || !input_dev) { - dev_err(&pdev->dev, "out of memory\n"); - error = -ENOMEM; - goto err_free_mem; + kbd = devm_kzalloc(&pdev->dev, sizeof(*kbd), GFP_KERNEL); + if (!kbd) { + dev_err(&pdev->dev, "not enough memory for driver data\n"); + return -ENOMEM; + } + + input_dev = devm_input_allocate_device(&pdev->dev); + if (!input_dev) { + dev_err(&pdev->dev, "unable to allocate input device\n"); + return -ENOMEM; } kbd->input = input_dev; @@ -217,37 +221,23 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) if (!pdata) { error = spear_kbd_parse_dt(pdev, kbd); if (error) - goto err_free_mem; + return error; } else { kbd->mode = pdata->mode; kbd->rep = pdata->rep; kbd->suspended_rate = pdata->suspended_rate; } - kbd->res = request_mem_region(res->start, resource_size(res), - pdev->name); - if (!kbd->res) { - dev_err(&pdev->dev, "keyboard region already claimed\n"); - error = -EBUSY; - goto err_free_mem; - } - - kbd->io_base = ioremap(res->start, resource_size(res)); - if (!kbd->io_base) { - dev_err(&pdev->dev, "ioremap failed for kbd_region\n"); - error = -ENOMEM; - goto err_release_mem_region; - } + kbd->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(kbd->io_base)) + return PTR_ERR(kbd->io_base); - kbd->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(kbd->clk)) { - error = PTR_ERR(kbd->clk); - goto err_iounmap; - } + kbd->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(kbd->clk)) + return PTR_ERR(kbd->clk); input_dev->name = "Spear Keyboard"; input_dev->phys = "keyboard/input0"; - input_dev->dev.parent = &pdev->dev; input_dev->id.bustype = BUS_HOST; input_dev->id.vendor = 0x0001; input_dev->id.product = 0x0001; @@ -259,7 +249,7 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) kbd->keycodes, input_dev); if (error) { dev_err(&pdev->dev, "Failed to build keymap\n"); - goto err_put_clk; + return error; } if (kbd->rep) @@ -268,48 +258,36 @@ static int __devinit spear_kbd_probe(struct platform_device *pdev) input_set_drvdata(input_dev, kbd); - error = request_irq(irq, spear_kbd_interrupt, 0, "keyboard", kbd); + error = devm_request_irq(&pdev->dev, irq, spear_kbd_interrupt, 0, + "keyboard", kbd); if (error) { - dev_err(&pdev->dev, "request_irq fail\n"); - goto err_put_clk; + dev_err(&pdev->dev, "request_irq failed\n"); + 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"); - goto err_free_irq; + clk_unprepare(kbd->clk); + return error; } device_init_wakeup(&pdev->dev, 1); platform_set_drvdata(pdev, kbd); return 0; - -err_free_irq: - free_irq(kbd->irq, kbd); -err_put_clk: - clk_put(kbd->clk); -err_iounmap: - iounmap(kbd->io_base); -err_release_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input_dev); - kfree(kbd); - - return error; } -static int __devexit spear_kbd_remove(struct platform_device *pdev) +static int spear_kbd_remove(struct platform_device *pdev) { struct spear_kbd *kbd = platform_get_drvdata(pdev); - free_irq(kbd->irq, kbd); input_unregister_device(kbd->input); - clk_put(kbd->clk); - iounmap(kbd->io_base); - release_mem_region(kbd->res->start, resource_size(kbd->res)); - kfree(kbd); + clk_unprepare(kbd->clk); device_init_wakeup(&pdev->dev, 0); platform_set_drvdata(pdev, NULL); @@ -333,7 +311,8 @@ static int spear_kbd_suspend(struct device *dev) mode_ctl_reg = readl_relaxed(kbd->io_base + MODE_CTL_REG); if (device_may_wakeup(&pdev->dev)) { - enable_irq_wake(kbd->irq); + if (!enable_irq_wake(kbd->irq)) + kbd->irq_wake_enabled = true; /* * reprogram the keyboard operating frequency as on some @@ -379,7 +358,10 @@ static int spear_kbd_resume(struct device *dev) mutex_lock(&input_dev->mutex); if (device_may_wakeup(&pdev->dev)) { - disable_irq_wake(kbd->irq); + if (kbd->irq_wake_enabled) { + kbd->irq_wake_enabled = false; + disable_irq_wake(kbd->irq); + } } else { if (input_dev->users) clk_enable(kbd->clk); @@ -407,7 +389,7 @@ MODULE_DEVICE_TABLE(of, spear_kbd_id_table); static struct platform_driver spear_kbd_driver = { .probe = spear_kbd_probe, - .remove = __devexit_p(spear_kbd_remove), + .remove = spear_kbd_remove, .driver = { .name = "keyboard", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c index 470a8778dec1..5cbec56f7720 100644 --- a/drivers/input/keyboard/stmpe-keypad.c +++ b/drivers/input/keyboard/stmpe-keypad.c @@ -166,7 +166,7 @@ static irqreturn_t stmpe_keypad_irq(int irq, void *dev) return IRQ_HANDLED; } -static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) +static int stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) { const struct stmpe_keypad_variant *variant = keypad->variant; unsigned int col_gpios = variant->col_gpios; @@ -207,7 +207,7 @@ static int __devinit stmpe_keypad_altfunc_init(struct stmpe_keypad *keypad) return stmpe_set_altfunc(stmpe, pins, STMPE_BLOCK_KEYPAD); } -static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) +static int stmpe_keypad_chip_init(struct stmpe_keypad *keypad) { const struct stmpe_keypad_platform_data *plat = keypad->plat; const struct stmpe_keypad_variant *variant = keypad->variant; @@ -257,105 +257,131 @@ static int __devinit stmpe_keypad_chip_init(struct stmpe_keypad *keypad) (plat->debounce_ms << 1)); } -static int __devinit stmpe_keypad_probe(struct platform_device *pdev) +static void stmpe_keypad_fill_used_pins(struct stmpe_keypad *keypad) { - struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); + int row, col; + + for (row = 0; row < STMPE_KEYPAD_MAX_ROWS; row++) { + for (col = 0; col < STMPE_KEYPAD_MAX_COLS; col++) { + int code = MATRIX_SCAN_CODE(row, col, + STMPE_KEYPAD_ROW_SHIFT); + if (keypad->keymap[code] != KEY_RESERVED) { + keypad->rows |= 1 << row; + keypad->cols |= 1 << col; + } + } + } +} + +#ifdef CONFIG_OF +static const struct stmpe_keypad_platform_data * +stmpe_keypad_of_probe(struct device *dev) +{ + struct device_node *np = dev->of_node; struct stmpe_keypad_platform_data *plat; + + if (!np) + return ERR_PTR(-ENODEV); + + plat = devm_kzalloc(dev, sizeof(*plat), GFP_KERNEL); + if (!plat) + return ERR_PTR(-ENOMEM); + + of_property_read_u32(np, "debounce-interval", &plat->debounce_ms); + of_property_read_u32(np, "st,scan-count", &plat->scan_count); + + plat->no_autorepeat = of_property_read_bool(np, "st,no-autorepeat"); + + return plat; +} +#else +static inline const struct stmpe_keypad_platform_data * +stmpe_keypad_of_probe(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} +#endif + +static int stmpe_keypad_probe(struct platform_device *pdev) +{ + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); + const struct stmpe_keypad_platform_data *plat; struct stmpe_keypad *keypad; struct input_dev *input; - int ret; + int error; int irq; - int i; plat = stmpe->pdata->keypad; - if (!plat) - return -ENODEV; + if (!plat) { + plat = stmpe_keypad_of_probe(&pdev->dev); + if (IS_ERR(plat)) + return PTR_ERR(plat); + } irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - keypad = kzalloc(sizeof(struct stmpe_keypad), GFP_KERNEL); + keypad = devm_kzalloc(&pdev->dev, sizeof(struct stmpe_keypad), + GFP_KERNEL); if (!keypad) return -ENOMEM; - input = input_allocate_device(); - if (!input) { - ret = -ENOMEM; - goto out_freekeypad; - } + input = devm_input_allocate_device(&pdev->dev); + if (!input) + return -ENOMEM; input->name = "STMPE keypad"; input->id.bustype = BUS_I2C; input->dev.parent = &pdev->dev; - ret = matrix_keypad_build_keymap(plat->keymap_data, NULL, - STMPE_KEYPAD_MAX_ROWS, - STMPE_KEYPAD_MAX_COLS, - keypad->keymap, input); - if (ret) - goto out_freeinput; + error = matrix_keypad_build_keymap(plat->keymap_data, NULL, + STMPE_KEYPAD_MAX_ROWS, + STMPE_KEYPAD_MAX_COLS, + keypad->keymap, input); + if (error) + return error; input_set_capability(input, EV_MSC, MSC_SCAN); if (!plat->no_autorepeat) __set_bit(EV_REP, input->evbit); - for (i = 0; i < plat->keymap_data->keymap_size; i++) { - unsigned int key = plat->keymap_data->keymap[i]; - - keypad->cols |= 1 << KEY_COL(key); - keypad->rows |= 1 << KEY_ROW(key); - } + stmpe_keypad_fill_used_pins(keypad); keypad->stmpe = stmpe; keypad->plat = plat; keypad->input = input; keypad->variant = &stmpe_keypad_variants[stmpe->partnum]; - ret = stmpe_keypad_chip_init(keypad); - if (ret < 0) - goto out_freeinput; + error = stmpe_keypad_chip_init(keypad); + if (error < 0) + return error; - ret = input_register_device(input); - if (ret) { - dev_err(&pdev->dev, - "unable to register input device: %d\n", ret); - goto out_freeinput; + error = devm_request_threaded_irq(&pdev->dev, irq, + NULL, stmpe_keypad_irq, + IRQF_ONESHOT, "stmpe-keypad", keypad); + if (error) { + dev_err(&pdev->dev, "unable to get irq: %d\n", error); + return error; } - ret = request_threaded_irq(irq, NULL, stmpe_keypad_irq, IRQF_ONESHOT, - "stmpe-keypad", keypad); - if (ret) { - dev_err(&pdev->dev, "unable to get irq: %d\n", ret); - goto out_unregisterinput; + error = input_register_device(input); + if (error) { + dev_err(&pdev->dev, + "unable to register input device: %d\n", error); + return error; } platform_set_drvdata(pdev, keypad); return 0; - -out_unregisterinput: - input_unregister_device(input); - input = NULL; -out_freeinput: - input_free_device(input); -out_freekeypad: - kfree(keypad); - return ret; } -static int __devexit stmpe_keypad_remove(struct platform_device *pdev) +static int stmpe_keypad_remove(struct platform_device *pdev) { struct stmpe_keypad *keypad = platform_get_drvdata(pdev); - struct stmpe *stmpe = keypad->stmpe; - int irq = platform_get_irq(pdev, 0); - - stmpe_disable(stmpe, STMPE_BLOCK_KEYPAD); - free_irq(irq, keypad); - input_unregister_device(keypad->input); - platform_set_drvdata(pdev, NULL); - kfree(keypad); + stmpe_disable(keypad->stmpe, STMPE_BLOCK_KEYPAD); return 0; } @@ -364,7 +390,7 @@ static struct platform_driver stmpe_keypad_driver = { .driver.name = "stmpe-keypad", .driver.owner = THIS_MODULE, .probe = stmpe_keypad_probe, - .remove = __devexit_p(stmpe_keypad_remove), + .remove = stmpe_keypad_remove, }; module_platform_driver(stmpe_keypad_driver); diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 7d498e698508..2fb0d76a04c4 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -299,7 +299,7 @@ static void tc3589x_keypad_close(struct input_dev *input) tc3589x_keypad_disable(keypad); } -static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) +static int tc3589x_keypad_probe(struct platform_device *pdev) { struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); struct tc_keypad *keypad; @@ -382,7 +382,7 @@ err_free_mem: return error; } -static int __devexit tc3589x_keypad_remove(struct platform_device *pdev) +static int tc3589x_keypad_remove(struct platform_device *pdev) { struct tc_keypad *keypad = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); @@ -448,7 +448,7 @@ static struct platform_driver tc3589x_keypad_driver = { .pm = &tc3589x_keypad_dev_pm_ops, }, .probe = tc3589x_keypad_probe, - .remove = __devexit_p(tc3589x_keypad_remove), + .remove = tc3589x_keypad_remove, }; module_platform_driver(tc3589x_keypad_driver); diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index c355cdde8d22..bfc832c35a7c 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -166,7 +166,7 @@ static void tca6416_keys_close(struct input_dev *dev) disable_irq(chip->irqnum); } -static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip) +static int tca6416_setup_registers(struct tca6416_keypad_chip *chip) { int error; @@ -197,7 +197,7 @@ static int __devinit tca6416_setup_registers(struct tca6416_keypad_chip *chip) return 0; } -static int __devinit tca6416_keypad_probe(struct i2c_client *client, +static int tca6416_keypad_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tca6416_keys_platform_data *pdata; @@ -313,7 +313,7 @@ fail1: return error; } -static int __devexit tca6416_keypad_remove(struct i2c_client *client) +static int tca6416_keypad_remove(struct i2c_client *client) { struct tca6416_keypad_chip *chip = i2c_get_clientdata(client); @@ -361,7 +361,7 @@ static struct i2c_driver tca6416_keypad_driver = { .pm = &tca6416_keypad_dev_pm_ops, }, .probe = tca6416_keypad_probe, - .remove = __devexit_p(tca6416_keypad_remove), + .remove = tca6416_keypad_remove, .id_table = tca6416_id, }; diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index 893869b29ed9..a34cc6714e5b 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -35,6 +35,7 @@ #include <linux/i2c.h> #include <linux/input.h> #include <linux/input/tca8418_keypad.h> +#include <linux/of.h> /* TCA8418 hardware limits */ #define TCA8418_MAX_ROWS 8 @@ -109,25 +110,11 @@ #define KEY_EVENT_CODE 0x7f #define KEY_EVENT_VALUE 0x80 - -static const struct i2c_device_id tca8418_id[] = { - { TCA8418_NAME, 8418, }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tca8418_id); - struct tca8418_keypad { - unsigned int rows; - unsigned int cols; - unsigned int keypad_mask; /* Mask for keypad col/rol regs */ - unsigned int irq; - unsigned int row_shift; - struct i2c_client *client; struct input_dev *input; - /* Flexible array member, must be at end of struct */ - unsigned short keymap[]; + unsigned int row_shift; }; /* @@ -172,6 +159,8 @@ static int tca8418_read_byte(struct tca8418_keypad *keypad_data, static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) { + struct input_dev *input = keypad_data->input; + unsigned short *keymap = input->keycode; int error, col, row; u8 reg, state, code; @@ -190,9 +179,8 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) col = (col) ? col - 1 : TCA8418_MAX_COLS - 1; code = MATRIX_SCAN_CODE(row, col, keypad_data->row_shift); - input_event(keypad_data->input, EV_MSC, MSC_SCAN, code); - input_report_key(keypad_data->input, - keypad_data->keymap[code], state); + input_event(input, EV_MSC, MSC_SCAN, code); + input_report_key(input, keymap[code], state); /* Read for next loop */ error = tca8418_read_byte(keypad_data, REG_KEY_EVENT_A, ®); @@ -202,7 +190,7 @@ static void tca8418_read_keypad(struct tca8418_keypad *keypad_data) dev_err(&keypad_data->client->dev, "unable to read REG_KEY_EVENT_A\n"); - input_sync(keypad_data->input); + input_sync(input); } /* @@ -218,16 +206,18 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id) if (error) { dev_err(&keypad_data->client->dev, "unable to read REG_INT_STAT\n"); - goto exit; + return IRQ_NONE; } + if (!reg) + return IRQ_NONE; + if (reg & INT_STAT_OVR_FLOW_INT) dev_warn(&keypad_data->client->dev, "overflow occurred\n"); if (reg & INT_STAT_K_INT) tca8418_read_keypad(keypad_data); -exit: /* Clear all interrupts, even IRQs we didn't check (GPI, CAD, LCK) */ reg = 0xff; error = tca8418_write_byte(keypad_data, REG_INT_STAT, reg); @@ -241,7 +231,8 @@ exit: /* * Configure the TCA8418 for keypad operation */ -static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data) +static int tca8418_configure(struct tca8418_keypad *keypad_data, + u32 rows, u32 cols) { int reg, error; @@ -253,9 +244,8 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data) /* Assemble a mask for row and column registers */ - reg = ~(~0 << keypad_data->rows); - reg += (~(~0 << keypad_data->cols)) << 8; - keypad_data->keypad_mask = reg; + reg = ~(~0 << rows); + reg += (~(~0 << cols)) << 8; /* Set registers to keypad mode */ error |= tca8418_write_byte(keypad_data, REG_KP_GPIO1, reg); @@ -270,145 +260,144 @@ static int __devinit tca8418_configure(struct tca8418_keypad *keypad_data) return error; } -static int __devinit tca8418_keypad_probe(struct i2c_client *client, +static int tca8418_keypad_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; const struct tca8418_keypad_platform_data *pdata = - client->dev.platform_data; + dev_get_platdata(dev); struct tca8418_keypad *keypad_data; struct input_dev *input; + const struct matrix_keymap_data *keymap_data = NULL; + u32 rows = 0, cols = 0; + bool rep = false; + bool irq_is_gpio = false; + int irq; int error, row_shift, max_keys; /* Copy the platform data */ - if (!pdata) { - dev_dbg(&client->dev, "no platform data\n"); - return -EINVAL; - } - - if (!pdata->keymap_data) { - dev_err(&client->dev, "no keymap data defined\n"); - return -EINVAL; + if (pdata) { + if (!pdata->keymap_data) { + dev_err(dev, "no keymap data defined\n"); + return -EINVAL; + } + keymap_data = pdata->keymap_data; + rows = pdata->rows; + cols = pdata->cols; + rep = pdata->rep; + irq_is_gpio = pdata->irq_is_gpio; + } else { + struct device_node *np = dev->of_node; + of_property_read_u32(np, "keypad,num-rows", &rows); + of_property_read_u32(np, "keypad,num-columns", &cols); + rep = of_property_read_bool(np, "keypad,autorepeat"); } - if (!pdata->rows || pdata->rows > TCA8418_MAX_ROWS) { - dev_err(&client->dev, "invalid rows\n"); + if (!rows || rows > TCA8418_MAX_ROWS) { + dev_err(dev, "invalid rows\n"); return -EINVAL; } - if (!pdata->cols || pdata->cols > TCA8418_MAX_COLS) { - dev_err(&client->dev, "invalid columns\n"); + if (!cols || cols > TCA8418_MAX_COLS) { + dev_err(dev, "invalid columns\n"); return -EINVAL; } /* Check i2c driver capabilities */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { - dev_err(&client->dev, "%s adapter not supported\n", + dev_err(dev, "%s adapter not supported\n", dev_driver_string(&client->adapter->dev)); return -ENODEV; } - row_shift = get_count_order(pdata->cols); - max_keys = pdata->rows << row_shift; + row_shift = get_count_order(cols); + max_keys = rows << row_shift; - /* Allocate memory for keypad_data, keymap and input device */ - keypad_data = kzalloc(sizeof(*keypad_data) + - max_keys * sizeof(keypad_data->keymap[0]), GFP_KERNEL); + /* Allocate memory for keypad_data and input device */ + keypad_data = devm_kzalloc(dev, sizeof(*keypad_data), GFP_KERNEL); if (!keypad_data) return -ENOMEM; - keypad_data->rows = pdata->rows; - keypad_data->cols = pdata->cols; keypad_data->client = client; keypad_data->row_shift = row_shift; /* Initialize the chip or fail if chip isn't present */ - error = tca8418_configure(keypad_data); + error = tca8418_configure(keypad_data, rows, cols); if (error < 0) - goto fail1; + return error; /* Configure input device */ - input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto fail1; - } + input = devm_input_allocate_device(dev); + if (!input) + return -ENOMEM; + keypad_data->input = input; input->name = client->name; - input->dev.parent = &client->dev; - input->id.bustype = BUS_I2C; input->id.vendor = 0x0001; input->id.product = 0x001; input->id.version = 0x0001; - error = matrix_keypad_build_keymap(pdata->keymap_data, NULL, - pdata->rows, pdata->cols, - keypad_data->keymap, input); + error = matrix_keypad_build_keymap(keymap_data, NULL, rows, cols, + NULL, input); if (error) { - dev_dbg(&client->dev, "Failed to build keymap\n"); - goto fail2; + dev_err(dev, "Failed to build keymap\n"); + return error; } - if (pdata->rep) + if (rep) __set_bit(EV_REP, input->evbit); input_set_capability(input, EV_MSC, MSC_SCAN); input_set_drvdata(input, keypad_data); - if (pdata->irq_is_gpio) - client->irq = gpio_to_irq(client->irq); + irq = client->irq; + if (irq_is_gpio) + irq = gpio_to_irq(irq); - error = request_threaded_irq(client->irq, NULL, tca8418_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - client->name, keypad_data); + error = devm_request_threaded_irq(dev, irq, NULL, tca8418_irq_handler, + IRQF_TRIGGER_FALLING | + IRQF_SHARED | + IRQF_ONESHOT, + client->name, keypad_data); if (error) { - dev_dbg(&client->dev, - "Unable to claim irq %d; error %d\n", + dev_err(dev, "Unable to claim irq %d; error %d\n", client->irq, error); - goto fail2; + return error; } error = input_register_device(input); if (error) { - dev_dbg(&client->dev, - "Unable to register input device, error: %d\n", error); - goto fail3; + dev_err(dev, "Unable to register input device, error: %d\n", + error); + return error; } - i2c_set_clientdata(client, keypad_data); return 0; - -fail3: - free_irq(client->irq, keypad_data); -fail2: - input_free_device(input); -fail1: - kfree(keypad_data); - return error; } -static int __devexit tca8418_keypad_remove(struct i2c_client *client) -{ - struct tca8418_keypad *keypad_data = i2c_get_clientdata(client); - - free_irq(keypad_data->client->irq, keypad_data); - - input_unregister_device(keypad_data->input); - - kfree(keypad_data); - - return 0; -} +static const struct i2c_device_id tca8418_id[] = { + { TCA8418_NAME, 8418, }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tca8418_id); +#ifdef CONFIG_OF +static const struct of_device_id tca8418_dt_ids[] = { + { .compatible = "ti,tca8418", }, + { } +}; +MODULE_DEVICE_TABLE(of, tca8418_dt_ids); +#endif static struct i2c_driver tca8418_keypad_driver = { .driver = { .name = TCA8418_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(tca8418_dt_ids), }, .probe = tca8418_keypad_probe, - .remove = __devexit_p(tca8418_keypad_remove), .id_table = tca8418_id, }; diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 5faaf2553e33..0e138ebcc768 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -29,8 +29,15 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/slab.h> -#include <linux/input/tegra_kbc.h> -#include <mach/clk.h> +#include <linux/input/matrix_keypad.h> +#include <linux/clk/tegra.h> + +#define KBC_MAX_GPIO 24 +#define KBC_MAX_KPENT 8 + +#define KBC_MAX_ROW 16 +#define KBC_MAX_COL 8 +#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) #define KBC_MAX_DEBOUNCE_CNT 0x3ffu @@ -67,10 +74,27 @@ #define KBC_ROW_SHIFT 3 +enum tegra_pin_type { + PIN_CFG_IGNORE, + PIN_CFG_COL, + PIN_CFG_ROW, +}; + +struct tegra_kbc_pin_cfg { + enum tegra_pin_type type; + unsigned char num; +}; + struct tegra_kbc { + struct device *dev; + unsigned int debounce_cnt; + unsigned int repeat_cnt; + struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; + const struct matrix_keymap_data *keymap_data; + bool wakeup; void __iomem *mmio; struct input_dev *idev; - unsigned int irq; + int irq; spinlock_t lock; unsigned int repoll_dly; unsigned long cp_dly_jiffies; @@ -78,7 +102,6 @@ struct tegra_kbc { bool use_fn_map; bool use_ghost_filter; bool keypress_caused_wake; - const struct tegra_kbc_platform_data *pdata; unsigned short keycode[KBC_MAX_KEY * 2]; unsigned short current_keys[KBC_MAX_KPENT]; unsigned int num_pressed_keys; @@ -87,147 +110,6 @@ struct tegra_kbc { struct clk *clk; }; -static const u32 tegra_kbc_default_keymap[] __devinitdata = { - KEY(0, 2, KEY_W), - KEY(0, 3, KEY_S), - KEY(0, 4, KEY_A), - KEY(0, 5, KEY_Z), - KEY(0, 7, KEY_FN), - - KEY(1, 7, KEY_LEFTMETA), - - KEY(2, 6, KEY_RIGHTALT), - KEY(2, 7, KEY_LEFTALT), - - KEY(3, 0, KEY_5), - KEY(3, 1, KEY_4), - KEY(3, 2, KEY_R), - KEY(3, 3, KEY_E), - KEY(3, 4, KEY_F), - KEY(3, 5, KEY_D), - KEY(3, 6, KEY_X), - - KEY(4, 0, KEY_7), - KEY(4, 1, KEY_6), - KEY(4, 2, KEY_T), - KEY(4, 3, KEY_H), - KEY(4, 4, KEY_G), - KEY(4, 5, KEY_V), - KEY(4, 6, KEY_C), - KEY(4, 7, KEY_SPACE), - - KEY(5, 0, KEY_9), - KEY(5, 1, KEY_8), - KEY(5, 2, KEY_U), - KEY(5, 3, KEY_Y), - KEY(5, 4, KEY_J), - KEY(5, 5, KEY_N), - KEY(5, 6, KEY_B), - KEY(5, 7, KEY_BACKSLASH), - - KEY(6, 0, KEY_MINUS), - KEY(6, 1, KEY_0), - KEY(6, 2, KEY_O), - KEY(6, 3, KEY_I), - KEY(6, 4, KEY_L), - KEY(6, 5, KEY_K), - KEY(6, 6, KEY_COMMA), - KEY(6, 7, KEY_M), - - KEY(7, 1, KEY_EQUAL), - KEY(7, 2, KEY_RIGHTBRACE), - KEY(7, 3, KEY_ENTER), - KEY(7, 7, KEY_MENU), - - KEY(8, 4, KEY_RIGHTSHIFT), - KEY(8, 5, KEY_LEFTSHIFT), - - KEY(9, 5, KEY_RIGHTCTRL), - KEY(9, 7, KEY_LEFTCTRL), - - KEY(11, 0, KEY_LEFTBRACE), - KEY(11, 1, KEY_P), - KEY(11, 2, KEY_APOSTROPHE), - KEY(11, 3, KEY_SEMICOLON), - KEY(11, 4, KEY_SLASH), - KEY(11, 5, KEY_DOT), - - KEY(12, 0, KEY_F10), - KEY(12, 1, KEY_F9), - KEY(12, 2, KEY_BACKSPACE), - KEY(12, 3, KEY_3), - KEY(12, 4, KEY_2), - KEY(12, 5, KEY_UP), - KEY(12, 6, KEY_PRINT), - KEY(12, 7, KEY_PAUSE), - - KEY(13, 0, KEY_INSERT), - KEY(13, 1, KEY_DELETE), - KEY(13, 3, KEY_PAGEUP), - KEY(13, 4, KEY_PAGEDOWN), - KEY(13, 5, KEY_RIGHT), - KEY(13, 6, KEY_DOWN), - KEY(13, 7, KEY_LEFT), - - KEY(14, 0, KEY_F11), - KEY(14, 1, KEY_F12), - KEY(14, 2, KEY_F8), - KEY(14, 3, KEY_Q), - KEY(14, 4, KEY_F4), - KEY(14, 5, KEY_F3), - KEY(14, 6, KEY_1), - KEY(14, 7, KEY_F7), - - KEY(15, 0, KEY_ESC), - KEY(15, 1, KEY_GRAVE), - KEY(15, 2, KEY_F5), - KEY(15, 3, KEY_TAB), - KEY(15, 4, KEY_F1), - KEY(15, 5, KEY_F2), - KEY(15, 6, KEY_CAPSLOCK), - KEY(15, 7, KEY_F6), - - /* Software Handled Function Keys */ - KEY(20, 0, KEY_KP7), - - KEY(21, 0, KEY_KP9), - KEY(21, 1, KEY_KP8), - KEY(21, 2, KEY_KP4), - KEY(21, 4, KEY_KP1), - - KEY(22, 1, KEY_KPSLASH), - KEY(22, 2, KEY_KP6), - KEY(22, 3, KEY_KP5), - KEY(22, 4, KEY_KP3), - KEY(22, 5, KEY_KP2), - KEY(22, 7, KEY_KP0), - - KEY(27, 1, KEY_KPASTERISK), - KEY(27, 3, KEY_KPMINUS), - KEY(27, 4, KEY_KPPLUS), - KEY(27, 5, KEY_KPDOT), - - KEY(28, 5, KEY_VOLUMEUP), - - KEY(29, 3, KEY_HOME), - KEY(29, 4, KEY_END), - KEY(29, 5, KEY_BRIGHTNESSDOWN), - KEY(29, 6, KEY_VOLUMEDOWN), - KEY(29, 7, KEY_BRIGHTNESSUP), - - KEY(30, 0, KEY_NUMLOCK), - KEY(30, 1, KEY_SCROLLLOCK), - KEY(30, 2, KEY_MUTE), - - KEY(31, 4, KEY_HELP), -}; - -static const -struct matrix_keymap_data tegra_kbc_default_keymap_data __devinitdata = { - .keymap = tegra_kbc_default_keymap, - .keymap_size = ARRAY_SIZE(tegra_kbc_default_keymap), -}; - static void tegra_kbc_report_released_keys(struct input_dev *input, unsigned short old_keycodes[], unsigned int old_num_keys, @@ -357,18 +239,6 @@ static void tegra_kbc_set_fifo_interrupt(struct tegra_kbc *kbc, bool enable) writel(val, kbc->mmio + KBC_CONTROL_0); } -static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) -{ - u32 val; - - val = readl(kbc->mmio + KBC_CONTROL_0); - if (enable) - val |= KBC_CONTROL_KEYPRESS_INT_EN; - else - val &= ~KBC_CONTROL_KEYPRESS_INT_EN; - writel(val, kbc->mmio + KBC_CONTROL_0); -} - static void tegra_kbc_keypress_timer(unsigned long data) { struct tegra_kbc *kbc = (struct tegra_kbc *)data; @@ -439,12 +309,11 @@ static irqreturn_t tegra_kbc_isr(int irq, void *args) static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; int i; unsigned int rst_val; /* Either mask all keys or none. */ - rst_val = (filter && !pdata->wakeup) ? ~0 : 0; + rst_val = (filter && !kbc->wakeup) ? ~0 : 0; for (i = 0; i < KBC_MAX_ROW; i++) writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); @@ -452,7 +321,6 @@ static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) static void tegra_kbc_config_pins(struct tegra_kbc *kbc) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; int i; for (i = 0; i < KBC_MAX_GPIO; i++) { @@ -468,13 +336,13 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) row_cfg &= ~r_mask; col_cfg &= ~c_mask; - switch (pdata->pin_cfg[i].type) { + switch (kbc->pin_cfg[i].type) { case PIN_CFG_ROW: - row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; + row_cfg |= ((kbc->pin_cfg[i].num << 1) | 1) << r_shft; break; case PIN_CFG_COL: - col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; + col_cfg |= ((kbc->pin_cfg[i].num << 1) | 1) << c_shft; break; case PIN_CFG_IGNORE: @@ -488,7 +356,6 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) static int tegra_kbc_start(struct tegra_kbc *kbc) { - const struct tegra_kbc_platform_data *pdata = kbc->pdata; unsigned int debounce_cnt; u32 val = 0; @@ -503,10 +370,10 @@ static int tegra_kbc_start(struct tegra_kbc *kbc) tegra_kbc_config_pins(kbc); tegra_kbc_setup_wakekeys(kbc, false); - writel(pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); + writel(kbc->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); /* Keyboard debounce count is maximum of 12 bits. */ - debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + debounce_cnt = min(kbc->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt); val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */ val |= KBC_CONTROL_FIFO_CNT_INT_EN; /* interrupt on FIFO threshold */ @@ -573,21 +440,20 @@ static void tegra_kbc_close(struct input_dev *dev) return tegra_kbc_stop(kbc); } -static bool __devinit -tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, - struct device *dev, unsigned int *num_rows) +static bool tegra_kbc_check_pin_cfg(const struct tegra_kbc *kbc, + unsigned int *num_rows) { int i; *num_rows = 0; for (i = 0; i < KBC_MAX_GPIO; i++) { - const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; + const struct tegra_kbc_pin_cfg *pin_cfg = &kbc->pin_cfg[i]; switch (pin_cfg->type) { case PIN_CFG_ROW: if (pin_cfg->num >= KBC_MAX_ROW) { - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid row number %d\n", i, pin_cfg->num); return false; @@ -597,7 +463,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, case PIN_CFG_COL: if (pin_cfg->num >= KBC_MAX_COL) { - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid column number %d\n", i, pin_cfg->num); return false; @@ -608,7 +474,7 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, break; default: - dev_err(dev, + dev_err(kbc->dev, "pin_cfg[%d]: invalid entry type %d\n", pin_cfg->type, pin_cfg->num); return false; @@ -618,154 +484,140 @@ tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, return true; } -#ifdef CONFIG_OF -static struct tegra_kbc_platform_data * __devinit tegra_kbc_dt_parse_pdata( - struct platform_device *pdev) +static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) { - struct tegra_kbc_platform_data *pdata; - struct device_node *np = pdev->dev.of_node; + struct device_node *np = kbc->dev->of_node; u32 prop; int i; - - if (!np) - return NULL; - - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return NULL; + u32 num_rows = 0; + u32 num_cols = 0; + 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)) - pdata->debounce_cnt = prop; + kbc->debounce_cnt = prop; if (!of_property_read_u32(np, "nvidia,repeat-delay-ms", &prop)) - pdata->repeat_cnt = prop; + kbc->repeat_cnt = prop; if (of_find_property(np, "nvidia,needs-ghost-filter", NULL)) - pdata->use_ghost_filter = true; + kbc->use_ghost_filter = true; if (of_find_property(np, "nvidia,wakeup-source", NULL)) - pdata->wakeup = true; + kbc->wakeup = true; - /* - * All currently known keymaps with device tree support use the same - * pin_cfg, so set it up here. - */ - for (i = 0; i < KBC_MAX_ROW; i++) { - pdata->pin_cfg[i].num = i; - pdata->pin_cfg[i].type = PIN_CFG_ROW; + 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); - for (i = 0; i < KBC_MAX_COL; i++) { - pdata->pin_cfg[KBC_MAX_ROW + i].num = i; - pdata->pin_cfg[KBC_MAX_ROW + i].type = PIN_CFG_COL; + 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); - return pdata; -} -#else -static inline struct tegra_kbc_platform_data *tegra_kbc_dt_parse_pdata( - struct platform_device *pdev) -{ - return NULL; -} -#endif + if (!of_get_property(np, "linux,keymap", &proplen)) { + dev_err(kbc->dev, "property linux,keymap not found\n"); + return -ENOENT; + } -static int __devinit tegra_kbd_setup_keymap(struct tegra_kbc *kbc) -{ - const struct tegra_kbc_platform_data *pdata = kbc->pdata; - const struct matrix_keymap_data *keymap_data = pdata->keymap_data; - unsigned int keymap_rows = KBC_MAX_KEY; - int retval; + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { + dev_err(kbc->dev, + "keypad rows/columns not porperly specified\n"); + return -EINVAL; + } - if (keymap_data && pdata->use_fn_map) - keymap_rows *= 2; + /* Set all pins as non-configured */ + for (i = 0; i < KBC_MAX_GPIO; i++) + kbc->pin_cfg[i].type = PIN_CFG_IGNORE; - retval = matrix_keypad_build_keymap(keymap_data, NULL, - keymap_rows, KBC_MAX_COL, - kbc->keycode, kbc->idev); - if (retval == -ENOSYS || retval == -ENOENT) { - /* - * If there is no OF support in kernel or keymap - * property is missing, use default keymap. - */ - retval = matrix_keypad_build_keymap( - &tegra_kbc_default_keymap_data, NULL, - keymap_rows, KBC_MAX_COL, - kbc->keycode, kbc->idev); + ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", + rows_cfg, num_rows); + if (ret < 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 -EINVAL; + } + + for (i = 0; i < num_rows; i++) { + kbc->pin_cfg[rows_cfg[i]].type = PIN_CFG_ROW; + kbc->pin_cfg[rows_cfg[i]].num = i; } - return retval; + 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; + } + + return 0; } -static int __devinit tegra_kbc_probe(struct platform_device *pdev) +static int tegra_kbc_probe(struct platform_device *pdev) { - const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; struct tegra_kbc *kbc; - struct input_dev *input_dev; struct resource *res; - int irq; int err; int num_rows = 0; unsigned int debounce_cnt; unsigned int scan_time_rows; + unsigned int keymap_rows = KBC_MAX_KEY; - if (!pdata) - pdata = tegra_kbc_dt_parse_pdata(pdev); + kbc = devm_kzalloc(&pdev->dev, sizeof(*kbc), GFP_KERNEL); + if (!kbc) { + dev_err(&pdev->dev, "failed to alloc memory for kbc\n"); + return -ENOMEM; + } - if (!pdata) - return -EINVAL; + kbc->dev = &pdev->dev; + spin_lock_init(&kbc->lock); - if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) { - err = -EINVAL; - goto err_free_pdata; - } + err = tegra_kbc_parse_dt(kbc); + if (err) + return err; + + if (!tegra_kbc_check_pin_cfg(kbc, &num_rows)) + return -EINVAL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "failed to get I/O memory\n"); - err = -ENXIO; - goto err_free_pdata; + return -ENXIO; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + kbc->irq = platform_get_irq(pdev, 0); + if (kbc->irq < 0) { dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); - err = -ENXIO; - goto err_free_pdata; + return -ENXIO; } - kbc = kzalloc(sizeof(*kbc), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!kbc || !input_dev) { - err = -ENOMEM; - goto err_free_mem; + kbc->idev = devm_input_allocate_device(&pdev->dev); + if (!kbc->idev) { + dev_err(&pdev->dev, "failed to allocate input device\n"); + return -ENOMEM; } - kbc->pdata = pdata; - kbc->idev = input_dev; - kbc->irq = irq; - spin_lock_init(&kbc->lock); setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) { - dev_err(&pdev->dev, "failed to request I/O memory\n"); - err = -EBUSY; - goto err_free_mem; - } - - kbc->mmio = ioremap(res->start, resource_size(res)); + kbc->mmio = devm_request_and_ioremap(&pdev->dev, res); if (!kbc->mmio) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - err = -ENXIO; - goto err_free_mem_region; + dev_err(&pdev->dev, "Cannot request memregion/iomap address\n"); + return -EBUSY; } - kbc->clk = clk_get(&pdev->dev, NULL); + kbc->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(kbc->clk)) { dev_err(&pdev->dev, "failed to get keyboard clock\n"); - err = PTR_ERR(kbc->clk); - goto err_iounmap; + return PTR_ERR(kbc->clk); } /* @@ -774,37 +626,38 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) * the rows. There is an additional delay before the row scanning * starts. The repoll delay is computed in milliseconds. */ - debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + debounce_cnt = min(kbc->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows; - kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; + kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + kbc->repeat_cnt; kbc->repoll_dly = DIV_ROUND_UP(kbc->repoll_dly, KBC_CYCLE_MS); - kbc->wakeup_key = pdata->wakeup_key; - kbc->use_fn_map = pdata->use_fn_map; - kbc->use_ghost_filter = pdata->use_ghost_filter; + kbc->idev->name = pdev->name; + kbc->idev->id.bustype = BUS_HOST; + kbc->idev->dev.parent = &pdev->dev; + kbc->idev->open = tegra_kbc_open; + kbc->idev->close = tegra_kbc_close; - input_dev->name = pdev->name; - input_dev->id.bustype = BUS_HOST; - input_dev->dev.parent = &pdev->dev; - input_dev->open = tegra_kbc_open; - input_dev->close = tegra_kbc_close; + if (kbc->keymap_data && kbc->use_fn_map) + keymap_rows *= 2; - err = tegra_kbd_setup_keymap(kbc); + err = matrix_keypad_build_keymap(kbc->keymap_data, NULL, + keymap_rows, KBC_MAX_COL, + kbc->keycode, kbc->idev); if (err) { dev_err(&pdev->dev, "failed to setup keymap\n"); - goto err_put_clk; + return err; } - __set_bit(EV_REP, input_dev->evbit); - input_set_capability(input_dev, EV_MSC, MSC_SCAN); + __set_bit(EV_REP, kbc->idev->evbit); + input_set_capability(kbc->idev, EV_MSC, MSC_SCAN); - input_set_drvdata(input_dev, kbc); + input_set_drvdata(kbc->idev, kbc); - err = request_irq(kbc->irq, tegra_kbc_isr, + err = devm_request_irq(&pdev->dev, kbc->irq, tegra_kbc_isr, IRQF_NO_SUSPEND | IRQF_TRIGGER_HIGH, pdev->name, kbc); if (err) { dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); - goto err_put_clk; + return err; } disable_irq(kbc->irq); @@ -812,60 +665,28 @@ static int __devinit tegra_kbc_probe(struct platform_device *pdev) err = input_register_device(kbc->idev); if (err) { dev_err(&pdev->dev, "failed to register input device\n"); - goto err_free_irq; + return err; } platform_set_drvdata(pdev, kbc); - device_init_wakeup(&pdev->dev, pdata->wakeup); + device_init_wakeup(&pdev->dev, kbc->wakeup); return 0; - -err_free_irq: - free_irq(kbc->irq, pdev); -err_put_clk: - clk_put(kbc->clk); -err_iounmap: - iounmap(kbc->mmio); -err_free_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input_dev); - kfree(kbc); -err_free_pdata: - if (!pdev->dev.platform_data) - kfree(pdata); - - return err; } -static int __devexit tegra_kbc_remove(struct platform_device *pdev) +#ifdef CONFIG_PM_SLEEP +static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable) { - struct tegra_kbc *kbc = platform_get_drvdata(pdev); - struct resource *res; - - platform_set_drvdata(pdev, NULL); - - free_irq(kbc->irq, pdev); - clk_put(kbc->clk); - - input_unregister_device(kbc->idev); - iounmap(kbc->mmio); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - /* - * If we do not have platform data attached to the device we - * allocated it ourselves and thus need to free it. - */ - if (!pdev->dev.platform_data) - kfree(kbc->pdata); - - kfree(kbc); + u32 val; - return 0; + val = readl(kbc->mmio + KBC_CONTROL_0); + if (enable) + val |= KBC_CONTROL_KEYPRESS_INT_EN; + else + val &= ~KBC_CONTROL_KEYPRESS_INT_EN; + writel(val, kbc->mmio + KBC_CONTROL_0); } -#ifdef CONFIG_PM_SLEEP static int tegra_kbc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -954,7 +775,6 @@ MODULE_DEVICE_TABLE(of, tegra_kbc_of_match); static struct platform_driver tegra_kbc_driver = { .probe = tegra_kbc_probe, - .remove = __devexit_p(tegra_kbc_remove), .driver = { .name = "tegra-kbc", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index 4c34f21fbe2d..ee1635011292 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -153,7 +153,7 @@ static void keypad_stop(struct input_dev *dev) clk_disable(kp->clk); } -static int __devinit keypad_probe(struct platform_device *pdev) +static int keypad_probe(struct platform_device *pdev) { const struct matrix_keypad_platform_data *pdata; const struct matrix_keymap_data *keymap_data; @@ -301,7 +301,7 @@ error_res: return error; } -static int __devexit keypad_remove(struct platform_device *pdev) +static int keypad_remove(struct platform_device *pdev) { struct keypad_data *kp = platform_get_drvdata(pdev); @@ -319,7 +319,7 @@ static int __devexit keypad_remove(struct platform_device *pdev) static struct platform_driver keypad_driver = { .probe = keypad_probe, - .remove = __devexit_p(keypad_remove), + .remove = keypad_remove, .driver.name = "tnetv107x-keypad", .driver.owner = THIS_MODULE, }; diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index a2c6f79aa101..04f84fd57173 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c @@ -271,7 +271,7 @@ static irqreturn_t do_kp_irq(int irq, void *_kp) return IRQ_HANDLED; } -static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) +static int twl4030_kp_program(struct twl4030_keypad *kp) { u8 reg; int i; @@ -328,7 +328,7 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp) * Registers keypad device with input subsystem * and configures TWL4030 keypad registers */ -static int __devinit twl4030_kp_probe(struct platform_device *pdev) +static int twl4030_kp_probe(struct platform_device *pdev) { struct twl4030_keypad_data *pdata = pdev->dev.platform_data; const struct matrix_keymap_data *keymap_data; @@ -432,7 +432,7 @@ err1: return error; } -static int __devexit twl4030_kp_remove(struct platform_device *pdev) +static int twl4030_kp_remove(struct platform_device *pdev) { struct twl4030_keypad *kp = platform_get_drvdata(pdev); @@ -452,7 +452,7 @@ static int __devexit twl4030_kp_remove(struct platform_device *pdev) static struct platform_driver twl4030_kp_driver = { .probe = twl4030_kp_probe, - .remove = __devexit_p(twl4030_kp_remove), + .remove = twl4030_kp_remove, .driver = { .name = "twl4030_keypad", .owner = THIS_MODULE, diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index e0f6cd1ad0fd..ee163bee8cce 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c @@ -118,7 +118,7 @@ static void w90p910_keypad_close(struct input_dev *dev) clk_disable(keypad->clk); } -static int __devinit w90p910_keypad_probe(struct platform_device *pdev) +static int w90p910_keypad_probe(struct platform_device *pdev) { const struct w90p910_keypad_platform_data *pdata = pdev->dev.platform_data; @@ -234,7 +234,7 @@ failed_free: return error; } -static int __devexit w90p910_keypad_remove(struct platform_device *pdev) +static int w90p910_keypad_remove(struct platform_device *pdev) { struct w90p910_keypad *keypad = platform_get_drvdata(pdev); struct resource *res; @@ -257,7 +257,7 @@ static int __devexit w90p910_keypad_remove(struct platform_device *pdev) static struct platform_driver w90p910_keypad_driver = { .probe = w90p910_keypad_probe, - .remove = __devexit_p(w90p910_keypad_remove), + .remove = w90p910_keypad_remove, .driver = { .name = "nuc900-kpi", .owner = THIS_MODULE, diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c index d88d9be1d1b7..3ae496ea5fe6 100644 --- a/drivers/input/matrix-keymap.c +++ b/drivers/input/matrix-keymap.c @@ -18,6 +18,7 @@ */ #include <linux/device.h> +#include <linux/gfp.h> #include <linux/kernel.h> #include <linux/types.h> #include <linux/input.h> @@ -123,6 +124,11 @@ static int matrix_keypad_parse_of_keymap(const char *propname, * it will attempt load the keymap from property specified by @keymap_name * argument (or "linux,keymap" if @keymap_name is %NULL). * + * If @keymap is %NULL the function will automatically allocate managed + * block of memory to store the keymap. This memory will be associated with + * the parent device and automatically freed when device unbinds from the + * driver. + * * Callers are expected to set up input_dev->dev.parent before calling this * function. */ @@ -133,12 +139,27 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data, struct input_dev *input_dev) { unsigned int row_shift = get_count_order(cols); + size_t max_keys = rows << row_shift; int i; int error; + if (WARN_ON(!input_dev->dev.parent)) + return -EINVAL; + + if (!keymap) { + keymap = devm_kzalloc(input_dev->dev.parent, + max_keys * sizeof(*keymap), + GFP_KERNEL); + if (!keymap) { + dev_err(input_dev->dev.parent, + "Unable to allocate memory for keymap"); + return -ENOMEM; + } + } + input_dev->keycode = keymap; input_dev->keycodesize = sizeof(*keymap); - input_dev->keycodemax = rows << row_shift; + input_dev->keycodemax = max_keys; __set_bit(EV_KEY, input_dev->evbit); diff --git a/drivers/input/misc/88pm80x_onkey.c b/drivers/input/misc/88pm80x_onkey.c index 7f26e7b6c228..ee43e5b7c881 100644 --- a/drivers/input/misc/88pm80x_onkey.c +++ b/drivers/input/misc/88pm80x_onkey.c @@ -62,7 +62,7 @@ static irqreturn_t pm80x_onkey_handler(int irq, void *data) static SIMPLE_DEV_PM_OPS(pm80x_onkey_pm_ops, pm80x_dev_suspend, pm80x_dev_resume); -static int __devinit pm80x_onkey_probe(struct platform_device *pdev) +static int pm80x_onkey_probe(struct platform_device *pdev) { struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -139,7 +139,7 @@ out: return err; } -static int __devexit pm80x_onkey_remove(struct platform_device *pdev) +static int pm80x_onkey_remove(struct platform_device *pdev) { struct pm80x_onkey_info *info = platform_get_drvdata(pdev); @@ -157,7 +157,7 @@ static struct platform_driver pm80x_onkey_driver = { .pm = &pm80x_onkey_pm_ops, }, .probe = pm80x_onkey_probe, - .remove = __devexit_p(pm80x_onkey_remove), + .remove = pm80x_onkey_remove, }; module_platform_driver(pm80x_onkey_driver); diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c index f9ce1835e4d7..abd8453e5212 100644 --- a/drivers/input/misc/88pm860x_onkey.c +++ b/drivers/input/misc/88pm860x_onkey.c @@ -56,7 +56,7 @@ static irqreturn_t pm860x_onkey_handler(int irq, void *data) return IRQ_HANDLED; } -static int __devinit pm860x_onkey_probe(struct platform_device *pdev) +static int pm860x_onkey_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm860x_onkey_info *info; @@ -121,7 +121,7 @@ out: return ret; } -static int __devexit pm860x_onkey_remove(struct platform_device *pdev) +static int pm860x_onkey_remove(struct platform_device *pdev) { struct pm860x_onkey_info *info = platform_get_drvdata(pdev); @@ -161,7 +161,7 @@ static struct platform_driver pm860x_onkey_driver = { .pm = &pm860x_onkey_pm_ops, }, .probe = pm860x_onkey_probe, - .remove = __devexit_p(pm860x_onkey_remove), + .remove = pm860x_onkey_remove, }; module_platform_driver(pm860x_onkey_driver); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 104a7c3153c0..259ef31abb18 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -300,8 +300,7 @@ config INPUT_ATI_REMOTE2 called ati_remote2. config INPUT_KEYSPAN_REMOTE - tristate "Keyspan DMR USB remote control (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Keyspan DMR USB remote control" depends on USB_ARCH_HAS_HCD select USB help @@ -350,7 +349,6 @@ config INPUT_POWERMATE config INPUT_YEALINK tristate "Yealink usb-p1k voip phone" - depends on EXPERIMENTAL depends on USB_ARCH_HAS_HCD select USB help @@ -366,7 +364,6 @@ config INPUT_YEALINK config INPUT_CM109 tristate "C-Media CM109 USB I/O Controller" - depends on EXPERIMENTAL depends on USB_ARCH_HAS_HCD select USB help @@ -377,6 +374,16 @@ config INPUT_CM109 To compile this driver as a module, choose M here: the module will be called cm109. +config INPUT_RETU_PWRBUTTON + tristate "Retu Power button Driver" + depends on MFD_RETU + help + Say Y here if you want to enable power key reporting via the + Retu chips found in Nokia Internet Tablets (770, N800, N810). + + To compile this driver as a module, choose M here. The module will + be called retu-pwrbutton. + config INPUT_TWL4030_PWRBUTTON tristate "TWL4030 Power button Driver" depends on TWL4030_CORE @@ -444,7 +451,7 @@ config INPUT_PCF50633_PMU config INPUT_PCF8574 tristate "PCF8574 Keypad input device" - depends on I2C && EXPERIMENTAL + depends on I2C help Say Y here if you want to support a keypad connected via I2C with a PCF8574. @@ -454,7 +461,7 @@ config INPUT_PCF8574 config INPUT_PWM_BEEPER tristate "PWM beeper support" - depends on HAVE_PWM + depends on HAVE_PWM || PWM help Say Y here to get support for PWM based beeper devices. @@ -496,6 +503,16 @@ config INPUT_DA9052_ONKEY To compile this driver as a module, choose M here: the module will be called da9052_onkey. +config INPUT_DA9055_ONKEY + tristate "Dialog Semiconductor DA9055 ONKEY" + depends on MFD_DA9055 + help + Support the ONKEY of DA9055 PMICs as an input device + reporting power button status. + + To compile this driver as a module, choose M here: the module + will be called da9055_onkey. + config INPUT_DM355EVM tristate "TI DaVinci DM355 EVM Keypad and IR Remote" depends on MFD_DM355EVM_MSP diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index 5ea769eda999..1f1e1b109d9d 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -24,6 +24,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_DA9052_ONKEY) += da9052_onkey.o +obj-$(CONFIG_INPUT_DA9055_ONKEY) += da9055_onkey.o obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o @@ -46,6 +47,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_RB532_BUTTON) += rb532_button.o +obj-$(CONFIG_INPUT_RETU_PWRBUTTON) += retu-pwrbutton.o obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c index 84ec691c05aa..2f090b46e716 100644 --- a/drivers/input/misc/ab8500-ponkey.c +++ b/drivers/input/misc/ab8500-ponkey.c @@ -45,7 +45,7 @@ static irqreturn_t ab8500_ponkey_handler(int irq, void *data) return IRQ_HANDLED; } -static int __devinit ab8500_ponkey_probe(struct platform_device *pdev) +static int ab8500_ponkey_probe(struct platform_device *pdev) { struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); struct ab8500_ponkey *ponkey; @@ -118,7 +118,7 @@ err_free_mem: return error; } -static int __devexit ab8500_ponkey_remove(struct platform_device *pdev) +static int ab8500_ponkey_remove(struct platform_device *pdev) { struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev); @@ -146,7 +146,7 @@ static struct platform_driver ab8500_ponkey_driver = { .of_match_table = of_match_ptr(ab8500_ponkey_match), }, .probe = ab8500_ponkey_probe, - .remove = __devexit_p(ab8500_ponkey_remove), + .remove = ab8500_ponkey_remove, }; module_platform_driver(ab8500_ponkey_driver); diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index c8a79015472a..29d2064c26f2 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -72,7 +72,7 @@ static int ad714x_i2c_read(struct ad714x_chip *chip, return 0; } -static int __devinit ad714x_i2c_probe(struct i2c_client *client, +static int ad714x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad714x_chip *chip; @@ -87,7 +87,7 @@ static int __devinit ad714x_i2c_probe(struct i2c_client *client, return 0; } -static int __devexit ad714x_i2c_remove(struct i2c_client *client) +static int ad714x_i2c_remove(struct i2c_client *client) { struct ad714x_chip *chip = i2c_get_clientdata(client); @@ -112,7 +112,7 @@ static struct i2c_driver ad714x_i2c_driver = { .pm = &ad714x_i2c_pm, }, .probe = ad714x_i2c_probe, - .remove = __devexit_p(ad714x_i2c_remove), + .remove = ad714x_i2c_remove, .id_table = ad714x_id, }; diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c index 75f6136d608e..bdccca42d138 100644 --- a/drivers/input/misc/ad714x-spi.c +++ b/drivers/input/misc/ad714x-spi.c @@ -83,7 +83,7 @@ static int ad714x_spi_write(struct ad714x_chip *chip, return 0; } -static int __devinit ad714x_spi_probe(struct spi_device *spi) +static int ad714x_spi_probe(struct spi_device *spi) { struct ad714x_chip *chip; int err; @@ -103,7 +103,7 @@ static int __devinit ad714x_spi_probe(struct spi_device *spi) return 0; } -static int __devexit ad714x_spi_remove(struct spi_device *spi) +static int ad714x_spi_remove(struct spi_device *spi) { struct ad714x_chip *chip = spi_get_drvdata(spi); @@ -120,7 +120,7 @@ static struct spi_driver ad714x_spi_driver = { .pm = &ad714x_spi_pm, }, .probe = ad714x_spi_probe, - .remove = __devexit_p(ad714x_spi_remove), + .remove = ad714x_spi_remove, }; module_spi_driver(ad714x_spi_driver); diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c index dd1d1c145a7f..535dda48cace 100644 --- a/drivers/input/misc/adxl34x-i2c.c +++ b/drivers/input/misc/adxl34x-i2c.c @@ -73,7 +73,7 @@ static const struct adxl34x_bus_ops adxl34x_i2c_bops = { .read_block = adxl34x_i2c_read_block, }; -static int __devinit adxl34x_i2c_probe(struct i2c_client *client, +static int adxl34x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct adxl34x *ac; @@ -98,7 +98,7 @@ static int __devinit adxl34x_i2c_probe(struct i2c_client *client, return 0; } -static int __devexit adxl34x_i2c_remove(struct i2c_client *client) +static int adxl34x_i2c_remove(struct i2c_client *client) { struct adxl34x *ac = i2c_get_clientdata(client); @@ -144,7 +144,7 @@ static struct i2c_driver adxl34x_driver = { .pm = &adxl34x_i2c_pm, }, .probe = adxl34x_i2c_probe, - .remove = __devexit_p(adxl34x_i2c_remove), + .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 820a802a1e6e..ad5f40d37e48 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -65,7 +65,7 @@ static const struct adxl34x_bus_ops adxl34x_spi_bops = { .read_block = adxl34x_spi_read_block, }; -static int __devinit adxl34x_spi_probe(struct spi_device *spi) +static int adxl34x_spi_probe(struct spi_device *spi) { struct adxl34x *ac; @@ -87,7 +87,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi) return 0; } -static int __devexit adxl34x_spi_remove(struct spi_device *spi) +static int adxl34x_spi_remove(struct spi_device *spi) { struct adxl34x *ac = dev_get_drvdata(&spi->dev); @@ -126,7 +126,7 @@ static struct spi_driver adxl34x_driver = { .pm = &adxl34x_spi_pm, }, .probe = adxl34x_spi_probe, - .remove = __devexit_p(adxl34x_spi_remove), + .remove = adxl34x_spi_remove, }; module_spi_driver(adxl34x_driver); diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index 1cf72fe513e6..0735de3a6468 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -232,7 +232,7 @@ static const struct adxl34x_platform_data adxl34x_default_init = { .ev_code_tap = {BTN_TOUCH, BTN_TOUCH, BTN_TOUCH}, /* EV_KEY {x,y,z} */ .power_mode = ADXL_AUTO_SLEEP | ADXL_LINK, - .fifo_mode = FIFO_STREAM, + .fifo_mode = ADXL_FIFO_STREAM, .watermark = 0, }; @@ -732,7 +732,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, mutex_init(&ac->mutex); input_dev->name = "ADXL34x accelerometer"; - revid = ac->bops->read(dev, DEVID); + revid = AC_READ(ac, DEVID); switch (revid) { case ID_ADXL345: @@ -809,7 +809,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (FIFO_MODE(pdata->fifo_mode) == FIFO_BYPASS) ac->fifo_delay = false; - ac->bops->write(dev, POWER_CTL, 0); + AC_WRITE(ac, POWER_CTL, 0); err = request_threaded_irq(ac->irq, NULL, adxl34x_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, @@ -827,7 +827,6 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, if (err) goto err_remove_attr; - AC_WRITE(ac, THRESH_TAP, pdata->tap_threshold); AC_WRITE(ac, OFSX, pdata->x_axis_offset); ac->hwcal.x = pdata->x_axis_offset; AC_WRITE(ac, OFSY, pdata->y_axis_offset); diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 26f13131639a..5d4402365a52 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c @@ -121,7 +121,7 @@ static int atlas_acpi_button_add(struct acpi_device *device) return err; } -static int atlas_acpi_button_remove(struct acpi_device *device, int type) +static int atlas_acpi_button_remove(struct acpi_device *device) { acpi_status status; diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index 1c4146fccfdf..a6666e142a91 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c @@ -90,7 +90,7 @@ static irqreturn_t bfin_rotary_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit bfin_rotary_probe(struct platform_device *pdev) +static int bfin_rotary_probe(struct platform_device *pdev) { struct bfin_rotary_platform_data *pdata = pdev->dev.platform_data; struct bfin_rot *rotary; @@ -196,7 +196,7 @@ out1: return error; } -static int __devexit bfin_rotary_remove(struct platform_device *pdev) +static int bfin_rotary_remove(struct platform_device *pdev) { struct bfin_rot *rotary = platform_get_drvdata(pdev); @@ -255,7 +255,7 @@ static const struct dev_pm_ops bfin_rotary_pm_ops = { static struct platform_driver bfin_rotary_device_driver = { .probe = bfin_rotary_probe, - .remove = __devexit_p(bfin_rotary_remove), + .remove = bfin_rotary_remove, .driver = { .name = "bfin-rotary", .owner = THIS_MODULE, diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c index e2f1e9f952b1..865c2f9d25b9 100644 --- a/drivers/input/misc/bma150.c +++ b/drivers/input/misc/bma150.c @@ -46,18 +46,6 @@ #define BMA150_POLL_MAX 200 #define BMA150_POLL_MIN 0 -#define BMA150_BW_25HZ 0 -#define BMA150_BW_50HZ 1 -#define BMA150_BW_100HZ 2 -#define BMA150_BW_190HZ 3 -#define BMA150_BW_375HZ 4 -#define BMA150_BW_750HZ 5 -#define BMA150_BW_1500HZ 6 - -#define BMA150_RANGE_2G 0 -#define BMA150_RANGE_4G 1 -#define BMA150_RANGE_8G 2 - #define BMA150_MODE_NORMAL 0 #define BMA150_MODE_SLEEP 2 #define BMA150_MODE_WAKE_UP 3 @@ -158,7 +146,7 @@ struct bma150_data { * are stated and verified by Bosch Sensortec where they are configured * to provide a generic sensitivity performance. */ -static struct bma150_cfg default_cfg __devinitdata = { +static struct bma150_cfg default_cfg = { .any_motion_int = 1, .hg_int = 1, .lg_int = 1, @@ -224,7 +212,7 @@ static int bma150_set_mode(struct bma150_data *bma150, u8 mode) return 0; } -static int __devinit bma150_soft_reset(struct bma150_data *bma150) +static int bma150_soft_reset(struct bma150_data *bma150) { int error; @@ -237,19 +225,19 @@ static int __devinit bma150_soft_reset(struct bma150_data *bma150) return 0; } -static int __devinit bma150_set_range(struct bma150_data *bma150, u8 range) +static int bma150_set_range(struct bma150_data *bma150, u8 range) { return bma150_set_reg_bits(bma150->client, range, BMA150_RANGE_POS, BMA150_RANGE_MSK, BMA150_RANGE_REG); } -static int __devinit bma150_set_bandwidth(struct bma150_data *bma150, u8 bw) +static int bma150_set_bandwidth(struct bma150_data *bma150, u8 bw) { return bma150_set_reg_bits(bma150->client, bw, BMA150_BANDWIDTH_POS, BMA150_BANDWIDTH_MSK, BMA150_BANDWIDTH_REG); } -static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150, +static int bma150_set_low_g_interrupt(struct bma150_data *bma150, u8 enable, u8 hyst, u8 dur, u8 thres) { int error; @@ -273,7 +261,7 @@ static int __devinit bma150_set_low_g_interrupt(struct bma150_data *bma150, BMA150_LOW_G_EN_REG); } -static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150, +static int bma150_set_high_g_interrupt(struct bma150_data *bma150, u8 enable, u8 hyst, u8 dur, u8 thres) { int error; @@ -300,7 +288,7 @@ static int __devinit bma150_set_high_g_interrupt(struct bma150_data *bma150, } -static int __devinit bma150_set_any_motion_interrupt(struct bma150_data *bma150, +static int bma150_set_any_motion_interrupt(struct bma150_data *bma150, u8 enable, u8 dur, u8 thres) { int error; @@ -372,7 +360,7 @@ static int bma150_open(struct bma150_data *bma150) int error; error = pm_runtime_get_sync(&bma150->client->dev); - if (error && error != -ENOSYS) + if (error < 0 && error != -ENOSYS) return error; /* @@ -424,7 +412,7 @@ static void bma150_poll_close(struct input_polled_dev *ipoll_dev) bma150_close(bma150); } -static int __devinit bma150_initialize(struct bma150_data *bma150, +static int bma150_initialize(struct bma150_data *bma150, const struct bma150_cfg *cfg) { int error; @@ -465,7 +453,7 @@ static int __devinit bma150_initialize(struct bma150_data *bma150, return bma150_set_mode(bma150, BMA150_MODE_SLEEP); } -static void __devinit bma150_init_input_device(struct bma150_data *bma150, +static void bma150_init_input_device(struct bma150_data *bma150, struct input_dev *idev) { idev->name = BMA150_DRIVER; @@ -479,7 +467,7 @@ static void __devinit bma150_init_input_device(struct bma150_data *bma150, input_set_abs_params(idev, ABS_Z, ABSMIN_ACC_VAL, ABSMAX_ACC_VAL, 0, 0); } -static int __devinit bma150_register_input_device(struct bma150_data *bma150) +static int bma150_register_input_device(struct bma150_data *bma150) { struct input_dev *idev; int error; @@ -504,7 +492,7 @@ static int __devinit bma150_register_input_device(struct bma150_data *bma150) return 0; } -static int __devinit bma150_register_polled_device(struct bma150_data *bma150) +static int bma150_register_polled_device(struct bma150_data *bma150) { struct input_polled_dev *ipoll_dev; int error; @@ -535,7 +523,7 @@ static int __devinit bma150_register_polled_device(struct bma150_data *bma150) return 0; } -static int __devinit bma150_probe(struct i2c_client *client, +static int bma150_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct bma150_platform_data *pdata = client->dev.platform_data; @@ -613,7 +601,7 @@ err_free_mem: return error; } -static int __devexit bma150_remove(struct i2c_client *client) +static int bma150_remove(struct i2c_client *client) { struct bma150_data *bma150 = i2c_get_clientdata(client); @@ -670,7 +658,7 @@ static struct i2c_driver bma150_driver = { .class = I2C_CLASS_HWMON, .id_table = bma150_id, .probe = bma150_probe, - .remove = __devexit_p(bma150_remove), + .remove = bma150_remove, }; module_i2c_driver(bma150_driver); diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c index fe9b85f07792..4fdef98ceb56 100644 --- a/drivers/input/misc/cma3000_d0x_i2c.c +++ b/drivers/input/misc/cma3000_d0x_i2c.c @@ -55,7 +55,7 @@ static const struct cma3000_bus_ops cma3000_i2c_bops = { .write = cma3000_i2c_set, }; -static int __devinit cma3000_i2c_probe(struct i2c_client *client, +static int cma3000_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cma3000_accl_data *data; @@ -69,7 +69,7 @@ static int __devinit cma3000_i2c_probe(struct i2c_client *client, return 0; } -static int __devexit cma3000_i2c_remove(struct i2c_client *client) +static int cma3000_i2c_remove(struct i2c_client *client) { struct cma3000_accl_data *data = i2c_get_clientdata(client); @@ -114,7 +114,7 @@ MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id); static struct i2c_driver cma3000_i2c_driver = { .probe = cma3000_i2c_probe, - .remove = __devexit_p(cma3000_i2c_remove), + .remove = cma3000_i2c_remove, .id_table = cma3000_i2c_id, .driver = { .name = "cma3000_i2c_accl", diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 53e43d295148..4f77f87847e8 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -73,7 +73,7 @@ static void handle_buttons(struct input_polled_dev *dev) } } -static int __devinit cobalt_buttons_probe(struct platform_device *pdev) +static int cobalt_buttons_probe(struct platform_device *pdev) { struct buttons_dev *bdev; struct input_polled_dev *poll_dev; @@ -135,7 +135,7 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev) return error; } -static int __devexit cobalt_buttons_remove(struct platform_device *pdev) +static int cobalt_buttons_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct buttons_dev *bdev = dev_get_drvdata(dev); @@ -157,7 +157,7 @@ MODULE_ALIAS("platform:Cobalt buttons"); static struct platform_driver cobalt_buttons_driver = { .probe = cobalt_buttons_probe, - .remove = __devexit_p(cobalt_buttons_remove), + .remove = cobalt_buttons_remove, .driver = { .name = "Cobalt buttons", .owner = THIS_MODULE, diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c index 3c843cd725fa..020569a499f2 100644 --- a/drivers/input/misc/da9052_onkey.c +++ b/drivers/input/misc/da9052_onkey.c @@ -24,7 +24,6 @@ struct da9052_onkey { struct da9052 *da9052; struct input_dev *input; struct delayed_work work; - unsigned int irq; }; static void da9052_onkey_query(struct da9052_onkey *onkey) @@ -71,12 +70,11 @@ static irqreturn_t da9052_onkey_irq(int irq, void *data) return IRQ_HANDLED; } -static int __devinit da9052_onkey_probe(struct platform_device *pdev) +static int da9052_onkey_probe(struct platform_device *pdev) { struct da9052 *da9052 = dev_get_drvdata(pdev->dev.parent); struct da9052_onkey *onkey; struct input_dev *input_dev; - int irq; int error; if (!da9052) { @@ -84,13 +82,6 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) return -EINVAL; } - irq = platform_get_irq_byname(pdev, "ONKEY"); - if (irq < 0) { - dev_err(&pdev->dev, - "Failed to get an IRQ for input device, %d\n", irq); - return -EINVAL; - } - onkey = kzalloc(sizeof(*onkey), GFP_KERNEL); input_dev = input_allocate_device(); if (!onkey || !input_dev) { @@ -101,7 +92,6 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) onkey->input = input_dev; onkey->da9052 = da9052; - onkey->irq = irq; INIT_DELAYED_WORK(&onkey->work, da9052_onkey_work); input_dev->name = "da9052-onkey"; @@ -111,13 +101,11 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) input_dev->evbit[0] = BIT_MASK(EV_KEY); __set_bit(KEY_POWER, input_dev->keybit); - error = request_threaded_irq(onkey->irq, NULL, da9052_onkey_irq, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "ONKEY", onkey); + error = da9052_request_irq(onkey->da9052, DA9052_IRQ_NONKEY, "ONKEY", + da9052_onkey_irq, onkey); if (error < 0) { dev_err(onkey->da9052->dev, - "Failed to register ONKEY IRQ %d, error = %d\n", - onkey->irq, error); + "Failed to register ONKEY IRQ: %d\n", error); goto err_free_mem; } @@ -132,7 +120,7 @@ static int __devinit da9052_onkey_probe(struct platform_device *pdev) return 0; err_free_irq: - free_irq(onkey->irq, onkey); + da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey); cancel_delayed_work_sync(&onkey->work); err_free_mem: input_free_device(input_dev); @@ -141,11 +129,11 @@ err_free_mem: return error; } -static int __devexit da9052_onkey_remove(struct platform_device *pdev) +static int da9052_onkey_remove(struct platform_device *pdev) { struct da9052_onkey *onkey = platform_get_drvdata(pdev); - free_irq(onkey->irq, onkey); + da9052_free_irq(onkey->da9052, DA9052_IRQ_NONKEY, onkey); cancel_delayed_work_sync(&onkey->work); input_unregister_device(onkey->input); @@ -156,7 +144,7 @@ static int __devexit da9052_onkey_remove(struct platform_device *pdev) static struct platform_driver da9052_onkey_driver = { .probe = da9052_onkey_probe, - .remove = __devexit_p(da9052_onkey_remove), + .remove = da9052_onkey_remove, .driver = { .name = "da9052-onkey", .owner = THIS_MODULE, diff --git a/drivers/input/misc/da9055_onkey.c b/drivers/input/misc/da9055_onkey.c new file mode 100644 index 000000000000..ee6ae3a00174 --- /dev/null +++ b/drivers/input/misc/da9055_onkey.c @@ -0,0 +1,171 @@ +/* + * ON pin driver for Dialog DA9055 PMICs + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: David Dajun Chen <dchen@diasemi.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/init.h> +#include <linux/input.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <linux/mfd/da9055/core.h> +#include <linux/mfd/da9055/reg.h> + +struct da9055_onkey { + struct da9055 *da9055; + struct input_dev *input; + struct delayed_work work; +}; + +static void da9055_onkey_query(struct da9055_onkey *onkey) +{ + int key_stat; + + key_stat = da9055_reg_read(onkey->da9055, DA9055_REG_STATUS_A); + if (key_stat < 0) { + dev_err(onkey->da9055->dev, + "Failed to read onkey event %d\n", key_stat); + } else { + key_stat &= DA9055_NOKEY_STS; + /* + * Onkey status bit is cleared when onkey button is relased. + */ + if (!key_stat) { + input_report_key(onkey->input, KEY_POWER, 0); + input_sync(onkey->input); + } + } + + /* + * Interrupt is generated only when the ONKEY pin is asserted. + * Hence the deassertion of the pin is simulated through work queue. + */ + if (key_stat) + schedule_delayed_work(&onkey->work, msecs_to_jiffies(10)); + +} + +static void da9055_onkey_work(struct work_struct *work) +{ + struct da9055_onkey *onkey = container_of(work, struct da9055_onkey, + work.work); + + da9055_onkey_query(onkey); +} + +static irqreturn_t da9055_onkey_irq(int irq, void *data) +{ + struct da9055_onkey *onkey = data; + + input_report_key(onkey->input, KEY_POWER, 1); + input_sync(onkey->input); + + da9055_onkey_query(onkey); + + return IRQ_HANDLED; +} + +static int da9055_onkey_probe(struct platform_device *pdev) +{ + struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent); + struct da9055_onkey *onkey; + struct input_dev *input_dev; + int irq, err; + + irq = platform_get_irq_byname(pdev, "ONKEY"); + if (irq < 0) { + dev_err(&pdev->dev, + "Failed to get an IRQ for input device, %d\n", irq); + return -EINVAL; + } + + onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL); + if (!onkey) { + dev_err(&pdev->dev, "Failed to allocate memory\n"); + return -ENOMEM; + } + + input_dev = input_allocate_device(); + if (!input_dev) { + dev_err(&pdev->dev, "Failed to allocate memory\n"); + return -ENOMEM; + } + + onkey->input = input_dev; + onkey->da9055 = da9055; + input_dev->name = "da9055-onkey"; + input_dev->phys = "da9055-onkey/input0"; + input_dev->dev.parent = &pdev->dev; + + input_dev->evbit[0] = BIT_MASK(EV_KEY); + __set_bit(KEY_POWER, input_dev->keybit); + + INIT_DELAYED_WORK(&onkey->work, da9055_onkey_work); + + irq = regmap_irq_get_virq(da9055->irq_data, irq); + err = request_threaded_irq(irq, NULL, da9055_onkey_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ONKEY", onkey); + if (err < 0) { + dev_err(&pdev->dev, + "Failed to register ONKEY IRQ %d, error = %d\n", + irq, err); + goto err_free_input; + } + + err = input_register_device(input_dev); + if (err) { + dev_err(&pdev->dev, "Unable to register input device, %d\n", + err); + goto err_free_irq; + } + + platform_set_drvdata(pdev, onkey); + + return 0; + +err_free_irq: + free_irq(irq, onkey); + cancel_delayed_work_sync(&onkey->work); +err_free_input: + input_free_device(input_dev); + + return err; +} + +static int da9055_onkey_remove(struct platform_device *pdev) +{ + struct da9055_onkey *onkey = platform_get_drvdata(pdev); + int irq = platform_get_irq_byname(pdev, "ONKEY"); + + irq = regmap_irq_get_virq(onkey->da9055->irq_data, irq); + free_irq(irq, onkey); + cancel_delayed_work_sync(&onkey->work); + input_unregister_device(onkey->input); + + return 0; +} + +static struct platform_driver da9055_onkey_driver = { + .probe = da9055_onkey_probe, + .remove = da9055_onkey_remove, + .driver = { + .name = "da9055-onkey", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(da9055_onkey_driver); + +MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); +MODULE_DESCRIPTION("Onkey driver for DA9055"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9055-onkey"); diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index c1313d8535c3..a309a5c0899e 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c @@ -173,7 +173,7 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) /*----------------------------------------------------------------------*/ -static int __devinit dm355evm_keys_probe(struct platform_device *pdev) +static int dm355evm_keys_probe(struct platform_device *pdev) { struct dm355evm_keys *keys; struct input_dev *input; @@ -239,7 +239,7 @@ fail1: return status; } -static int __devexit dm355evm_keys_remove(struct platform_device *pdev) +static int dm355evm_keys_remove(struct platform_device *pdev) { struct dm355evm_keys *keys = platform_get_drvdata(pdev); @@ -262,7 +262,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev) */ static struct platform_driver dm355evm_keys_driver = { .probe = dm355evm_keys_probe, - .remove = __devexit_p(dm355evm_keys_remove), + .remove = dm355evm_keys_remove, .driver = { .owner = THIS_MODULE, .name = "dm355evm_keys", diff --git a/drivers/input/misc/gp2ap002a00f.c b/drivers/input/misc/gp2ap002a00f.c index b6664cfa340a..fe30bd0fe4bd 100644 --- a/drivers/input/misc/gp2ap002a00f.c +++ b/drivers/input/misc/gp2ap002a00f.c @@ -98,7 +98,7 @@ static void gp2a_device_close(struct input_dev *dev) "unable to deactivate, err %d\n", error); } -static int __devinit gp2a_initialize(struct gp2a_data *dt) +static int gp2a_initialize(struct gp2a_data *dt) { int error; @@ -122,7 +122,7 @@ static int __devinit gp2a_initialize(struct gp2a_data *dt) return error; } -static int __devinit gp2a_probe(struct i2c_client *client, +static int gp2a_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct gp2a_platform_data *pdata = client->dev.platform_data; @@ -205,7 +205,7 @@ err_hw_shutdown: return error; } -static int __devexit gp2a_remove(struct i2c_client *client) +static int gp2a_remove(struct i2c_client *client) { struct gp2a_data *dt = i2c_get_clientdata(client); const struct gp2a_platform_data *pdata = dt->pdata; @@ -277,7 +277,7 @@ static struct i2c_driver gp2a_i2c_driver = { .pm = &gp2a_pm, }, .probe = gp2a_probe, - .remove = __devexit_p(gp2a_remove), + .remove = gp2a_remove, .id_table = gp2a_i2c_id, }; diff --git a/drivers/input/misc/gpio_tilt_polled.c b/drivers/input/misc/gpio_tilt_polled.c index 277a0574c199..da05cca8b562 100644 --- a/drivers/input/misc/gpio_tilt_polled.c +++ b/drivers/input/misc/gpio_tilt_polled.c @@ -96,7 +96,7 @@ static void gpio_tilt_polled_close(struct input_polled_dev *dev) pdata->disable(tdev->dev); } -static int __devinit gpio_tilt_polled_probe(struct platform_device *pdev) +static int gpio_tilt_polled_probe(struct platform_device *pdev) { const struct gpio_tilt_platform_data *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; @@ -179,7 +179,7 @@ err_free_tdev: return error; } -static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev) +static int gpio_tilt_polled_remove(struct platform_device *pdev) { struct gpio_tilt_polled_dev *tdev = platform_get_drvdata(pdev); const struct gpio_tilt_platform_data *pdata = tdev->pdata; @@ -198,7 +198,7 @@ static int __devexit gpio_tilt_polled_remove(struct platform_device *pdev) static struct platform_driver gpio_tilt_polled_driver = { .probe = gpio_tilt_polled_probe, - .remove = __devexit_p(gpio_tilt_polled_remove), + .remove = gpio_tilt_polled_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 50e283068301..6ab3decc86e6 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -87,7 +87,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) +static int ixp4xx_spkr_probe(struct platform_device *dev) { struct input_dev *input_dev; int err; @@ -132,7 +132,7 @@ static int __devinit ixp4xx_spkr_probe(struct platform_device *dev) return err; } -static int __devexit ixp4xx_spkr_remove(struct platform_device *dev) +static int ixp4xx_spkr_remove(struct platform_device *dev) { struct input_dev *input_dev = platform_get_drvdata(dev); unsigned int pin = (unsigned int) input_get_drvdata(input_dev); @@ -165,7 +165,7 @@ static struct platform_driver ixp4xx_spkr_platform_driver = { .owner = THIS_MODULE, }, .probe = ixp4xx_spkr_probe, - .remove = __devexit_p(ixp4xx_spkr_remove), + .remove = ixp4xx_spkr_remove, .shutdown = ixp4xx_spkr_shutdown, }; module_platform_driver(ixp4xx_spkr_platform_driver); diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c index f46139f19ff1..a993b67a8a5b 100644 --- a/drivers/input/misc/kxtj9.c +++ b/drivers/input/misc/kxtj9.c @@ -295,7 +295,7 @@ static void kxtj9_input_close(struct input_dev *dev) kxtj9_disable(tj9); } -static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9, +static void kxtj9_init_input_device(struct kxtj9_data *tj9, struct input_dev *input_dev) { __set_bit(EV_ABS, input_dev->evbit); @@ -308,7 +308,7 @@ static void __devinit kxtj9_init_input_device(struct kxtj9_data *tj9, input_dev->dev.parent = &tj9->client->dev; } -static int __devinit kxtj9_setup_input_device(struct kxtj9_data *tj9) +static int kxtj9_setup_input_device(struct kxtj9_data *tj9) { struct input_dev *input_dev; int err; @@ -433,7 +433,7 @@ static void kxtj9_polled_input_close(struct input_polled_dev *dev) kxtj9_disable(tj9); } -static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9) +static int kxtj9_setup_polled_device(struct kxtj9_data *tj9) { int err; struct input_polled_dev *poll_dev; @@ -466,7 +466,7 @@ static int __devinit kxtj9_setup_polled_device(struct kxtj9_data *tj9) return 0; } -static void __devexit kxtj9_teardown_polled_device(struct kxtj9_data *tj9) +static void kxtj9_teardown_polled_device(struct kxtj9_data *tj9) { input_unregister_polled_device(tj9->poll_dev); input_free_polled_device(tj9->poll_dev); @@ -485,7 +485,7 @@ static inline void kxtj9_teardown_polled_device(struct kxtj9_data *tj9) #endif -static int __devinit kxtj9_verify(struct kxtj9_data *tj9) +static int kxtj9_verify(struct kxtj9_data *tj9) { int retval; @@ -506,7 +506,7 @@ out: return retval; } -static int __devinit kxtj9_probe(struct i2c_client *client, +static int kxtj9_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct kxtj9_platform_data *pdata = client->dev.platform_data; @@ -594,7 +594,7 @@ err_free_mem: return err; } -static int __devexit kxtj9_remove(struct i2c_client *client) +static int kxtj9_remove(struct i2c_client *client) { struct kxtj9_data *tj9 = i2c_get_clientdata(client); @@ -663,7 +663,7 @@ static struct i2c_driver kxtj9_driver = { .pm = &kxtj9_pm_ops, }, .probe = kxtj9_probe, - .remove = __devexit_p(kxtj9_remove), + .remove = kxtj9_remove, .id_table = kxtj9_id, }; diff --git a/drivers/input/misc/m68kspkr.c b/drivers/input/misc/m68kspkr.c index 0c64d9bb718e..b40ee4b47f4f 100644 --- a/drivers/input/misc/m68kspkr.c +++ b/drivers/input/misc/m68kspkr.c @@ -48,7 +48,7 @@ static int m68kspkr_event(struct input_dev *dev, unsigned int type, unsigned int return 0; } -static int __devinit m68kspkr_probe(struct platform_device *dev) +static int m68kspkr_probe(struct platform_device *dev) { struct input_dev *input_dev; int err; @@ -80,7 +80,7 @@ static int __devinit m68kspkr_probe(struct platform_device *dev) return 0; } -static int __devexit m68kspkr_remove(struct platform_device *dev) +static int m68kspkr_remove(struct platform_device *dev) { struct input_dev *input_dev = platform_get_drvdata(dev); @@ -104,7 +104,7 @@ static struct platform_driver m68kspkr_platform_driver = { .owner = THIS_MODULE, }, .probe = m68kspkr_probe, - .remove = __devexit_p(m68kspkr_remove), + .remove = m68kspkr_remove, .shutdown = m68kspkr_shutdown, }; diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c index 0a12b74140d3..369a39de4ff3 100644 --- a/drivers/input/misc/max8925_onkey.c +++ b/drivers/input/misc/max8925_onkey.c @@ -62,7 +62,7 @@ static irqreturn_t max8925_onkey_handler(int irq, void *data) return IRQ_HANDLED; } -static int __devinit max8925_onkey_probe(struct platform_device *pdev) +static int max8925_onkey_probe(struct platform_device *pdev) { struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); struct max8925_onkey_info *info; @@ -141,7 +141,7 @@ err_free_mem: return error; } -static int __devexit max8925_onkey_remove(struct platform_device *pdev) +static int max8925_onkey_remove(struct platform_device *pdev) { struct max8925_onkey_info *info = platform_get_drvdata(pdev); struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); @@ -195,7 +195,7 @@ static struct platform_driver max8925_onkey_driver = { .pm = &max8925_onkey_pm_ops, }, .probe = max8925_onkey_probe, - .remove = __devexit_p(max8925_onkey_remove), + .remove = max8925_onkey_remove, }; module_platform_driver(max8925_onkey_driver); diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c index 05b7b8bfaf0a..e973133212a5 100644 --- a/drivers/input/misc/max8997_haptic.c +++ b/drivers/input/misc/max8997_haptic.c @@ -241,7 +241,7 @@ static void max8997_haptic_close(struct input_dev *dev) max8997_haptic_disable(chip); } -static int __devinit max8997_haptic_probe(struct platform_device *pdev) +static int max8997_haptic_probe(struct platform_device *pdev) { struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); const struct max8997_platform_data *pdata = @@ -354,7 +354,7 @@ err_free_mem: return error; } -static int __devexit max8997_haptic_remove(struct platform_device *pdev) +static int max8997_haptic_remove(struct platform_device *pdev) { struct max8997_haptic *chip = platform_get_drvdata(pdev); @@ -396,7 +396,7 @@ static struct platform_driver max8997_haptic_driver = { .pm = &max8997_haptic_pm_ops, }, .probe = max8997_haptic_probe, - .remove = __devexit_p(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 8428f1e8e83e..0906ca593d5f 100644 --- a/drivers/input/misc/mc13783-pwrbutton.c +++ b/drivers/input/misc/mc13783-pwrbutton.c @@ -89,7 +89,7 @@ static irqreturn_t button_irq(int irq, void *_priv) return IRQ_HANDLED; } -static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev) +static int mc13783_pwrbutton_probe(struct platform_device *pdev) { const struct mc13xxx_buttons_platform_data *pdata; struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); @@ -230,7 +230,7 @@ free_input_dev: return err; } -static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev) +static int mc13783_pwrbutton_remove(struct platform_device *pdev) { struct mc13783_pwrb *priv = platform_get_drvdata(pdev); const struct mc13xxx_buttons_platform_data *pdata; @@ -257,7 +257,7 @@ static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev) static struct platform_driver mc13783_pwrbutton_driver = { .probe = mc13783_pwrbutton_probe, - .remove = __devexit_p(mc13783_pwrbutton_remove), + .remove = mc13783_pwrbutton_remove, .driver = { .name = "mc13783-pwrbutton", .owner = THIS_MODULE, diff --git a/drivers/input/misc/mma8450.c b/drivers/input/misc/mma8450.c index 873ebced544e..480557f14f23 100644 --- a/drivers/input/misc/mma8450.c +++ b/drivers/input/misc/mma8450.c @@ -167,7 +167,7 @@ static void mma8450_close(struct input_polled_dev *dev) /* * I2C init/probing/exit functions */ -static int __devinit mma8450_probe(struct i2c_client *c, +static int mma8450_probe(struct i2c_client *c, const struct i2c_device_id *id) { struct input_polled_dev *idev; @@ -212,7 +212,7 @@ err_free_mem: return err; } -static int __devexit mma8450_remove(struct i2c_client *c) +static int mma8450_remove(struct i2c_client *c) { struct mma8450 *m = i2c_get_clientdata(c); struct input_polled_dev *idev = m->idev; @@ -243,7 +243,7 @@ static struct i2c_driver mma8450_driver = { .of_match_table = mma8450_dt_ids, }, .probe = mma8450_probe, - .remove = __devexit_p(mma8450_remove), + .remove = mma8450_remove, .id_table = mma8450_id, }; diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c index 306f84c2d8fb..dce0d95943c5 100644 --- a/drivers/input/misc/mpu3050.c +++ b/drivers/input/misc/mpu3050.c @@ -257,7 +257,7 @@ static irqreturn_t mpu3050_interrupt_thread(int irq, void *data) * * Called during device probe; configures the sampling method. */ -static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor) +static int mpu3050_hw_init(struct mpu3050_sensor *sensor) { struct i2c_client *client = sensor->client; int ret; @@ -306,7 +306,7 @@ static int __devinit mpu3050_hw_init(struct mpu3050_sensor *sensor) * * If present install the relevant sysfs interfaces and input device. */ -static int __devinit mpu3050_probe(struct i2c_client *client, +static int mpu3050_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mpu3050_sensor *sensor; @@ -402,7 +402,7 @@ err_free_mem: * * Our sensor is going away, clean up the resources. */ -static int __devexit mpu3050_remove(struct i2c_client *client) +static int mpu3050_remove(struct i2c_client *client) { struct mpu3050_sensor *sensor = i2c_get_clientdata(client); @@ -471,7 +471,7 @@ static struct i2c_driver mpu3050_i2c_driver = { .of_match_table = mpu3050_of_match, }, .probe = mpu3050_probe, - .remove = __devexit_p(mpu3050_remove), + .remove = mpu3050_remove, .id_table = mpu3050_ids, }; diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index e09b4fe81913..40ac9a5adf89 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c @@ -48,7 +48,7 @@ static irqreturn_t pcap_keys_handler(int irq, void *_pcap_keys) return IRQ_HANDLED; } -static int __devinit pcap_keys_probe(struct platform_device *pdev) +static int pcap_keys_probe(struct platform_device *pdev) { int err = -ENOMEM; struct pcap_keys *pcap_keys; @@ -104,7 +104,7 @@ fail: return err; } -static int __devexit pcap_keys_remove(struct platform_device *pdev) +static int pcap_keys_remove(struct platform_device *pdev) { struct pcap_keys *pcap_keys = platform_get_drvdata(pdev); @@ -119,7 +119,7 @@ static int __devexit pcap_keys_remove(struct platform_device *pdev) static struct platform_driver pcap_keys_device_driver = { .probe = pcap_keys_probe, - .remove = __devexit_p(pcap_keys_remove), + .remove = pcap_keys_remove, .driver = { .name = "pcap-keys", .owner = THIS_MODULE, diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 53891de80b0e..73b13ebabe56 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c @@ -53,7 +53,7 @@ pcf50633_input_irq(int irq, void *data) input_sync(input->input_dev); } -static int __devinit pcf50633_input_probe(struct platform_device *pdev) +static int pcf50633_input_probe(struct platform_device *pdev) { struct pcf50633_input *input; struct input_dev *input_dev; @@ -93,7 +93,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) return 0; } -static int __devexit pcf50633_input_remove(struct platform_device *pdev) +static int pcf50633_input_remove(struct platform_device *pdev) { struct pcf50633_input *input = platform_get_drvdata(pdev); @@ -111,7 +111,7 @@ static struct platform_driver pcf50633_input_driver = { .name = "pcf50633-input", }, .probe = pcf50633_input_probe, - .remove = __devexit_p(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 544c6635abe9..e37392976fdd 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -82,7 +82,7 @@ static irqreturn_t pcf8574_kp_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int pcf8574_kp_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i, ret; struct input_dev *idev; @@ -156,7 +156,7 @@ static int __devinit pcf8574_kp_probe(struct i2c_client *client, const struct i2 return ret; } -static int __devexit pcf8574_kp_remove(struct i2c_client *client) +static int pcf8574_kp_remove(struct i2c_client *client) { struct kp_data *lp = i2c_get_clientdata(client); @@ -212,7 +212,7 @@ static struct i2c_driver pcf8574_kp_driver = { #endif }, .probe = pcf8574_kp_probe, - .remove = __devexit_p(pcf8574_kp_remove), + .remove = pcf8574_kp_remove, .id_table = pcf8574_kp_id, }; diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index b2484aa07f32..199db78acc4f 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -63,7 +63,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c return 0; } -static int __devinit pcspkr_probe(struct platform_device *dev) +static int pcspkr_probe(struct platform_device *dev) { struct input_dev *pcspkr_dev; int err; @@ -95,7 +95,7 @@ static int __devinit pcspkr_probe(struct platform_device *dev) return 0; } -static int __devexit pcspkr_remove(struct platform_device *dev) +static int pcspkr_remove(struct platform_device *dev) { struct input_dev *pcspkr_dev = platform_get_drvdata(dev); @@ -131,7 +131,7 @@ static struct platform_driver pcspkr_platform_driver = { .pm = &pcspkr_pm_ops, }, .probe = pcspkr_probe, - .remove = __devexit_p(pcspkr_remove), + .remove = pcspkr_remove, .shutdown = pcspkr_shutdown, }; module_platform_driver(pcspkr_platform_driver); diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c index dfbfb463ea5d..a9da65e41c5b 100644 --- a/drivers/input/misc/pm8xxx-vibrator.c +++ b/drivers/input/misc/pm8xxx-vibrator.c @@ -178,7 +178,7 @@ static int pm8xxx_vib_play_effect(struct input_dev *dev, void *data, return 0; } -static int __devinit pm8xxx_vib_probe(struct platform_device *pdev) +static int pm8xxx_vib_probe(struct platform_device *pdev) { struct pm8xxx_vib *vib; @@ -242,7 +242,7 @@ err_free_mem: return error; } -static int __devexit pm8xxx_vib_remove(struct platform_device *pdev) +static int pm8xxx_vib_remove(struct platform_device *pdev) { struct pm8xxx_vib *vib = platform_get_drvdata(pdev); @@ -270,7 +270,7 @@ static SIMPLE_DEV_PM_OPS(pm8xxx_vib_pm_ops, pm8xxx_vib_suspend, NULL); static struct platform_driver pm8xxx_vib_driver = { .probe = pm8xxx_vib_probe, - .remove = __devexit_p(pm8xxx_vib_remove), + .remove = pm8xxx_vib_remove, .driver = { .name = "pm8xxx-vib", .owner = THIS_MODULE, diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c index 0f83d0f1d015..4b811be73974 100644 --- a/drivers/input/misc/pmic8xxx-pwrkey.c +++ b/drivers/input/misc/pmic8xxx-pwrkey.c @@ -81,7 +81,7 @@ static int pmic8xxx_pwrkey_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(pm8xxx_pwr_key_pm_ops, pmic8xxx_pwrkey_suspend, pmic8xxx_pwrkey_resume); -static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) +static int pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); @@ -187,7 +187,7 @@ free_pwrkey: return err; } -static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev) +static int pmic8xxx_pwrkey_remove(struct platform_device *pdev) { struct pmic8xxx_pwrkey *pwrkey = platform_get_drvdata(pdev); int key_release_irq = platform_get_irq(pdev, 0); @@ -206,7 +206,7 @@ static int __devexit pmic8xxx_pwrkey_remove(struct platform_device *pdev) static struct platform_driver pmic8xxx_pwrkey_driver = { .probe = pmic8xxx_pwrkey_probe, - .remove = __devexit_p(pmic8xxx_pwrkey_remove), + .remove = pmic8xxx_pwrkey_remove, .driver = { .name = PM8XXX_PWRKEY_DEV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c index fc84c8a51147..0808868461de 100644 --- a/drivers/input/misc/pwm-beeper.c +++ b/drivers/input/misc/pwm-beeper.c @@ -65,7 +65,7 @@ static int pwm_beeper_event(struct input_dev *input, return 0; } -static int __devinit pwm_beeper_probe(struct platform_device *pdev) +static int pwm_beeper_probe(struct platform_device *pdev) { unsigned long pwm_id = (unsigned long)pdev->dev.platform_data; struct pwm_beeper *beeper; @@ -75,7 +75,11 @@ static int __devinit pwm_beeper_probe(struct platform_device *pdev) if (!beeper) return -ENOMEM; - beeper->pwm = pwm_request(pwm_id, "pwm beeper"); + beeper->pwm = pwm_get(&pdev->dev, NULL); + if (IS_ERR(beeper->pwm)) { + dev_dbg(&pdev->dev, "unable to request PWM, trying legacy API\n"); + beeper->pwm = pwm_request(pwm_id, "pwm beeper"); + } if (IS_ERR(beeper->pwm)) { error = PTR_ERR(beeper->pwm); @@ -125,7 +129,7 @@ err_free: return error; } -static int __devexit pwm_beeper_remove(struct platform_device *pdev) +static int pwm_beeper_remove(struct platform_device *pdev) { struct pwm_beeper *beeper = platform_get_drvdata(pdev); @@ -171,13 +175,21 @@ static SIMPLE_DEV_PM_OPS(pwm_beeper_pm_ops, #define PWM_BEEPER_PM_OPS NULL #endif +#ifdef CONFIG_OF +static const struct of_device_id pwm_beeper_match[] = { + { .compatible = "pwm-beeper", }, + { }, +}; +#endif + static struct platform_driver pwm_beeper_driver = { .probe = pwm_beeper_probe, - .remove = __devexit_p(pwm_beeper_remove), + .remove = pwm_beeper_remove, .driver = { .name = "pwm-beeper", .owner = THIS_MODULE, .pm = PWM_BEEPER_PM_OPS, + .of_match_table = of_match_ptr(pwm_beeper_match), }, }; module_platform_driver(pwm_beeper_driver); diff --git a/drivers/input/misc/rb532_button.c b/drivers/input/misc/rb532_button.c index aeb02bcf7233..fb4f8ac3343b 100644 --- a/drivers/input/misc/rb532_button.c +++ b/drivers/input/misc/rb532_button.c @@ -51,7 +51,7 @@ static void rb532_button_poll(struct input_polled_dev *poll_dev) input_sync(poll_dev->input); } -static int __devinit rb532_button_probe(struct platform_device *pdev) +static int rb532_button_probe(struct platform_device *pdev) { struct input_polled_dev *poll_dev; int error; @@ -81,7 +81,7 @@ static int __devinit rb532_button_probe(struct platform_device *pdev) return 0; } -static int __devexit rb532_button_remove(struct platform_device *pdev) +static int rb532_button_remove(struct platform_device *pdev) { struct input_polled_dev *poll_dev = dev_get_drvdata(&pdev->dev); @@ -94,7 +94,7 @@ static int __devexit rb532_button_remove(struct platform_device *pdev) static struct platform_driver rb532_button_driver = { .probe = rb532_button_probe, - .remove = __devexit_p(rb532_button_remove), + .remove = rb532_button_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/misc/retu-pwrbutton.c b/drivers/input/misc/retu-pwrbutton.c new file mode 100644 index 000000000000..7ca09baa0016 --- /dev/null +++ b/drivers/input/misc/retu-pwrbutton.c @@ -0,0 +1,99 @@ +/* + * Retu power button driver. + * + * Copyright (C) 2004-2010 Nokia Corporation + * + * Original code written by Ari Saastamoinen, Juha Yrjölä and Felipe Balbi. + * Rewritten by Aaro Koskinen. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/errno.h> +#include <linux/input.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mfd/retu.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> + +#define RETU_STATUS_PWRONX (1 << 5) + +static irqreturn_t retu_pwrbutton_irq(int irq, void *_pwr) +{ + struct input_dev *idev = _pwr; + struct retu_dev *rdev = input_get_drvdata(idev); + bool state; + + state = !(retu_read(rdev, RETU_REG_STATUS) & RETU_STATUS_PWRONX); + input_report_key(idev, KEY_POWER, state); + input_sync(idev); + + return IRQ_HANDLED; +} + +static int retu_pwrbutton_probe(struct platform_device *pdev) +{ + struct retu_dev *rdev = dev_get_drvdata(pdev->dev.parent); + struct input_dev *idev; + int irq; + int error; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + idev = devm_input_allocate_device(&pdev->dev); + if (!idev) + return -ENOMEM; + + idev->name = "retu-pwrbutton"; + idev->dev.parent = &pdev->dev; + + input_set_capability(idev, EV_KEY, KEY_POWER); + input_set_drvdata(idev, rdev); + + error = devm_request_threaded_irq(&pdev->dev, irq, + NULL, retu_pwrbutton_irq, 0, + "retu-pwrbutton", idev); + if (error) + return error; + + error = input_register_device(idev); + if (error) + return error; + + return 0; +} + +static int retu_pwrbutton_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver retu_pwrbutton_driver = { + .probe = retu_pwrbutton_probe, + .remove = retu_pwrbutton_remove, + .driver = { + .name = "retu-pwrbutton", + .owner = THIS_MODULE, + }, +}; +module_platform_driver(retu_pwrbutton_driver); + +MODULE_ALIAS("platform:retu-pwrbutton"); +MODULE_DESCRIPTION("Retu Power Button"); +MODULE_AUTHOR("Ari Saastamoinen"); +MODULE_AUTHOR("Felipe Balbi"); +MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 99a49e4968d2..aff47b2c38ff 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -149,8 +149,7 @@ static struct of_device_id rotary_encoder_of_match[] = { }; MODULE_DEVICE_TABLE(of, rotary_encoder_of_match); -static struct rotary_encoder_platform_data * __devinit -rotary_encoder_parse_dt(struct device *dev) +static struct rotary_encoder_platform_data *rotary_encoder_parse_dt(struct device *dev) { const struct of_device_id *of_id = of_match_device(rotary_encoder_of_match, dev); @@ -192,7 +191,7 @@ rotary_encoder_parse_dt(struct device *dev) } #endif -static int __devinit rotary_encoder_probe(struct platform_device *pdev) +static int rotary_encoder_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct rotary_encoder_platform_data *pdata = dev_get_platdata(dev); @@ -302,7 +301,7 @@ exit_free_mem: return err; } -static int __devexit rotary_encoder_remove(struct platform_device *pdev) +static int rotary_encoder_remove(struct platform_device *pdev) { struct rotary_encoder *encoder = platform_get_drvdata(pdev); const struct rotary_encoder_platform_data *pdata = encoder->pdata; @@ -325,7 +324,7 @@ static int __devexit rotary_encoder_remove(struct platform_device *pdev) static struct platform_driver rotary_encoder_driver = { .probe = rotary_encoder_probe, - .remove = __devexit_p(rotary_encoder_remove), + .remove = rotary_encoder_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index 5d9fd5571199..ad6415ceaf5f 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c @@ -91,7 +91,7 @@ static void handle_buttons(struct input_polled_dev *dev) } } -static int __devinit sgi_buttons_probe(struct platform_device *pdev) +static int sgi_buttons_probe(struct platform_device *pdev) { struct buttons_dev *bdev; struct input_polled_dev *poll_dev; @@ -143,7 +143,7 @@ static int __devinit sgi_buttons_probe(struct platform_device *pdev) return error; } -static int __devexit sgi_buttons_remove(struct platform_device *pdev) +static int sgi_buttons_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct buttons_dev *bdev = dev_get_drvdata(dev); @@ -158,7 +158,7 @@ static int __devexit sgi_buttons_remove(struct platform_device *pdev) static struct platform_driver sgi_buttons_driver = { .probe = sgi_buttons_probe, - .remove = __devexit_p(sgi_buttons_remove), + .remove = sgi_buttons_remove, .driver = { .name = "sgibtns", .owner = THIS_MODULE, diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index 0122f5351577..a53586a7fbdb 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c @@ -139,7 +139,7 @@ static int grover_spkr_event(struct input_dev *dev, unsigned int type, unsigned return 0; } -static int __devinit sparcspkr_probe(struct device *dev) +static int sparcspkr_probe(struct device *dev) { struct sparcspkr_state *state = dev_get_drvdata(dev); struct input_dev *input_dev; @@ -182,7 +182,7 @@ static void sparcspkr_shutdown(struct platform_device *dev) state->event(input_dev, EV_SND, SND_BELL, 0); } -static int __devinit bbc_beep_probe(struct platform_device *op) +static int bbc_beep_probe(struct platform_device *op) { struct sparcspkr_state *state; struct bbc_beep_info *info; @@ -229,7 +229,7 @@ out_err: return err; } -static int __devexit bbc_remove(struct platform_device *op) +static int bbc_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct input_dev *input_dev = state->input_dev; @@ -263,11 +263,11 @@ static struct platform_driver bbc_beep_driver = { .of_match_table = bbc_beep_match, }, .probe = bbc_beep_probe, - .remove = __devexit_p(bbc_remove), + .remove = bbc_remove, .shutdown = sparcspkr_shutdown, }; -static int __devinit grover_beep_probe(struct platform_device *op) +static int grover_beep_probe(struct platform_device *op) { struct sparcspkr_state *state; struct grover_beep_info *info; @@ -310,7 +310,7 @@ out_err: return err; } -static int __devexit grover_remove(struct platform_device *op) +static int grover_remove(struct platform_device *op) { struct sparcspkr_state *state = dev_get_drvdata(&op->dev); struct grover_beep_info *info = &state->u.grover; @@ -345,7 +345,7 @@ static struct platform_driver grover_beep_driver = { .of_match_table = grover_beep_match, }, .probe = grover_beep_probe, - .remove = __devexit_p(grover_remove), + .remove = grover_remove, .shutdown = sparcspkr_shutdown, }; diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index b3dd96d6448b..27c2bc8aa890 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c @@ -39,8 +39,7 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) int err; u8 value; - err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, - STS_HW_CONDITIONS); + err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &value, STS_HW_CONDITIONS); if (!err) { pm_wakeup_event(pwr->dev.parent, 0); input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index 2194a3c7236a..68a5f33152a8 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c @@ -43,7 +43,6 @@ struct vibra_info { struct device *dev; struct input_dev *input_dev; - struct workqueue_struct *workqueue; struct work_struct play_work; bool enabled; @@ -143,19 +142,7 @@ static int vibra_play(struct input_dev *input, void *data, if (!info->speed) info->speed = effect->u.rumble.weak_magnitude >> 9; info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; - queue_work(info->workqueue, &info->play_work); - return 0; -} - -static int twl4030_vibra_open(struct input_dev *input) -{ - struct vibra_info *info = input_get_drvdata(input); - - info->workqueue = create_singlethread_workqueue("vibra"); - if (info->workqueue == NULL) { - dev_err(&input->dev, "couldn't create workqueue\n"); - return -ENOMEM; - } + schedule_work(&info->play_work); return 0; } @@ -164,9 +151,6 @@ static void twl4030_vibra_close(struct input_dev *input) struct vibra_info *info = input_get_drvdata(input); cancel_work_sync(&info->play_work); - INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ - destroy_workqueue(info->workqueue); - info->workqueue = NULL; if (info->enabled) vibra_disable(info); @@ -207,7 +191,7 @@ static bool twl4030_vibra_check_coexist(struct twl4030_vibra_data *pdata, return false; } -static int __devinit twl4030_vibra_probe(struct platform_device *pdev) +static int twl4030_vibra_probe(struct platform_device *pdev) { struct twl4030_vibra_data *pdata = pdev->dev.platform_data; struct device_node *twl4030_core_node = pdev->dev.parent->of_node; @@ -219,7 +203,7 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev) return -EINVAL; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -227,11 +211,10 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev) info->coexist = twl4030_vibra_check_coexist(pdata, twl4030_core_node); INIT_WORK(&info->play_work, vibra_play_work); - info->input_dev = input_allocate_device(); + info->input_dev = devm_input_allocate_device(&pdev->dev); if (info->input_dev == NULL) { dev_err(&pdev->dev, "couldn't allocate input device\n"); - ret = -ENOMEM; - goto err_kzalloc; + return -ENOMEM; } input_set_drvdata(info->input_dev, info); @@ -239,14 +222,13 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev) info->input_dev->name = "twl4030:vibrator"; info->input_dev->id.version = 1; info->input_dev->dev.parent = pdev->dev.parent; - info->input_dev->open = twl4030_vibra_open; info->input_dev->close = twl4030_vibra_close; __set_bit(FF_RUMBLE, info->input_dev->ffbit); ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); if (ret < 0) { dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); - goto err_ialloc; + return ret; } ret = input_register_device(info->input_dev); @@ -262,28 +244,11 @@ static int __devinit twl4030_vibra_probe(struct platform_device *pdev) err_iff: input_ff_destroy(info->input_dev); -err_ialloc: - input_free_device(info->input_dev); -err_kzalloc: - kfree(info); return ret; } -static int __devexit twl4030_vibra_remove(struct platform_device *pdev) -{ - struct vibra_info *info = platform_get_drvdata(pdev); - - /* this also free ff-memless and calls close if needed */ - input_unregister_device(info->input_dev); - kfree(info); - platform_set_drvdata(pdev, NULL); - - return 0; -} - static struct platform_driver twl4030_vibra_driver = { .probe = twl4030_vibra_probe, - .remove = __devexit_p(twl4030_vibra_remove), .driver = { .name = "twl4030-vibra", .owner = THIS_MODULE, diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c index c8a288ae1d5b..0c2dfc8e9691 100644 --- a/drivers/input/misc/twl6040-vibra.c +++ b/drivers/input/misc/twl6040-vibra.c @@ -255,7 +255,7 @@ static int twl6040_vibra_suspend(struct device *dev) static SIMPLE_DEV_PM_OPS(twl6040_vibra_pm_ops, twl6040_vibra_suspend, NULL); -static int __devinit twl6040_vibra_probe(struct platform_device *pdev) +static int twl6040_vibra_probe(struct platform_device *pdev) { struct twl6040_vibra_data *pdata = pdev->dev.platform_data; struct device *twl6040_core_dev = pdev->dev.parent; @@ -275,7 +275,7 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) return -EINVAL; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) { dev_err(&pdev->dev, "couldn't allocate memory\n"); return -ENOMEM; @@ -309,53 +309,23 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) if ((!info->vibldrv_res && !info->viblmotor_res) || (!info->vibrdrv_res && !info->vibrmotor_res)) { dev_err(info->dev, "invalid vibra driver/motor resistance\n"); - ret = -EINVAL; - goto err_kzalloc; + return -EINVAL; } info->irq = platform_get_irq(pdev, 0); if (info->irq < 0) { dev_err(info->dev, "invalid irq\n"); - ret = -EINVAL; - goto err_kzalloc; + return -EINVAL; } mutex_init(&info->mutex); - info->input_dev = input_allocate_device(); - if (info->input_dev == NULL) { - dev_err(info->dev, "couldn't allocate input device\n"); - ret = -ENOMEM; - goto err_kzalloc; - } - - input_set_drvdata(info->input_dev, info); - - info->input_dev->name = "twl6040:vibrator"; - info->input_dev->id.version = 1; - info->input_dev->dev.parent = pdev->dev.parent; - info->input_dev->close = twl6040_vibra_close; - __set_bit(FF_RUMBLE, info->input_dev->ffbit); - - ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); - if (ret < 0) { - dev_err(info->dev, "couldn't register vibrator to FF\n"); - goto err_ialloc; - } - - ret = input_register_device(info->input_dev); - if (ret < 0) { - dev_err(info->dev, "couldn't register input device\n"); - goto err_iff; - } - - platform_set_drvdata(pdev, info); - - ret = request_threaded_irq(info->irq, NULL, twl6040_vib_irq_handler, 0, - "twl6040_irq_vib", info); + ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL, + twl6040_vib_irq_handler, 0, + "twl6040_irq_vib", info); if (ret) { dev_err(info->dev, "VIB IRQ request failed: %d\n", ret); - goto err_irq; + return ret; } info->supplies[0].supply = "vddvibl"; @@ -368,7 +338,7 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) ARRAY_SIZE(info->supplies), info->supplies); if (ret) { dev_err(info->dev, "couldn't get regulators %d\n", ret); - goto err_regulator; + return ret; } if (vddvibl_uV) { @@ -377,7 +347,7 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) if (ret) { dev_err(info->dev, "failed to set VDDVIBL volt %d\n", ret); - goto err_voltage; + goto err_regulator; } } @@ -387,53 +357,65 @@ static int __devinit twl6040_vibra_probe(struct platform_device *pdev) if (ret) { dev_err(info->dev, "failed to set VDDVIBR volt %d\n", ret); - goto err_voltage; + goto err_regulator; } } - info->workqueue = alloc_workqueue("twl6040-vibra", 0, 0); - if (info->workqueue == NULL) { - dev_err(info->dev, "couldn't create workqueue\n"); + INIT_WORK(&info->play_work, vibra_play_work); + + info->input_dev = input_allocate_device(); + if (info->input_dev == NULL) { + dev_err(info->dev, "couldn't allocate input device\n"); ret = -ENOMEM; - goto err_voltage; + goto err_regulator; } - INIT_WORK(&info->play_work, vibra_play_work); + + input_set_drvdata(info->input_dev, info); + + info->input_dev->name = "twl6040:vibrator"; + info->input_dev->id.version = 1; + info->input_dev->dev.parent = pdev->dev.parent; + info->input_dev->close = twl6040_vibra_close; + __set_bit(FF_RUMBLE, info->input_dev->ffbit); + + ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); + if (ret < 0) { + dev_err(info->dev, "couldn't register vibrator to FF\n"); + goto err_ialloc; + } + + ret = input_register_device(info->input_dev); + if (ret < 0) { + dev_err(info->dev, "couldn't register input device\n"); + goto err_iff; + } + + platform_set_drvdata(pdev, info); return 0; -err_voltage: - regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); -err_regulator: - free_irq(info->irq, info); -err_irq: - input_unregister_device(info->input_dev); - info->input_dev = NULL; err_iff: - if (info->input_dev) - input_ff_destroy(info->input_dev); + input_ff_destroy(info->input_dev); err_ialloc: input_free_device(info->input_dev); -err_kzalloc: - kfree(info); +err_regulator: + regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); return ret; } -static int __devexit twl6040_vibra_remove(struct platform_device *pdev) +static int twl6040_vibra_remove(struct platform_device *pdev) { struct vibra_info *info = platform_get_drvdata(pdev); input_unregister_device(info->input_dev); - free_irq(info->irq, info); regulator_bulk_free(ARRAY_SIZE(info->supplies), info->supplies); - destroy_workqueue(info->workqueue); - kfree(info); return 0; } static struct platform_driver twl6040_vibra_driver = { .probe = twl6040_vibra_probe, - .remove = __devexit_p(twl6040_vibra_remove), + .remove = twl6040_vibra_remove, .driver = { .name = "twl6040-vibra", .owner = THIS_MODULE, diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index e2bdfd4bea70..56536f4b9572 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c @@ -170,7 +170,7 @@ static u16 bios_pop_queue(void) return regs.eax; } -static void __devinit bios_attach(void) +static void bios_attach(void) { struct regs regs; @@ -190,7 +190,7 @@ static void bios_detach(void) call_bios(®s); } -static u8 __devinit bios_get_cmos_address(void) +static u8 bios_get_cmos_address(void) { struct regs regs; @@ -202,7 +202,7 @@ static u8 __devinit bios_get_cmos_address(void) return regs.ecx; } -static u16 __devinit bios_get_default_setting(u8 subsys) +static u16 bios_get_default_setting(u8 subsys) { struct regs regs; @@ -1052,7 +1052,7 @@ static struct led_classdev wistron_wifi_led = { .brightness_set = wistron_wifi_led_set, }; -static void __devinit wistron_led_init(struct device *parent) +static void wistron_led_init(struct device *parent) { if (leds_present & FE_WIFI_LED) { u16 wifi = bios_get_default_setting(WIFI); @@ -1077,7 +1077,7 @@ static void __devinit wistron_led_init(struct device *parent) } } -static void __devexit wistron_led_remove(void) +static void wistron_led_remove(void) { if (leds_present & FE_MAIL_LED) led_classdev_unregister(&wistron_mail_led); @@ -1168,7 +1168,7 @@ static void wistron_poll(struct input_polled_dev *dev) dev->poll_interval = POLL_INTERVAL_DEFAULT; } -static int __devinit wistron_setup_keymap(struct input_dev *dev, +static int wistron_setup_keymap(struct input_dev *dev, struct key_entry *entry) { switch (entry->type) { @@ -1199,7 +1199,7 @@ static int __devinit wistron_setup_keymap(struct input_dev *dev, return 0; } -static int __devinit setup_input_dev(void) +static int setup_input_dev(void) { struct input_dev *input_dev; int error; @@ -1237,7 +1237,7 @@ static int __devinit setup_input_dev(void) /* Driver core */ -static int __devinit wistron_probe(struct platform_device *dev) +static int wistron_probe(struct platform_device *dev) { int err; @@ -1277,7 +1277,7 @@ static int __devinit wistron_probe(struct platform_device *dev) return 0; } -static int __devexit wistron_remove(struct platform_device *dev) +static int wistron_remove(struct platform_device *dev) { wistron_led_remove(); input_unregister_polled_device(wistron_idev); @@ -1334,7 +1334,7 @@ static struct platform_driver wistron_driver = { #endif }, .probe = wistron_probe, - .remove = __devexit_p(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 6790a812a1db..caa2c4068f09 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -69,14 +69,15 @@ static irqreturn_t wm831x_on_irq(int irq, void *data) return IRQ_HANDLED; } -static int __devinit wm831x_on_probe(struct platform_device *pdev) +static int wm831x_on_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); struct wm831x_on *wm831x_on; int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0)); int ret; - wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); + wm831x_on = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_on), + GFP_KERNEL); if (!wm831x_on) { dev_err(&pdev->dev, "Can't allocate data\n"); return -ENOMEM; @@ -85,7 +86,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) wm831x_on->wm831x = wm831x; INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on); - wm831x_on->dev = input_allocate_device(); + wm831x_on->dev = devm_input_allocate_device(&pdev->dev); if (!wm831x_on->dev) { dev_err(&pdev->dev, "Can't allocate input dev\n"); ret = -ENOMEM; @@ -118,28 +119,24 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) err_irq: free_irq(irq, wm831x_on); err_input_dev: - input_free_device(wm831x_on->dev); err: - kfree(wm831x_on); return ret; } -static int __devexit wm831x_on_remove(struct platform_device *pdev) +static int wm831x_on_remove(struct platform_device *pdev) { struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); free_irq(irq, wm831x_on); cancel_delayed_work_sync(&wm831x_on->work); - input_unregister_device(wm831x_on->dev); - kfree(wm831x_on); return 0; } static struct platform_driver wm831x_on_driver = { .probe = wm831x_on_probe, - .remove = __devexit_p(wm831x_on_remove), + .remove = wm831x_on_remove, .driver = { .name = "wm831x-on", .owner = THIS_MODULE, diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 6f7d99013031..e21c1816a8f9 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -104,7 +104,7 @@ static irqreturn_t input_handler(int rq, void *dev_id) return IRQ_HANDLED; } -static int __devinit xenkbd_probe(struct xenbus_device *dev, +static int xenkbd_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { int ret, i, abs; diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index cd6268cf7cd5..802bd6a72d73 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig @@ -68,6 +68,16 @@ config MOUSE_PS2_SYNAPTICS If unsure, say Y. +config MOUSE_PS2_CYPRESS + bool "Cypress PS/2 mouse protocol extension" if EXPERT + default y + depends on MOUSE_PS2 + help + Say Y here if you have a Cypress PS/2 Trackpad connected to + your system. + + If unsure, say Y. + config MOUSE_PS2_LIFEBOOK bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EXPERT default y @@ -193,6 +203,18 @@ config MOUSE_BCM5974 To compile this driver as a module, choose M here: the module will be called bcm5974. +config MOUSE_CYAPA + tristate "Cypress APA I2C Trackpad support" + depends on I2C + help + This driver adds support for Cypress All Points Addressable (APA) + I2C Trackpads, including the ones used in 2012 Samsung Chromebooks. + + Say Y here if you have a Cypress APA I2C Trackpad. + + To compile this driver as a module, choose M here: the module will be + called cyapa. + config MOUSE_INPORT tristate "InPort/MS/ATIXL busmouse" depends on ISA diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index 46ba7556fd4f..c25efdb3f288 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_MOUSE_AMIGA) += amimouse.o obj-$(CONFIG_MOUSE_APPLETOUCH) += appletouch.o obj-$(CONFIG_MOUSE_ATARI) += atarimouse.o obj-$(CONFIG_MOUSE_BCM5974) += bcm5974.o +obj-$(CONFIG_MOUSE_CYAPA) += cyapa.o obj-$(CONFIG_MOUSE_GPIO) += gpio_mouse.o obj-$(CONFIG_MOUSE_INPORT) += inport.o obj-$(CONFIG_MOUSE_LOGIBM) += logibm.o @@ -32,3 +33,4 @@ psmouse-$(CONFIG_MOUSE_PS2_LIFEBOOK) += lifebook.o psmouse-$(CONFIG_MOUSE_PS2_SENTELIC) += sentelic.o psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT) += trackpoint.o psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT) += touchkit_ps2.o +psmouse-$(CONFIG_MOUSE_PS2_CYPRESS) += cypress_ps2.o diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index cf5af1f495ec..7b99fc7c9438 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -27,14 +27,11 @@ /* * Definitions for ALPS version 3 and 4 command mode protocol */ -#define ALPS_V3_X_MAX 2000 -#define ALPS_V3_Y_MAX 1400 - -#define ALPS_BITMAP_X_BITS 15 -#define ALPS_BITMAP_Y_BITS 11 - #define ALPS_CMD_NIBBLE_10 0x01f2 +#define ALPS_REG_BASE_RUSHMORE 0xc2c0 +#define ALPS_REG_BASE_PINNACLE 0x0000 + static const struct alps_nibble_commands alps_v3_nibble_commands[] = { { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */ { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */ @@ -109,11 +106,14 @@ static const struct alps_model_info alps_model_data[] = { { { 0x73, 0x02, 0x50 }, 0x00, ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x52, 0x01, 0x14 }, 0x00, ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ - { { 0x73, 0x02, 0x64 }, 0x9b, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, - { { 0x73, 0x02, 0x64 }, 0x9d, ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT }, { { 0x73, 0x02, 0x64 }, 0x8a, ALPS_PROTO_V4, 0x8f, 0x8f, 0 }, }; +static void alps_set_abs_params_st(struct alps_data *priv, + struct input_dev *dev1); +static void alps_set_abs_params_mt(struct alps_data *priv, + struct input_dev *dev1); + /* * XXX - this entry is suspicious. First byte has zero lower nibble, * which is what a normal mouse would report. Also, the value 0x0e @@ -122,10 +122,10 @@ static const struct alps_model_info alps_model_data[] = { /* Packet formats are described in Documentation/input/alps.txt */ -static bool alps_is_valid_first_byte(const struct alps_model_info *model, +static bool alps_is_valid_first_byte(struct alps_data *priv, unsigned char data) { - return (data & model->mask0) == model->byte0; + return (data & priv->mask0) == priv->byte0; } static void alps_report_buttons(struct psmouse *psmouse, @@ -158,14 +158,13 @@ static void alps_report_buttons(struct psmouse *psmouse, static void alps_process_packet_v1_v2(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; unsigned char *packet = psmouse->packet; struct input_dev *dev = psmouse->dev; struct input_dev *dev2 = priv->dev2; int x, y, z, ges, fin, left, right, middle; int back = 0, forward = 0; - if (model->proto_version == ALPS_PROTO_V1) { + if (priv->proto_version == ALPS_PROTO_V1) { left = packet[2] & 0x10; right = packet[2] & 0x08; middle = 0; @@ -181,12 +180,12 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) z = packet[5]; } - if (model->flags & ALPS_FW_BK_1) { + if (priv->flags & ALPS_FW_BK_1) { back = packet[0] & 0x10; forward = packet[2] & 4; } - if (model->flags & ALPS_FW_BK_2) { + if (priv->flags & ALPS_FW_BK_2) { back = packet[3] & 4; forward = packet[2] & 4; if ((middle = forward && back)) @@ -196,7 +195,7 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) ges = packet[2] & 1; fin = packet[2] & 2; - if ((model->flags & ALPS_DUALPOINT) && z == 127) { + if ((priv->flags & ALPS_DUALPOINT) && z == 127) { input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); @@ -239,15 +238,15 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) input_report_abs(dev, ABS_PRESSURE, z); input_report_key(dev, BTN_TOOL_FINGER, z > 0); - if (model->flags & ALPS_WHEEL) + if (priv->flags & ALPS_WHEEL) input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); - if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { input_report_key(dev, BTN_FORWARD, forward); input_report_key(dev, BTN_BACK, back); } - if (model->flags & ALPS_FOUR_BUTTONS) { + if (priv->flags & ALPS_FOUR_BUTTONS) { input_report_key(dev, BTN_0, packet[2] & 4); input_report_key(dev, BTN_1, packet[0] & 0x10); input_report_key(dev, BTN_2, packet[3] & 4); @@ -267,7 +266,8 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse) * These points are returned in x1, y1, x2, and y2 when the return value * is greater than 0. */ -static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, +static int alps_process_bitmap(struct alps_data *priv, + unsigned int x_map, unsigned int y_map, int *x1, int *y1, int *x2, int *y2) { struct alps_bitmap_point { @@ -309,7 +309,7 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, * y bitmap is reversed for what we need (lower positions are in * higher bits), so we process from the top end. */ - y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - ALPS_BITMAP_Y_BITS); + y_map = y_map << (sizeof(y_map) * BITS_PER_BYTE - priv->y_bits); prev_bit = 0; point = &y_low; for (i = 0; y_map != 0; i++, y_map <<= 1) { @@ -355,16 +355,18 @@ static int alps_process_bitmap(unsigned int x_map, unsigned int y_map, } } - *x1 = (ALPS_V3_X_MAX * (2 * x_low.start_bit + x_low.num_bits - 1)) / - (2 * (ALPS_BITMAP_X_BITS - 1)); - *y1 = (ALPS_V3_Y_MAX * (2 * y_low.start_bit + y_low.num_bits - 1)) / - (2 * (ALPS_BITMAP_Y_BITS - 1)); + *x1 = (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) / + (2 * (priv->x_bits - 1)); + *y1 = (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) / + (2 * (priv->y_bits - 1)); if (fingers > 1) { - *x2 = (ALPS_V3_X_MAX * (2 * x_high.start_bit + x_high.num_bits - 1)) / - (2 * (ALPS_BITMAP_X_BITS - 1)); - *y2 = (ALPS_V3_Y_MAX * (2 * y_high.start_bit + y_high.num_bits - 1)) / - (2 * (ALPS_BITMAP_Y_BITS - 1)); + *x2 = (priv->x_max * + (2 * x_high.start_bit + x_high.num_bits - 1)) / + (2 * (priv->x_bits - 1)); + *y2 = (priv->y_max * + (2 * y_high.start_bit + y_high.num_bits - 1)) / + (2 * (priv->y_bits - 1)); } return fingers; @@ -448,17 +450,57 @@ static void alps_process_trackstick_packet_v3(struct psmouse *psmouse) return; } +static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p) +{ + f->left = !!(p[3] & 0x01); + f->right = !!(p[3] & 0x02); + f->middle = !!(p[3] & 0x04); + + f->ts_left = !!(p[3] & 0x10); + f->ts_right = !!(p[3] & 0x20); + f->ts_middle = !!(p[3] & 0x40); +} + +static void alps_decode_pinnacle(struct alps_fields *f, unsigned char *p) +{ + f->first_mp = !!(p[4] & 0x40); + f->is_mp = !!(p[0] & 0x40); + + f->fingers = (p[5] & 0x3) + 1; + f->x_map = ((p[4] & 0x7e) << 8) | + ((p[1] & 0x7f) << 2) | + ((p[0] & 0x30) >> 4); + f->y_map = ((p[3] & 0x70) << 4) | + ((p[2] & 0x7f) << 1) | + (p[4] & 0x01); + + f->x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) | + ((p[0] & 0x30) >> 4); + f->y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f); + f->z = p[5] & 0x7f; + + alps_decode_buttons_v3(f, p); +} + +static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) +{ + alps_decode_pinnacle(f, p); + + f->x_map |= (p[5] & 0x10) << 11; + f->y_map |= (p[5] & 0x20) << 6; +} + static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; unsigned char *packet = psmouse->packet; struct input_dev *dev = psmouse->dev; struct input_dev *dev2 = priv->dev2; - int x, y, z; - int left, right, middle; int x1 = 0, y1 = 0, x2 = 0, y2 = 0; int fingers = 0, bmap_fingers; - unsigned int x_bitmap, y_bitmap; + struct alps_fields f; + + priv->decode_fields(&f, packet); /* * There's no single feature of touchpad position and bitmap packets @@ -473,16 +515,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) * packet. Check for this, and when it happens process the * position packet as usual. */ - if (packet[0] & 0x40) { - fingers = (packet[5] & 0x3) + 1; - x_bitmap = ((packet[4] & 0x7e) << 8) | - ((packet[1] & 0x7f) << 2) | - ((packet[0] & 0x30) >> 4); - y_bitmap = ((packet[3] & 0x70) << 4) | - ((packet[2] & 0x7f) << 1) | - (packet[4] & 0x01); - - bmap_fingers = alps_process_bitmap(x_bitmap, y_bitmap, + if (f.is_mp) { + fingers = f.fingers; + bmap_fingers = alps_process_bitmap(priv, + f.x_map, f.y_map, &x1, &y1, &x2, &y2); /* @@ -493,7 +529,7 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) fingers = bmap_fingers; /* Now process position packet */ - packet = priv->multi_data; + priv->decode_fields(&f, priv->multi_data); } else { priv->multi_packet = 0; } @@ -507,10 +543,10 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) * out misidentified bitmap packets, we reject anything with this * bit set. */ - if (packet[0] & 0x40) + if (f.is_mp) return; - if (!priv->multi_packet && (packet[4] & 0x40)) { + if (!priv->multi_packet && f.first_mp) { priv->multi_packet = 1; memcpy(priv->multi_data, packet, sizeof(priv->multi_data)); return; @@ -518,22 +554,13 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) priv->multi_packet = 0; - left = packet[3] & 0x01; - right = packet[3] & 0x02; - middle = packet[3] & 0x04; - - x = ((packet[1] & 0x7f) << 4) | ((packet[4] & 0x30) >> 2) | - ((packet[0] & 0x30) >> 4); - y = ((packet[2] & 0x7f) << 4) | (packet[4] & 0x0f); - z = packet[5] & 0x7f; - /* * Sometimes the hardware sends a single packet with z = 0 * in the middle of a stream. Real releases generate packets * with x, y, and z all zero, so these seem to be flukes. * Ignore them. */ - if (x && y && !z) + if (f.x && f.y && !f.z) return; /* @@ -541,12 +568,12 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) * to rely on ST data. */ if (!fingers) { - x1 = x; - y1 = y; - fingers = z > 0 ? 1 : 0; + x1 = f.x; + y1 = f.y; + fingers = f.z > 0 ? 1 : 0; } - if (z >= 64) + if (f.z >= 64) input_report_key(dev, BTN_TOUCH, 1); else input_report_key(dev, BTN_TOUCH, 0); @@ -555,26 +582,22 @@ static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) input_mt_report_finger_count(dev, fingers); - input_report_key(dev, BTN_LEFT, left); - input_report_key(dev, BTN_RIGHT, right); - input_report_key(dev, BTN_MIDDLE, middle); + input_report_key(dev, BTN_LEFT, f.left); + input_report_key(dev, BTN_RIGHT, f.right); + input_report_key(dev, BTN_MIDDLE, f.middle); - if (z > 0) { - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); + if (f.z > 0) { + input_report_abs(dev, ABS_X, f.x); + input_report_abs(dev, ABS_Y, f.y); } - input_report_abs(dev, ABS_PRESSURE, z); + input_report_abs(dev, ABS_PRESSURE, f.z); input_sync(dev); if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) { - left = packet[3] & 0x10; - right = packet[3] & 0x20; - middle = packet[3] & 0x40; - - input_report_key(dev2, BTN_LEFT, left); - input_report_key(dev2, BTN_RIGHT, right); - input_report_key(dev2, BTN_MIDDLE, middle); + input_report_key(dev2, BTN_LEFT, f.ts_left); + input_report_key(dev2, BTN_RIGHT, f.ts_right); + input_report_key(dev2, BTN_MIDDLE, f.ts_middle); input_sync(dev2); } } @@ -639,7 +662,7 @@ static void alps_process_packet_v4(struct psmouse *psmouse) ((priv->multi_data[3] & 0x1f) << 5) | (priv->multi_data[1] & 0x1f); - fingers = alps_process_bitmap(x_bitmap, y_bitmap, + fingers = alps_process_bitmap(priv, x_bitmap, y_bitmap, &x1, &y1, &x2, &y2); /* Store MT data.*/ @@ -696,25 +719,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse) input_sync(dev); } -static void alps_process_packet(struct psmouse *psmouse) -{ - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - switch (model->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - alps_process_packet_v1_v2(psmouse); - break; - case ALPS_PROTO_V3: - alps_process_packet_v3(psmouse); - break; - case ALPS_PROTO_V4: - alps_process_packet_v4(psmouse); - break; - } -} - static void alps_report_bare_ps2_packet(struct psmouse *psmouse, unsigned char packet[], bool report_buttons) @@ -765,15 +769,14 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) if (((psmouse->packet[3] | psmouse->packet[4] | psmouse->packet[5]) & 0x80) || - (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { + (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) { psmouse_dbg(psmouse, - "refusing packet %x %x %x %x (suspected interleaved ps/2)\n", - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5], psmouse->packet[6]); + "refusing packet %4ph (suspected interleaved ps/2)\n", + psmouse->packet + 3); return PSMOUSE_BAD_DATA; } - alps_process_packet(psmouse); + priv->process_packet(psmouse); /* Continue with the next packet */ psmouse->packet[0] = psmouse->packet[6]; @@ -817,6 +820,7 @@ static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) static void alps_flush_packet(unsigned long data) { struct psmouse *psmouse = (struct psmouse *)data; + struct alps_data *priv = psmouse->private; serio_pause_rx(psmouse->ps2dev.serio); @@ -831,11 +835,10 @@ static void alps_flush_packet(unsigned long data) psmouse->packet[4] | psmouse->packet[5]) & 0x80) { psmouse_dbg(psmouse, - "refusing packet %x %x %x (suspected interleaved ps/2)\n", - psmouse->packet[3], psmouse->packet[4], - psmouse->packet[5]); + "refusing packet %3ph (suspected interleaved ps/2)\n", + psmouse->packet + 3); } else { - alps_process_packet(psmouse); + priv->process_packet(psmouse); } psmouse->pktcnt = 0; } @@ -846,7 +849,6 @@ static void alps_flush_packet(unsigned long data) static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ if (psmouse->pktcnt == 3) { @@ -859,15 +861,15 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ - if ((model->flags & ALPS_PS2_INTERLEAVED) && + if ((priv->flags & ALPS_PS2_INTERLEAVED) && psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { return alps_handle_interleaved_ps2(psmouse); } - if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { + if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) { psmouse_dbg(psmouse, "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", - psmouse->packet[0], model->mask0, model->byte0); + psmouse->packet[0], priv->mask0, priv->byte0); return PSMOUSE_BAD_DATA; } @@ -881,7 +883,7 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) } if (psmouse->pktcnt == psmouse->pktsize) { - alps_process_packet(psmouse); + priv->process_packet(psmouse); return PSMOUSE_FULL_PACKET; } @@ -969,24 +971,42 @@ static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr, return __alps_command_mode_write_reg(psmouse, value); } +static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, + int repeated_command, unsigned char *param) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + param[0] = 0; + if (init_command && ps2_command(ps2dev, param, init_command)) + return -EIO; + + if (ps2_command(ps2dev, NULL, repeated_command) || + ps2_command(ps2dev, NULL, repeated_command) || + ps2_command(ps2dev, NULL, repeated_command)) + return -EIO; + + param[0] = param[1] = param[2] = 0xff; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -EIO; + + psmouse_dbg(psmouse, "%2.2X report: %2.2x %2.2x %2.2x\n", + repeated_command, param[0], param[1], param[2]); + return 0; +} + static int alps_enter_command_mode(struct psmouse *psmouse, unsigned char *resp) { unsigned char param[4]; - struct ps2dev *ps2dev = &psmouse->ps2dev; - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { + if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) { psmouse_err(psmouse, "failed to enter command mode\n"); return -1; } - if (param[0] != 0x88 && param[1] != 0x07) { + if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { psmouse_dbg(psmouse, - "unknown response while entering command mode: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); + "unknown response while entering command mode\n"); return -1; } @@ -1003,99 +1023,6 @@ static inline int alps_exit_command_mode(struct psmouse *psmouse) return 0; } -static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version) -{ - struct ps2dev *ps2dev = &psmouse->ps2dev; - static const unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 }; - unsigned char param[4]; - const struct alps_model_info *model = NULL; - int i; - - /* - * First try "E6 report". - * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. - * The bits 0-2 of the first byte will be 1s if some buttons are - * pressed. - */ - param[0] = 0; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11)) - return NULL; - - param[0] = param[1] = param[2] = 0xff; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return NULL; - - psmouse_dbg(psmouse, "E6 report: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - - if ((param[0] & 0xf8) != 0 || param[1] != 0 || - (param[2] != 10 && param[2] != 100)) - return NULL; - - /* - * Now try "E7 report". Allowed responses are in - * alps_model_data[].signature - */ - param[0] = 0; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21)) - return NULL; - - param[0] = param[1] = param[2] = 0xff; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return NULL; - - psmouse_dbg(psmouse, "E7 report: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - - if (version) { - for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++) - /* empty */; - *version = (param[0] << 8) | (param[1] << 4) | i; - } - - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (!memcmp(param, alps_model_data[i].signature, - sizeof(alps_model_data[i].signature))) { - model = alps_model_data + i; - break; - } - } - - if (model && model->proto_version > ALPS_PROTO_V2) { - /* - * Need to check command mode response to identify - * model - */ - model = NULL; - if (alps_enter_command_mode(psmouse, param)) { - psmouse_warn(psmouse, - "touchpad failed to enter command mode\n"); - } else { - for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { - if (alps_model_data[i].proto_version > ALPS_PROTO_V2 && - alps_model_data[i].command_mode_resp == param[0]) { - model = alps_model_data + i; - break; - } - } - alps_exit_command_mode(psmouse); - - if (!model) - psmouse_dbg(psmouse, - "Unknown command mode response %2.2x\n", - param[0]); - } - } - - return model; -} - /* * For DualPoint devices select the device that should respond to * subsequent commands. It looks like glidepad is behind stickpointer, @@ -1139,18 +1066,10 @@ static int alps_absolute_mode_v1_v2(struct psmouse *psmouse) static int alps_get_status(struct psmouse *psmouse, char *param) { - struct ps2dev *ps2dev = &psmouse->ps2dev; - /* Get status: 0xF5 0xF5 0xF5 0xE9 */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param)) return -1; - psmouse_dbg(psmouse, "Status: %2.2x %2.2x %2.2x", - param[0], param[1], param[2]); - return 0; } @@ -1192,16 +1111,16 @@ static int alps_poll(struct psmouse *psmouse) unsigned char buf[sizeof(psmouse->packet)]; bool poll_failed; - if (priv->i->flags & ALPS_PASS) + if (priv->flags & ALPS_PASS) alps_passthrough_mode_v2(psmouse, true); poll_failed = ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; - if (priv->i->flags & ALPS_PASS) + if (priv->flags & ALPS_PASS) alps_passthrough_mode_v2(psmouse, false); - if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) + if (poll_failed || (buf[0] & priv->mask0) != priv->byte0) return -1; if ((psmouse->badbyte & 0xc8) == 0x08) { @@ -1219,9 +1138,8 @@ static int alps_poll(struct psmouse *psmouse) static int alps_hw_init_v1_v2(struct psmouse *psmouse) { struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - if ((model->flags & ALPS_PASS) && + if ((priv->flags & ALPS_PASS) && alps_passthrough_mode_v2(psmouse, true)) { return -1; } @@ -1236,7 +1154,7 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) return -1; } - if ((model->flags & ALPS_PASS) && + if ((priv->flags & ALPS_PASS) && alps_passthrough_mode_v2(psmouse, false)) { return -1; } @@ -1251,26 +1169,31 @@ static int alps_hw_init_v1_v2(struct psmouse *psmouse) } /* - * Enable or disable passthrough mode to the trackstick. Must be in - * command mode when calling this function. + * Enable or disable passthrough mode to the trackstick. */ -static int alps_passthrough_mode_v3(struct psmouse *psmouse, bool enable) +static int alps_passthrough_mode_v3(struct psmouse *psmouse, + int reg_base, bool enable) { - int reg_val; + int reg_val, ret = -1; - reg_val = alps_command_mode_read_reg(psmouse, 0x0008); - if (reg_val == -1) + if (alps_enter_command_mode(psmouse, NULL)) return -1; + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); + if (reg_val == -1) + goto error; + if (enable) reg_val |= 0x01; else reg_val &= ~0x01; - if (__alps_command_mode_write_reg(psmouse, reg_val)) - return -1; + ret = __alps_command_mode_write_reg(psmouse, reg_val); - return 0; +error: + if (alps_exit_command_mode(psmouse)) + ret = -1; + return ret; } /* Must be in command mode when calling this function */ @@ -1289,73 +1212,102 @@ static int alps_absolute_mode_v3(struct psmouse *psmouse) return 0; } -static int alps_hw_init_v3(struct psmouse *psmouse) +static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) { - struct alps_data *priv = psmouse->private; - struct ps2dev *ps2dev = &psmouse->ps2dev; - int reg_val; - unsigned char param[4]; - - priv->nibble_commands = alps_v3_nibble_commands; - priv->addr_command = PSMOUSE_CMD_RESET_WRAP; + int ret = -EIO, reg_val; if (alps_enter_command_mode(psmouse, NULL)) goto error; - /* Check for trackstick */ - reg_val = alps_command_mode_read_reg(psmouse, 0x0008); + reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); if (reg_val == -1) goto error; - if (reg_val & 0x80) { - if (alps_passthrough_mode_v3(psmouse, true)) - goto error; - if (alps_exit_command_mode(psmouse)) - goto error; + + /* bit 7: trackstick is present */ + ret = reg_val & 0x80 ? 0 : -ENODEV; + +error: + alps_exit_command_mode(psmouse); + return ret; +} + +static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + int ret = 0; + unsigned char param[4]; + + if (alps_passthrough_mode_v3(psmouse, reg_base, true)) + return -EIO; + + /* + * E7 report for the trackstick + * + * There have been reports of failures to seem to trace back + * to the above trackstick check failing. When these occur + * this E7 report fails, so when that happens we continue + * with the assumption that there isn't a trackstick after + * all. + */ + if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) { + psmouse_warn(psmouse, "trackstick E7 report failed\n"); + ret = -ENODEV; + } else { + psmouse_dbg(psmouse, + "trackstick E7 report: %2.2x %2.2x %2.2x\n", + param[0], param[1], param[2]); /* - * E7 report for the trackstick - * - * There have been reports of failures to seem to trace back - * to the above trackstick check failing. When these occur - * this E7 report fails, so when that happens we continue - * with the assumption that there isn't a trackstick after - * all. + * Not sure what this does, but it is absolutely + * essential. Without it, the touchpad does not + * work at all and the trackstick just emits normal + * PS/2 packets. */ - param[0] = 0x64; - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) || - ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) { - psmouse_warn(psmouse, "trackstick E7 report failed\n"); - } else { - psmouse_dbg(psmouse, - "trackstick E7 report: %2.2x %2.2x %2.2x\n", - param[0], param[1], param[2]); - - /* - * Not sure what this does, but it is absolutely - * essential. Without it, the touchpad does not - * work at all and the trackstick just emits normal - * PS/2 packets. - */ - if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || - alps_command_mode_send_nibble(psmouse, 0x9) || - alps_command_mode_send_nibble(psmouse, 0x4)) { - psmouse_err(psmouse, - "Error sending magic E6 sequence\n"); - goto error_passthrough; - } + if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) || + alps_command_mode_send_nibble(psmouse, 0x9) || + alps_command_mode_send_nibble(psmouse, 0x4)) { + psmouse_err(psmouse, + "Error sending magic E6 sequence\n"); + ret = -EIO; + goto error; } - if (alps_enter_command_mode(psmouse, NULL)) - goto error_passthrough; - if (alps_passthrough_mode_v3(psmouse, false)) - goto error; + /* + * This ensures the trackstick packets are in the format + * supported by this driver. If bit 1 isn't set the packet + * format is different. + */ + if (alps_enter_command_mode(psmouse, NULL) || + alps_command_mode_write_reg(psmouse, + reg_base + 0x08, 0x82) || + alps_exit_command_mode(psmouse)) + ret = -EIO; } - if (alps_absolute_mode_v3(psmouse)) { +error: + if (alps_passthrough_mode_v3(psmouse, reg_base, false)) + ret = -EIO; + + return ret; +} + +static int alps_hw_init_v3(struct psmouse *psmouse) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val; + unsigned char param[4]; + + reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE); + if (reg_val == -EIO) + goto error; + if (reg_val == 0 && + alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) + goto error; + + if (alps_enter_command_mode(psmouse, NULL) || + alps_absolute_mode_v3(psmouse)) { psmouse_err(psmouse, "Failed to enter absolute mode\n"); goto error; } @@ -1392,14 +1344,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04)) goto error; - /* - * This ensures the trackstick packets are in the format - * supported by this driver. If bit 1 isn't set the packet - * format is different. - */ - if (alps_command_mode_write_reg(psmouse, 0x0008, 0x82)) - goto error; - alps_exit_command_mode(psmouse); /* Set rate and enable data reporting */ @@ -1412,10 +1356,6 @@ static int alps_hw_init_v3(struct psmouse *psmouse) return 0; -error_passthrough: - /* Something failed while in passthrough mode, so try to get out */ - if (!alps_enter_command_mode(psmouse, NULL)) - alps_passthrough_mode_v3(psmouse, false); error: /* * Leaving the touchpad in command mode will essentially render @@ -1426,6 +1366,50 @@ error: return -1; } +static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) +{ + struct alps_data *priv = psmouse->private; + struct ps2dev *ps2dev = &psmouse->ps2dev; + int reg_val, ret = -1; + + if (priv->flags & ALPS_DUALPOINT) { + reg_val = alps_setup_trackstick_v3(psmouse, + ALPS_REG_BASE_RUSHMORE); + if (reg_val == -EIO) + goto error; + if (reg_val == -ENODEV) + priv->flags &= ~ALPS_DUALPOINT; + } + + if (alps_enter_command_mode(psmouse, NULL) || + alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || + alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) + goto error; + + reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6); + if (reg_val == -1) + goto error; + if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd)) + goto error; + + if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64)) + goto error; + + /* enter absolute mode */ + reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4); + if (reg_val == -1) + goto error; + if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02)) + goto error; + + alps_exit_command_mode(psmouse); + return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE); + +error: + alps_exit_command_mode(psmouse); + return ret; +} + /* Must be in command mode when calling this function */ static int alps_absolute_mode_v4(struct psmouse *psmouse) { @@ -1444,13 +1428,9 @@ static int alps_absolute_mode_v4(struct psmouse *psmouse) static int alps_hw_init_v4(struct psmouse *psmouse) { - struct alps_data *priv = psmouse->private; struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char param[4]; - priv->nibble_commands = alps_v4_nibble_commands; - priv->addr_command = PSMOUSE_CMD_DISABLE; - if (alps_enter_command_mode(psmouse, NULL)) goto error; @@ -1519,39 +1499,140 @@ error: return -1; } -static int alps_hw_init(struct psmouse *psmouse) +static void alps_set_defaults(struct alps_data *priv) { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - int ret = -1; + priv->byte0 = 0x8f; + priv->mask0 = 0x8f; + priv->flags = ALPS_DUALPOINT; + + priv->x_max = 2000; + priv->y_max = 1400; + priv->x_bits = 15; + priv->y_bits = 11; - switch (model->proto_version) { + switch (priv->proto_version) { case ALPS_PROTO_V1: case ALPS_PROTO_V2: - ret = alps_hw_init_v1_v2(psmouse); + priv->hw_init = alps_hw_init_v1_v2; + priv->process_packet = alps_process_packet_v1_v2; + priv->set_abs_params = alps_set_abs_params_st; break; case ALPS_PROTO_V3: - ret = alps_hw_init_v3(psmouse); + priv->hw_init = alps_hw_init_v3; + priv->process_packet = alps_process_packet_v3; + priv->set_abs_params = alps_set_abs_params_mt; + priv->decode_fields = alps_decode_pinnacle; + priv->nibble_commands = alps_v3_nibble_commands; + priv->addr_command = PSMOUSE_CMD_RESET_WRAP; break; case ALPS_PROTO_V4: - ret = alps_hw_init_v4(psmouse); + priv->hw_init = alps_hw_init_v4; + priv->process_packet = alps_process_packet_v4; + priv->set_abs_params = alps_set_abs_params_mt; + priv->nibble_commands = alps_v4_nibble_commands; + priv->addr_command = PSMOUSE_CMD_DISABLE; break; } +} - return ret; +static int alps_match_table(struct psmouse *psmouse, struct alps_data *priv, + unsigned char *e7, unsigned char *ec) +{ + const struct alps_model_info *model; + int i; + + for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) { + model = &alps_model_data[i]; + + if (!memcmp(e7, model->signature, sizeof(model->signature)) && + (!model->command_mode_resp || + model->command_mode_resp == ec[2])) { + + priv->proto_version = model->proto_version; + alps_set_defaults(priv); + + priv->flags = model->flags; + priv->byte0 = model->byte0; + priv->mask0 = model->mask0; + + return 0; + } + } + + return -EINVAL; +} + +static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) +{ + unsigned char e6[4], e7[4], ec[4]; + + /* + * First try "E6 report". + * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed. + * The bits 0-2 of the first byte will be 1s if some buttons are + * pressed. + */ + if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, + PSMOUSE_CMD_SETSCALE11, e6)) + return -EIO; + + if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100)) + return -EINVAL; + + /* + * Now get the "E7" and "EC" reports. These will uniquely identify + * most ALPS touchpads. + */ + if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, + PSMOUSE_CMD_SETSCALE21, e7) || + alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES, + PSMOUSE_CMD_RESET_WRAP, ec) || + alps_exit_command_mode(psmouse)) + return -EIO; + + if (alps_match_table(psmouse, priv, e7, ec) == 0) { + return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x08) { + priv->proto_version = ALPS_PROTO_V3; + alps_set_defaults(priv); + + priv->hw_init = alps_hw_init_rushmore_v3; + priv->decode_fields = alps_decode_rushmore; + priv->x_bits = 16; + priv->y_bits = 12; + + /* hack to make addr_command, nibble_command available */ + psmouse->private = priv; + + if (alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_RUSHMORE)) + priv->flags &= ~ALPS_DUALPOINT; + + return 0; + } else if (ec[0] == 0x88 && ec[1] == 0x07 && + ec[2] >= 0x90 && ec[2] <= 0x9d) { + priv->proto_version = ALPS_PROTO_V3; + alps_set_defaults(priv); + + return 0; + } + + psmouse_info(psmouse, + "Unknown ALPS touchpad: E7=%2.2x %2.2x %2.2x, EC=%2.2x %2.2x %2.2x\n", + e7[0], e7[1], e7[2], ec[0], ec[1], ec[2]); + + return -EINVAL; } static int alps_reconnect(struct psmouse *psmouse) { - const struct alps_model_info *model; + struct alps_data *priv = psmouse->private; psmouse_reset(psmouse); - model = alps_get_model(psmouse, NULL); - if (!model) + if (alps_identify(psmouse, priv) < 0) return -1; - return alps_hw_init(psmouse); + return priv->hw_init(psmouse); } static void alps_disconnect(struct psmouse *psmouse) @@ -1564,12 +1645,33 @@ static void alps_disconnect(struct psmouse *psmouse) kfree(priv); } +static void alps_set_abs_params_st(struct alps_data *priv, + struct input_dev *dev1) +{ + input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); + input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); +} + +static void alps_set_abs_params_mt(struct alps_data *priv, + struct input_dev *dev1) +{ + set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); + input_mt_init_slots(dev1, 2, 0); + input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); + input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); + + set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); + set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); + set_bit(BTN_TOOL_QUADTAP, dev1->keybit); + + input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0); + input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0); +} + int alps_init(struct psmouse *psmouse) { struct alps_data *priv; - const struct alps_model_info *model; struct input_dev *dev1 = psmouse->dev, *dev2; - int version; priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL); dev2 = input_allocate_device(); @@ -1583,13 +1685,10 @@ int alps_init(struct psmouse *psmouse) psmouse_reset(psmouse); - model = alps_get_model(psmouse, &version); - if (!model) + if (alps_identify(psmouse, priv) < 0) goto init_fail; - priv->i = model; - - if (alps_hw_init(psmouse)) + if (priv->hw_init(psmouse)) goto init_fail; /* @@ -1611,41 +1710,20 @@ int alps_init(struct psmouse *psmouse) dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); - switch (model->proto_version) { - case ALPS_PROTO_V1: - case ALPS_PROTO_V2: - input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); - break; - case ALPS_PROTO_V3: - case ALPS_PROTO_V4: - set_bit(INPUT_PROP_SEMI_MT, dev1->propbit); - input_mt_init_slots(dev1, 2, 0); - input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, ALPS_V3_X_MAX, 0, 0); - input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, ALPS_V3_Y_MAX, 0, 0); - - set_bit(BTN_TOOL_DOUBLETAP, dev1->keybit); - set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit); - set_bit(BTN_TOOL_QUADTAP, dev1->keybit); - - input_set_abs_params(dev1, ABS_X, 0, ALPS_V3_X_MAX, 0, 0); - input_set_abs_params(dev1, ABS_Y, 0, ALPS_V3_Y_MAX, 0, 0); - break; - } - + priv->set_abs_params(priv, dev1); input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); - if (model->flags & ALPS_WHEEL) { + if (priv->flags & ALPS_WHEEL) { dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); } - if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { + if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); } - if (model->flags & ALPS_FOUR_BUTTONS) { + if (priv->flags & ALPS_FOUR_BUTTONS) { dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); @@ -1656,7 +1734,8 @@ int alps_init(struct psmouse *psmouse) snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); dev2->phys = priv->phys; - dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; + dev2->name = (priv->flags & ALPS_DUALPOINT) ? + "DualPoint Stick" : "PS/2 Mouse"; dev2->id.bustype = BUS_I8042; dev2->id.vendor = 0x0002; dev2->id.product = PSMOUSE_ALPS; @@ -1675,7 +1754,7 @@ int alps_init(struct psmouse *psmouse) psmouse->poll = alps_poll; psmouse->disconnect = alps_disconnect; psmouse->reconnect = alps_reconnect; - psmouse->pktsize = model->proto_version == ALPS_PROTO_V4 ? 8 : 6; + psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6; /* We are having trouble resyncing ALPS touchpads so disable it for now */ psmouse->resync_time = 0; @@ -1692,18 +1771,16 @@ init_fail: int alps_detect(struct psmouse *psmouse, bool set_properties) { - int version; - const struct alps_model_info *model; + struct alps_data dummy; - model = alps_get_model(psmouse, &version); - if (!model) + if (alps_identify(psmouse, &dummy) < 0) return -1; if (set_properties) { psmouse->vendor = "ALPS"; - psmouse->name = model->flags & ALPS_DUALPOINT ? + psmouse->name = dummy.flags & ALPS_DUALPOINT ? "DualPoint TouchPad" : "GlidePoint"; - psmouse->model = version; + psmouse->model = dummy.proto_version << 8; } return 0; } diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index ae1ac354c778..970480551b6e 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h @@ -12,35 +12,146 @@ #ifndef _ALPS_H #define _ALPS_H -#define ALPS_PROTO_V1 0 -#define ALPS_PROTO_V2 1 -#define ALPS_PROTO_V3 2 -#define ALPS_PROTO_V4 3 +#define ALPS_PROTO_V1 1 +#define ALPS_PROTO_V2 2 +#define ALPS_PROTO_V3 3 +#define ALPS_PROTO_V4 4 +/** + * struct alps_model_info - touchpad ID table + * @signature: E7 response string to match. + * @command_mode_resp: For V3/V4 touchpads, the final byte of the EC response + * (aka command mode response) identifies the firmware minor version. This + * can be used to distinguish different hardware models which are not + * uniquely identifiable through their E7 responses. + * @proto_version: Indicates V1/V2/V3/... + * @byte0: Helps figure out whether a position report packet matches the + * known format for this model. The first byte of the report, ANDed with + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). + * + * Many (but not all) ALPS touchpads can be identified by looking at the + * values returned in the "E7 report" and/or the "EC report." This table + * lists a number of such touchpads. + */ struct alps_model_info { - unsigned char signature[3]; - unsigned char command_mode_resp; /* v3/v4 only */ + unsigned char signature[3]; + unsigned char command_mode_resp; unsigned char proto_version; - unsigned char byte0, mask0; - unsigned char flags; + unsigned char byte0, mask0; + unsigned char flags; }; +/** + * struct alps_nibble_commands - encodings for register accesses + * @command: PS/2 command used for the nibble + * @data: Data supplied as an argument to the PS/2 command, if applicable + * + * The ALPS protocol uses magic sequences to transmit binary data to the + * touchpad, as it is generally not OK to send arbitrary bytes out the + * PS/2 port. Each of the sequences in this table sends one nibble of the + * register address or (write) data. Different versions of the ALPS protocol + * use slightly different encodings. + */ struct alps_nibble_commands { int command; unsigned char data; }; +/** + * struct alps_fields - decoded version of the report packet + * @x_map: Bitmap of active X positions for MT. + * @y_map: Bitmap of active Y positions for MT. + * @fingers: Number of fingers for MT. + * @x: X position for ST. + * @y: Y position for ST. + * @z: Z position for ST. + * @first_mp: Packet is the first of a multi-packet report. + * @is_mp: Packet is part of a multi-packet report. + * @left: Left touchpad button is active. + * @right: Right touchpad button is active. + * @middle: Middle touchpad button is active. + * @ts_left: Left trackstick button is active. + * @ts_right: Right trackstick button is active. + * @ts_middle: Middle trackstick button is active. + */ +struct alps_fields { + unsigned int x_map; + unsigned int y_map; + unsigned int fingers; + unsigned int x; + unsigned int y; + unsigned int z; + unsigned int first_mp:1; + unsigned int is_mp:1; + + unsigned int left:1; + unsigned int right:1; + unsigned int middle:1; + + unsigned int ts_left:1; + unsigned int ts_right:1; + unsigned int ts_middle:1; +}; + +/** + * struct alps_data - private data structure for the ALPS driver + * @dev2: "Relative" device used to report trackstick or mouse activity. + * @phys: Physical path for the relative device. + * @nibble_commands: Command mapping used for touchpad register accesses. + * @addr_command: Command used to tell the touchpad that a register address + * follows. + * @proto_version: Indicates V1/V2/V3/... + * @byte0: Helps figure out whether a position report packet matches the + * known format for this model. The first byte of the report, ANDed with + * mask0, should match byte0. + * @mask0: The mask used to check the first byte of the report. + * @flags: Additional device capabilities (passthrough port, trackstick, etc.). + * @x_max: Largest possible X position value. + * @y_max: Largest possible Y position value. + * @x_bits: Number of X bits in the MT bitmap. + * @y_bits: Number of Y bits in the MT bitmap. + * @hw_init: Protocol-specific hardware init function. + * @process_packet: Protocol-specific function to process a report packet. + * @decode_fields: Protocol-specific function to read packet bitfields. + * @set_abs_params: Protocol-specific function to configure the input_dev. + * @prev_fin: Finger bit from previous packet. + * @multi_packet: Multi-packet data in progress. + * @multi_data: Saved multi-packet data. + * @x1: First X coordinate from last MT report. + * @x2: Second X coordinate from last MT report. + * @y1: First Y coordinate from last MT report. + * @y2: Second Y coordinate from last MT report. + * @fingers: Number of fingers from last MT report. + * @quirks: Bitmap of ALPS_QUIRK_*. + * @timer: Timer for flushing out the final report packet in the stream. + */ struct alps_data { - struct input_dev *dev2; /* Relative device */ - char phys[32]; /* Phys */ - const struct alps_model_info *i;/* Info */ + struct input_dev *dev2; + char phys[32]; + + /* these are autodetected when the device is identified */ const struct alps_nibble_commands *nibble_commands; - int addr_command; /* Command to set register address */ - int prev_fin; /* Finger bit from previous packet */ - int multi_packet; /* Multi-packet data in progress */ - unsigned char multi_data[6]; /* Saved multi-packet data */ - int x1, x2, y1, y2; /* Coordinates from last MT report */ - int fingers; /* Number of fingers from MT report */ + int addr_command; + unsigned char proto_version; + unsigned char byte0, mask0; + unsigned char flags; + int x_max; + int y_max; + int x_bits; + int y_bits; + + int (*hw_init)(struct psmouse *psmouse); + void (*process_packet)(struct psmouse *psmouse); + void (*decode_fields)(struct alps_fields *f, unsigned char *p); + void (*set_abs_params)(struct alps_data *priv, struct input_dev *dev1); + + int prev_fin; + int multi_packet; + unsigned char multi_data[6]; + int x1, x2, y1, y2; + int fingers; u8 quirks; struct timer_list timer; }; diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c new file mode 100644 index 000000000000..b409c3d7d4fb --- /dev/null +++ b/drivers/input/mouse/cyapa.c @@ -0,0 +1,973 @@ +/* + * Cypress APA trackpad with I2C interface + * + * Author: Dudley Du <dudl@cypress.com> + * Further cleanup and restructuring by: + * Daniel Kurtz <djkurtz@chromium.org> + * Benson Leung <bleung@chromium.org> + * + * Copyright (C) 2011-2012 Cypress Semiconductor, Inc. + * Copyright (C) 2011-2012 Google, Inc. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/slab.h> + +/* APA trackpad firmware generation */ +#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */ + +#define CYAPA_NAME "Cypress APA Trackpad (cyapa)" + +/* commands for read/write registers of Cypress trackpad */ +#define CYAPA_CMD_SOFT_RESET 0x00 +#define CYAPA_CMD_POWER_MODE 0x01 +#define CYAPA_CMD_DEV_STATUS 0x02 +#define CYAPA_CMD_GROUP_DATA 0x03 +#define CYAPA_CMD_GROUP_CMD 0x04 +#define CYAPA_CMD_GROUP_QUERY 0x05 +#define CYAPA_CMD_BL_STATUS 0x06 +#define CYAPA_CMD_BL_HEAD 0x07 +#define CYAPA_CMD_BL_CMD 0x08 +#define CYAPA_CMD_BL_DATA 0x09 +#define CYAPA_CMD_BL_ALL 0x0a +#define CYAPA_CMD_BLK_PRODUCT_ID 0x0b +#define CYAPA_CMD_BLK_HEAD 0x0c + +/* report data start reg offset address. */ +#define DATA_REG_START_OFFSET 0x0000 + +#define BL_HEAD_OFFSET 0x00 +#define BL_DATA_OFFSET 0x10 + +/* + * Operational Device Status Register + * + * bit 7: Valid interrupt source + * bit 6 - 4: Reserved + * bit 3 - 2: Power status + * bit 1 - 0: Device status + */ +#define REG_OP_STATUS 0x00 +#define OP_STATUS_SRC 0x80 +#define OP_STATUS_POWER 0x0c +#define OP_STATUS_DEV 0x03 +#define OP_STATUS_MASK (OP_STATUS_SRC | OP_STATUS_POWER | OP_STATUS_DEV) + +/* + * Operational Finger Count/Button Flags Register + * + * bit 7 - 4: Number of touched finger + * bit 3: Valid data + * bit 2: Middle Physical Button + * bit 1: Right Physical Button + * bit 0: Left physical Button + */ +#define REG_OP_DATA1 0x01 +#define OP_DATA_VALID 0x08 +#define OP_DATA_MIDDLE_BTN 0x04 +#define OP_DATA_RIGHT_BTN 0x02 +#define OP_DATA_LEFT_BTN 0x01 +#define OP_DATA_BTN_MASK (OP_DATA_MIDDLE_BTN | OP_DATA_RIGHT_BTN | \ + OP_DATA_LEFT_BTN) + +/* + * Bootloader Status Register + * + * bit 7: Busy + * bit 6 - 5: Reserved + * bit 4: Bootloader running + * bit 3 - 1: Reserved + * bit 0: Checksum valid + */ +#define REG_BL_STATUS 0x01 +#define BL_STATUS_BUSY 0x80 +#define BL_STATUS_RUNNING 0x10 +#define BL_STATUS_DATA_VALID 0x08 +#define BL_STATUS_CSUM_VALID 0x01 + +/* + * Bootloader Error Register + * + * bit 7: Invalid + * bit 6: Invalid security key + * bit 5: Bootloading + * bit 4: Command checksum + * bit 3: Flash protection error + * bit 2: Flash checksum error + * bit 1 - 0: Reserved + */ +#define REG_BL_ERROR 0x02 +#define BL_ERROR_INVALID 0x80 +#define BL_ERROR_INVALID_KEY 0x40 +#define BL_ERROR_BOOTLOADING 0x20 +#define BL_ERROR_CMD_CSUM 0x10 +#define BL_ERROR_FLASH_PROT 0x08 +#define BL_ERROR_FLASH_CSUM 0x04 + +#define BL_STATUS_SIZE 3 /* length of bootloader status registers */ +#define BLK_HEAD_BYTES 32 + +#define PRODUCT_ID_SIZE 16 +#define QUERY_DATA_SIZE 27 +#define REG_PROTOCOL_GEN_QUERY_OFFSET 20 + +#define REG_OFFSET_DATA_BASE 0x0000 +#define REG_OFFSET_COMMAND_BASE 0x0028 +#define REG_OFFSET_QUERY_BASE 0x002a + +#define CAPABILITY_LEFT_BTN_MASK (0x01 << 3) +#define CAPABILITY_RIGHT_BTN_MASK (0x01 << 4) +#define CAPABILITY_MIDDLE_BTN_MASK (0x01 << 5) +#define CAPABILITY_BTN_MASK (CAPABILITY_LEFT_BTN_MASK | \ + CAPABILITY_RIGHT_BTN_MASK | \ + CAPABILITY_MIDDLE_BTN_MASK) + +#define CYAPA_OFFSET_SOFT_RESET REG_OFFSET_COMMAND_BASE + +#define REG_OFFSET_POWER_MODE (REG_OFFSET_COMMAND_BASE + 1) + +#define PWR_MODE_MASK 0xfc +#define PWR_MODE_FULL_ACTIVE (0x3f << 2) +#define PWR_MODE_IDLE (0x05 << 2) /* default sleep time is 50 ms. */ +#define PWR_MODE_OFF (0x00 << 2) + +#define PWR_STATUS_MASK 0x0c +#define PWR_STATUS_ACTIVE (0x03 << 2) +#define PWR_STATUS_IDLE (0x02 << 2) +#define PWR_STATUS_OFF (0x00 << 2) + +/* + * CYAPA trackpad device states. + * Used in register 0x00, bit1-0, DeviceStatus field. + * Other values indicate device is in an abnormal state and must be reset. + */ +#define CYAPA_DEV_NORMAL 0x03 +#define CYAPA_DEV_BUSY 0x01 + +enum cyapa_state { + CYAPA_STATE_OP, + CYAPA_STATE_BL_IDLE, + CYAPA_STATE_BL_ACTIVE, + CYAPA_STATE_BL_BUSY, + CYAPA_STATE_NO_DEVICE, +}; + + +struct cyapa_touch { + /* + * high bits or x/y position value + * bit 7 - 4: high 4 bits of x position value + * bit 3 - 0: high 4 bits of y position value + */ + u8 xy_hi; + u8 x_lo; /* low 8 bits of x position value. */ + u8 y_lo; /* low 8 bits of y position value. */ + u8 pressure; + /* id range is 1 - 15. It is incremented with every new touch. */ + u8 id; +} __packed; + +/* The touch.id is used as the MT slot id, thus max MT slot is 15 */ +#define CYAPA_MAX_MT_SLOTS 15 + +struct cyapa_reg_data { + /* + * bit 0 - 1: device status + * bit 3 - 2: power mode + * bit 6 - 4: reserved + * bit 7: interrupt valid bit + */ + u8 device_status; + /* + * bit 7 - 4: number of fingers currently touching pad + * bit 3: valid data check bit + * bit 2: middle mechanism button state if exists + * bit 1: right mechanism button state if exists + * bit 0: left mechanism button state if exists + */ + u8 finger_btn; + /* CYAPA reports up to 5 touches per packet. */ + struct cyapa_touch touches[5]; +} __packed; + +/* The main device structure */ +struct cyapa { + enum cyapa_state state; + + struct i2c_client *client; + struct input_dev *input; + char phys[32]; /* device physical location */ + int irq; + bool irq_wake; /* irq wake is enabled */ + bool smbus; + + /* read from query data region. */ + char product_id[16]; + u8 btn_capability; + u8 gen; + int max_abs_x; + int max_abs_y; + int physical_size_x; + int physical_size_y; +}; + +static const u8 bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07 }; +static const u8 bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07 }; + +struct cyapa_cmd_len { + u8 cmd; + u8 len; +}; + +#define CYAPA_ADAPTER_FUNC_NONE 0 +#define CYAPA_ADAPTER_FUNC_I2C 1 +#define CYAPA_ADAPTER_FUNC_SMBUS 2 +#define CYAPA_ADAPTER_FUNC_BOTH 3 + +/* + * macros for SMBus communication + */ +#define SMBUS_READ 0x01 +#define SMBUS_WRITE 0x00 +#define SMBUS_ENCODE_IDX(cmd, idx) ((cmd) | (((idx) & 0x03) << 1)) +#define SMBUS_ENCODE_RW(cmd, rw) ((cmd) | ((rw) & 0x01)) +#define SMBUS_BYTE_BLOCK_CMD_MASK 0x80 +#define SMBUS_GROUP_BLOCK_CMD_MASK 0x40 + + /* for byte read/write command */ +#define CMD_RESET 0 +#define CMD_POWER_MODE 1 +#define CMD_DEV_STATUS 2 +#define SMBUS_BYTE_CMD(cmd) (((cmd) & 0x3f) << 1) +#define CYAPA_SMBUS_RESET SMBUS_BYTE_CMD(CMD_RESET) +#define CYAPA_SMBUS_POWER_MODE SMBUS_BYTE_CMD(CMD_POWER_MODE) +#define CYAPA_SMBUS_DEV_STATUS SMBUS_BYTE_CMD(CMD_DEV_STATUS) + + /* for group registers read/write command */ +#define REG_GROUP_DATA 0 +#define REG_GROUP_CMD 2 +#define REG_GROUP_QUERY 3 +#define SMBUS_GROUP_CMD(grp) (0x80 | (((grp) & 0x07) << 3)) +#define CYAPA_SMBUS_GROUP_DATA SMBUS_GROUP_CMD(REG_GROUP_DATA) +#define CYAPA_SMBUS_GROUP_CMD SMBUS_GROUP_CMD(REG_GROUP_CMD) +#define CYAPA_SMBUS_GROUP_QUERY SMBUS_GROUP_CMD(REG_GROUP_QUERY) + + /* for register block read/write command */ +#define CMD_BL_STATUS 0 +#define CMD_BL_HEAD 1 +#define CMD_BL_CMD 2 +#define CMD_BL_DATA 3 +#define CMD_BL_ALL 4 +#define CMD_BLK_PRODUCT_ID 5 +#define CMD_BLK_HEAD 6 +#define SMBUS_BLOCK_CMD(cmd) (0xc0 | (((cmd) & 0x1f) << 1)) + +/* register block read/write command in bootloader mode */ +#define CYAPA_SMBUS_BL_STATUS SMBUS_BLOCK_CMD(CMD_BL_STATUS) +#define CYAPA_SMBUS_BL_HEAD SMBUS_BLOCK_CMD(CMD_BL_HEAD) +#define CYAPA_SMBUS_BL_CMD SMBUS_BLOCK_CMD(CMD_BL_CMD) +#define CYAPA_SMBUS_BL_DATA SMBUS_BLOCK_CMD(CMD_BL_DATA) +#define CYAPA_SMBUS_BL_ALL SMBUS_BLOCK_CMD(CMD_BL_ALL) + +/* register block read/write command in operational mode */ +#define CYAPA_SMBUS_BLK_PRODUCT_ID SMBUS_BLOCK_CMD(CMD_BLK_PRODUCT_ID) +#define CYAPA_SMBUS_BLK_HEAD SMBUS_BLOCK_CMD(CMD_BLK_HEAD) + +static const struct cyapa_cmd_len cyapa_i2c_cmds[] = { + { CYAPA_OFFSET_SOFT_RESET, 1 }, + { REG_OFFSET_COMMAND_BASE + 1, 1 }, + { REG_OFFSET_DATA_BASE, 1 }, + { REG_OFFSET_DATA_BASE, sizeof(struct cyapa_reg_data) }, + { REG_OFFSET_COMMAND_BASE, 0 }, + { REG_OFFSET_QUERY_BASE, QUERY_DATA_SIZE }, + { BL_HEAD_OFFSET, 3 }, + { BL_HEAD_OFFSET, 16 }, + { BL_HEAD_OFFSET, 16 }, + { BL_DATA_OFFSET, 16 }, + { BL_HEAD_OFFSET, 32 }, + { REG_OFFSET_QUERY_BASE, PRODUCT_ID_SIZE }, + { REG_OFFSET_DATA_BASE, 32 } +}; + +static const struct cyapa_cmd_len cyapa_smbus_cmds[] = { + { CYAPA_SMBUS_RESET, 1 }, + { CYAPA_SMBUS_POWER_MODE, 1 }, + { CYAPA_SMBUS_DEV_STATUS, 1 }, + { CYAPA_SMBUS_GROUP_DATA, sizeof(struct cyapa_reg_data) }, + { CYAPA_SMBUS_GROUP_CMD, 2 }, + { CYAPA_SMBUS_GROUP_QUERY, QUERY_DATA_SIZE }, + { CYAPA_SMBUS_BL_STATUS, 3 }, + { CYAPA_SMBUS_BL_HEAD, 16 }, + { CYAPA_SMBUS_BL_CMD, 16 }, + { CYAPA_SMBUS_BL_DATA, 16 }, + { CYAPA_SMBUS_BL_ALL, 32 }, + { CYAPA_SMBUS_BLK_PRODUCT_ID, PRODUCT_ID_SIZE }, + { CYAPA_SMBUS_BLK_HEAD, 16 }, +}; + +static ssize_t cyapa_i2c_reg_read_block(struct cyapa *cyapa, u8 reg, size_t len, + u8 *values) +{ + return i2c_smbus_read_i2c_block_data(cyapa->client, reg, len, values); +} + +static ssize_t cyapa_i2c_reg_write_block(struct cyapa *cyapa, u8 reg, + size_t len, const u8 *values) +{ + return i2c_smbus_write_i2c_block_data(cyapa->client, reg, len, values); +} + +/* + * cyapa_smbus_read_block - perform smbus block read command + * @cyapa - private data structure of the driver + * @cmd - the properly encoded smbus command + * @len - expected length of smbus command result + * @values - buffer to store smbus command result + * + * Returns negative errno, else the number of bytes written. + * + * Note: + * In trackpad device, the memory block allocated for I2C register map + * is 256 bytes, so the max read block for I2C bus is 256 bytes. + */ +static ssize_t cyapa_smbus_read_block(struct cyapa *cyapa, u8 cmd, size_t len, + u8 *values) +{ + ssize_t ret; + u8 index; + u8 smbus_cmd; + u8 *buf; + struct i2c_client *client = cyapa->client; + + if (!(SMBUS_BYTE_BLOCK_CMD_MASK & cmd)) + return -EINVAL; + + if (SMBUS_GROUP_BLOCK_CMD_MASK & cmd) { + /* read specific block registers command. */ + smbus_cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); + ret = i2c_smbus_read_block_data(client, smbus_cmd, values); + goto out; + } + + ret = 0; + for (index = 0; index * I2C_SMBUS_BLOCK_MAX < len; index++) { + smbus_cmd = SMBUS_ENCODE_IDX(cmd, index); + smbus_cmd = SMBUS_ENCODE_RW(smbus_cmd, SMBUS_READ); + buf = values + I2C_SMBUS_BLOCK_MAX * index; + ret = i2c_smbus_read_block_data(client, smbus_cmd, buf); + if (ret < 0) + goto out; + } + +out: + return ret > 0 ? len : ret; +} + +static s32 cyapa_read_byte(struct cyapa *cyapa, u8 cmd_idx) +{ + u8 cmd; + + if (cyapa->smbus) { + cmd = cyapa_smbus_cmds[cmd_idx].cmd; + cmd = SMBUS_ENCODE_RW(cmd, SMBUS_READ); + } else { + cmd = cyapa_i2c_cmds[cmd_idx].cmd; + } + return i2c_smbus_read_byte_data(cyapa->client, cmd); +} + +static s32 cyapa_write_byte(struct cyapa *cyapa, u8 cmd_idx, u8 value) +{ + u8 cmd; + + if (cyapa->smbus) { + cmd = cyapa_smbus_cmds[cmd_idx].cmd; + cmd = SMBUS_ENCODE_RW(cmd, SMBUS_WRITE); + } else { + cmd = cyapa_i2c_cmds[cmd_idx].cmd; + } + return i2c_smbus_write_byte_data(cyapa->client, cmd, value); +} + +static ssize_t cyapa_read_block(struct cyapa *cyapa, u8 cmd_idx, u8 *values) +{ + u8 cmd; + size_t len; + + if (cyapa->smbus) { + cmd = cyapa_smbus_cmds[cmd_idx].cmd; + len = cyapa_smbus_cmds[cmd_idx].len; + return cyapa_smbus_read_block(cyapa, cmd, len, values); + } else { + cmd = cyapa_i2c_cmds[cmd_idx].cmd; + len = cyapa_i2c_cmds[cmd_idx].len; + return cyapa_i2c_reg_read_block(cyapa, cmd, len, values); + } +} + +/* + * Query device for its current operating state. + * + */ +static int cyapa_get_state(struct cyapa *cyapa) +{ + int ret; + u8 status[BL_STATUS_SIZE]; + + cyapa->state = CYAPA_STATE_NO_DEVICE; + + /* + * Get trackpad status by reading 3 registers starting from 0. + * If the device is in the bootloader, this will be BL_HEAD. + * If the device is in operation mode, this will be the DATA regs. + * + */ + ret = cyapa_i2c_reg_read_block(cyapa, BL_HEAD_OFFSET, BL_STATUS_SIZE, + status); + + /* + * On smbus systems in OP mode, the i2c_reg_read will fail with + * -ETIMEDOUT. In this case, try again using the smbus equivalent + * command. This should return a BL_HEAD indicating CYAPA_STATE_OP. + */ + if (cyapa->smbus && (ret == -ETIMEDOUT || ret == -ENXIO)) + ret = cyapa_read_block(cyapa, CYAPA_CMD_BL_STATUS, status); + + if (ret != BL_STATUS_SIZE) + goto error; + + if ((status[REG_OP_STATUS] & OP_STATUS_SRC) == OP_STATUS_SRC) { + switch (status[REG_OP_STATUS] & OP_STATUS_DEV) { + case CYAPA_DEV_NORMAL: + case CYAPA_DEV_BUSY: + cyapa->state = CYAPA_STATE_OP; + break; + default: + ret = -EAGAIN; + goto error; + } + } else { + if (status[REG_BL_STATUS] & BL_STATUS_BUSY) + cyapa->state = CYAPA_STATE_BL_BUSY; + else if (status[REG_BL_ERROR] & BL_ERROR_BOOTLOADING) + cyapa->state = CYAPA_STATE_BL_ACTIVE; + else + cyapa->state = CYAPA_STATE_BL_IDLE; + } + + return 0; +error: + return (ret < 0) ? ret : -EAGAIN; +} + +/* + * Poll device for its status in a loop, waiting up to timeout for a response. + * + * When the device switches state, it usually takes ~300 ms. + * However, when running a new firmware image, the device must calibrate its + * sensors, which can take as long as 2 seconds. + * + * Note: The timeout has granularity of the polling rate, which is 100 ms. + * + * Returns: + * 0 when the device eventually responds with a valid non-busy state. + * -ETIMEDOUT if device never responds (too many -EAGAIN) + * < 0 other errors + */ +static int cyapa_poll_state(struct cyapa *cyapa, unsigned int timeout) +{ + int ret; + int tries = timeout / 100; + + ret = cyapa_get_state(cyapa); + while ((ret || cyapa->state >= CYAPA_STATE_BL_BUSY) && tries--) { + msleep(100); + ret = cyapa_get_state(cyapa); + } + return (ret == -EAGAIN || ret == -ETIMEDOUT) ? -ETIMEDOUT : ret; +} + +static int cyapa_bl_deactivate(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_deactivate), + bl_deactivate); + if (ret < 0) + return ret; + + /* wait for bootloader to switch to idle state; should take < 100ms */ + msleep(100); + ret = cyapa_poll_state(cyapa, 500); + if (ret < 0) + return ret; + if (cyapa->state != CYAPA_STATE_BL_IDLE) + return -EAGAIN; + return 0; +} + +/* + * Exit bootloader + * + * Send bl_exit command, then wait 50 - 100 ms to let device transition to + * operational mode. If this is the first time the device's firmware is + * running, it can take up to 2 seconds to calibrate its sensors. So, poll + * the device's new state for up to 2 seconds. + * + * Returns: + * -EIO failure while reading from device + * -EAGAIN device is stuck in bootloader, b/c it has invalid firmware + * 0 device is supported and in operational mode + */ +static int cyapa_bl_exit(struct cyapa *cyapa) +{ + int ret; + + ret = cyapa_i2c_reg_write_block(cyapa, 0, sizeof(bl_exit), bl_exit); + if (ret < 0) + return ret; + + /* + * Wait for bootloader to exit, and operation mode to start. + * Normally, this takes at least 50 ms. + */ + usleep_range(50000, 100000); + /* + * In addition, when a device boots for the first time after being + * updated to new firmware, it must first calibrate its sensors, which + * can take up to an additional 2 seconds. + */ + ret = cyapa_poll_state(cyapa, 2000); + if (ret < 0) + return ret; + if (cyapa->state != CYAPA_STATE_OP) + return -EAGAIN; + + return 0; +} + +/* + * Set device power mode + * + */ +static int cyapa_set_power_mode(struct cyapa *cyapa, u8 power_mode) +{ + struct device *dev = &cyapa->client->dev; + int ret; + u8 power; + + if (cyapa->state != CYAPA_STATE_OP) + return 0; + + ret = cyapa_read_byte(cyapa, CYAPA_CMD_POWER_MODE); + if (ret < 0) + return ret; + + power = ret & ~PWR_MODE_MASK; + power |= power_mode & PWR_MODE_MASK; + ret = cyapa_write_byte(cyapa, CYAPA_CMD_POWER_MODE, power); + if (ret < 0) + dev_err(dev, "failed to set power_mode 0x%02x err = %d\n", + power_mode, ret); + return ret; +} + +static int cyapa_get_query_data(struct cyapa *cyapa) +{ + u8 query_data[QUERY_DATA_SIZE]; + int ret; + + if (cyapa->state != CYAPA_STATE_OP) + return -EBUSY; + + ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_QUERY, query_data); + if (ret < 0) + return ret; + if (ret != QUERY_DATA_SIZE) + return -EIO; + + memcpy(&cyapa->product_id[0], &query_data[0], 5); + cyapa->product_id[5] = '-'; + memcpy(&cyapa->product_id[6], &query_data[5], 6); + cyapa->product_id[12] = '-'; + memcpy(&cyapa->product_id[13], &query_data[11], 2); + cyapa->product_id[15] = '\0'; + + cyapa->btn_capability = query_data[19] & CAPABILITY_BTN_MASK; + + cyapa->gen = query_data[20] & 0x0f; + + cyapa->max_abs_x = ((query_data[21] & 0xf0) << 4) | query_data[22]; + cyapa->max_abs_y = ((query_data[21] & 0x0f) << 8) | query_data[23]; + + cyapa->physical_size_x = + ((query_data[24] & 0xf0) << 4) | query_data[25]; + cyapa->physical_size_y = + ((query_data[24] & 0x0f) << 8) | query_data[26]; + + return 0; +} + +/* + * Check if device is operational. + * + * An operational device is responding, has exited bootloader, and has + * firmware supported by this driver. + * + * Returns: + * -EBUSY no device or in bootloader + * -EIO failure while reading from device + * -EAGAIN device is still in bootloader + * if ->state = CYAPA_STATE_BL_IDLE, device has invalid firmware + * -EINVAL device is in operational mode, but not supported by this driver + * 0 device is supported + */ +static int cyapa_check_is_operational(struct cyapa *cyapa) +{ + struct device *dev = &cyapa->client->dev; + static const char unique_str[] = "CYTRA"; + int ret; + + ret = cyapa_poll_state(cyapa, 2000); + if (ret < 0) + return ret; + switch (cyapa->state) { + case CYAPA_STATE_BL_ACTIVE: + ret = cyapa_bl_deactivate(cyapa); + if (ret) + return ret; + + /* Fallthrough state */ + case CYAPA_STATE_BL_IDLE: + ret = cyapa_bl_exit(cyapa); + if (ret) + return ret; + + /* Fallthrough state */ + case CYAPA_STATE_OP: + ret = cyapa_get_query_data(cyapa); + if (ret < 0) + return ret; + + /* only support firmware protocol gen3 */ + if (cyapa->gen != CYAPA_GEN3) { + dev_err(dev, "unsupported protocol version (%d)", + cyapa->gen); + return -EINVAL; + } + + /* only support product ID starting with CYTRA */ + if (memcmp(cyapa->product_id, unique_str, + sizeof(unique_str) - 1) != 0) { + dev_err(dev, "unsupported product ID (%s)\n", + cyapa->product_id); + return -EINVAL; + } + return 0; + + default: + return -EIO; + } + return 0; +} + +static irqreturn_t cyapa_irq(int irq, void *dev_id) +{ + struct cyapa *cyapa = dev_id; + struct device *dev = &cyapa->client->dev; + struct input_dev *input = cyapa->input; + struct cyapa_reg_data data; + int i; + int ret; + int num_fingers; + + if (device_may_wakeup(dev)) + pm_wakeup_event(dev, 0); + + ret = cyapa_read_block(cyapa, CYAPA_CMD_GROUP_DATA, (u8 *)&data); + if (ret != sizeof(data)) + goto out; + + if ((data.device_status & OP_STATUS_SRC) != OP_STATUS_SRC || + (data.device_status & OP_STATUS_DEV) != CYAPA_DEV_NORMAL || + (data.finger_btn & OP_DATA_VALID) != OP_DATA_VALID) { + goto out; + } + + num_fingers = (data.finger_btn >> 4) & 0x0f; + for (i = 0; i < num_fingers; i++) { + const struct cyapa_touch *touch = &data.touches[i]; + /* Note: touch->id range is 1 to 15; slots are 0 to 14. */ + int slot = touch->id - 1; + + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); + input_report_abs(input, ABS_MT_POSITION_X, + ((touch->xy_hi & 0xf0) << 4) | touch->x_lo); + input_report_abs(input, ABS_MT_POSITION_Y, + ((touch->xy_hi & 0x0f) << 8) | touch->y_lo); + input_report_abs(input, ABS_MT_PRESSURE, touch->pressure); + } + + input_mt_sync_frame(input); + + if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) + input_report_key(input, BTN_LEFT, + data.finger_btn & OP_DATA_LEFT_BTN); + + if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) + input_report_key(input, BTN_MIDDLE, + data.finger_btn & OP_DATA_MIDDLE_BTN); + + if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) + input_report_key(input, BTN_RIGHT, + data.finger_btn & OP_DATA_RIGHT_BTN); + + input_sync(input); + +out: + return IRQ_HANDLED; +} + +static u8 cyapa_check_adapter_functionality(struct i2c_client *client) +{ + u8 ret = CYAPA_ADAPTER_FUNC_NONE; + + if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + ret |= CYAPA_ADAPTER_FUNC_I2C; + if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK)) + ret |= CYAPA_ADAPTER_FUNC_SMBUS; + return ret; +} + +static int cyapa_create_input_dev(struct cyapa *cyapa) +{ + struct device *dev = &cyapa->client->dev; + int ret; + struct input_dev *input; + + if (!cyapa->physical_size_x || !cyapa->physical_size_y) + return -EINVAL; + + input = cyapa->input = input_allocate_device(); + if (!input) { + dev_err(dev, "allocate memory for input device failed\n"); + return -ENOMEM; + } + + input->name = CYAPA_NAME; + input->phys = cyapa->phys; + input->id.bustype = BUS_I2C; + input->id.version = 1; + input->id.product = 0; /* means any product in eventcomm. */ + input->dev.parent = &cyapa->client->dev; + + input_set_drvdata(input, cyapa); + + __set_bit(EV_ABS, input->evbit); + + /* finger position */ + input_set_abs_params(input, ABS_MT_POSITION_X, 0, cyapa->max_abs_x, 0, + 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, 0, cyapa->max_abs_y, 0, + 0); + input_set_abs_params(input, ABS_MT_PRESSURE, 0, 255, 0, 0); + + input_abs_set_res(input, ABS_MT_POSITION_X, + cyapa->max_abs_x / cyapa->physical_size_x); + input_abs_set_res(input, ABS_MT_POSITION_Y, + cyapa->max_abs_y / cyapa->physical_size_y); + + if (cyapa->btn_capability & CAPABILITY_LEFT_BTN_MASK) + __set_bit(BTN_LEFT, input->keybit); + if (cyapa->btn_capability & CAPABILITY_MIDDLE_BTN_MASK) + __set_bit(BTN_MIDDLE, input->keybit); + if (cyapa->btn_capability & CAPABILITY_RIGHT_BTN_MASK) + __set_bit(BTN_RIGHT, input->keybit); + + if (cyapa->btn_capability == CAPABILITY_LEFT_BTN_MASK) + __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); + + /* handle pointer emulation and unused slots in core */ + ret = input_mt_init_slots(input, CYAPA_MAX_MT_SLOTS, + INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED); + if (ret) { + dev_err(dev, "allocate memory for MT slots failed, %d\n", ret); + goto err_free_device; + } + + /* Register the device in input subsystem */ + ret = input_register_device(input); + if (ret) { + dev_err(dev, "input device register failed, %d\n", ret); + goto err_free_device; + } + return 0; + +err_free_device: + input_free_device(input); + cyapa->input = NULL; + return ret; +} + +static int cyapa_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + int ret; + u8 adapter_func; + struct cyapa *cyapa; + struct device *dev = &client->dev; + + adapter_func = cyapa_check_adapter_functionality(client); + if (adapter_func == CYAPA_ADAPTER_FUNC_NONE) { + dev_err(dev, "not a supported I2C/SMBus adapter\n"); + return -EIO; + } + + cyapa = kzalloc(sizeof(struct cyapa), GFP_KERNEL); + if (!cyapa) { + dev_err(dev, "allocate memory for cyapa failed\n"); + return -ENOMEM; + } + + cyapa->gen = CYAPA_GEN3; + cyapa->client = client; + i2c_set_clientdata(client, cyapa); + sprintf(cyapa->phys, "i2c-%d-%04x/input0", client->adapter->nr, + client->addr); + + /* i2c isn't supported, use smbus */ + if (adapter_func == CYAPA_ADAPTER_FUNC_SMBUS) + cyapa->smbus = true; + cyapa->state = CYAPA_STATE_NO_DEVICE; + ret = cyapa_check_is_operational(cyapa); + if (ret) { + dev_err(dev, "device not operational, %d\n", ret); + goto err_mem_free; + } + + ret = cyapa_create_input_dev(cyapa); + if (ret) { + dev_err(dev, "create input_dev instance failed, %d\n", ret); + goto err_mem_free; + } + + ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); + if (ret) { + dev_err(dev, "set active power failed, %d\n", ret); + goto err_unregister_device; + } + + cyapa->irq = client->irq; + ret = request_threaded_irq(cyapa->irq, + NULL, + cyapa_irq, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "cyapa", + cyapa); + if (ret) { + dev_err(dev, "IRQ request failed: %d\n, ", ret); + goto err_unregister_device; + } + + return 0; + +err_unregister_device: + input_unregister_device(cyapa->input); +err_mem_free: + kfree(cyapa); + + return ret; +} + +static int cyapa_remove(struct i2c_client *client) +{ + struct cyapa *cyapa = i2c_get_clientdata(client); + + free_irq(cyapa->irq, cyapa); + input_unregister_device(cyapa->input); + cyapa_set_power_mode(cyapa, PWR_MODE_OFF); + kfree(cyapa); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int cyapa_suspend(struct device *dev) +{ + int ret; + u8 power_mode; + struct cyapa *cyapa = dev_get_drvdata(dev); + + disable_irq(cyapa->irq); + + /* + * Set trackpad device to idle mode if wakeup is allowed, + * otherwise turn off. + */ + power_mode = device_may_wakeup(dev) ? PWR_MODE_IDLE + : PWR_MODE_OFF; + ret = cyapa_set_power_mode(cyapa, power_mode); + if (ret < 0) + dev_err(dev, "set power mode failed, %d\n", ret); + + if (device_may_wakeup(dev)) + cyapa->irq_wake = (enable_irq_wake(cyapa->irq) == 0); + return 0; +} + +static int cyapa_resume(struct device *dev) +{ + int ret; + struct cyapa *cyapa = dev_get_drvdata(dev); + + if (device_may_wakeup(dev) && cyapa->irq_wake) + disable_irq_wake(cyapa->irq); + + ret = cyapa_set_power_mode(cyapa, PWR_MODE_FULL_ACTIVE); + if (ret) + dev_warn(dev, "resume active power failed, %d\n", ret); + + enable_irq(cyapa->irq); + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static SIMPLE_DEV_PM_OPS(cyapa_pm_ops, cyapa_suspend, cyapa_resume); + +static const struct i2c_device_id cyapa_id_table[] = { + { "cyapa", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, cyapa_id_table); + +static struct i2c_driver cyapa_driver = { + .driver = { + .name = "cyapa", + .owner = THIS_MODULE, + .pm = &cyapa_pm_ops, + }, + + .probe = cyapa_probe, + .remove = cyapa_remove, + .id_table = cyapa_id_table, +}; + +module_i2c_driver(cyapa_driver); + +MODULE_DESCRIPTION("Cypress APA I2C Trackpad Driver"); +MODULE_AUTHOR("Dudley Du <dudl@cypress.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c new file mode 100644 index 000000000000..1673dc6c8092 --- /dev/null +++ b/drivers/input/mouse/cypress_ps2.c @@ -0,0 +1,725 @@ +/* + * Cypress Trackpad PS/2 mouse driver + * + * Copyright (c) 2012 Cypress Semiconductor Corporation. + * + * Author: + * Dudley Du <dudl@cypress.com> + * + * Additional contributors include: + * Kamal Mostafa <kamal@canonical.com> + * Kyle Fazzari <git@status.e4ward.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/serio.h> +#include <linux/libps2.h> +#include <linux/input.h> +#include <linux/input/mt.h> +#include <linux/sched.h> +#include <linux/wait.h> + +#include "cypress_ps2.h" + +#undef CYTP_DEBUG_VERBOSE /* define this and DEBUG for more verbose dump */ + +static void cypress_set_packet_size(struct psmouse *psmouse, unsigned int n) +{ + struct cytp_data *cytp = psmouse->private; + 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 int cypress_ps2_sendbyte(struct psmouse *psmouse, int value) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + + if (ps2_sendbyte(ps2dev, value & 0xff, CYTP_CMD_TIMEOUT) < 0) { + 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; + } + +#ifdef CYTP_DEBUG_VERBOSE + psmouse_dbg(psmouse, "sending command 0x%02x succeeded, resp 0xfa\n", + value & 0xff); +#endif + + return 0; +} + +static int cypress_ps2_ext_cmd(struct psmouse *psmouse, unsigned short cmd, + unsigned char data) +{ + struct ps2dev *ps2dev = &psmouse->ps2dev; + int tries = CYTP_PS2_CMD_TRIES; + int rc; + + ps2_begin_command(ps2dev); + + do { + /* + * Send extension command byte (0xE8 or 0xF3). + * 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, 0x00); + if (rc == CYTP_PS2_RETRY) + 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(&psmouse->ps2dev); + + old_state = psmouse->state; + psmouse->state = PSMOUSE_CMD_MODE; + psmouse->pktcnt = 0; + + 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; + + ps2_end_command(&psmouse->ps2dev); + + return rc; +} + +static bool cypress_verify_cmd_state(struct psmouse *psmouse, + unsigned char cmd, unsigned char *param) +{ + bool rate_match = false; + bool resolution_match = false; + int i; + + /* callers will do further checking. */ + if (cmd == CYTP_CMD_READ_CYPRESS_ID || + cmd == CYTP_CMD_STANDARD_MODE || + cmd == CYTP_CMD_READ_TP_METRICS) + return true; + + if ((~param[0] & DFLT_RESP_BITS_VALID) == DFLT_RESP_BITS_VALID && + (param[0] & DFLT_RESP_BIT_MODE) == DFLT_RESP_STREAM_MODE) { + for (i = 0; i < sizeof(cytp_resolution); i++) + if (cytp_resolution[i] == param[1]) + resolution_match = true; + + for (i = 0; i < sizeof(cytp_rate); i++) + if (cytp_rate[i] == param[2]) + rate_match = true; + + if (resolution_match && rate_match) + return true; + } + + psmouse_dbg(psmouse, "verify cmd state failed.\n"); + return false; +} + +static int cypress_send_ext_cmd(struct psmouse *psmouse, unsigned char cmd, + unsigned char *param) +{ + int tries = CYTP_PS2_CMD_TRIES; + int rc; + + 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; + + } while (--tries > 0); + + return -EIO; +} + +int cypress_detect(struct psmouse *psmouse, bool set_properties) +{ + unsigned char param[3]; + + if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) + return -ENODEV; + + /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ + if (param[0] != 0x33 || param[1] != 0xCC) + return -ENODEV; + + if (set_properties) { + psmouse->vendor = "Cypress"; + psmouse->name = "Trackpad"; + } + + return 0; +} + +static int cypress_read_fw_version(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + unsigned char param[3]; + + if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_CYPRESS_ID, param)) + return -ENODEV; + + /* Check for Cypress Trackpad signature bytes: 0x33 0xCC */ + if (param[0] != 0x33 || param[1] != 0xCC) + return -ENODEV; + + cytp->fw_version = param[2] & FW_VERSION_MASX; + cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; + + psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); + psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", + cytp->tp_metrics_supported); + + return 0; +} + +static int cypress_read_tp_metrics(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + unsigned char param[8]; + + /* set default values for tp metrics. */ + cytp->tp_width = CYTP_DEFAULT_WIDTH; + cytp->tp_high = CYTP_DEFAULT_HIGH; + cytp->tp_max_abs_x = CYTP_ABS_MAX_X; + cytp->tp_max_abs_y = CYTP_ABS_MAX_Y; + cytp->tp_min_pressure = CYTP_MIN_PRESSURE; + cytp->tp_max_pressure = CYTP_MAX_PRESSURE; + cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; + cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; + + memset(param, 0, sizeof(param)); + if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { + /* Update trackpad parameters. */ + cytp->tp_max_abs_x = (param[1] << 8) | param[0]; + cytp->tp_max_abs_y = (param[3] << 8) | param[2]; + cytp->tp_min_pressure = param[4]; + cytp->tp_max_pressure = param[5]; + } + + if (!cytp->tp_max_pressure || + cytp->tp_max_pressure < cytp->tp_min_pressure || + !cytp->tp_width || !cytp->tp_high || + !cytp->tp_max_abs_x || + cytp->tp_max_abs_x < cytp->tp_width || + !cytp->tp_max_abs_y || + cytp->tp_max_abs_y < cytp->tp_high) + return -EINVAL; + + cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; + cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; + +#ifdef CYTP_DEBUG_VERBOSE + psmouse_dbg(psmouse, "Dump trackpad hardware configuration as below:\n"); + psmouse_dbg(psmouse, "cytp->tp_width = %d\n", cytp->tp_width); + psmouse_dbg(psmouse, "cytp->tp_high = %d\n", cytp->tp_high); + psmouse_dbg(psmouse, "cytp->tp_max_abs_x = %d\n", cytp->tp_max_abs_x); + psmouse_dbg(psmouse, "cytp->tp_max_abs_y = %d\n", cytp->tp_max_abs_y); + psmouse_dbg(psmouse, "cytp->tp_min_pressure = %d\n", cytp->tp_min_pressure); + psmouse_dbg(psmouse, "cytp->tp_max_pressure = %d\n", cytp->tp_max_pressure); + psmouse_dbg(psmouse, "cytp->tp_res_x = %d\n", cytp->tp_res_x); + psmouse_dbg(psmouse, "cytp->tp_res_y = %d\n", cytp->tp_res_y); + + psmouse_dbg(psmouse, "tp_type_APA = %d\n", + (param[6] & TP_METRICS_BIT_APA) ? 1 : 0); + psmouse_dbg(psmouse, "tp_type_MTG = %d\n", + (param[6] & TP_METRICS_BIT_MTG) ? 1 : 0); + psmouse_dbg(psmouse, "tp_palm = %d\n", + (param[6] & TP_METRICS_BIT_PALM) ? 1 : 0); + psmouse_dbg(psmouse, "tp_stubborn = %d\n", + (param[6] & TP_METRICS_BIT_STUBBORN) ? 1 : 0); + psmouse_dbg(psmouse, "tp_1f_jitter = %d\n", + (param[6] & TP_METRICS_BIT_1F_JITTER) >> 2); + psmouse_dbg(psmouse, "tp_2f_jitter = %d\n", + (param[6] & TP_METRICS_BIT_2F_JITTER) >> 4); + psmouse_dbg(psmouse, "tp_1f_spike = %d\n", + param[7] & TP_METRICS_BIT_1F_SPIKE); + psmouse_dbg(psmouse, "tp_2f_spike = %d\n", + (param[7] & TP_METRICS_BIT_2F_SPIKE) >> 2); + psmouse_dbg(psmouse, "tp_abs_packet_format_set = %d\n", + (param[7] & TP_METRICS_BIT_ABS_PKT_FORMAT_SET) >> 4); +#endif + + return 0; +} + +static int cypress_query_hardware(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + int ret; + + ret = cypress_read_fw_version(psmouse); + if (ret) + return ret; + + if (cytp->tp_metrics_supported) { + ret = cypress_read_tp_metrics(psmouse); + if (ret) + return ret; + } + + return 0; +} + +static int cypress_set_absolute_mode(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + unsigned char param[3]; + + if (cypress_send_ext_cmd(psmouse, CYTP_CMD_ABS_WITH_PRESSURE_MODE, param) < 0) + return -1; + + cytp->mode = (cytp->mode & ~CYTP_BIT_ABS_REL_MASK) + | CYTP_BIT_ABS_PRESSURE; + cypress_set_packet_size(psmouse, 5); + + return 0; +} + +/* + * Reset trackpad device. + * This is also the default mode when trackpad powered on. + */ +static void cypress_reset(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + + cytp->mode = 0; + + psmouse_reset(psmouse); +} + +static int cypress_set_input_params(struct input_dev *input, + struct cytp_data *cytp) +{ + int ret; + + if (!cytp->tp_res_x || !cytp->tp_res_y) + return -EINVAL; + + __set_bit(EV_ABS, input->evbit); + input_set_abs_params(input, ABS_X, 0, cytp->tp_max_abs_x, 0, 0); + input_set_abs_params(input, ABS_Y, 0, cytp->tp_max_abs_y, 0, 0); + input_set_abs_params(input, ABS_PRESSURE, + cytp->tp_min_pressure, cytp->tp_max_pressure, 0, 0); + input_set_abs_params(input, ABS_TOOL_WIDTH, 0, 255, 0, 0); + + /* finger position */ + input_set_abs_params(input, ABS_MT_POSITION_X, 0, cytp->tp_max_abs_x, 0, 0); + 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; + + __set_bit(INPUT_PROP_SEMI_MT, input->propbit); + + input_abs_set_res(input, ABS_X, cytp->tp_res_x); + input_abs_set_res(input, ABS_Y, cytp->tp_res_y); + + input_abs_set_res(input, ABS_MT_POSITION_X, cytp->tp_res_x); + input_abs_set_res(input, ABS_MT_POSITION_Y, cytp->tp_res_y); + + __set_bit(BTN_TOUCH, input->keybit); + __set_bit(BTN_TOOL_FINGER, input->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); + __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); + __set_bit(BTN_TOOL_QUADTAP, input->keybit); + __set_bit(BTN_TOOL_QUINTTAP, input->keybit); + + __clear_bit(EV_REL, input->evbit); + __clear_bit(REL_X, input->relbit); + __clear_bit(REL_Y, input->relbit); + + __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); + __set_bit(EV_KEY, input->evbit); + __set_bit(BTN_LEFT, input->keybit); + __set_bit(BTN_RIGHT, input->keybit); + __set_bit(BTN_MIDDLE, input->keybit); + + input_set_drvdata(input, cytp); + + return 0; +} + +static int cypress_get_finger_count(unsigned char header_byte) +{ + unsigned char bits6_7; + int finger_count; + + bits6_7 = header_byte >> 6; + finger_count = bits6_7 & 0x03; + + if (finger_count == 1) + return 1; + + if (header_byte & ABS_HSCROLL_BIT) { + /* HSCROLL gets added on to 0 finger count. */ + switch (finger_count) { + case 0: return 4; + case 2: return 5; + default: + /* Invalid contact (e.g. palm). Ignore it. */ + return -1; + } + } + + return finger_count; +} + + +static int cypress_parse_packet(struct psmouse *psmouse, + struct cytp_data *cytp, struct cytp_report_data *report_data) +{ + unsigned char *packet = psmouse->packet; + unsigned char header_byte = packet[0]; + int contact_cnt; + + memset(report_data, 0, sizeof(struct cytp_report_data)); + + contact_cnt = cypress_get_finger_count(header_byte); + + if (contact_cnt < 0) /* e.g. palm detect */ + return -EINVAL; + + report_data->contact_cnt = contact_cnt; + + report_data->tap = (header_byte & ABS_MULTIFINGER_TAP) ? 1 : 0; + + if (report_data->contact_cnt == 1) { + report_data->contacts[0].x = + ((packet[1] & 0x70) << 4) | packet[2]; + report_data->contacts[0].y = + ((packet[1] & 0x07) << 8) | packet[3]; + if (cytp->mode & CYTP_BIT_ABS_PRESSURE) + report_data->contacts[0].z = packet[4]; + + } else if (report_data->contact_cnt >= 2) { + report_data->contacts[0].x = + ((packet[1] & 0x70) << 4) | packet[2]; + report_data->contacts[0].y = + ((packet[1] & 0x07) << 8) | packet[3]; + if (cytp->mode & CYTP_BIT_ABS_PRESSURE) + report_data->contacts[0].z = packet[4]; + + report_data->contacts[1].x = + ((packet[5] & 0xf0) << 4) | packet[6]; + report_data->contacts[1].y = + ((packet[5] & 0x0f) << 8) | packet[7]; + if (cytp->mode & CYTP_BIT_ABS_PRESSURE) + report_data->contacts[1].z = report_data->contacts[0].z; + } + + report_data->left = (header_byte & BTN_LEFT_BIT) ? 1 : 0; + report_data->right = (header_byte & BTN_RIGHT_BIT) ? 1 : 0; + + /* + * This is only true if one of the mouse buttons were tapped. Make + * sure it doesn't turn into a click. The regular tap-to-click + * functionality will handle that on its own. If we don't do this, + * disabling tap-to-click won't affect the mouse button zones. + */ + if (report_data->tap) + report_data->left = 0; + +#ifdef CYTP_DEBUG_VERBOSE + { + int i; + int n = report_data->contact_cnt; + psmouse_dbg(psmouse, "Dump parsed report data as below:\n"); + psmouse_dbg(psmouse, "contact_cnt = %d\n", + report_data->contact_cnt); + if (n > CYTP_MAX_MT_SLOTS) + n = CYTP_MAX_MT_SLOTS; + for (i = 0; i < n; i++) + psmouse_dbg(psmouse, "contacts[%d] = {%d, %d, %d}\n", i, + report_data->contacts[i].x, + report_data->contacts[i].y, + report_data->contacts[i].z); + psmouse_dbg(psmouse, "left = %d\n", report_data->left); + psmouse_dbg(psmouse, "right = %d\n", report_data->right); + psmouse_dbg(psmouse, "middle = %d\n", report_data->middle); + } +#endif + + return 0; +} + +static void cypress_process_packet(struct psmouse *psmouse, bool zero_pkt) +{ + int i; + struct input_dev *input = psmouse->dev; + struct cytp_data *cytp = psmouse->private; + struct cytp_report_data report_data; + struct cytp_contact *contact; + struct input_mt_pos pos[CYTP_MAX_MT_SLOTS]; + int slots[CYTP_MAX_MT_SLOTS]; + int n; + + if (cypress_parse_packet(psmouse, cytp, &report_data)) + return; + + n = report_data.contact_cnt; + + if (n > CYTP_MAX_MT_SLOTS) + n = CYTP_MAX_MT_SLOTS; + + for (i = 0; i < n; i++) { + contact = &report_data.contacts[i]; + pos[i].x = contact->x; + pos[i].y = contact->y; + } + + input_mt_assign_slots(input, slots, pos, n); + + for (i = 0; i < n; i++) { + contact = &report_data.contacts[i]; + input_mt_slot(input, slots[i]); + input_mt_report_slot_state(input, MT_TOOL_FINGER, true); + input_report_abs(input, ABS_MT_POSITION_X, contact->x); + input_report_abs(input, ABS_MT_POSITION_Y, contact->y); + input_report_abs(input, ABS_MT_PRESSURE, contact->z); + } + + input_mt_sync_frame(input); + + input_mt_report_finger_count(input, report_data.contact_cnt); + + input_report_key(input, BTN_LEFT, report_data.left); + input_report_key(input, BTN_RIGHT, report_data.right); + input_report_key(input, BTN_MIDDLE, report_data.middle); + + input_sync(input); +} + +static psmouse_ret_t cypress_validate_byte(struct psmouse *psmouse) +{ + int contact_cnt; + int index = psmouse->pktcnt - 1; + unsigned char *packet = psmouse->packet; + struct cytp_data *cytp = psmouse->private; + + if (index < 0 || index > cytp->pkt_size) + return PSMOUSE_BAD_DATA; + + if (index == 0 && (packet[0] & 0xfc) == 0) { + /* call packet process for reporting finger leave. */ + cypress_process_packet(psmouse, 1); + return PSMOUSE_FULL_PACKET; + } + + /* + * Perform validation (and adjust packet size) based only on the + * first byte; allow all further bytes through. + */ + if (index != 0) + return PSMOUSE_GOOD_DATA; + + /* + * If absolute/relative mode bit has not been set yet, just pass + * the byte through. + */ + if ((cytp->mode & CYTP_BIT_ABS_REL_MASK) == 0) + return PSMOUSE_GOOD_DATA; + + if ((packet[0] & 0x08) == 0x08) + return PSMOUSE_BAD_DATA; + + contact_cnt = cypress_get_finger_count(packet[0]); + + if (contact_cnt < 0) + return PSMOUSE_BAD_DATA; + + if (cytp->mode & CYTP_BIT_ABS_NO_PRESSURE) + cypress_set_packet_size(psmouse, contact_cnt == 2 ? 7 : 4); + else + cypress_set_packet_size(psmouse, contact_cnt == 2 ? 8 : 5); + + return PSMOUSE_GOOD_DATA; +} + +static psmouse_ret_t cypress_protocol_handler(struct psmouse *psmouse) +{ + struct cytp_data *cytp = psmouse->private; + + if (psmouse->pktcnt >= cytp->pkt_size) { + cypress_process_packet(psmouse, 0); + return PSMOUSE_FULL_PACKET; + } + + return cypress_validate_byte(psmouse); +} + +static void cypress_set_rate(struct psmouse *psmouse, unsigned int rate) +{ + struct cytp_data *cytp = psmouse->private; + + if (rate >= 80) { + psmouse->rate = 80; + cytp->mode |= CYTP_BIT_HIGH_RATE; + } else { + psmouse->rate = 40; + cytp->mode &= ~CYTP_BIT_HIGH_RATE; + } + + ps2_command(&psmouse->ps2dev, (unsigned char *)&psmouse->rate, + PSMOUSE_CMD_SETRATE); +} + +static void cypress_disconnect(struct psmouse *psmouse) +{ + cypress_reset(psmouse); + kfree(psmouse->private); + psmouse->private = NULL; +} + +static int cypress_reconnect(struct psmouse *psmouse) +{ + int tries = CYTP_PS2_CMD_TRIES; + int rc; + + do { + cypress_reset(psmouse); + rc = cypress_detect(psmouse, false); + } while (rc && (--tries > 0)); + + if (rc) { + psmouse_err(psmouse, "Reconnect: unable to detect trackpad.\n"); + return -1; + } + + if (cypress_set_absolute_mode(psmouse)) { + psmouse_err(psmouse, "Reconnect: Unable to initialize Cypress absolute mode.\n"); + return -1; + } + + return 0; +} + +int cypress_init(struct psmouse *psmouse) +{ + struct cytp_data *cytp; + + cytp = (struct cytp_data *)kzalloc(sizeof(struct cytp_data), GFP_KERNEL); + psmouse->private = (void *)cytp; + if (cytp == NULL) + return -ENOMEM; + + cypress_reset(psmouse); + + psmouse->pktsize = 8; + + if (cypress_query_hardware(psmouse)) { + psmouse_err(psmouse, "Unable to query Trackpad hardware.\n"); + goto err_exit; + } + + if (cypress_set_absolute_mode(psmouse)) { + psmouse_err(psmouse, "init: Unable to initialize Cypress absolute mode.\n"); + goto err_exit; + } + + if (cypress_set_input_params(psmouse->dev, cytp) < 0) { + psmouse_err(psmouse, "init: Unable to set input params.\n"); + goto err_exit; + } + + psmouse->model = 1; + psmouse->protocol_handler = cypress_protocol_handler; + psmouse->set_rate = cypress_set_rate; + psmouse->disconnect = cypress_disconnect; + psmouse->reconnect = cypress_reconnect; + psmouse->cleanup = cypress_reset; + psmouse->resync_time = 0; + + return 0; + +err_exit: + /* + * Reset Cypress Trackpad as a standard mouse. Then + * let psmouse driver commmunicating with it as default PS2 mouse. + */ + cypress_reset(psmouse); + + psmouse->private = NULL; + kfree(cytp); + + return -1; +} + +bool cypress_supported(void) +{ + return true; +} diff --git a/drivers/input/mouse/cypress_ps2.h b/drivers/input/mouse/cypress_ps2.h new file mode 100644 index 000000000000..4720f21d2d70 --- /dev/null +++ b/drivers/input/mouse/cypress_ps2.h @@ -0,0 +1,191 @@ +#ifndef _CYPRESS_PS2_H +#define _CYPRESS_PS2_H + +#include "psmouse.h" + +#define CMD_BITS_MASK 0x03 +#define COMPOSIT(x, s) (((x) & CMD_BITS_MASK) << (s)) + +#define ENCODE_CMD(aa, bb, cc, dd) \ + (COMPOSIT((aa), 6) | COMPOSIT((bb), 4) | COMPOSIT((cc), 2) | COMPOSIT((dd), 0)) +#define CYTP_CMD_ABS_NO_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 0) +#define CYTP_CMD_ABS_WITH_PRESSURE_MODE ENCODE_CMD(0, 1, 0, 1) +#define CYTP_CMD_SMBUS_MODE ENCODE_CMD(0, 1, 1, 0) +#define CYTP_CMD_STANDARD_MODE ENCODE_CMD(0, 2, 0, 0) /* not implemented yet. */ +#define CYTP_CMD_CYPRESS_REL_MODE ENCODE_CMD(1, 1, 1, 1) /* not implemented yet. */ +#define CYTP_CMD_READ_CYPRESS_ID ENCODE_CMD(0, 0, 0, 0) +#define CYTP_CMD_READ_TP_METRICS ENCODE_CMD(0, 0, 0, 1) +#define CYTP_CMD_SET_HSCROLL_WIDTH(w) ENCODE_CMD(1, 1, 0, (w)) +#define CYTP_CMD_SET_HSCROLL_MASK ENCODE_CMD(1, 1, 0, 0) +#define CYTP_CMD_SET_VSCROLL_WIDTH(w) ENCODE_CMD(1, 2, 0, (w)) +#define CYTP_CMD_SET_VSCROLL_MASK ENCODE_CMD(1, 2, 0, 0) +#define CYTP_CMD_SET_PALM_GEOMETRY(e) ENCODE_CMD(1, 2, 1, (e)) +#define CYTP_CMD_PALM_GEMMETRY_MASK ENCODE_CMD(1, 2, 1, 0) +#define CYTP_CMD_SET_PALM_SENSITIVITY(s) ENCODE_CMD(1, 2, 2, (s)) +#define CYTP_CMD_PALM_SENSITIVITY_MASK ENCODE_CMD(1, 2, 2, 0) +#define CYTP_CMD_SET_MOUSE_SENSITIVITY(s) ENCODE_CMD(1, 3, ((s) >> 2), (s)) +#define CYTP_CMD_MOUSE_SENSITIVITY_MASK ENCODE_CMD(1, 3, 0, 0) +#define CYTP_CMD_REQUEST_BASELINE_STATUS ENCODE_CMD(2, 0, 0, 1) +#define CYTP_CMD_REQUEST_RECALIBRATION ENCODE_CMD(2, 0, 0, 3) + +#define DECODE_CMD_AA(x) (((x) >> 6) & CMD_BITS_MASK) +#define DECODE_CMD_BB(x) (((x) >> 4) & CMD_BITS_MASK) +#define DECODE_CMD_CC(x) (((x) >> 2) & CMD_BITS_MASK) +#define DECODE_CMD_DD(x) ((x) & CMD_BITS_MASK) + +/* Cypress trackpad working mode. */ +#define CYTP_BIT_ABS_PRESSURE (1 << 3) +#define CYTP_BIT_ABS_NO_PRESSURE (1 << 2) +#define CYTP_BIT_CYPRESS_REL (1 << 1) +#define CYTP_BIT_STANDARD_REL (1 << 0) +#define CYTP_BIT_REL_MASK (CYTP_BIT_CYPRESS_REL | CYTP_BIT_STANDARD_REL) +#define CYTP_BIT_ABS_MASK (CYTP_BIT_ABS_PRESSURE | CYTP_BIT_ABS_NO_PRESSURE) +#define CYTP_BIT_ABS_REL_MASK (CYTP_BIT_ABS_MASK | CYTP_BIT_REL_MASK) + +#define CYTP_BIT_HIGH_RATE (1 << 4) +/* + * report mode bit is set, firmware working in Remote Mode. + * report mode bit is cleared, firmware working in Stream Mode. + */ +#define CYTP_BIT_REPORT_MODE (1 << 5) + +/* scrolling width values for set HSCROLL and VSCROLL width command. */ +#define SCROLL_WIDTH_NARROW 1 +#define SCROLL_WIDTH_NORMAL 2 +#define SCROLL_WIDTH_WIDE 3 + +#define PALM_GEOMETRY_ENABLE 1 +#define PALM_GEOMETRY_DISABLE 0 + +#define TP_METRICS_MASK 0x80 +#define FW_VERSION_MASX 0x7f +#define FW_VER_HIGH_MASK 0x70 +#define FW_VER_LOW_MASK 0x0f + +/* Times to retry a ps2_command and millisecond delay between tries. */ +#define CYTP_PS2_CMD_TRIES 3 +#define CYTP_PS2_CMD_DELAY 500 + +/* time out for PS/2 command only in milliseconds. */ +#define CYTP_CMD_TIMEOUT 200 +#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 +#define CYTP_DEFAULT_WIDTH (CYTP_105001_WIDTH) +#define CYTP_DEFAULT_HIGH (CYTP_105001_HIGH) + +#define CYTP_ABS_MAX_X 1600 +#define CYTP_ABS_MAX_Y 900 +#define CYTP_MAX_PRESSURE 255 +#define CYTP_MIN_PRESSURE 0 + +/* header byte bits of relative package. */ +#define BTN_LEFT_BIT 0x01 +#define BTN_RIGHT_BIT 0x02 +#define BTN_MIDDLE_BIT 0x04 +#define REL_X_SIGN_BIT 0x10 +#define REL_Y_SIGN_BIT 0x20 + +/* header byte bits of absolute package. */ +#define ABS_VSCROLL_BIT 0x10 +#define ABS_HSCROLL_BIT 0x20 +#define ABS_MULTIFINGER_TAP 0x04 +#define ABS_EDGE_MOTION_MASK 0x80 + +#define DFLT_RESP_BITS_VALID 0x88 /* SMBus bit should not be set. */ +#define DFLT_RESP_SMBUS_BIT 0x80 +#define DFLT_SMBUS_MODE 0x80 +#define DFLT_PS2_MODE 0x00 +#define DFLT_RESP_BIT_MODE 0x40 +#define DFLT_RESP_REMOTE_MODE 0x40 +#define DFLT_RESP_STREAM_MODE 0x00 +#define DFLT_RESP_BIT_REPORTING 0x20 +#define DFLT_RESP_BIT_SCALING 0x10 + +#define TP_METRICS_BIT_PALM 0x80 +#define TP_METRICS_BIT_STUBBORN 0x40 +#define TP_METRICS_BIT_2F_JITTER 0x30 +#define TP_METRICS_BIT_1F_JITTER 0x0c +#define TP_METRICS_BIT_APA 0x02 +#define TP_METRICS_BIT_MTG 0x01 +#define TP_METRICS_BIT_ABS_PKT_FORMAT_SET 0xf0 +#define TP_METRICS_BIT_2F_SPIKE 0x0c +#define TP_METRICS_BIT_1F_SPIKE 0x03 + +/* bits of first byte response of E9h-Status Request command. */ +#define RESP_BTN_RIGHT_BIT 0x01 +#define RESP_BTN_MIDDLE_BIT 0x02 +#define RESP_BTN_LEFT_BIT 0x04 +#define RESP_SCALING_BIT 0x10 +#define RESP_ENABLE_BIT 0x20 +#define RESP_REMOTE_BIT 0x40 +#define RESP_SMBUS_BIT 0x80 + +#define CYTP_MAX_MT_SLOTS 2 + +struct cytp_contact { + int x; + int y; + int z; /* also named as touch pressure. */ +}; + +/* The structure of Cypress Trackpad event data. */ +struct cytp_report_data { + int contact_cnt; + struct cytp_contact contacts[CYTP_MAX_MT_SLOTS]; + unsigned int left:1; + unsigned int right:1; + unsigned int middle:1; + unsigned int tap:1; /* multi-finger tap detected. */ +}; + +/* The structure of Cypress Trackpad device private data. */ +struct cytp_data { + int fw_version; + + int pkt_size; + int mode; + + int tp_min_pressure; + int tp_max_pressure; + int tp_width; /* X direction physical size in mm. */ + int tp_high; /* Y direction physical size in mm. */ + int tp_max_abs_x; /* Max X absolute units that can be reported. */ + int tp_max_abs_y; /* Max Y absolute units that can be reported. */ + + int tp_res_x; /* X resolution in units/mm. */ + int tp_res_y; /* Y resolution in units/mm. */ + + int tp_metrics_supported; +}; + + +#ifdef CONFIG_MOUSE_PS2_CYPRESS +int cypress_detect(struct psmouse *psmouse, bool set_properties); +int cypress_init(struct psmouse *psmouse); +bool cypress_supported(void); +#else +inline int cypress_detect(struct psmouse *psmouse, bool set_properties) +{ + return -ENOSYS; +} +inline int cypress_init(struct psmouse *psmouse) +{ + return -ENOSYS; +} +inline bool cypress_supported(void) +{ + return 0; +} +#endif /* CONFIG_MOUSE_PS2_CYPRESS */ + +#endif /* _CYPRESS_PS2_H */ diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 39fe9b737cae..532eaca4cc56 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) input_sync(input); } -static int __devinit gpio_mouse_probe(struct platform_device *pdev) +static int gpio_mouse_probe(struct platform_device *pdev) { struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; struct input_polled_dev *input_poll; @@ -150,7 +150,7 @@ static int __devinit gpio_mouse_probe(struct platform_device *pdev) return error; } -static int __devexit gpio_mouse_remove(struct platform_device *pdev) +static int gpio_mouse_remove(struct platform_device *pdev) { struct input_polled_dev *input = platform_get_drvdata(pdev); struct gpio_mouse_platform_data *pdata = input->private; @@ -172,7 +172,7 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) static struct platform_driver gpio_mouse_device_driver = { .probe = gpio_mouse_probe, - .remove = __devexit_p(gpio_mouse_remove), + .remove = gpio_mouse_remove, .driver = { .name = "gpio_mouse", .owner = THIS_MODULE, diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 5f278176eb9b..0a60717b91c6 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c @@ -64,7 +64,7 @@ static void dc_mouse_close(struct input_dev *dev) } /* allow the mouse to be used */ -static int __devinit probe_maple_mouse(struct device *dev) +static int probe_maple_mouse(struct device *dev) { struct maple_device *mdev = to_maple_dev(dev); struct maple_driver *mdrv = to_maple_driver(dev->driver); @@ -114,7 +114,7 @@ fail: return error; } -static int __devexit remove_maple_mouse(struct device *dev) +static int remove_maple_mouse(struct device *dev) { struct maple_device *mdev = to_maple_dev(dev); struct dc_mouse *mse = maple_get_drvdata(mdev); @@ -132,7 +132,7 @@ static struct maple_driver dc_mouse_driver = { .drv = { .name = "Dreamcast_mouse", .probe = probe_maple_mouse, - .remove = __devexit_p(remove_maple_mouse), + .remove = remove_maple_mouse, }, }; diff --git a/drivers/input/mouse/navpoint.c b/drivers/input/mouse/navpoint.c index c29ae7654d5e..8e1b98ea5648 100644 --- a/drivers/input/mouse/navpoint.c +++ b/drivers/input/mouse/navpoint.c @@ -206,7 +206,7 @@ static void navpoint_close(struct input_dev *input) navpoint_down(navpoint); } -static int __devinit navpoint_probe(struct platform_device *pdev) +static int navpoint_probe(struct platform_device *pdev) { const struct navpoint_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -299,7 +299,7 @@ err_free_gpio: return error; } -static int __devexit navpoint_remove(struct platform_device *pdev) +static int navpoint_remove(struct platform_device *pdev) { const struct navpoint_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -353,7 +353,7 @@ static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume); static struct platform_driver navpoint_driver = { .probe = navpoint_probe, - .remove = __devexit_p(navpoint_remove), + .remove = navpoint_remove, .driver = { .name = "navpoint", .owner = THIS_MODULE, diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 22fe2547e169..cff065f6261c 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -34,6 +34,7 @@ #include "touchkit_ps2.h" #include "elantech.h" #include "sentelic.h" +#include "cypress_ps2.h" #define DRIVER_DESC "PS/2 mouse driver" @@ -759,6 +760,28 @@ static int psmouse_extensions(struct psmouse *psmouse, } /* + * Try Cypress Trackpad. + * Must try it before Finger Sensing Pad because Finger Sensing Pad probe + * upsets some modules of Cypress Trackpads. + */ + if (max_proto > PSMOUSE_IMEX && + cypress_detect(psmouse, set_properties) == 0) { + if (cypress_supported()) { + if (cypress_init(psmouse) == 0) + return PSMOUSE_CYPRESS; + + /* + * Finger Sensing Pad probe upsets some modules of + * Cypress Trackpad, must avoid Finger Sensing Pad + * probe if Cypress Trackpad device detected. + */ + return PSMOUSE_PS2; + } + + max_proto = PSMOUSE_IMEX; + } + +/* * Try ALPS TouchPad */ if (max_proto > PSMOUSE_IMEX) { @@ -896,6 +919,15 @@ static const struct psmouse_protocol psmouse_protocols[] = { .alias = "thinkps", .detect = thinking_detect, }, +#ifdef CONFIG_MOUSE_PS2_CYPRESS + { + .type = PSMOUSE_CYPRESS, + .name = "CyPS/2", + .alias = "cypress", + .detect = cypress_detect, + .init = cypress_init, + }, +#endif { .type = PSMOUSE_GENPS, .name = "GenPS/2", diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index fe1df231ba4c..2f0b39d59a9b 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h @@ -95,6 +95,7 @@ enum psmouse_type { PSMOUSE_ELANTECH, PSMOUSE_FSP, PSMOUSE_SYNAPTICS_RELATIVE, + PSMOUSE_CYPRESS, PSMOUSE_AUTO /* This one should always be last */ }; diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 4fe055f2c536..0ecb9e7945eb 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c @@ -143,7 +143,7 @@ static void pxa930_trkball_close(struct input_dev *dev) pxa930_trkball_disable(trkball); } -static int __devinit pxa930_trkball_probe(struct platform_device *pdev) +static int pxa930_trkball_probe(struct platform_device *pdev) { struct pxa930_trkball *trkball; struct input_dev *input; @@ -230,7 +230,7 @@ failed: return error; } -static int __devexit pxa930_trkball_remove(struct platform_device *pdev) +static int pxa930_trkball_remove(struct platform_device *pdev) { struct pxa930_trkball *trkball = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); @@ -248,7 +248,7 @@ static struct platform_driver pxa930_trkball_driver = { .name = "pxa930-trkball", }, .probe = pxa930_trkball_probe, - .remove = __devexit_p(pxa930_trkball_remove), + .remove = pxa930_trkball_remove, }; module_platform_driver(pxa930_trkball_driver); diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index e582922bacf7..cc7e0d4a8f93 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -791,7 +791,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); fsp_set_slot(dev, 1, false, 0, 0); } - if (fgrs > 0) { + if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) { input_report_abs(dev, ABS_X, abs_x); input_report_abs(dev, ABS_Y, abs_y); } diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 12d12ca3fee0..2f78538e09d0 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -722,11 +722,13 @@ static void synaptics_report_mt_data(struct psmouse *psmouse, default: /* * If the finger slot contained in SGM is valid, and either - * hasn't changed, or is new, then report SGM in MTB slot 0. + * hasn't changed, or is new, or the old SGM has now moved to + * AGM, then report SGM in MTB slot 0. * Otherwise, empty MTB slot 0. */ if (mt_state->sgm != -1 && - (mt_state->sgm == old->sgm || old->sgm == -1)) + (mt_state->sgm == old->sgm || + old->sgm == -1 || mt_state->agm == old->sgm)) synaptics_report_slot(dev, 0, sgm); else synaptics_report_slot(dev, 0, NULL); @@ -735,9 +737,31 @@ static void synaptics_report_mt_data(struct psmouse *psmouse, * If the finger slot contained in AGM is valid, and either * hasn't changed, or is new, then report AGM in MTB slot 1. * Otherwise, empty MTB slot 1. + * + * However, in the case where the AGM is new, make sure that + * that it is either the same as the old SGM, or there was no + * SGM. + * + * Otherwise, if the SGM was just 1, and the new AGM is 2, then + * the new AGM will keep the old SGM's tracking ID, which can + * cause apparent drumroll. This happens if in the following + * valid finger sequence: + * + * Action SGM AGM (MTB slot:Contact) + * 1. Touch contact 0 (0:0) + * 2. Touch contact 1 (0:0, 1:1) + * 3. Lift contact 0 (1:1) + * 4. Touch contacts 2,3 (0:2, 1:3) + * + * In step 4, contact 3, in AGM must not be given the same + * tracking ID as contact 1 had in step 3. To avoid this, + * the first agm with contact 3 is dropped and slot 1 is + * invalidated (tracking ID = -1). */ if (mt_state->agm != -1 && - (mt_state->agm == old->agm || old->agm == -1)) + (mt_state->agm == old->agm || + (old->agm == -1 && + (old->sgm == -1 || mt_state->agm == old->sgm)))) synaptics_report_slot(dev, 1, agm); else synaptics_report_slot(dev, 1, NULL); @@ -1247,11 +1271,11 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); if (SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) { - input_mt_init_slots(dev, 2, 0); set_abs_position_params(dev, priv, ABS_MT_POSITION_X, ABS_MT_POSITION_Y); /* Image sensors can report per-contact pressure */ input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); + input_mt_init_slots(dev, 2, INPUT_MT_POINTER); /* Image sensors can signal 4 and 5 finger clicks */ __set_bit(BTN_TOOL_QUADTAP, dev->keybit); diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 063a174d3a88..ad822608f6ee 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -535,7 +535,7 @@ static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *clien return touch; } -static int __devinit synaptics_i2c_probe(struct i2c_client *client, +static int synaptics_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { int ret; @@ -601,7 +601,7 @@ err_mem_free: return ret; } -static int __devexit synaptics_i2c_remove(struct i2c_client *client) +static int synaptics_i2c_remove(struct i2c_client *client) { struct synaptics_i2c *touch = i2c_get_clientdata(client); @@ -662,7 +662,7 @@ static struct i2c_driver synaptics_i2c_driver = { }, .probe = synaptics_i2c_probe, - .remove = __devexit_p(synaptics_i2c_remove), + .remove = synaptics_i2c_remove, .id_table = synaptics_i2c_id_table, }; diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 55f2c2293ec6..6e9cc765e0dc 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -36,6 +36,7 @@ config SERIO_I8042 config SERIO_SERPORT tristate "Serial port line discipline" default y + depends on TTY help Say Y here if you plan to use an input device (mouse, joystick, tablet, 6dof) that communicates over the RS232 serial (COM) port. @@ -234,4 +235,14 @@ config SERIO_PS2MULT To compile this driver as a module, choose M here: the module will be called ps2mult. +config SERIO_ARC_PS2 + tristate "ARC PS/2 support" + depends on GENERIC_HARDIRQS + help + Say Y here if you have an ARC FPGA platform with a PS/2 + controller in it. + + To compile this driver as a module, choose M here; the module + will be called arc_ps2. + endif diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index dbbe37616c92..4b0c8f84f1c1 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_SERIO_RAW) += serio_raw.o obj-$(CONFIG_SERIO_AMS_DELTA) += ams_delta_serio.o obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o +obj-$(CONFIG_SERIO_ARC_PS2) += arc_ps2.o diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c index cc11f4efe119..479ce5fe8955 100644 --- a/drivers/input/serio/altera_ps2.c +++ b/drivers/input/serio/altera_ps2.c @@ -81,7 +81,7 @@ static void altera_ps2_close(struct serio *io) /* * Add one device to this driver. */ -static int __devinit altera_ps2_probe(struct platform_device *pdev) +static int altera_ps2_probe(struct platform_device *pdev) { struct ps2if *ps2if; struct serio *serio; @@ -159,7 +159,7 @@ static int __devinit altera_ps2_probe(struct platform_device *pdev) /* * Remove one device from this driver. */ -static int __devexit altera_ps2_remove(struct platform_device *pdev) +static int altera_ps2_remove(struct platform_device *pdev) { struct ps2if *ps2if = platform_get_drvdata(pdev); @@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(of, altera_ps2_match); */ static struct platform_driver altera_ps2_driver = { .probe = altera_ps2_probe, - .remove = __devexit_p(altera_ps2_remove), + .remove = altera_ps2_remove, .driver = { .name = DRV_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 2e77246c2e5a..4e2fd44865e1 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c @@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) clk_disable_unprepare(kmi->clk); } -static int __devinit amba_kmi_probe(struct amba_device *dev, +static int amba_kmi_probe(struct amba_device *dev, const struct amba_id *id) { struct amba_kmi_port *kmi; @@ -163,7 +163,7 @@ static int __devinit amba_kmi_probe(struct amba_device *dev, return ret; } -static int __devexit amba_kmi_remove(struct amba_device *dev) +static int amba_kmi_remove(struct amba_device *dev) { struct amba_kmi_port *kmi = amba_get_drvdata(dev); @@ -204,7 +204,7 @@ static struct amba_driver ambakmi_driver = { }, .id_table = amba_kmi_idtable, .probe = amba_kmi_probe, - .remove = __devexit_p(amba_kmi_remove), + .remove = amba_kmi_remove, .resume = amba_kmi_resume, }; diff --git a/drivers/input/serio/arc_ps2.c b/drivers/input/serio/arc_ps2.c new file mode 100644 index 000000000000..c52e3e589f72 --- /dev/null +++ b/drivers/input/serio/arc_ps2.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver is originally developed by Pavel Sokolov <psokolov@synopsys.com> + */ + +#include <linux/err.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/serio.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/slab.h> + +#define ARC_PS2_PORTS 2 + +#define ARC_ARC_PS2_ID 0x0001f609 + +#define STAT_TIMEOUT 128 + +#define PS2_STAT_RX_FRM_ERR (1) +#define PS2_STAT_RX_BUF_OVER (1 << 1) +#define PS2_STAT_RX_INT_EN (1 << 2) +#define PS2_STAT_RX_VAL (1 << 3) +#define PS2_STAT_TX_ISNOT_FUL (1 << 4) +#define PS2_STAT_TX_INT_EN (1 << 5) + +struct arc_ps2_port { + void __iomem *data_addr; + void __iomem *status_addr; + struct serio *io; +}; + +struct arc_ps2_data { + struct arc_ps2_port port[ARC_PS2_PORTS]; + void __iomem *addr; + unsigned int frame_error; + unsigned int buf_overflow; + unsigned int total_int; +}; + +static void arc_ps2_check_rx(struct arc_ps2_data *arc_ps2, + struct arc_ps2_port *port) +{ + unsigned int timeout = 1000; + unsigned int flag, status; + unsigned char data; + + do { + status = ioread32(port->status_addr); + if (!(status & PS2_STAT_RX_VAL)) + return; + + data = ioread32(port->data_addr) & 0xff; + + flag = 0; + arc_ps2->total_int++; + if (status & PS2_STAT_RX_FRM_ERR) { + arc_ps2->frame_error++; + flag |= SERIO_PARITY; + } else if (status & PS2_STAT_RX_BUF_OVER) { + arc_ps2->buf_overflow++; + flag |= SERIO_FRAME; + } + + serio_interrupt(port->io, data, flag); + } while (--timeout); + + dev_err(&port->io->dev, "PS/2 hardware stuck\n"); +} + +static irqreturn_t arc_ps2_interrupt(int irq, void *dev) +{ + struct arc_ps2_data *arc_ps2 = dev; + int i; + + for (i = 0; i < ARC_PS2_PORTS; i++) + arc_ps2_check_rx(arc_ps2, &arc_ps2->port[i]); + + return IRQ_HANDLED; +} + +static int arc_ps2_write(struct serio *io, unsigned char val) +{ + unsigned status; + struct arc_ps2_port *port = io->port_data; + int timeout = STAT_TIMEOUT; + + do { + status = ioread32(port->status_addr); + cpu_relax(); + + if (status & PS2_STAT_TX_ISNOT_FUL) { + iowrite32(val & 0xff, port->data_addr); + return 0; + } + + } while (--timeout); + + dev_err(&io->dev, "write timeout\n"); + return -ETIMEDOUT; +} + +static int arc_ps2_open(struct serio *io) +{ + struct arc_ps2_port *port = io->port_data; + + iowrite32(PS2_STAT_RX_INT_EN, port->status_addr); + + return 0; +} + +static void arc_ps2_close(struct serio *io) +{ + struct arc_ps2_port *port = io->port_data; + + iowrite32(ioread32(port->status_addr) & ~PS2_STAT_RX_INT_EN, + port->status_addr); +} + +static void __iomem *arc_ps2_calc_addr(struct arc_ps2_data *arc_ps2, + int index, bool status) +{ + void __iomem *addr; + + addr = arc_ps2->addr + 4 + 4 * index; + if (status) + addr += ARC_PS2_PORTS * 4; + + return addr; +} + +static void arc_ps2_inhibit_ports(struct arc_ps2_data *arc_ps2) +{ + void __iomem *addr; + u32 val; + int i; + + for (i = 0; i < ARC_PS2_PORTS; i++) { + addr = arc_ps2_calc_addr(arc_ps2, i, true); + val = ioread32(addr); + val &= ~(PS2_STAT_RX_INT_EN | PS2_STAT_TX_INT_EN); + iowrite32(val, addr); + } +} + +static int arc_ps2_create_port(struct platform_device *pdev, + struct arc_ps2_data *arc_ps2, + int index) +{ + struct arc_ps2_port *port = &arc_ps2->port[index]; + struct serio *io; + + io = kzalloc(sizeof(struct serio), GFP_KERNEL); + if (!io) + return -ENOMEM; + + io->id.type = SERIO_8042; + io->write = arc_ps2_write; + io->open = arc_ps2_open; + io->close = arc_ps2_close; + snprintf(io->name, sizeof(io->name), "ARC PS/2 port%d", index); + snprintf(io->phys, sizeof(io->phys), "arc/serio%d", index); + io->port_data = port; + + port->io = io; + + port->data_addr = arc_ps2_calc_addr(arc_ps2, index, false); + port->status_addr = arc_ps2_calc_addr(arc_ps2, index, true); + + dev_dbg(&pdev->dev, "port%d is allocated (data = 0x%p, status = 0x%p)\n", + index, port->data_addr, port->status_addr); + + serio_register_port(port->io); + return 0; +} + +static int arc_ps2_probe(struct platform_device *pdev) +{ + struct arc_ps2_data *arc_ps2; + struct resource *res; + int irq; + int error, id, i; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no IO memory defined\n"); + return -EINVAL; + } + + irq = platform_get_irq_byname(pdev, "arc_ps2_irq"); + if (irq < 0) { + dev_err(&pdev->dev, "no IRQ defined\n"); + return -EINVAL; + } + + arc_ps2 = devm_kzalloc(&pdev->dev, sizeof(struct arc_ps2_data), + GFP_KERNEL); + if (!arc_ps2) { + dev_err(&pdev->dev, "out of memory\n"); + return -ENOMEM; + } + + arc_ps2->addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(arc_ps2->addr)) + return PTR_ERR(arc_ps2->addr); + + dev_info(&pdev->dev, "irq = %d, address = 0x%p, ports = %i\n", + irq, arc_ps2->addr, ARC_PS2_PORTS); + + id = ioread32(arc_ps2->addr); + if (id != ARC_ARC_PS2_ID) { + dev_err(&pdev->dev, "device id does not match\n"); + return -ENXIO; + } + + arc_ps2_inhibit_ports(arc_ps2); + + error = devm_request_irq(&pdev->dev, irq, arc_ps2_interrupt, + 0, "arc_ps2", arc_ps2); + if (error) { + dev_err(&pdev->dev, "Could not allocate IRQ\n"); + return error; + } + + for (i = 0; i < ARC_PS2_PORTS; i++) { + error = arc_ps2_create_port(pdev, arc_ps2, i); + if (error) { + while (--i >= 0) + serio_unregister_port(arc_ps2->port[i].io); + return error; + } + } + + platform_set_drvdata(pdev, arc_ps2); + + return 0; +} + +static int arc_ps2_remove(struct platform_device *pdev) +{ + struct arc_ps2_data *arc_ps2 = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < ARC_PS2_PORTS; i++) + serio_unregister_port(arc_ps2->port[i].io); + + dev_dbg(&pdev->dev, "interrupt count = %i\n", arc_ps2->total_int); + dev_dbg(&pdev->dev, "frame error count = %i\n", arc_ps2->frame_error); + dev_dbg(&pdev->dev, "buffer overflow count = %i\n", + arc_ps2->buf_overflow); + + return 0; +} + +static struct platform_driver arc_ps2_driver = { + .driver = { + .name = "arc_ps2", + .owner = THIS_MODULE, + }, + .probe = arc_ps2_probe, + .remove = arc_ps2_remove, +}; + +module_platform_driver(arc_ps2_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Pavel Sokolov <psokolov@synopsys.com>"); +MODULE_DESCRIPTION("ARC PS/2 Driver"); diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 852816567241..cfe549d4eaa5 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -175,7 +175,7 @@ static int __init ct82c710_detect(void) return 0; } -static int __devinit ct82c710_probe(struct platform_device *dev) +static int ct82c710_probe(struct platform_device *dev) { ct82c710_port = kzalloc(sizeof(struct serio), GFP_KERNEL); if (!ct82c710_port) @@ -199,7 +199,7 @@ static int __devinit ct82c710_probe(struct platform_device *dev) return 0; } -static int __devexit ct82c710_remove(struct platform_device *dev) +static int ct82c710_remove(struct platform_device *dev) { serio_unregister_port(ct82c710_port); @@ -212,7 +212,7 @@ static struct platform_driver ct82c710_driver = { .owner = THIS_MODULE, }, .probe = ct82c710_probe, - .remove = __devexit_p(ct82c710_remove), + .remove = ct82c710_remove, }; diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index 4225f5d6b15f..8d9ba0c3827c 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c @@ -327,7 +327,7 @@ static void gscps2_close(struct serio *port) * @return: success/error report */ -static int __devinit gscps2_probe(struct parisc_device *dev) +static int gscps2_probe(struct parisc_device *dev) { struct gscps2port *ps2port; struct serio *serio; @@ -414,7 +414,7 @@ fail_nomem: * @return: success/error report */ -static int __devexit gscps2_remove(struct parisc_device *dev) +static int gscps2_remove(struct parisc_device *dev) { struct gscps2port *ps2port = dev_get_drvdata(&dev->dev); @@ -444,7 +444,7 @@ static struct parisc_driver parisc_ps2_driver = { .name = "gsc_ps2", .id_table = gscps2_device_tbl, .probe = gscps2_probe, - .remove = __devexit_p(gscps2_remove), + .remove = gscps2_remove, }; static int __init gscps2_init(void) diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index bfd3865d886b..65605e4ef3cf 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c @@ -686,13 +686,12 @@ static int hilse_donode(hil_mlc *mlc) write_lock_irqsave(&mlc->lock, flags); pack = node->object.packet; out: - if (mlc->istarted) - goto out2; - /* Prepare to receive input */ - if ((node + 1)->act & HILSE_IN) - hilse_setup_input(mlc, node + 1); + if (!mlc->istarted) { + /* Prepare to receive input */ + if ((node + 1)->act & HILSE_IN) + hilse_setup_input(mlc, node + 1); + } - out2: write_unlock_irqrestore(&mlc->lock, flags); if (down_trylock(&mlc->osem)) { @@ -1010,8 +1009,6 @@ static int __init hil_mlc_init(void) static void __exit hil_mlc_exit(void) { del_timer_sync(&hil_mlcs_kicker); - - tasklet_disable(&hil_mlcs_tasklet); tasklet_kill(&hil_mlcs_tasklet); } diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h index 5d48bb66aa73..a5eed2ade53d 100644 --- a/drivers/input/serio/i8042-io.h +++ b/drivers/input/serio/i8042-io.h @@ -76,7 +76,7 @@ static inline int i8042_platform_init(void) if (check_legacy_ioport(I8042_DATA_REG)) return -ENODEV; #endif -#if !defined(__sh__) && !defined(__alpha__) && !defined(__mips__) +#if !defined(__sh__) && !defined(__alpha__) if (!request_region(I8042_DATA_REG, 16, "i8042")) return -EBUSY; #endif diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index 395a9af3adcd..d6aa4c67dbb6 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h @@ -49,7 +49,7 @@ static inline void i8042_write_command(int val) #define OBP_PS2MS_NAME1 "kdmouse" #define OBP_PS2MS_NAME2 "mouse" -static int __devinit sparc_i8042_probe(struct platform_device *op) +static int sparc_i8042_probe(struct platform_device *op) { struct device_node *dp = op->dev.of_node; @@ -80,7 +80,7 @@ static int __devinit sparc_i8042_probe(struct platform_device *op) return 0; } -static int __devexit sparc_i8042_remove(struct platform_device *op) +static int sparc_i8042_remove(struct platform_device *op) { of_iounmap(kbd_res, kbd_iobase, 8); @@ -102,7 +102,7 @@ static struct platform_driver sparc_i8042_driver = { .of_match_table = sparc_i8042_match, }, .probe = sparc_i8042_probe, - .remove = __devexit_p(sparc_i8042_remove), + .remove = sparc_i8042_remove, }; static int __init i8042_platform_init(void) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index d6cc77a53c7e..5f306f79da0c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -921,6 +921,7 @@ static int __init i8042_platform_init(void) int retval; #ifdef CONFIG_X86 + u8 a20_on = 0xdf; /* Just return if pre-detection shows no i8042 controller exist */ if (!x86_platform.i8042_detect()) return -ENODEV; @@ -960,6 +961,14 @@ static int __init i8042_platform_init(void) if (dmi_check_system(i8042_dmi_dritek_table)) i8042_dritek = true; + + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to + * resume from S3. So we do it here and hope that nothing breaks. + */ + i8042_command(&a20_on, 0x10d1); + i8042_command(NULL, 0x00ff); /* Null command for SMM firmware */ #endif /* CONFIG_X86 */ return retval; diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 86564414b75a..78e4de42efaa 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1284,7 +1284,7 @@ static void __init i8042_register_ports(void) } } -static void __devexit i8042_unregister_ports(void) +static void i8042_unregister_ports(void) { int i; @@ -1437,7 +1437,7 @@ static int __init i8042_probe(struct platform_device *dev) return error; } -static int __devexit i8042_remove(struct platform_device *dev) +static int i8042_remove(struct platform_device *dev) { i8042_unregister_ports(); i8042_free_irqs(); @@ -1455,7 +1455,7 @@ static struct platform_driver i8042_driver = { .pm = &i8042_pm_ops, #endif }, - .remove = __devexit_p(i8042_remove), + .remove = i8042_remove, .shutdown = i8042_shutdown, }; diff --git a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c index 61da763b1209..bc85e1cc66d8 100644 --- a/drivers/input/serio/maceps2.c +++ b/drivers/input/serio/maceps2.c @@ -116,7 +116,7 @@ static void maceps2_close(struct serio *dev) } -static struct serio * __devinit maceps2_allocate_port(int idx) +static struct serio *maceps2_allocate_port(int idx) { struct serio *serio; @@ -135,7 +135,7 @@ static struct serio * __devinit maceps2_allocate_port(int idx) return serio; } -static int __devinit maceps2_probe(struct platform_device *dev) +static int maceps2_probe(struct platform_device *dev) { maceps2_port[0] = maceps2_allocate_port(0); maceps2_port[1] = maceps2_allocate_port(1); @@ -151,7 +151,7 @@ static int __devinit maceps2_probe(struct platform_device *dev) return 0; } -static int __devexit maceps2_remove(struct platform_device *dev) +static int maceps2_remove(struct platform_device *dev) { serio_unregister_port(maceps2_port[0]); serio_unregister_port(maceps2_port[1]); @@ -165,7 +165,7 @@ static struct platform_driver maceps2_driver = { .owner = THIS_MODULE, }, .probe = maceps2_probe, - .remove = __devexit_p(maceps2_remove), + .remove = maceps2_remove, }; static int __init maceps2_init(void) diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 0c42497aaaf4..76f83836fd5a 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c @@ -127,7 +127,7 @@ static void pcips2_close(struct serio *io) free_irq(ps2if->dev->irq, ps2if); } -static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int pcips2_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct pcips2_data *ps2if; struct serio *serio; @@ -176,7 +176,7 @@ static int __devinit pcips2_probe(struct pci_dev *dev, const struct pci_device_i return ret; } -static void __devexit pcips2_remove(struct pci_dev *dev) +static void pcips2_remove(struct pci_dev *dev) { struct pcips2_data *ps2if = pci_get_drvdata(dev); @@ -212,7 +212,7 @@ static struct pci_driver pcips2_driver = { .name = "pcips2", .id_table = pcips2_ids, .probe = pcips2_probe, - .remove = __devexit_p(pcips2_remove), + .remove = pcips2_remove, }; module_pci_driver(pcips2_driver); diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index 0c0df7f73802..70fe542839fb 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c @@ -122,7 +122,7 @@ static void q40kbd_close(struct serio *port) q40kbd_flush(q40kbd); } -static int __devinit q40kbd_probe(struct platform_device *pdev) +static int q40kbd_probe(struct platform_device *pdev) { struct q40kbd *q40kbd; struct serio *port; @@ -168,7 +168,7 @@ err_free_mem: return error; } -static int __devexit q40kbd_remove(struct platform_device *pdev) +static int q40kbd_remove(struct platform_device *pdev) { struct q40kbd *q40kbd = platform_get_drvdata(pdev); @@ -190,7 +190,7 @@ static struct platform_driver q40kbd_driver = { .name = "q40kbd", .owner = THIS_MODULE, }, - .remove = __devexit_p(q40kbd_remove), + .remove = q40kbd_remove, }; static int __init q40kbd_init(void) diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 2af5df6a8fba..567566ae0dae 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -114,7 +114,7 @@ static void rpckbd_close(struct serio *port) * Allocate and initialize serio structure for subsequent registration * with serio core. */ -static int __devinit rpckbd_probe(struct platform_device *dev) +static int rpckbd_probe(struct platform_device *dev) { struct rpckbd_data *rpckbd; struct serio *serio; @@ -153,7 +153,7 @@ static int __devinit rpckbd_probe(struct platform_device *dev) return 0; } -static int __devexit rpckbd_remove(struct platform_device *dev) +static int rpckbd_remove(struct platform_device *dev) { struct serio *serio = platform_get_drvdata(dev); struct rpckbd_data *rpckbd = serio->port_data; @@ -166,7 +166,7 @@ static int __devexit rpckbd_remove(struct platform_device *dev) static struct platform_driver rpckbd_driver = { .probe = rpckbd_probe, - .remove = __devexit_p(rpckbd_remove), + .remove = rpckbd_remove, .driver = { .name = "kart", .owner = THIS_MODULE, diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index 389766707534..b3e688911fd9 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c @@ -193,7 +193,7 @@ static void ps2_close(struct serio *io) /* * Clear the input buffer. */ -static void __devinit ps2_clear_input(struct ps2if *ps2if) +static void ps2_clear_input(struct ps2if *ps2if) { int maxread = 100; @@ -203,7 +203,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) } } -static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, +static unsigned int ps2_test_one(struct ps2if *ps2if, unsigned int mask) { unsigned int val; @@ -220,7 +220,7 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, * Test the keyboard interface. We basically check to make sure that * we can drive each line to the keyboard independently of each other. */ -static int __devinit ps2_test(struct ps2if *ps2if) +static int ps2_test(struct ps2if *ps2if) { unsigned int stat; int ret = 0; @@ -251,7 +251,7 @@ static int __devinit ps2_test(struct ps2if *ps2if) /* * Add one device to this driver. */ -static int __devinit ps2_probe(struct sa1111_dev *dev) +static int ps2_probe(struct sa1111_dev *dev) { struct ps2if *ps2if; struct serio *serio; @@ -334,7 +334,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) /* * Remove one device from this driver. */ -static int __devexit ps2_remove(struct sa1111_dev *dev) +static int ps2_remove(struct sa1111_dev *dev) { struct ps2if *ps2if = sa1111_get_drvdata(dev); @@ -357,7 +357,7 @@ static struct sa1111_driver ps2_driver = { }, .devid = SA1111_DEVID_PS2, .probe = ps2_probe, - .remove = __devexit_p(ps2_remove), + .remove = ps2_remove, }; static int __init ps2_init(void) diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index d0f7533dbf88..25fc5971f426 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -891,8 +891,6 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv) return serio_match_port(serio_drv->id_table, serio); } -#ifdef CONFIG_HOTPLUG - #define SERIO_ADD_UEVENT_VAR(fmt, val...) \ do { \ int err = add_uevent_var(env, fmt, val); \ @@ -920,15 +918,6 @@ static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) } #undef SERIO_ADD_UEVENT_VAR -#else - -static int serio_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - return -ENODEV; -} - -#endif /* CONFIG_HOTPLUG */ - #ifdef CONFIG_PM static int serio_suspend(struct device *dev) { diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index 1e983bec7d86..17be85948ffd 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c @@ -233,7 +233,7 @@ static void sxps2_close(struct serio *pserio) * It returns 0, if the driver is bound to the PS/2 device, or a negative * value if there is an error. */ -static int __devinit xps2_of_probe(struct platform_device *ofdev) +static int xps2_of_probe(struct platform_device *ofdev) { struct resource r_irq; /* Interrupt resources */ struct resource r_mem; /* IO mem resources */ @@ -333,7 +333,7 @@ failed1: * if the driver module is being unloaded. It frees any resources allocated to * the device. */ -static int __devexit xps2_of_remove(struct platform_device *of_dev) +static int xps2_of_remove(struct platform_device *of_dev) { struct xps2data *drvdata = platform_get_drvdata(of_dev); struct resource r_mem; /* IO mem resources */ @@ -355,7 +355,7 @@ static int __devexit xps2_of_remove(struct platform_device *of_dev) } /* Match table for of_platform binding */ -static const struct of_device_id xps2_of_match[] __devinitconst = { +static const struct of_device_id xps2_of_match[] = { { .compatible = "xlnx,xps-ps2-1.00.a", }, { /* end of list */ }, }; @@ -368,7 +368,7 @@ static struct platform_driver xps2_of_driver = { .of_match_table = xps2_of_match, }, .probe = xps2_of_probe, - .remove = __devexit_p(xps2_of_remove), + .remove = xps2_of_remove, }; module_platform_driver(xps2_of_driver); diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 858ad446de91..aaf23aeae2ea 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -386,23 +386,40 @@ static int wacom_parse_hid(struct usb_interface *intf, if (usage == WCM_DESKTOP) { if (finger) { features->device_type = BTN_TOOL_FINGER; - if (features->type == TABLETPC2FG) { - /* need to reset back */ + + switch (features->type) { + case TABLETPC2FG: features->pktlen = WACOM_PKGLEN_TPC2FG; - } + break; - if (features->type == MTSCREEN || features->type == WACOM_24HDT) + case MTSCREEN: + case WACOM_24HDT: features->pktlen = WACOM_PKGLEN_MTOUCH; + break; - if (features->type == BAMBOO_PT) { - /* need to reset back */ + case MTTPC: + features->pktlen = WACOM_PKGLEN_MTTPC; + break; + + case BAMBOO_PT: features->pktlen = WACOM_PKGLEN_BBTOUCH; + break; + + default: + features->pktlen = WACOM_PKGLEN_GRAPHIRE; + break; + } + + switch (features->type) { + case BAMBOO_PT: features->x_phy = get_unaligned_le16(&report[i + 5]); features->x_max = get_unaligned_le16(&report[i + 8]); i += 15; - } else if (features->type == WACOM_24HDT) { + break; + + case WACOM_24HDT: features->x_max = get_unaligned_le16(&report[i + 3]); features->x_phy = @@ -410,7 +427,9 @@ static int wacom_parse_hid(struct usb_interface *intf, features->unit = report[i - 1]; features->unitExpo = report[i - 3]; i += 12; - } else { + break; + + default: features->x_max = get_unaligned_le16(&report[i + 3]); features->x_phy = @@ -418,10 +437,11 @@ static int wacom_parse_hid(struct usb_interface *intf, features->unit = report[i + 9]; features->unitExpo = report[i + 11]; i += 12; + break; } } else if (pen) { /* penabled only accepts exact bytes of data */ - if (features->type == TABLETPC2FG) + if (features->type >= TABLETPC) features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = @@ -434,32 +454,40 @@ static int wacom_parse_hid(struct usb_interface *intf, case HID_USAGE_Y: if (usage == WCM_DESKTOP) { if (finger) { - int type = features->type; - - if (type == TABLETPC2FG || type == MTSCREEN) { + switch (features->type) { + case TABLETPC2FG: + case MTSCREEN: + case MTTPC: features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i + 6]); i += 7; - } else if (type == WACOM_24HDT) { + break; + + case WACOM_24HDT: features->y_max = get_unaligned_le16(&report[i + 3]); features->y_phy = get_unaligned_le16(&report[i - 2]); i += 7; - } else if (type == BAMBOO_PT) { + break; + + case BAMBOO_PT: features->y_phy = get_unaligned_le16(&report[i + 3]); features->y_max = get_unaligned_le16(&report[i + 6]); i += 12; - } else { + break; + + default: features->y_max = features->x_max; features->y_phy = get_unaligned_le16(&report[i + 3]); i += 4; + break; } } else if (pen) { features->y_max = @@ -525,10 +553,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int if (!rep_data) return error; - rep_data[0] = report_id; - rep_data[1] = mode; - do { + rep_data[0] = report_id; + rep_data[1] = mode; + error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, report_id, rep_data, length, 1); if (error >= 0) diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 0a67031ffc13..41b6fbf60112 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -359,6 +359,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) case 0x802: /* Intuos4 General Pen */ case 0x804: /* Intuos4 Marker Pen */ case 0x40802: /* Intuos4 Classic Pen */ + case 0x18803: /* DTH2242 Grip Pen */ case 0x022: wacom->tool[idx] = BTN_TOOL_PEN; break; @@ -467,9 +468,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || - (features->type >= INTUOS5S && features->type <= INTUOS5L) || - (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) { + if (features->type >= INTUOS4S && features->type <= WACOM_24HD) { t = (t << 1) | (data[1] & 1); } input_report_abs(input, ABS_PRESSURE, t); @@ -540,6 +539,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_key(input, wacom->tool[1], 0); input_report_abs(input, ABS_MISC, 0); } + } else if (features->type == DTK) { + input_report_key(input, BTN_0, (data[6] & 0x01)); + input_report_key(input, BTN_1, (data[6] & 0x02)); + input_report_key(input, BTN_2, (data[6] & 0x04)); + input_report_key(input, BTN_3, (data[6] & 0x08)); + input_report_key(input, BTN_4, (data[6] & 0x10)); + input_report_key(input, BTN_5, (data[6] & 0x20)); } else if (features->type == WACOM_24HD) { input_report_key(input, BTN_0, (data[6] & 0x01)); input_report_key(input, BTN_1, (data[6] & 0x02)); @@ -787,25 +793,6 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) return 1; } -static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid) -{ - int touch_max = wacom->features.touch_max; - int i; - - if (!wacom->slots) - return -1; - - for (i = 0; i < touch_max; ++i) { - if (wacom->slots[i] == contactid) - return i; - } - for (i = 0; i < touch_max; ++i) { - if (wacom->slots[i] == -1) - return i; - } - return -1; -} - static int int_dist(int x1, int y1, int x2, int y2) { int x = x2 - x1; @@ -835,8 +822,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) for (i = 0; i < contacts_to_send; i++) { int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1; bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity; - int id = data[offset + 1]; - int slot = find_slot_from_contactid(wacom, id); + int slot = input_mt_get_slot_by_key(input, data[offset + 1]); if (slot < 0) continue; @@ -858,9 +844,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); input_report_abs(input, ABS_MT_ORIENTATION, w > h); } - wacom->slots[slot] = touch ? id : -1; } - input_mt_report_pointer_emulation(input, true); wacom->num_contacts_left -= contacts_to_send; @@ -877,6 +861,11 @@ static int wacom_mt_touch(struct wacom_wac *wacom) int i; int current_num_contacts = data[2]; int contacts_to_send = 0; + int x_offset = 0; + + /* MTTPC does not support Height and Width */ + if (wacom->features.type == MTTPC) + x_offset = -4; /* * First packet resets the counter since only the first @@ -889,10 +878,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom) contacts_to_send = min(5, wacom->num_contacts_left); for (i = 0; i < contacts_to_send; i++) { - int offset = (WACOM_BYTES_PER_MT_PACKET * i) + 3; + int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3; bool touch = data[offset] & 0x1; int id = le16_to_cpup((__le16 *)&data[offset + 1]); - int slot = find_slot_from_contactid(wacom, id); + int slot = input_mt_get_slot_by_key(input, id); if (slot < 0) continue; @@ -900,14 +889,12 @@ static int wacom_mt_touch(struct wacom_wac *wacom) input_mt_slot(input, slot); input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); if (touch) { - int x = le16_to_cpup((__le16 *)&data[offset + 7]); - int y = le16_to_cpup((__le16 *)&data[offset + 9]); + int x = le16_to_cpup((__le16 *)&data[offset + x_offset + 7]); + int y = le16_to_cpup((__le16 *)&data[offset + x_offset + 9]); input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_Y, y); } - wacom->slots[slot] = touch ? id : -1; } - input_mt_report_pointer_emulation(input, true); wacom->num_contacts_left -= contacts_to_send; @@ -939,12 +926,11 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom) contact_with_no_pen_down_count++; } } + input_mt_report_pointer_emulation(input, true); /* keep touch state for pen event */ wacom->shared->touch_down = (contact_with_no_pen_down_count > 0); - input_mt_report_pointer_emulation(input, true); - return 1; } @@ -1101,12 +1087,15 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) { struct input_dev *input = wacom->input; - int slot_id = data[0] - 2; /* data[0] is between 2 and 17 */ bool touch = data[1] & 0x80; + int slot = input_mt_get_slot_by_key(input, data[0]); + + if (slot < 0) + return; touch = touch && !wacom->shared->stylus_in_proximity; - input_mt_slot(input, slot_id); + input_mt_slot(input, slot); input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); if (touch) { @@ -1159,7 +1148,6 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) wacom_bpt3_button_msg(wacom, data + offset); } - input_mt_report_pointer_emulation(input, true); input_sync(input); @@ -1316,6 +1304,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case WACOM_21UX2: case WACOM_22HD: case WACOM_24HD: + case DTK: sync = wacom_intuos_irq(wacom_wac); break; @@ -1336,6 +1325,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) case TABLETPCE: case TABLETPC2FG: case MTSCREEN: + case MTTPC: sync = wacom_tpc_irq(wacom_wac, len); break; @@ -1440,39 +1430,64 @@ static unsigned int wacom_calculate_touch_res(unsigned int logical_max, return (logical_max * 100) / physical_max; } -int wacom_setup_input_capabilities(struct input_dev *input_dev, - struct wacom_wac *wacom_wac) +static void wacom_abs_set_axis(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; - int i; - - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - - __set_bit(BTN_TOUCH, input_dev->keybit); - - input_set_abs_params(input_dev, ABS_X, 0, features->x_max, - features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, - features->y_fuzz, 0); if (features->device_type == BTN_TOOL_PEN) { - input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, - features->pressure_fuzz, 0); + input_set_abs_params(input_dev, ABS_X, 0, features->x_max, + features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, + features->y_fuzz, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, + features->pressure_max, features->pressure_fuzz, 0); /* penabled devices have fixed resolution for each model */ input_abs_set_res(input_dev, ABS_X, features->x_resolution); input_abs_set_res(input_dev, ABS_Y, features->y_resolution); } else { - input_abs_set_res(input_dev, ABS_X, - wacom_calculate_touch_res(features->x_max, - features->x_phy)); - input_abs_set_res(input_dev, ABS_Y, - wacom_calculate_touch_res(features->y_max, - features->y_phy)); + if (features->touch_max <= 2) { + input_set_abs_params(input_dev, ABS_X, 0, + features->x_max, features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + features->y_max, features->y_fuzz, 0); + input_abs_set_res(input_dev, ABS_X, + wacom_calculate_touch_res(features->x_max, + features->x_phy)); + input_abs_set_res(input_dev, ABS_Y, + wacom_calculate_touch_res(features->y_max, + features->y_phy)); + } + + if (features->touch_max > 1) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + features->x_max, features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + features->y_max, features->y_fuzz, 0); + input_abs_set_res(input_dev, ABS_MT_POSITION_X, + wacom_calculate_touch_res(features->x_max, + features->x_phy)); + input_abs_set_res(input_dev, ABS_MT_POSITION_Y, + wacom_calculate_touch_res(features->y_max, + features->y_phy)); + } } +} + +int wacom_setup_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) +{ + struct wacom_features *features = &wacom_wac->features; + int i; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(ABS_MISC, input_dev->absbit); + wacom_abs_set_axis(input_dev, wacom_wac); + switch (wacom_wac->features.type) { case WACOM_MO: input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); @@ -1509,12 +1524,17 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_Y, input_dev->keybit); __set_bit(BTN_Z, input_dev->keybit); - for (i = 0; i < 10; i++) + for (i = 6; i < 10; i++) __set_bit(BTN_0 + i, input_dev->keybit); __set_bit(KEY_PROG1, input_dev->keybit); __set_bit(KEY_PROG2, input_dev->keybit); __set_bit(KEY_PROG3, input_dev->keybit); + /* fall through */ + + case DTK: + for (i = 0; i < 6; i++) + __set_bit(BTN_0 + i, input_dev->keybit); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); @@ -1610,24 +1630,11 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, } else if (features->device_type == BTN_TOOL_FINGER) { __clear_bit(ABS_MISC, input_dev->absbit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); - __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); - - input_mt_init_slots(input_dev, features->touch_max, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); - - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, features->x_max, - features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, features->y_max, - features->y_fuzz, 0); + input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); } break; @@ -1657,27 +1664,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case MTSCREEN: - if (features->device_type == BTN_TOOL_FINGER) { - wacom_wac->slots = kmalloc(features->touch_max * - sizeof(int), - GFP_KERNEL); - if (!wacom_wac->slots) - return -ENOMEM; - - for (i = 0; i < features->touch_max; i++) - wacom_wac->slots[i] = -1; - } - /* fall through */ - + case MTTPC: case TABLETPC2FG: if (features->device_type == BTN_TOOL_FINGER) { - input_mt_init_slots(input_dev, features->touch_max, 0); - input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE, - 0, MT_TOOL_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, features->y_max, 0, 0); + unsigned int flags = INPUT_MT_DIRECT; + + if (wacom_wac->features.type == TABLETPC2FG) + flags = 0; + + input_mt_init_slots(input_dev, features->touch_max, flags); } /* fall through */ @@ -1720,35 +1715,26 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_POINTER, input_dev->propbit); if (features->device_type == BTN_TOOL_FINGER) { + unsigned int flags = INPUT_MT_POINTER; + __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); __set_bit(BTN_BACK, input_dev->keybit); __set_bit(BTN_RIGHT, input_dev->keybit); - __set_bit(BTN_TOOL_FINGER, input_dev->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); - input_mt_init_slots(input_dev, features->touch_max, 0); - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - __set_bit(BTN_TOOL_TRIPLETAP, - input_dev->keybit); - __set_bit(BTN_TOOL_QUADTAP, - input_dev->keybit); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); + } else { + __set_bit(BTN_TOOL_FINGER, input_dev->keybit); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); + flags = 0; } - - input_set_abs_params(input_dev, ABS_MT_POSITION_X, - 0, features->x_max, - features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, - 0, features->y_max, - features->y_fuzz, 0); + input_mt_init_slots(input_dev, features->touch_max, flags); } else if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -1973,6 +1959,13 @@ static const struct wacom_features wacom_features_0xCE = static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x59 = /* Pen */ + { "Wacom DTH2242", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047, + 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; +static const struct wacom_features wacom_features_0x5D = /* Touch */ + { "Wacom DTH2242", .type = WACOM_24HDT, + .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10 }; static const struct wacom_features wacom_features_0xCC = { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; @@ -2018,6 +2011,15 @@ static const struct wacom_features wacom_features_0xED = static const struct wacom_features wacom_features_0xEF = { "Wacom ISDv4 EF", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x100 = + { "Wacom ISDv4 100", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, + 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x101 = + { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, + 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0x4001 = + { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, + 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x47 = { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2034,7 +2036,8 @@ static const struct wacom_features wacom_features_0xD1 = .touch_max = 2 }; static const struct wacom_features wacom_features_0xD2 = { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, - 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .touch_max = 2 }; static const struct wacom_features wacom_features_0xD3 = { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13700, 1023, 31, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, @@ -2137,6 +2140,8 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x43) }, { USB_DEVICE_WACOM(0x44) }, { USB_DEVICE_WACOM(0x45) }, + { USB_DEVICE_WACOM(0x59) }, + { USB_DEVICE_WACOM(0x5D) }, { USB_DEVICE_WACOM(0xB0) }, { USB_DEVICE_WACOM(0xB1) }, { USB_DEVICE_WACOM(0xB2) }, @@ -2194,6 +2199,9 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xEC) }, { USB_DEVICE_WACOM(0xED) }, { USB_DEVICE_WACOM(0xEF) }, + { USB_DEVICE_WACOM(0x100) }, + { USB_DEVICE_WACOM(0x101) }, + { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_WACOM(0xF4) }, { USB_DEVICE_WACOM(0xF8) }, diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 345f1e76975e..5f9a7721e16c 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -26,6 +26,7 @@ #define WACOM_PKGLEN_BBPEN 10 #define WACOM_PKGLEN_WIRELESS 32 #define WACOM_PKGLEN_MTOUCH 62 +#define WACOM_PKGLEN_MTTPC 40 /* wacom data size per MT contact */ #define WACOM_BYTES_PER_MT_PACKET 11 @@ -77,6 +78,7 @@ enum { INTUOS5L, WACOM_21UX2, WACOM_22HD, + DTK, WACOM_24HD, CINTIQ, WACOM_BEE, @@ -88,6 +90,7 @@ enum { TABLETPCE, TABLETPC2FG, MTSCREEN, + MTTPC, MAX_TYPE }; @@ -133,7 +136,6 @@ struct wacom_wac { int pid; int battery_capacity; int num_contacts_left; - int *slots; }; #endif diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c index 326218dbd6e6..c7068942ebe8 100644 --- a/drivers/input/touchscreen/88pm860x-ts.c +++ b/drivers/input/touchscreen/88pm860x-ts.c @@ -115,7 +115,7 @@ static void pm860x_touch_close(struct input_dev *dev) } #ifdef CONFIG_OF -static int __devinit pm860x_touch_dt_init(struct platform_device *pdev, +static int pm860x_touch_dt_init(struct platform_device *pdev, struct pm860x_chip *chip, int *res_x) { @@ -169,7 +169,7 @@ static int __devinit pm860x_touch_dt_init(struct platform_device *pdev, #define pm860x_touch_dt_init(x, y, z) (-1) #endif -static int __devinit pm860x_touch_probe(struct platform_device *pdev) +static int pm860x_touch_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); struct pm860x_touch_pdata *pdata = pdev->dev.platform_data; @@ -293,7 +293,7 @@ out: return ret; } -static int __devexit pm860x_touch_remove(struct platform_device *pdev) +static int pm860x_touch_remove(struct platform_device *pdev) { struct pm860x_touch *touch = platform_get_drvdata(pdev); @@ -310,7 +310,7 @@ static struct platform_driver pm860x_touch_driver = { .owner = THIS_MODULE, }, .probe = pm860x_touch_probe, - .remove = __devexit_p(pm860x_touch_remove), + .remove = pm860x_touch_remove, }; module_platform_driver(pm860x_touch_driver); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index f7668b24c378..f9a5fd89bc02 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -111,18 +111,6 @@ config TOUCHSCREEN_AUO_PIXCIR To compile this driver as a module, choose M here: the module will be called auo-pixcir-ts. -config TOUCHSCREEN_BITSY - tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" - depends on SA1100_BITSY - select SERIO - help - Say Y here if you have the h3600 (Bitsy) touchscreen. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called h3600_ts_input. - config TOUCHSCREEN_BU21013 tristate "BU21013 based touch panel controllers" depends on I2C @@ -371,7 +359,7 @@ config TOUCHSCREEN_MCS5000 config TOUCHSCREEN_MMS114 tristate "MELFAS MMS114 touchscreen" - depends on I2C + depends on I2C && GENERIC_HARDIRQS help Say Y here if you have the MELFAS MMS114 touchscreen controller chip in your system. @@ -529,9 +517,9 @@ config TOUCHSCREEN_TOUCHWIN To compile this driver as a module, choose M here: the module will be called touchwin. -config TOUCHSCREEN_TI_TSCADC +config TOUCHSCREEN_TI_AM335X_TSC tristate "TI Touchscreen Interface" - depends on ARCH_OMAP2PLUS + depends on MFD_TI_AM335X_TSCADC help Say Y here if you have 4/5/8 wire touchscreen controller to be connected to the ADC controller on your TI AM335x SoC. @@ -539,7 +527,7 @@ config TOUCHSCREEN_TI_TSCADC If unsure, say N. To compile this driver as a module, choose M here: the - module will be called ti_tscadc. + module will be called ti_am335x_tsc. config TOUCHSCREEN_ATMEL_TSADCC tristate "Atmel Touchscreen Interface" diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 178eb128d90f..6bfbeab67c9f 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o -obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o @@ -52,7 +51,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o -obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o +obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index 2c7692108e6c..23fa829b869d 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -682,7 +682,7 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) } } -static int __devinit ad7877_probe(struct spi_device *spi) +static int ad7877_probe(struct spi_device *spi) { struct ad7877 *ts; struct input_dev *input_dev; @@ -810,7 +810,7 @@ err_free_mem: return err; } -static int __devexit ad7877_remove(struct spi_device *spi) +static int ad7877_remove(struct spi_device *spi) { struct ad7877 *ts = dev_get_drvdata(&spi->dev); @@ -857,7 +857,7 @@ static struct spi_driver ad7877_driver = { .pm = &ad7877_pm, }, .probe = ad7877_probe, - .remove = __devexit_p(ad7877_remove), + .remove = ad7877_remove, }; module_spi_driver(ad7877_driver); diff --git a/drivers/input/touchscreen/ad7879-i2c.c b/drivers/input/touchscreen/ad7879-i2c.c index 3054354d0dd3..dcf390771549 100644 --- a/drivers/input/touchscreen/ad7879-i2c.c +++ b/drivers/input/touchscreen/ad7879-i2c.c @@ -54,7 +54,7 @@ static const struct ad7879_bus_ops ad7879_i2c_bus_ops = { .write = ad7879_i2c_write, }; -static int __devinit ad7879_i2c_probe(struct i2c_client *client, +static int ad7879_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct ad7879 *ts; @@ -75,7 +75,7 @@ static int __devinit ad7879_i2c_probe(struct i2c_client *client, return 0; } -static int __devexit ad7879_i2c_remove(struct i2c_client *client) +static int ad7879_i2c_remove(struct i2c_client *client) { struct ad7879 *ts = i2c_get_clientdata(client); @@ -98,7 +98,7 @@ static struct i2c_driver ad7879_i2c_driver = { .pm = &ad7879_pm_ops, }, .probe = ad7879_i2c_probe, - .remove = __devexit_p(ad7879_i2c_remove), + .remove = ad7879_i2c_remove, .id_table = ad7879_id, }; diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c index db49abf056ba..606da5bd6115 100644 --- a/drivers/input/touchscreen/ad7879-spi.c +++ b/drivers/input/touchscreen/ad7879-spi.c @@ -110,7 +110,7 @@ static const struct ad7879_bus_ops ad7879_spi_bus_ops = { .write = ad7879_spi_write, }; -static int __devinit ad7879_spi_probe(struct spi_device *spi) +static int ad7879_spi_probe(struct spi_device *spi) { struct ad7879 *ts; int err; @@ -137,7 +137,7 @@ static int __devinit ad7879_spi_probe(struct spi_device *spi) return 0; } -static int __devexit ad7879_spi_remove(struct spi_device *spi) +static int ad7879_spi_remove(struct spi_device *spi) { struct ad7879 *ts = spi_get_drvdata(spi); @@ -154,7 +154,7 @@ static struct spi_driver ad7879_spi_driver = { .pm = &ad7879_pm_ops, }, .probe = ad7879_spi_probe, - .remove = __devexit_p(ad7879_spi_remove), + .remove = ad7879_spi_remove, }; module_spi_driver(ad7879_spi_driver); diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 78e5d9ab0ba7..4f702b3ec1a3 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -955,7 +955,7 @@ static int ads7846_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); -static int __devinit ads7846_setup_pendown(struct spi_device *spi, +static int ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) { struct ads7846_platform_data *pdata = spi->dev.platform_data; @@ -997,7 +997,7 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, * Set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ -static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts, +static void ads7846_setup_spi_msg(struct ads7846 *ts, const struct ads7846_platform_data *pdata) { struct spi_message *m = &ts->msg[0]; @@ -1196,7 +1196,7 @@ static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts, spi_message_add_tail(x, m); } -static int __devinit ads7846_probe(struct spi_device *spi) +static int ads7846_probe(struct spi_device *spi) { struct ads7846 *ts; struct ads7846_packet *packet; @@ -1390,7 +1390,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) return err; } -static int __devexit ads7846_remove(struct spi_device *spi) +static int ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); @@ -1434,7 +1434,7 @@ static struct spi_driver ads7846_driver = { .pm = &ads7846_pm, }, .probe = ads7846_probe, - .remove = __devexit_p(ads7846_remove), + .remove = ads7846_remove, }; module_spi_driver(ads7846_driver); diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 1df2396af008..d04f810cb1dd 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1095,7 +1095,7 @@ static void mxt_input_close(struct input_dev *dev) mxt_stop(data); } -static int __devinit mxt_probe(struct i2c_client *client, +static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct mxt_platform_data *pdata = client->dev.platform_data; @@ -1200,7 +1200,7 @@ err_free_mem: return error; } -static int __devexit mxt_remove(struct i2c_client *client) +static int mxt_remove(struct i2c_client *client) { struct mxt_data *data = i2c_get_clientdata(client); @@ -1270,7 +1270,7 @@ static struct i2c_driver mxt_driver = { .pm = &mxt_pm_ops, }, .probe = mxt_probe, - .remove = __devexit_p(mxt_remove), + .remove = mxt_remove, .id_table = mxt_id, }; diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index ea392ee138ed..95f6785a94b0 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c @@ -177,7 +177,7 @@ static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) * The functions for inserting/removing us as a module. */ -static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) +static int atmel_tsadcc_probe(struct platform_device *pdev) { struct atmel_tsadcc *ts_dev; struct input_dev *input_dev; @@ -323,7 +323,7 @@ err_free_mem: return err; } -static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) +static int atmel_tsadcc_remove(struct platform_device *pdev) { struct atmel_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev); struct resource *res; @@ -346,7 +346,7 @@ static int __devexit atmel_tsadcc_remove(struct platform_device *pdev) static struct platform_driver atmel_tsadcc_driver = { .probe = atmel_tsadcc_probe, - .remove = __devexit_p(atmel_tsadcc_remove), + .remove = atmel_tsadcc_remove, .driver = { .name = "atmel_tsadcc", }, diff --git a/drivers/input/touchscreen/auo-pixcir-ts.c b/drivers/input/touchscreen/auo-pixcir-ts.c index c7047b6bb020..c6e19a96348e 100644 --- a/drivers/input/touchscreen/auo-pixcir-ts.c +++ b/drivers/input/touchscreen/auo-pixcir-ts.c @@ -286,7 +286,7 @@ static int auo_pixcir_power_mode(struct auo_pixcir_ts *ts, int mode) return 0; } -static __devinit int auo_pixcir_int_config(struct auo_pixcir_ts *ts, +static int auo_pixcir_int_config(struct auo_pixcir_ts *ts, int int_setting) { struct i2c_client *client = ts->client; @@ -482,7 +482,7 @@ unlock: static SIMPLE_DEV_PM_OPS(auo_pixcir_pm_ops, auo_pixcir_suspend, auo_pixcir_resume); -static int __devinit auo_pixcir_probe(struct i2c_client *client, +static int auo_pixcir_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; @@ -599,7 +599,7 @@ err_gpio_int: return ret; } -static int __devexit auo_pixcir_remove(struct i2c_client *client) +static int auo_pixcir_remove(struct i2c_client *client) { struct auo_pixcir_ts *ts = i2c_get_clientdata(client); const struct auo_pixcir_ts_platdata *pdata = client->dev.platform_data; @@ -631,7 +631,7 @@ static struct i2c_driver auo_pixcir_driver = { .pm = &auo_pixcir_pm_ops, }, .probe = auo_pixcir_probe, - .remove = __devexit_p(auo_pixcir_remove), + .remove = auo_pixcir_remove, .id_table = auo_pixcir_idtable, }; diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 5c487d23f11c..b9b5ddad6658 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -14,6 +14,9 @@ #include <linux/slab.h> #include <linux/regulator/consumer.h> #include <linux/module.h> +#include <linux/gpio.h> +#include <linux/of.h> +#include <linux/of_gpio.h> #define PEN_DOWN_INTR 0 #define MAX_FINGERS 2 @@ -148,11 +151,12 @@ struct bu21013_ts_data { struct i2c_client *client; wait_queue_head_t wait; - bool touch_stopped; const struct bu21013_platform_device *chip; struct input_dev *in_dev; - unsigned int intr_pin; struct regulator *regulator; + unsigned int irq; + unsigned int intr_pin; + bool touch_stopped; }; /** @@ -262,7 +266,7 @@ static irqreturn_t bu21013_gpio_irq(int irq, void *device_data) return IRQ_NONE; } - data->intr_pin = data->chip->irq_read_val(); + data->intr_pin = gpio_get_value(data->chip->touch_pin); if (data->intr_pin == PEN_DOWN_INTR) wait_event_timeout(data->wait, data->touch_stopped, msecs_to_jiffies(2)); @@ -418,8 +422,70 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) { bu21013_data->touch_stopped = true; wake_up(&bu21013_data->wait); - free_irq(bu21013_data->chip->irq, bu21013_data); + free_irq(bu21013_data->irq, bu21013_data); +} + +/** + * bu21013_cs_disable() - deconfigures the touch panel controller + * @bu21013_data: device structure pointer + * + * This function is used to deconfigure the chip selection + * for touch panel controller. + */ +static void bu21013_cs_disable(struct bu21013_ts_data *bu21013_data) +{ + int error; + + error = gpio_direction_output(bu21013_data->chip->cs_pin, 0); + if (error < 0) + dev_warn(&bu21013_data->client->dev, + "%s: gpio direction failed, error: %d\n", + __func__, error); + else + gpio_set_value(bu21013_data->chip->cs_pin, 0); + + gpio_free(bu21013_data->chip->cs_pin); +} + +#ifdef CONFIG_OF +static const struct bu21013_platform_device * +bu21013_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct bu21013_platform_device *pdata; + + if (!np) { + dev_err(dev, "no device tree or platform data\n"); + return ERR_PTR(-EINVAL); + } + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + pdata->y_flip = pdata->x_flip = false; + + pdata->x_flip = of_property_read_bool(np, "rohm,flip-x"); + pdata->y_flip = of_property_read_bool(np, "rohm,flip-y"); + + of_property_read_u32(np, "rohm,touch-max-x", &pdata->touch_x_max); + of_property_read_u32(np, "rohm,touch-max-y", &pdata->touch_y_max); + + pdata->touch_pin = of_get_named_gpio(np, "touch-gpio", 0); + pdata->cs_pin = of_get_named_gpio(np, "reset-gpio", 0); + + pdata->ext_clk = false; + + return pdata; } +#else +static inline const struct bu21013_platform_device * +bu21013_parse_dt(struct device *dev) +{ + dev_err(dev, "no platform data available\n"); + return ERR_PTR(-EINVAL); +} +#endif /** * bu21013_probe() - initializes the i2c-client touchscreen driver @@ -429,13 +495,13 @@ static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data) * This function used to initializes the i2c-client touchscreen * driver and returns integer. */ -static int __devinit bu21013_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int bu21013_probe(struct i2c_client *client, + const struct i2c_device_id *id) { + const struct bu21013_platform_device *pdata = + dev_get_platdata(&client->dev); struct bu21013_ts_data *bu21013_data; struct input_dev *in_dev; - const struct bu21013_platform_device *pdata = - client->dev.platform_data; int error; if (!i2c_check_functionality(client->adapter, @@ -445,7 +511,13 @@ static int __devinit bu21013_probe(struct i2c_client *client, } if (!pdata) { - dev_err(&client->dev, "platform data not defined\n"); + pdata = bu21013_parse_dt(&client->dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + } + + if (!gpio_is_valid(pdata->touch_pin)) { + dev_err(&client->dev, "invalid touch_pin supplied\n"); return -EINVAL; } @@ -460,8 +532,9 @@ static int __devinit bu21013_probe(struct i2c_client *client, bu21013_data->in_dev = in_dev; bu21013_data->chip = pdata; bu21013_data->client = client; + bu21013_data->irq = gpio_to_irq(pdata->touch_pin); - bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH"); + bu21013_data->regulator = regulator_get(&client->dev, "avdd"); if (IS_ERR(bu21013_data->regulator)) { dev_err(&client->dev, "regulator_get failed\n"); error = PTR_ERR(bu21013_data->regulator); @@ -478,12 +551,11 @@ static int __devinit bu21013_probe(struct i2c_client *client, init_waitqueue_head(&bu21013_data->wait); /* configure the gpio pins */ - if (pdata->cs_en) { - error = pdata->cs_en(pdata->cs_pin); - if (error < 0) { - dev_err(&client->dev, "chip init failed\n"); - goto err_disable_regulator; - } + error = gpio_request_one(pdata->cs_pin, GPIOF_OUT_INIT_HIGH, + "touchp_reset"); + if (error < 0) { + dev_err(&client->dev, "Unable to request gpio reset_pin\n"); + goto err_disable_regulator; } /* configure the touch panel controller */ @@ -508,12 +580,13 @@ static int __devinit bu21013_probe(struct i2c_client *client, pdata->touch_y_max, 0, 0); input_set_drvdata(in_dev, bu21013_data); - error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, + error = request_threaded_irq(bu21013_data->irq, NULL, bu21013_gpio_irq, IRQF_TRIGGER_FALLING | IRQF_SHARED | IRQF_ONESHOT, DRIVER_TP, bu21013_data); if (error) { - dev_err(&client->dev, "request irq %d failed\n", pdata->irq); + dev_err(&client->dev, "request irq %d failed\n", + bu21013_data->irq); goto err_cs_disable; } @@ -531,7 +604,7 @@ static int __devinit bu21013_probe(struct i2c_client *client, err_free_irq: bu21013_free_irq(bu21013_data); err_cs_disable: - pdata->cs_dis(pdata->cs_pin); + bu21013_cs_disable(bu21013_data); err_disable_regulator: regulator_disable(bu21013_data->regulator); err_put_regulator: @@ -549,13 +622,13 @@ err_free_mem: * This function uses to remove the i2c-client * touchscreen driver and returns integer. */ -static int __devexit bu21013_remove(struct i2c_client *client) +static int bu21013_remove(struct i2c_client *client) { struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client); bu21013_free_irq(bu21013_data); - bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); + bu21013_cs_disable(bu21013_data); input_unregister_device(bu21013_data->in_dev); @@ -584,9 +657,9 @@ static int bu21013_suspend(struct device *dev) bu21013_data->touch_stopped = true; if (device_may_wakeup(&client->dev)) - enable_irq_wake(bu21013_data->chip->irq); + enable_irq_wake(bu21013_data->irq); else - disable_irq(bu21013_data->chip->irq); + disable_irq(bu21013_data->irq); regulator_disable(bu21013_data->regulator); @@ -621,9 +694,9 @@ static int bu21013_resume(struct device *dev) bu21013_data->touch_stopped = false; if (device_may_wakeup(&client->dev)) - disable_irq_wake(bu21013_data->chip->irq); + disable_irq_wake(bu21013_data->irq); else - enable_irq(bu21013_data->chip->irq); + enable_irq(bu21013_data->irq); return 0; } @@ -649,7 +722,7 @@ static struct i2c_driver bu21013_driver = { #endif }, .probe = bu21013_probe, - .remove = __devexit_p(bu21013_remove), + .remove = bu21013_remove, .id_table = bu21013_id, }; diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c index 464f1bf4b61d..96e0eedcc7e5 100644 --- a/drivers/input/touchscreen/cy8ctmg110_ts.c +++ b/drivers/input/touchscreen/cy8ctmg110_ts.c @@ -99,9 +99,18 @@ static int cy8ctmg110_read_regs(struct cy8ctmg110 *tsc, int ret; struct i2c_msg msg[2] = { /* first write slave position to i2c devices */ - { client->addr, 0, 1, &cmd }, + { + .addr = client->addr, + .len = 1, + .buf = &cmd + }, /* Second read data from position */ - { client->addr, I2C_M_RD, len, data } + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = len, + .buf = data + } }; ret = i2c_transfer(client->adapter, msg, 2); @@ -166,7 +175,7 @@ static irqreturn_t cy8ctmg110_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit cy8ctmg110_probe(struct i2c_client *client, +static int cy8ctmg110_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct cy8ctmg110_pdata *pdata = client->dev.platform_data; @@ -314,7 +323,7 @@ static int cy8ctmg110_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(cy8ctmg110_pm, cy8ctmg110_suspend, cy8ctmg110_resume); #endif -static int __devexit cy8ctmg110_remove(struct i2c_client *client) +static int cy8ctmg110_remove(struct i2c_client *client) { struct cy8ctmg110 *ts = i2c_get_clientdata(client); @@ -348,7 +357,7 @@ static struct i2c_driver cy8ctmg110_driver = { }, .id_table = cy8ctmg110_idtable, .probe = cy8ctmg110_probe, - .remove = __devexit_p(cy8ctmg110_remove), + .remove = cy8ctmg110_remove, }; module_i2c_driver(cy8ctmg110_driver); diff --git a/drivers/input/touchscreen/cyttsp_i2c.c b/drivers/input/touchscreen/cyttsp_i2c.c index 2af1d0c52bcd..4dbdf44b8fc5 100644 --- a/drivers/input/touchscreen/cyttsp_i2c.c +++ b/drivers/input/touchscreen/cyttsp_i2c.c @@ -81,7 +81,7 @@ static const struct cyttsp_bus_ops cyttsp_i2c_bus_ops = { .read = cyttsp_i2c_read_block_data, }; -static int __devinit cyttsp_i2c_probe(struct i2c_client *client, +static int cyttsp_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cyttsp *ts; @@ -102,7 +102,7 @@ static int __devinit cyttsp_i2c_probe(struct i2c_client *client, return 0; } -static int __devexit cyttsp_i2c_remove(struct i2c_client *client) +static int cyttsp_i2c_remove(struct i2c_client *client) { struct cyttsp *ts = i2c_get_clientdata(client); @@ -124,7 +124,7 @@ static struct i2c_driver cyttsp_i2c_driver = { .pm = &cyttsp_pm_ops, }, .probe = cyttsp_i2c_probe, - .remove = __devexit_p(cyttsp_i2c_remove), + .remove = cyttsp_i2c_remove, .id_table = cyttsp_i2c_id, }; diff --git a/drivers/input/touchscreen/cyttsp_spi.c b/drivers/input/touchscreen/cyttsp_spi.c index 9f263410407b..861b7f77605b 100644 --- a/drivers/input/touchscreen/cyttsp_spi.c +++ b/drivers/input/touchscreen/cyttsp_spi.c @@ -147,7 +147,7 @@ static const struct cyttsp_bus_ops cyttsp_spi_bus_ops = { .read = cyttsp_spi_read_block_data, }; -static int __devinit cyttsp_spi_probe(struct spi_device *spi) +static int cyttsp_spi_probe(struct spi_device *spi) { struct cyttsp *ts; int error; @@ -172,7 +172,7 @@ static int __devinit cyttsp_spi_probe(struct spi_device *spi) return 0; } -static int __devexit cyttsp_spi_remove(struct spi_device *spi) +static int cyttsp_spi_remove(struct spi_device *spi) { struct cyttsp *ts = spi_get_drvdata(spi); @@ -188,12 +188,11 @@ static struct spi_driver cyttsp_spi_driver = { .pm = &cyttsp_pm_ops, }, .probe = cyttsp_spi_probe, - .remove = __devexit_p(cyttsp_spi_remove), + .remove = cyttsp_spi_remove, }; module_spi_driver(cyttsp_spi_driver); -MODULE_ALIAS("spi:cyttsp"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard Product (TTSP) SPI driver"); MODULE_AUTHOR("Cypress"); diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 36b65cf10d7f..34ad84105e6e 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c @@ -297,7 +297,7 @@ static void da9034_touch_close(struct input_dev *dev) } -static int __devinit da9034_touch_probe(struct platform_device *pdev) +static int da9034_touch_probe(struct platform_device *pdev) { struct da9034_touch_pdata *pdata = pdev->dev.platform_data; struct da9034_touch *touch; @@ -361,7 +361,7 @@ err_free_touch: return ret; } -static int __devexit da9034_touch_remove(struct platform_device *pdev) +static int da9034_touch_remove(struct platform_device *pdev) { struct da9034_touch *touch = platform_get_drvdata(pdev); @@ -377,7 +377,7 @@ static struct platform_driver da9034_touch_driver = { .owner = THIS_MODULE, }, .probe = da9034_touch_probe, - .remove = __devexit_p(da9034_touch_remove), + .remove = da9034_touch_remove, }; module_platform_driver(da9034_touch_driver); diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c index e8df341090c0..8f561e22bdd4 100644 --- a/drivers/input/touchscreen/da9052_tsi.c +++ b/drivers/input/touchscreen/da9052_tsi.c @@ -27,8 +27,6 @@ struct da9052_tsi { struct input_dev *dev; struct delayed_work ts_pen_work; struct mutex mutex; - unsigned int irq_pendwn; - unsigned int irq_datardy; bool stopped; bool adc_on; }; @@ -45,8 +43,8 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) if (!tsi->stopped) { /* Mask PEN_DOWN event and unmask TSI_READY event */ - disable_irq_nosync(tsi->irq_pendwn); - enable_irq(tsi->irq_datardy); + da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN); + da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); da9052_ts_adc_toggle(tsi, true); @@ -137,13 +135,13 @@ static void da9052_ts_pen_work(struct work_struct *work) return; /* Mask TSI_READY event and unmask PEN_DOWN event */ - disable_irq(tsi->irq_datardy); - enable_irq(tsi->irq_pendwn); + da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); + da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); } } } -static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052) +static int da9052_ts_configure_gpio(struct da9052 *da9052) { int error; @@ -162,7 +160,7 @@ static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052) return 0; } -static int __devinit da9052_configure_tsi(struct da9052_tsi *tsi) +static int da9052_configure_tsi(struct da9052_tsi *tsi) { int error; @@ -197,7 +195,7 @@ static int da9052_ts_input_open(struct input_dev *input_dev) mb(); /* Unmask PEN_DOWN event */ - enable_irq(tsi->irq_pendwn); + da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); /* Enable Pen Detect Circuit */ return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, @@ -210,11 +208,11 @@ static void da9052_ts_input_close(struct input_dev *input_dev) tsi->stopped = true; mb(); - disable_irq(tsi->irq_pendwn); + da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); cancel_delayed_work_sync(&tsi->ts_pen_work); if (tsi->adc_on) { - disable_irq(tsi->irq_datardy); + da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); da9052_ts_adc_toggle(tsi, false); /* @@ -222,33 +220,24 @@ static void da9052_ts_input_close(struct input_dev *input_dev) * twice and we need to enable it to keep enable/disable * counter balanced. IRQ is still off though. */ - enable_irq(tsi->irq_pendwn); + da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); } /* Disable Pen Detect Circuit */ da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); } -static int __devinit da9052_ts_probe(struct platform_device *pdev) +static int da9052_ts_probe(struct platform_device *pdev) { struct da9052 *da9052; struct da9052_tsi *tsi; struct input_dev *input_dev; - int irq_pendwn; - int irq_datardy; int error; da9052 = dev_get_drvdata(pdev->dev.parent); if (!da9052) return -EINVAL; - irq_pendwn = platform_get_irq_byname(pdev, "PENDWN"); - irq_datardy = platform_get_irq_byname(pdev, "TSIRDY"); - if (irq_pendwn < 0 || irq_datardy < 0) { - dev_err(da9052->dev, "Unable to determine device interrupts\n"); - return -ENXIO; - } - tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); input_dev = input_allocate_device(); if (!tsi || !input_dev) { @@ -258,8 +247,6 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev) tsi->da9052 = da9052; tsi->dev = input_dev; - tsi->irq_pendwn = da9052->irq_base + irq_pendwn; - tsi->irq_datardy = da9052->irq_base + irq_datardy; tsi->stopped = true; INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); @@ -287,31 +274,25 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev) /* Disable ADC */ da9052_ts_adc_toggle(tsi, false); - error = request_threaded_irq(tsi->irq_pendwn, - NULL, da9052_ts_pendwn_irq, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "PENDWN", tsi); + error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN, + "pendown-irq", da9052_ts_pendwn_irq, tsi); if (error) { dev_err(tsi->da9052->dev, - "Failed to register PENDWN IRQ %d, error = %d\n", - tsi->irq_pendwn, error); + "Failed to register PENDWN IRQ: %d\n", error); goto err_free_mem; } - error = request_threaded_irq(tsi->irq_datardy, - NULL, da9052_ts_datardy_irq, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, - "TSIRDY", tsi); + error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY, + "tsiready-irq", da9052_ts_datardy_irq, tsi); if (error) { dev_err(tsi->da9052->dev, - "Failed to register TSIRDY IRQ %d, error = %d\n", - tsi->irq_datardy, error); + "Failed to register TSIRDY IRQ :%d\n", error); goto err_free_pendwn_irq; } /* Mask PEN_DOWN and TSI_READY events */ - disable_irq(tsi->irq_pendwn); - disable_irq(tsi->irq_datardy); + da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN); + da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY); error = da9052_configure_tsi(tsi); if (error) @@ -326,9 +307,9 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev) return 0; err_free_datardy_irq: - free_irq(tsi->irq_datardy, tsi); + da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); err_free_pendwn_irq: - free_irq(tsi->irq_pendwn, tsi); + da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); err_free_mem: kfree(tsi); input_free_device(input_dev); @@ -336,14 +317,14 @@ err_free_mem: return error; } -static int __devexit da9052_ts_remove(struct platform_device *pdev) +static int da9052_ts_remove(struct platform_device *pdev) { struct da9052_tsi *tsi = platform_get_drvdata(pdev); da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); - free_irq(tsi->irq_pendwn, tsi); - free_irq(tsi->irq_datardy, tsi); + da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi); + da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi); input_unregister_device(tsi->dev); kfree(tsi); @@ -355,7 +336,7 @@ static int __devexit da9052_ts_remove(struct platform_device *pdev) static struct platform_driver da9052_tsi_driver = { .probe = da9052_ts_probe, - .remove = __devexit_p(da9052_ts_remove), + .remove = da9052_ts_remove, .driver = { .name = "da9052-tsi", .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c index 099d144ab7c9..a9170157b442 100644 --- a/drivers/input/touchscreen/edt-ft5x06.c +++ b/drivers/input/touchscreen/edt-ft5x06.c @@ -491,14 +491,6 @@ static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode) DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get, edt_ft5x06_debugfs_mode_set, "%llu\n"); -static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode, - struct file *file) -{ - file->private_data = inode->i_private; - - return 0; -} - static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file, char __user *buf, size_t count, loff_t *off) { @@ -579,11 +571,11 @@ out: static const struct file_operations debugfs_raw_data_fops = { - .open = edt_ft5x06_debugfs_raw_data_open, + .open = simple_open, .read = edt_ft5x06_debugfs_raw_data_read, }; -static void __devinit +static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, const char *debugfs_name) { @@ -600,7 +592,7 @@ edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata, tsdata->debug_dir, tsdata, &debugfs_raw_data_fops); } -static void __devexit +static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) { if (tsdata->debug_dir) @@ -625,7 +617,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata) -static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client, +static int edt_ft5x06_ts_reset(struct i2c_client *client, int reset_pin) { int error; @@ -649,7 +641,7 @@ static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client, return 0; } -static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client, +static int edt_ft5x06_ts_identify(struct i2c_client *client, char *model_name, char *fw_version) { @@ -683,7 +675,7 @@ static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client, pdata->name <= edt_ft5x06_attr_##name.limit_high) \ edt_ft5x06_register_write(tsdata, reg, pdata->name) -static void __devinit +static void edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, const struct edt_ft5x06_platform_data *pdata) { @@ -697,7 +689,7 @@ edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata, EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE); } -static void __devinit +static void edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) { tsdata->threshold = edt_ft5x06_register_read(tsdata, @@ -710,7 +702,7 @@ edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata) tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y); } -static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client, +static int edt_ft5x06_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct edt_ft5x06_platform_data *pdata = @@ -830,7 +822,7 @@ err_free_mem: return error; } -static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client) +static int edt_ft5x06_ts_remove(struct i2c_client *client) { const struct edt_ft5x06_platform_data *pdata = dev_get_platdata(&client->dev); @@ -891,7 +883,7 @@ static struct i2c_driver edt_ft5x06_ts_driver = { }, .id_table = edt_ft5x06_ts_id, .probe = edt_ft5x06_ts_probe, - .remove = __devexit_p(edt_ft5x06_ts_remove), + .remove = edt_ft5x06_ts_remove, }; module_i2c_driver(edt_ft5x06_ts_driver); diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 908407efc672..55255a940072 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -154,7 +154,7 @@ static void eeti_ts_close(struct input_dev *dev) eeti_ts_stop(priv); } -static int __devinit eeti_ts_probe(struct i2c_client *client, +static int eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { struct eeti_ts_platform_data *pdata = client->dev.platform_data; @@ -248,7 +248,7 @@ err0: return err; } -static int __devexit eeti_ts_remove(struct i2c_client *client) +static int eeti_ts_remove(struct i2c_client *client) { struct eeti_ts_priv *priv = i2c_get_clientdata(client); @@ -321,7 +321,7 @@ static struct i2c_driver eeti_ts_driver = { #endif }, .probe = eeti_ts_probe, - .remove = __devexit_p(eeti_ts_remove), + .remove = eeti_ts_remove, .id_table = eeti_ts_id, }; diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index 13fa62fdfb0b..17c9097f3b5d 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -153,7 +153,7 @@ static int egalax_wake_up_device(struct i2c_client *client) return 0; } -static int __devinit egalax_firmware_version(struct i2c_client *client) +static int egalax_firmware_version(struct i2c_client *client) { static const u8 cmd[MAX_I2C_DATA_LEN] = { 0x03, 0x03, 0xa, 0x01, 0x41 }; int ret; @@ -165,7 +165,7 @@ static int __devinit egalax_firmware_version(struct i2c_client *client) return 0; } -static int __devinit egalax_ts_probe(struct i2c_client *client, +static int egalax_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct egalax_ts *ts; @@ -246,7 +246,7 @@ err_free_ts: return error; } -static __devexit int egalax_ts_remove(struct i2c_client *client) +static int egalax_ts_remove(struct i2c_client *client) { struct egalax_ts *ts = i2c_get_clientdata(client); @@ -301,7 +301,7 @@ static struct i2c_driver egalax_ts_driver = { }, .id_table = egalax_ts_id, .probe = egalax_ts_probe, - .remove = __devexit_p(egalax_ts_remove), + .remove = egalax_ts_remove, }; module_i2c_driver(egalax_ts_driver); diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c deleted file mode 100644 index b9e8686a6f1c..000000000000 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2001 "Crazy" James Simmons jsimmons@transvirtual.com - * - * Sponsored by Transvirtual Technology. - * - * Derived from the code in h3600_ts.[ch] by Charles Flynn - */ - -/* - * Driver for the h3600 Touch Screen and other Atmel controlled devices. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so by - * e-mail - mail your message to <jsimmons@transvirtual.com>. - */ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/init.h> -#include <linux/delay.h> - -/* SA1100 serial defines */ -#include <mach/hardware.h> -#include <mach/irqs.h> - -#define DRIVER_DESC "H3600 touchscreen driver" - -MODULE_AUTHOR("James Simmons <jsimmons@transvirtual.com>"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -/* - * Definitions & global arrays. - */ - -/* The start and end of frame characters SOF and EOF */ -#define CHAR_SOF 0x02 -#define CHAR_EOF 0x03 -#define FRAME_OVERHEAD 3 /* CHAR_SOF,CHAR_EOF,LENGTH = 3 */ - -/* - Atmel events and response IDs contained in frame. - Programmer has no control over these numbers. - TODO there are holes - specifically 1,7,0x0a -*/ -#define VERSION_ID 0 /* Get Version (request/response) */ -#define KEYBD_ID 2 /* Keyboard (event) */ -#define TOUCHS_ID 3 /* Touch Screen (event)*/ -#define EEPROM_READ_ID 4 /* (request/response) */ -#define EEPROM_WRITE_ID 5 /* (request/response) */ -#define THERMAL_ID 6 /* (request/response) */ -#define NOTIFY_LED_ID 8 /* (request/response) */ -#define BATTERY_ID 9 /* (request/response) */ -#define SPI_READ_ID 0x0b /* ( request/response) */ -#define SPI_WRITE_ID 0x0c /* ( request/response) */ -#define FLITE_ID 0x0d /* backlight ( request/response) */ -#define STX_ID 0xa1 /* extension pack status (req/resp) */ - -#define MAX_ID 14 - -#define H3600_MAX_LENGTH 16 -#define H3600_KEY 0xf - -#define H3600_SCANCODE_RECORD 1 /* 1 -> record button */ -#define H3600_SCANCODE_CALENDAR 2 /* 2 -> calendar */ -#define H3600_SCANCODE_CONTACTS 3 /* 3 -> contact */ -#define H3600_SCANCODE_Q 4 /* 4 -> Q button */ -#define H3600_SCANCODE_START 5 /* 5 -> start menu */ -#define H3600_SCANCODE_UP 6 /* 6 -> up */ -#define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ -#define H3600_SCANCODE_LEFT 8 /* 8 -> left */ -#define H3600_SCANCODE_DOWN 9 /* 9 -> down */ - -/* - * Per-touchscreen data. - */ -struct h3600_dev { - struct input_dev *dev; - struct serio *serio; - unsigned char event; /* event ID from packet */ - unsigned char chksum; - unsigned char len; - unsigned char idx; - unsigned char buf[H3600_MAX_LENGTH]; - char phys[32]; -}; - -static irqreturn_t action_button_handler(int irq, void *dev_id) -{ - int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; - struct input_dev *dev = dev_id; - - input_report_key(dev, KEY_ENTER, down); - input_sync(dev); - - return IRQ_HANDLED; -} - -static irqreturn_t npower_button_handler(int irq, void *dev_id) -{ - int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; - struct input_dev *dev = dev_id; - - /* - * This interrupt is only called when we release the key. So we have - * to fake a key press. - */ - input_report_key(dev, KEY_SUSPEND, 1); - input_report_key(dev, KEY_SUSPEND, down); - input_sync(dev); - - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM - -static int flite_brightness = 25; - -enum flite_pwr { - FLITE_PWR_OFF = 0, - FLITE_PWR_ON = 1 -}; - -/* - * h3600_flite_power: enables or disables power to frontlight, using last bright */ -unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) -{ - unsigned char brightness = (pwr == FLITE_PWR_OFF) ? 0 : flite_brightness; - struct h3600_dev *ts = input_get_drvdata(dev); - - /* Must be in this order */ - serio_write(ts->serio, 1); - serio_write(ts->serio, pwr); - serio_write(ts->serio, brightness); - - return 0; -} - -#endif - -/* - * This function translates the native event packets to linux input event - * packets. Some packets coming from serial are not touchscreen related. In - * this case we send them off to be processed elsewhere. - */ -static void h3600ts_process_packet(struct h3600_dev *ts) -{ - struct input_dev *dev = ts->dev; - static int touched = 0; - int key, down = 0; - - switch (ts->event) { - /* - Buttons - returned as a single byte - 7 6 5 4 3 2 1 0 - S x x x N N N N - - S switch state ( 0=pressed 1=released) - x Unused. - NNNN switch number 0-15 - - Note: This is true for non interrupt generated key events. - */ - case KEYBD_ID: - down = (ts->buf[0] & 0x80) ? 0 : 1; - - switch (ts->buf[0] & 0x7f) { - case H3600_SCANCODE_RECORD: - key = KEY_RECORD; - break; - case H3600_SCANCODE_CALENDAR: - key = KEY_PROG1; - break; - case H3600_SCANCODE_CONTACTS: - key = KEY_PROG2; - break; - case H3600_SCANCODE_Q: - key = KEY_Q; - break; - case H3600_SCANCODE_START: - key = KEY_PROG3; - break; - case H3600_SCANCODE_UP: - key = KEY_UP; - break; - case H3600_SCANCODE_RIGHT: - key = KEY_RIGHT; - break; - case H3600_SCANCODE_LEFT: - key = KEY_LEFT; - break; - case H3600_SCANCODE_DOWN: - key = KEY_DOWN; - break; - default: - key = 0; - } - if (key) - input_report_key(dev, key, down); - break; - /* - * Native touchscreen event data is formatted as shown below:- - * - * +-------+-------+-------+-------+ - * | Xmsb | Xlsb | Ymsb | Ylsb | - * +-------+-------+-------+-------+ - * byte 0 1 2 3 - */ - case TOUCHS_ID: - if (!touched) { - input_report_key(dev, BTN_TOUCH, 1); - touched = 1; - } - - if (ts->len) { - unsigned short x, y; - - x = ts->buf[0]; x <<= 8; x += ts->buf[1]; - y = ts->buf[2]; y <<= 8; y += ts->buf[3]; - - input_report_abs(dev, ABS_X, x); - input_report_abs(dev, ABS_Y, y); - } else { - input_report_key(dev, BTN_TOUCH, 0); - touched = 0; - } - break; - default: - /* Send a non input event elsewhere */ - break; - } - - input_sync(dev); -} - -/* - * h3600ts_event() handles events from the input module. - */ -static int h3600ts_event(struct input_dev *dev, unsigned int type, - unsigned int code, int value) -{ -#if 0 - struct h3600_dev *ts = input_get_drvdata(dev); - - switch (type) { - case EV_LED: { - // serio_write(ts->serio, SOME_CMD); - return 0; - } - } - return -1; -#endif - return 0; -} - -/* - Frame format - byte 1 2 3 len + 4 - +-------+---------------+---------------+--=------------+ - |SOF |id |len | len bytes | Chksum | - +-------+---------------+---------------+--=------------+ - bit 0 7 8 11 12 15 16 - - +-------+---------------+-------+ - |SOF |id |0 |Chksum | - Note Chksum does not include SOF - +-------+---------------+-------+ - bit 0 7 8 11 12 15 16 - -*/ - -static int state; - -/* decode States */ -#define STATE_SOF 0 /* start of FRAME */ -#define STATE_ID 1 /* state where we decode the ID & len */ -#define STATE_DATA 2 /* state where we decode data */ -#define STATE_EOF 3 /* state where we decode checksum or EOF */ - -static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) -{ - struct h3600_dev *ts = serio_get_drvdata(serio); - - /* - * We have a new frame coming in. - */ - switch (state) { - case STATE_SOF: - if (data == CHAR_SOF) - state = STATE_ID; - break; - case STATE_ID: - ts->event = (data & 0xf0) >> 4; - ts->len = (data & 0xf); - ts->idx = 0; - if (ts->event >= MAX_ID) { - state = STATE_SOF; - break; - } - ts->chksum = data; - state = (ts->len > 0) ? STATE_DATA : STATE_EOF; - break; - case STATE_DATA: - ts->chksum += data; - ts->buf[ts->idx]= data; - if (++ts->idx == ts->len) - state = STATE_EOF; - break; - case STATE_EOF: - state = STATE_SOF; - if (data == CHAR_EOF || data == ts->chksum) - h3600ts_process_packet(ts); - break; - default: - printk("Error3\n"); - break; - } - - return IRQ_HANDLED; -} - -/* - * h3600ts_connect() is the routine that is called when someone adds a - * new serio device that supports H3600 protocol and registers it as - * an input device. - */ -static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) -{ - struct h3600_dev *ts; - struct input_dev *input_dev; - int err; - - ts = kzalloc(sizeof(struct h3600_dev), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts || !input_dev) { - err = -ENOMEM; - goto fail1; - } - - ts->serio = serio; - ts->dev = input_dev; - snprintf(ts->phys, sizeof(ts->phys), "%s/input0", serio->phys); - - input_dev->name = "H3600 TouchScreen"; - input_dev->phys = ts->phys; - input_dev->id.bustype = BUS_RS232; - input_dev->id.vendor = SERIO_H3600; - input_dev->id.product = 0x0666; /* FIXME !!! We can ask the hardware */ - input_dev->id.version = 0x0100; - input_dev->dev.parent = &serio->dev; - - input_set_drvdata(input_dev, ts); - - input_dev->event = h3600ts_event; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | - BIT_MASK(EV_LED) | BIT_MASK(EV_PWR); - input_dev->ledbit[0] = BIT_MASK(LED_SLEEP); - input_set_abs_params(input_dev, ABS_X, 60, 985, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 35, 1024, 0, 0); - - set_bit(KEY_RECORD, input_dev->keybit); - set_bit(KEY_Q, input_dev->keybit); - set_bit(KEY_PROG1, input_dev->keybit); - set_bit(KEY_PROG2, input_dev->keybit); - set_bit(KEY_PROG3, input_dev->keybit); - set_bit(KEY_UP, input_dev->keybit); - set_bit(KEY_RIGHT, input_dev->keybit); - set_bit(KEY_LEFT, input_dev->keybit); - set_bit(KEY_DOWN, input_dev->keybit); - set_bit(KEY_ENTER, input_dev->keybit); - set_bit(KEY_SUSPEND, input_dev->keybit); - set_bit(BTN_TOUCH, input_dev->keybit); - - /* Device specific stuff */ - set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); - set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); - - if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, - IRQF_SHARED, "h3600_action", ts->dev)) { - printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); - err = -EBUSY; - goto fail1; - } - - if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, - IRQF_SHARED, "h3600_suspend", ts->dev)) { - printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n"); - err = -EBUSY; - goto fail2; - } - - serio_set_drvdata(serio, ts); - - err = serio_open(serio, drv); - if (err) - goto fail3; - - //h3600_flite_control(1, 25); /* default brightness */ - err = input_register_device(ts->dev); - if (err) - goto fail4; - - return 0; - -fail4: serio_close(serio); -fail3: serio_set_drvdata(serio, NULL); - free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); -fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); -fail1: input_free_device(input_dev); - kfree(ts); - return err; -} - -/* - * h3600ts_disconnect() is the opposite of h3600ts_connect() - */ - -static void h3600ts_disconnect(struct serio *serio) -{ - struct h3600_dev *ts = serio_get_drvdata(serio); - - free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev); - free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev); - input_get_device(ts->dev); - input_unregister_device(ts->dev); - serio_close(serio); - serio_set_drvdata(serio, NULL); - input_put_device(ts->dev); - kfree(ts); -} - -/* - * The serio driver structure. - */ - -static struct serio_device_id h3600ts_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_H3600, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; - -MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids); - -static struct serio_driver h3600ts_drv = { - .driver = { - .name = "h3600ts", - }, - .description = DRIVER_DESC, - .id_table = h3600ts_serio_ids, - .interrupt = h3600ts_interrupt, - .connect = h3600ts_connect, - .disconnect = h3600ts_disconnect, -}; - -module_serio_driver(h3600ts_drv); diff --git a/drivers/input/touchscreen/htcpen.c b/drivers/input/touchscreen/htcpen.c index d13143b68b3e..6c4fb8436957 100644 --- a/drivers/input/touchscreen/htcpen.c +++ b/drivers/input/touchscreen/htcpen.c @@ -102,7 +102,7 @@ static void htcpen_close(struct input_dev *dev) synchronize_irq(HTCPEN_IRQ); } -static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id) +static int htcpen_isa_probe(struct device *dev, unsigned int id) { struct input_dev *htcpen_dev; int err = -EBUSY; @@ -174,7 +174,7 @@ static int __devinit htcpen_isa_probe(struct device *dev, unsigned int id) return err; } -static int __devexit htcpen_isa_remove(struct device *dev, unsigned int id) +static int htcpen_isa_remove(struct device *dev, unsigned int id) { struct input_dev *htcpen_dev = dev_get_drvdata(dev); @@ -210,7 +210,7 @@ static int htcpen_isa_resume(struct device *dev, unsigned int n) static struct isa_driver htcpen_isa_driver = { .probe = htcpen_isa_probe, - .remove = __devexit_p(htcpen_isa_remove), + .remove = htcpen_isa_remove, #ifdef CONFIG_PM .suspend = htcpen_isa_suspend, .resume = htcpen_isa_resume, diff --git a/drivers/input/touchscreen/ili210x.c b/drivers/input/touchscreen/ili210x.c index 4ac69760ec08..1418bdda61bb 100644 --- a/drivers/input/touchscreen/ili210x.c +++ b/drivers/input/touchscreen/ili210x.c @@ -180,7 +180,7 @@ static const struct attribute_group ili210x_attr_group = { .attrs = ili210x_attributes, }; -static int __devinit ili210x_i2c_probe(struct i2c_client *client, +static int ili210x_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; @@ -298,7 +298,7 @@ err_free_mem: return error; } -static int __devexit ili210x_i2c_remove(struct i2c_client *client) +static int ili210x_i2c_remove(struct i2c_client *client) { struct ili210x *priv = i2c_get_clientdata(client); @@ -350,7 +350,7 @@ static struct i2c_driver ili210x_ts_driver = { }, .id_table = ili210x_i2c_id, .probe = ili210x_i2c_probe, - .remove = __devexit_p(ili210x_i2c_remove), + .remove = ili210x_i2c_remove, }; module_i2c_driver(ili210x_ts_driver); diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c index cf299377fc49..465db5dba8b4 100644 --- a/drivers/input/touchscreen/intel-mid-touch.c +++ b/drivers/input/touchscreen/intel-mid-touch.c @@ -427,7 +427,7 @@ out: } /* Utility to read PMIC ID */ -static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev) +static int mrstouch_read_pmic_id(uint *vendor, uint *rev) { int err; u8 r; @@ -446,7 +446,7 @@ static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev) * Parse ADC channels to find end of the channel configured by other ADC user * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels */ -static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) +static int mrstouch_chan_parse(struct mrstouch_dev *tsdev) { int found = 0; int err, i; @@ -478,7 +478,7 @@ static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev) /* * Writes touch screen channels to ADC address selection registers */ -static int __devinit mrstouch_ts_chan_set(uint offset) +static int mrstouch_ts_chan_set(uint offset) { u16 chan; @@ -494,7 +494,7 @@ static int __devinit mrstouch_ts_chan_set(uint offset) } /* Initialize ADC */ -static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev) +static int mrstouch_adc_init(struct mrstouch_dev *tsdev) { int err, start; u8 ra, rm; @@ -568,7 +568,7 @@ static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev) /* Probe function for touch screen driver */ -static int __devinit mrstouch_probe(struct platform_device *pdev) +static int mrstouch_probe(struct platform_device *pdev) { struct mrstouch_dev *tsdev; struct input_dev *input; @@ -643,7 +643,7 @@ err_free_mem: return err; } -static int __devexit mrstouch_remove(struct platform_device *pdev) +static int mrstouch_remove(struct platform_device *pdev) { struct mrstouch_dev *tsdev = platform_get_drvdata(pdev); @@ -662,7 +662,7 @@ static struct platform_driver mrstouch_driver = { .owner = THIS_MODULE, }, .probe = mrstouch_probe, - .remove = __devexit_p(mrstouch_remove), + .remove = mrstouch_remove, }; module_platform_driver(mrstouch_driver); diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index 7f03d1bd916e..282d7c7ad2fc 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c @@ -99,7 +99,7 @@ static irqreturn_t jornada720_ts_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static int __devinit jornada720_ts_probe(struct platform_device *pdev) +static int jornada720_ts_probe(struct platform_device *pdev) { struct jornada_ts *jornada_ts; struct input_dev *input_dev; @@ -151,7 +151,7 @@ static int __devinit jornada720_ts_probe(struct platform_device *pdev) return error; } -static int __devexit jornada720_ts_remove(struct platform_device *pdev) +static int jornada720_ts_remove(struct platform_device *pdev) { struct jornada_ts *jornada_ts = platform_get_drvdata(pdev); @@ -168,7 +168,7 @@ MODULE_ALIAS("platform:jornada_ts"); static struct platform_driver jornada720_ts_driver = { .probe = jornada720_ts_probe, - .remove = __devexit_p(jornada720_ts_remove), + .remove = jornada720_ts_remove, .driver = { .name = "jornada_ts", .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index 4c2b8ed3bf16..9101ee529c92 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -203,7 +203,7 @@ static void lpc32xx_ts_close(struct input_dev *dev) lpc32xx_stop_tsc(tsc); } -static int __devinit lpc32xx_ts_probe(struct platform_device *pdev) +static int lpc32xx_ts_probe(struct platform_device *pdev) { struct lpc32xx_tsc *tsc; struct input_dev *input; @@ -309,7 +309,7 @@ err_free_mem: return error; } -static int __devexit lpc32xx_ts_remove(struct platform_device *pdev) +static int lpc32xx_ts_remove(struct platform_device *pdev) { struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev); struct resource *res; @@ -394,7 +394,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); static struct platform_driver lpc32xx_ts_driver = { .probe = lpc32xx_ts_probe, - .remove = __devexit_p(lpc32xx_ts_remove), + .remove = lpc32xx_ts_remove, .driver = { .name = MOD_NAME, .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c index 4eab50b856d7..00bc6caa27f5 100644 --- a/drivers/input/touchscreen/max11801_ts.c +++ b/drivers/input/touchscreen/max11801_ts.c @@ -156,7 +156,7 @@ out: return IRQ_HANDLED; } -static void __devinit max11801_ts_phy_init(struct max11801_data *data) +static void max11801_ts_phy_init(struct max11801_data *data) { struct i2c_client *client = data->client; @@ -174,7 +174,7 @@ static void __devinit max11801_ts_phy_init(struct max11801_data *data) max11801_write_reg(client, OP_MODE_CONF_REG, 0x36); } -static int __devinit max11801_ts_probe(struct i2c_client *client, +static int max11801_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct max11801_data *data; @@ -228,7 +228,7 @@ err_free_mem: return error; } -static __devexit int max11801_ts_remove(struct i2c_client *client) +static int max11801_ts_remove(struct i2c_client *client) { struct max11801_data *data = i2c_get_clientdata(client); @@ -252,7 +252,7 @@ static struct i2c_driver max11801_ts_driver = { }, .id_table = max11801_ts_id, .probe = max11801_ts_probe, - .remove = __devexit_p(max11801_ts_remove), + .remove = max11801_ts_remove, }; module_i2c_driver(max11801_ts_driver); diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c index 48dc5b0d26f1..02103b6abb39 100644 --- a/drivers/input/touchscreen/mc13783_ts.c +++ b/drivers/input/touchscreen/mc13783_ts.c @@ -229,7 +229,7 @@ err_free_mem: return ret; } -static int __devexit mc13783_ts_remove(struct platform_device *pdev) +static int mc13783_ts_remove(struct platform_device *pdev) { struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); @@ -243,7 +243,7 @@ static int __devexit mc13783_ts_remove(struct platform_device *pdev) } static struct platform_driver mc13783_ts_driver = { - .remove = __devexit_p(mc13783_ts_remove), + .remove = mc13783_ts_remove, .driver = { .owner = THIS_MODULE, .name = MC13783_TS_NAME, diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index b528511861ce..f9f4e0c56eda 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -187,7 +187,7 @@ static void mcs5000_ts_phys_init(struct mcs5000_ts_data *data) OP_MODE_ACTIVE | REPORT_RATE_80); } -static int __devinit mcs5000_ts_probe(struct i2c_client *client, +static int mcs5000_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct mcs5000_ts_data *data; @@ -249,7 +249,7 @@ err_free_mem: return ret; } -static int __devexit mcs5000_ts_remove(struct i2c_client *client) +static int mcs5000_ts_remove(struct i2c_client *client) { struct mcs5000_ts_data *data = i2c_get_clientdata(client); @@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(i2c, mcs5000_ts_id); static struct i2c_driver mcs5000_ts_driver = { .probe = mcs5000_ts_probe, - .remove = __devexit_p(mcs5000_ts_remove), + .remove = mcs5000_ts_remove, .driver = { .name = "mcs5000_ts", #ifdef CONFIG_PM diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 560cf09d1c5a..4a29ddf6bf1e 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/of.h> #include <linux/i2c.h> #include <linux/i2c/mms114.h> #include <linux/input/mt.h> @@ -360,14 +361,63 @@ static void mms114_input_close(struct input_dev *dev) mms114_stop(data); } -static int __devinit mms114_probe(struct i2c_client *client, +#ifdef CONFIG_OF +static struct mms114_platform_data *mms114_parse_dt(struct device *dev) +{ + struct mms114_platform_data *pdata; + struct device_node *np = dev->of_node; + + if (!np) + return NULL; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(dev, "failed to allocate platform data\n"); + return NULL; + } + + if (of_property_read_u32(np, "x-size", &pdata->x_size)) { + dev_err(dev, "failed to get x-size property\n"); + return NULL; + }; + + if (of_property_read_u32(np, "y-size", &pdata->y_size)) { + dev_err(dev, "failed to get y-size property\n"); + return NULL; + }; + + of_property_read_u32(np, "contact-threshold", + &pdata->contact_threshold); + of_property_read_u32(np, "moving-threshold", + &pdata->moving_threshold); + + if (of_find_property(np, "x-invert", NULL)) + pdata->x_invert = true; + if (of_find_property(np, "y-invert", NULL)) + pdata->y_invert = true; + + return pdata; +} +#else +static inline struct mms114_platform_data *mms114_parse_dt(struct device *dev) +{ + return NULL; +} +#endif + +static int mms114_probe(struct i2c_client *client, const struct i2c_device_id *id) { + const struct mms114_platform_data *pdata; struct mms114_data *data; struct input_dev *input_dev; int error; - if (!client->dev.platform_data) { + pdata = dev_get_platdata(&client->dev); + if (!pdata) + pdata = mms114_parse_dt(&client->dev); + + if (!pdata) { dev_err(&client->dev, "Need platform data\n"); return -EINVAL; } @@ -379,17 +429,17 @@ static int __devinit mms114_probe(struct i2c_client *client, return -ENODEV; } - data = kzalloc(sizeof(struct mms114_data), GFP_KERNEL); - input_dev = input_allocate_device(); + data = devm_kzalloc(&client->dev, sizeof(struct mms114_data), + GFP_KERNEL); + input_dev = devm_input_allocate_device(&client->dev); if (!data || !input_dev) { dev_err(&client->dev, "Failed to allocate memory\n"); - error = -ENOMEM; - goto err_free_mem; + return -ENOMEM; } data->client = client; data->input_dev = input_dev; - data->pdata = client->dev.platform_data; + data->pdata = pdata; input_dev->name = "MELPAS MMS114 Touchscreen"; input_dev->id.bustype = BUS_I2C; @@ -416,57 +466,36 @@ static int __devinit mms114_probe(struct i2c_client *client, input_set_drvdata(input_dev, data); i2c_set_clientdata(client, data); - data->core_reg = regulator_get(&client->dev, "avdd"); + data->core_reg = devm_regulator_get(&client->dev, "avdd"); if (IS_ERR(data->core_reg)) { error = PTR_ERR(data->core_reg); dev_err(&client->dev, "Unable to get the Core regulator (%d)\n", error); - goto err_free_mem; + return error; } - data->io_reg = regulator_get(&client->dev, "vdd"); + data->io_reg = devm_regulator_get(&client->dev, "vdd"); if (IS_ERR(data->io_reg)) { error = PTR_ERR(data->io_reg); dev_err(&client->dev, "Unable to get the IO regulator (%d)\n", error); - goto err_core_reg; + return error; } - error = request_threaded_irq(client->irq, NULL, mms114_interrupt, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "mms114", data); + error = devm_request_threaded_irq(&client->dev, client->irq, NULL, + mms114_interrupt, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(&client->dev), data); if (error) { dev_err(&client->dev, "Failed to register interrupt\n"); - goto err_io_reg; + return error; } disable_irq(client->irq); error = input_register_device(data->input_dev); - if (error) - goto err_free_irq; - - return 0; - -err_free_irq: - free_irq(client->irq, data); -err_io_reg: - regulator_put(data->io_reg); -err_core_reg: - regulator_put(data->core_reg); -err_free_mem: - input_free_device(input_dev); - kfree(data); - return error; -} - -static int __devexit mms114_remove(struct i2c_client *client) -{ - struct mms114_data *data = i2c_get_clientdata(client); - - free_irq(client->irq, data); - regulator_put(data->io_reg); - regulator_put(data->core_reg); - input_unregister_device(data->input_dev); - kfree(data); + if (error) { + dev_err(&client->dev, "Failed to register input device\n"); + return error; + } return 0; } @@ -525,14 +554,21 @@ static const struct i2c_device_id mms114_id[] = { }; MODULE_DEVICE_TABLE(i2c, mms114_id); +#ifdef CONFIG_OF +static struct of_device_id mms114_dt_match[] = { + { .compatible = "melfas,mms114" }, + { } +}; +#endif + static struct i2c_driver mms114_driver = { .driver = { .name = "mms114", .owner = THIS_MODULE, .pm = &mms114_pm_ops, + .of_match_table = of_match_ptr(mms114_dt_match), }, .probe = mms114_probe, - .remove = __devexit_p(mms114_remove), .id_table = mms114_id, }; diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index f57aeb80f7e3..f22e04dd4e16 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c @@ -137,7 +137,7 @@ static void pcap_ts_close(struct input_dev *dev) pcap_ts->read_state << PCAP_ADC_TS_M_SHIFT); } -static int __devinit pcap_ts_probe(struct platform_device *pdev) +static int pcap_ts_probe(struct platform_device *pdev) { struct input_dev *input_dev; struct pcap_ts *pcap_ts; @@ -202,7 +202,7 @@ fail: return err; } -static int __devexit pcap_ts_remove(struct platform_device *pdev) +static int pcap_ts_remove(struct platform_device *pdev) { struct pcap_ts *pcap_ts = platform_get_drvdata(pdev); @@ -245,7 +245,7 @@ static const struct dev_pm_ops pcap_ts_pm_ops = { static struct platform_driver pcap_ts_driver = { .probe = pcap_ts_probe, - .remove = __devexit_p(pcap_ts_remove), + .remove = pcap_ts_remove, .driver = { .name = "pcap-ts", .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/pixcir_i2c_ts.c b/drivers/input/touchscreen/pixcir_i2c_ts.c index 953b4c105cad..6cc6b36663ff 100644 --- a/drivers/input/touchscreen/pixcir_i2c_ts.c +++ b/drivers/input/touchscreen/pixcir_i2c_ts.c @@ -125,7 +125,7 @@ static int pixcir_i2c_ts_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); -static int __devinit pixcir_i2c_ts_probe(struct i2c_client *client, +static int pixcir_i2c_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { const struct pixcir_ts_platform_data *pdata = client->dev.platform_data; @@ -189,7 +189,7 @@ err_free_mem: return error; } -static int __devexit pixcir_i2c_ts_remove(struct i2c_client *client) +static int pixcir_i2c_ts_remove(struct i2c_client *client) { struct pixcir_i2c_ts_data *tsdata = i2c_get_clientdata(client); @@ -218,7 +218,7 @@ static struct i2c_driver pixcir_i2c_ts_driver = { .pm = &pixcir_dev_pm_ops, }, .probe = pixcir_i2c_ts_probe, - .remove = __devexit_p(pixcir_i2c_ts_remove), + .remove = pixcir_i2c_ts_remove, .id_table = pixcir_i2c_ts_id, }; diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 549fa29548f8..b061af2c8376 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -238,7 +238,7 @@ static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select) * Initialise, find and allocate any resources we need to run and then * register with the ADC and input systems. */ -static int __devinit s3c2410ts_probe(struct platform_device *pdev) +static int s3c2410ts_probe(struct platform_device *pdev) { struct s3c2410_ts_mach_info *info; struct device *dev = &pdev->dev; @@ -365,7 +365,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) * * Free up our state ready to be removed. */ -static int __devexit s3c2410ts_remove(struct platform_device *pdev) +static int s3c2410ts_remove(struct platform_device *pdev) { free_irq(ts.irq_tc, ts.input); del_timer_sync(&touch_timer); @@ -430,7 +430,7 @@ static struct platform_driver s3c_ts_driver = { }, .id_table = s3cts_driver_ids, .probe = s3c2410ts_probe, - .remove = __devexit_p(s3c2410ts_remove), + .remove = s3c2410ts_remove, }; module_platform_driver(s3c_ts_driver); diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 6cb68a1981bf..d9d05e222428 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -139,7 +139,7 @@ end: return IRQ_HANDLED; } -static int __devinit st1232_ts_probe(struct i2c_client *client, +static int st1232_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct st1232_ts_data *ts; @@ -206,7 +206,7 @@ err_free_mem: return error; } -static int __devexit st1232_ts_remove(struct i2c_client *client) +static int st1232_ts_remove(struct i2c_client *client) { struct st1232_ts_data *ts = i2c_get_clientdata(client); @@ -255,7 +255,7 @@ static const struct i2c_device_id st1232_ts_id[] = { MODULE_DEVICE_TABLE(i2c, st1232_ts_id); #ifdef CONFIG_OF -static const struct of_device_id st1232_ts_dt_ids[] __devinitconst = { +static const struct of_device_id st1232_ts_dt_ids[] = { { .compatible = "sitronix,st1232", }, { } }; @@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); static struct i2c_driver st1232_ts_driver = { .probe = st1232_ts_probe, - .remove = __devexit_p(st1232_ts_remove), + .remove = st1232_ts_remove, .id_table = st1232_ts_id, .driver = { .name = ST1232_TS_NAME, diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c index 692b685720ce..59e81b00f244 100644 --- a/drivers/input/touchscreen/stmpe-ts.c +++ b/drivers/input/touchscreen/stmpe-ts.c @@ -1,4 +1,5 @@ -/* STMicroelectronics STMPE811 Touchscreen Driver +/* + * STMicroelectronics STMPE811 Touchscreen Driver * * (C) 2010 Luotao Fu <l.fu@pengutronix.de> * All rights reserved. @@ -16,6 +17,7 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/input.h> #include <linux/slab.h> @@ -118,6 +120,7 @@ static void stmpe_work(struct work_struct *work) __stmpe_reset_fifo(ts->stmpe); input_report_abs(ts->idev, ABS_PRESSURE, 0); + input_report_key(ts->idev, BTN_TOUCH, 0); input_sync(ts->idev); } @@ -151,6 +154,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) input_report_abs(ts->idev, ABS_X, x); input_report_abs(ts->idev, ABS_Y, y); input_report_abs(ts->idev, ABS_PRESSURE, z); + input_report_key(ts->idev, BTN_TOUCH, 1); input_sync(ts->idev); /* flush the FIFO after we have read out our values. */ @@ -166,7 +170,7 @@ static irqreturn_t stmpe_ts_handler(int irq, void *data) return IRQ_HANDLED; } -static int __devinit stmpe_init_hw(struct stmpe_touch *ts) +static int stmpe_init_hw(struct stmpe_touch *ts) { int ret; u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask; @@ -261,41 +265,18 @@ static void stmpe_ts_close(struct input_dev *dev) STMPE_TSC_CTRL_TSC_EN, 0); } -static int __devinit stmpe_input_probe(struct platform_device *pdev) +static void stmpe_ts_get_platform_info(struct platform_device *pdev, + struct stmpe_touch *ts) { struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent); - struct stmpe_platform_data *pdata = stmpe->pdata; - struct stmpe_touch *ts; - struct input_dev *idev; + struct device_node *np = pdev->dev.of_node; struct stmpe_ts_platform_data *ts_pdata = NULL; - int ret; - int ts_irq; - - ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); - if (ts_irq < 0) - return ts_irq; - - ts = kzalloc(sizeof(*ts), GFP_KERNEL); - if (!ts) { - ret = -ENOMEM; - goto err_out; - } - idev = input_allocate_device(); - if (!idev) { - ret = -ENOMEM; - goto err_free_ts; - } - - platform_set_drvdata(pdev, ts); ts->stmpe = stmpe; - ts->idev = idev; - ts->dev = &pdev->dev; - if (pdata) - ts_pdata = pdata->ts; + if (stmpe->pdata && stmpe->pdata->ts) { + ts_pdata = stmpe->pdata->ts; - if (ts_pdata) { ts->sample_time = ts_pdata->sample_time; ts->mod_12b = ts_pdata->mod_12b; ts->ref_sel = ts_pdata->ref_sel; @@ -305,22 +286,71 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev) ts->settling = ts_pdata->settling; ts->fraction_z = ts_pdata->fraction_z; ts->i_drive = ts_pdata->i_drive; + } else if (np) { + u32 val; + + if (!of_property_read_u32(np, "st,sample-time", &val)) + ts->sample_time = val; + if (!of_property_read_u32(np, "st,mod-12b", &val)) + ts->mod_12b = val; + if (!of_property_read_u32(np, "st,ref-sel", &val)) + ts->ref_sel = val; + if (!of_property_read_u32(np, "st,adc-freq", &val)) + ts->adc_freq = val; + if (!of_property_read_u32(np, "st,ave-ctrl", &val)) + ts->ave_ctrl = val; + if (!of_property_read_u32(np, "st,touch-det-delay", &val)) + ts->touch_det_delay = val; + if (!of_property_read_u32(np, "st,settling", &val)) + ts->settling = val; + if (!of_property_read_u32(np, "st,fraction-z", &val)) + ts->fraction_z = val; + if (!of_property_read_u32(np, "st,i-drive", &val)) + ts->i_drive = val; } +} + +static int stmpe_input_probe(struct platform_device *pdev) +{ + struct stmpe_touch *ts; + struct input_dev *idev; + int error; + int ts_irq; + + ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); + if (ts_irq < 0) + return ts_irq; + + ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + idev = devm_input_allocate_device(&pdev->dev); + if (!idev) + return -ENOMEM; + + platform_set_drvdata(pdev, ts); + ts->idev = idev; + ts->dev = &pdev->dev; + + stmpe_ts_get_platform_info(pdev, ts); INIT_DELAYED_WORK(&ts->work, stmpe_work); - ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler, - IRQF_ONESHOT, STMPE_TS_NAME, ts); - if (ret) { + error = devm_request_threaded_irq(&pdev->dev, ts_irq, + NULL, stmpe_ts_handler, + IRQF_ONESHOT, STMPE_TS_NAME, ts); + if (error) { dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq); - goto err_free_input; + return error; } - ret = stmpe_init_hw(ts); - if (ret) - goto err_free_irq; + error = stmpe_init_hw(ts); + if (error) + return error; idev->name = STMPE_TS_NAME; + idev->phys = STMPE_TS_NAME"/input0"; idev->id.bustype = BUS_I2C; idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); @@ -334,40 +364,21 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev) input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0); input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0); - ret = input_register_device(idev); - if (ret) { + error = input_register_device(idev); + if (error) { dev_err(&pdev->dev, "Could not register input device\n"); - goto err_free_irq; + return error; } - return ret; - -err_free_irq: - free_irq(ts_irq, ts); -err_free_input: - input_free_device(idev); - platform_set_drvdata(pdev, NULL); -err_free_ts: - kfree(ts); -err_out: - return ret; + return 0; } -static int __devexit stmpe_ts_remove(struct platform_device *pdev) +static int stmpe_ts_remove(struct platform_device *pdev) { struct stmpe_touch *ts = platform_get_drvdata(pdev); - unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN); - free_irq(ts_irq, ts); - - platform_set_drvdata(pdev, NULL); - - input_unregister_device(ts->idev); - - kfree(ts); - return 0; } @@ -377,7 +388,7 @@ static struct platform_driver stmpe_ts_driver = { .owner = THIS_MODULE, }, .probe = stmpe_input_probe, - .remove = __devexit_p(stmpe_ts_remove), + .remove = stmpe_ts_remove, }; module_platform_driver(stmpe_ts_driver); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c new file mode 100644 index 000000000000..51e7b87827a4 --- /dev/null +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -0,0 +1,398 @@ +/* + * TI Touch Screen driver + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/input.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/input/ti_am335x_tsc.h> +#include <linux/delay.h> + +#include <linux/mfd/ti_am335x_tscadc.h> + +#define ADCFSM_STEPID 0x10 +#define SEQ_SETTLE 275 +#define MAX_12BIT ((1 << 12) - 1) + +struct titsc { + struct input_dev *input; + struct ti_tscadc_dev *mfd_tscadc; + unsigned int irq; + unsigned int wires; + unsigned int x_plate_resistance; + bool pen_down; + int steps_to_configure; +}; + +static unsigned int titsc_readl(struct titsc *ts, unsigned int reg) +{ + return readl(ts->mfd_tscadc->tscadc_base + reg); +} + +static void titsc_writel(struct titsc *tsc, unsigned int reg, + unsigned int val) +{ + writel(val, tsc->mfd_tscadc->tscadc_base + reg); +} + +static void titsc_step_config(struct titsc *ts_dev) +{ + unsigned int config; + int i, total_steps; + + /* Configure the Step registers */ + total_steps = 2 * ts_dev->steps_to_configure; + + config = STEPCONFIG_MODE_HWSYNC | + STEPCONFIG_AVG_16 | STEPCONFIG_XPP; + switch (ts_dev->wires) { + case 4: + config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + break; + case 5: + config |= STEPCONFIG_YNN | + STEPCONFIG_INP_AN4 | STEPCONFIG_XNN | + STEPCONFIG_YPP; + break; + case 8: + config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN; + break; + } + + for (i = 1; i <= ts_dev->steps_to_configure; i++) { + titsc_writel(ts_dev, REG_STEPCONFIG(i), config); + titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); + } + + config = 0; + config = STEPCONFIG_MODE_HWSYNC | + STEPCONFIG_AVG_16 | STEPCONFIG_YNN | + STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1; + switch (ts_dev->wires) { + case 4: + config |= STEPCONFIG_YPP; + break; + case 5: + config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 | + STEPCONFIG_XNP | STEPCONFIG_YPN; + break; + case 8: + config |= STEPCONFIG_YPP; + break; + } + + for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) { + titsc_writel(ts_dev, REG_STEPCONFIG(i), config); + titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); + } + + config = 0; + /* Charge step configuration */ + config = STEPCONFIG_XPP | STEPCONFIG_YNN | + STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR | + STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1; + + titsc_writel(ts_dev, REG_CHARGECONFIG, config); + titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); + + config = 0; + /* Configure to calculate pressure */ + config = STEPCONFIG_MODE_HWSYNC | + STEPCONFIG_AVG_16 | STEPCONFIG_YPP | + STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM; + titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config); + titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1), + STEPCONFIG_OPENDLY); + + config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1; + titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config); + titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2), + STEPCONFIG_OPENDLY); + + titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); +} + +static void titsc_read_coordinates(struct titsc *ts_dev, + unsigned int *x, unsigned int *y) +{ + unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT); + unsigned int prev_val_x = ~0, prev_val_y = ~0; + unsigned int prev_diff_x = ~0, prev_diff_y = ~0; + unsigned int read, diff; + unsigned int i, channel; + + /* + * Delta filter is used to remove large variations in sampled + * values from ADC. The filter tries to predict where the next + * coordinate could be. This is done by taking a previous + * coordinate and subtracting it form current one. Further the + * algorithm compares the difference with that of a present value, + * if true the value is reported to the sub system. + */ + for (i = 0; i < fifocount - 1; i++) { + read = titsc_readl(ts_dev, REG_FIFO0); + channel = read & 0xf0000; + channel = channel >> 0x10; + if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) { + read &= 0xfff; + diff = abs(read - prev_val_x); + if (diff < prev_diff_x) { + prev_diff_x = diff; + *x = read; + } + prev_val_x = read; + } + + read = titsc_readl(ts_dev, REG_FIFO1); + channel = read & 0xf0000; + channel = channel >> 0x10; + if ((channel >= ts_dev->steps_to_configure) && + (channel < (2 * ts_dev->steps_to_configure - 1))) { + read &= 0xfff; + diff = abs(read - prev_val_y); + if (diff < prev_diff_y) { + prev_diff_y = diff; + *y = read; + } + prev_val_y = read; + } + } +} + +static irqreturn_t titsc_irq(int irq, void *dev) +{ + struct titsc *ts_dev = dev; + struct input_dev *input_dev = ts_dev->input; + unsigned int status, irqclr = 0; + unsigned int x = 0, y = 0; + unsigned int z1, z2, z; + unsigned int fsm; + unsigned int fifo1count, fifo0count; + int i; + + status = titsc_readl(ts_dev, REG_IRQSTATUS); + if (status & IRQENB_FIFO0THRES) { + titsc_read_coordinates(ts_dev, &x, &y); + + z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff; + z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff; + + fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT); + for (i = 0; i < fifo1count; i++) + titsc_readl(ts_dev, REG_FIFO1); + + fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT); + for (i = 0; i < fifo0count; i++) + titsc_readl(ts_dev, REG_FIFO0); + + if (ts_dev->pen_down && z1 != 0 && z2 != 0) { + /* + * Calculate pressure using formula + * Resistance(touch) = x plate resistance * + * x postion/4096 * ((z2 / z1) - 1) + */ + z = z2 - z1; + z *= x; + z *= ts_dev->x_plate_resistance; + z /= z1; + z = (z + 2047) >> 12; + + if (z <= MAX_12BIT) { + input_report_abs(input_dev, ABS_X, x); + input_report_abs(input_dev, ABS_Y, y); + input_report_abs(input_dev, ABS_PRESSURE, z); + input_report_key(input_dev, BTN_TOUCH, 1); + input_sync(input_dev); + } + } + irqclr |= IRQENB_FIFO0THRES; + } + + /* + * Time for sequencer to settle, to read + * correct state of the sequencer. + */ + udelay(SEQ_SETTLE); + + status = titsc_readl(ts_dev, REG_RAWIRQSTATUS); + if (status & IRQENB_PENUP) { + /* Pen up event */ + fsm = titsc_readl(ts_dev, REG_ADCFSM); + if (fsm == ADCFSM_STEPID) { + ts_dev->pen_down = false; + input_report_key(input_dev, BTN_TOUCH, 0); + input_report_abs(input_dev, ABS_PRESSURE, 0); + input_sync(input_dev); + } else { + ts_dev->pen_down = true; + } + irqclr |= IRQENB_PENUP; + } + + titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); + + titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC); + return IRQ_HANDLED; +} + +/* + * The functions for inserting/removing driver as a module. + */ + +static int titsc_probe(struct platform_device *pdev) +{ + struct titsc *ts_dev; + struct input_dev *input_dev; + struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct mfd_tscadc_board *pdata; + int err; + + pdata = tscadc_dev->dev->platform_data; + + if (!pdata) { + dev_err(&pdev->dev, "Could not find platform data\n"); + return -EINVAL; + } + + /* Allocate memory for device */ + ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!ts_dev || !input_dev) { + dev_err(&pdev->dev, "failed to allocate memory.\n"); + err = -ENOMEM; + goto err_free_mem; + } + + tscadc_dev->tsc = ts_dev; + ts_dev->mfd_tscadc = tscadc_dev; + ts_dev->input = input_dev; + ts_dev->irq = tscadc_dev->irq; + ts_dev->wires = pdata->tsc_init->wires; + ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance; + ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure; + + err = request_irq(ts_dev->irq, titsc_irq, + 0, pdev->dev.driver->name, ts_dev); + if (err) { + dev_err(&pdev->dev, "failed to allocate irq.\n"); + goto err_free_mem; + } + + titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); + titsc_step_config(ts_dev); + titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure); + + input_dev->name = "ti-tsc"; + input_dev->dev.parent = &pdev->dev; + + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); + + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); + + /* register to the input system */ + err = input_register_device(input_dev); + if (err) + goto err_free_irq; + + platform_set_drvdata(pdev, ts_dev); + return 0; + +err_free_irq: + free_irq(ts_dev->irq, ts_dev); +err_free_mem: + input_free_device(input_dev); + kfree(ts_dev); + return err; +} + +static int titsc_remove(struct platform_device *pdev) +{ + struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data; + struct titsc *ts_dev = tscadc_dev->tsc; + + free_irq(ts_dev->irq, ts_dev); + + input_unregister_device(ts_dev->input); + + platform_set_drvdata(pdev, NULL); + kfree(ts_dev); + return 0; +} + +#ifdef CONFIG_PM +static int titsc_suspend(struct device *dev) +{ + struct ti_tscadc_dev *tscadc_dev = dev->platform_data; + struct titsc *ts_dev = tscadc_dev->tsc; + unsigned int idle; + + if (device_may_wakeup(tscadc_dev->dev)) { + idle = titsc_readl(ts_dev, REG_IRQENABLE); + titsc_writel(ts_dev, REG_IRQENABLE, + (idle | IRQENB_HW_PEN)); + titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); + } + return 0; +} + +static int titsc_resume(struct device *dev) +{ + struct ti_tscadc_dev *tscadc_dev = dev->platform_data; + struct titsc *ts_dev = tscadc_dev->tsc; + + if (device_may_wakeup(tscadc_dev->dev)) { + titsc_writel(ts_dev, REG_IRQWAKEUP, + 0x00); + titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN); + } + titsc_step_config(ts_dev); + titsc_writel(ts_dev, REG_FIFO0THR, + ts_dev->steps_to_configure); + return 0; +} + +static const struct dev_pm_ops titsc_pm_ops = { + .suspend = titsc_suspend, + .resume = titsc_resume, +}; +#define TITSC_PM_OPS (&titsc_pm_ops) +#else +#define TITSC_PM_OPS NULL +#endif + +static struct platform_driver ti_tsc_driver = { + .probe = titsc_probe, + .remove = titsc_remove, + .driver = { + .name = "tsc", + .owner = THIS_MODULE, + .pm = TITSC_PM_OPS, + }, +}; +module_platform_driver(ti_tsc_driver); + +MODULE_DESCRIPTION("TI touchscreen controller driver"); +MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c deleted file mode 100644 index d229c741d544..000000000000 --- a/drivers/input/touchscreen/ti_tscadc.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * TI Touch Screen driver - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any - * kind, whether express or implied; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/input/ti_tscadc.h> -#include <linux/delay.h> - -#define REG_IRQEOI 0x020 -#define REG_RAWIRQSTATUS 0x024 -#define REG_IRQSTATUS 0x028 -#define REG_IRQENABLE 0x02C -#define REG_IRQWAKEUP 0x034 -#define REG_CTRL 0x040 -#define REG_ADCFSM 0x044 -#define REG_CLKDIV 0x04C -#define REG_SE 0x054 -#define REG_IDLECONFIG 0x058 -#define REG_CHARGECONFIG 0x05C -#define REG_CHARGEDELAY 0x060 -#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8)) -#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8)) -#define REG_STEPCONFIG13 0x0C4 -#define REG_STEPDELAY13 0x0C8 -#define REG_STEPCONFIG14 0x0CC -#define REG_STEPDELAY14 0x0D0 -#define REG_FIFO0CNT 0xE4 -#define REG_FIFO1THR 0xF4 -#define REG_FIFO0 0x100 -#define REG_FIFO1 0x200 - -/* Register Bitfields */ -#define IRQWKUP_ENB BIT(0) -#define STPENB_STEPENB 0x7FFF -#define IRQENB_FIFO1THRES BIT(5) -#define IRQENB_PENUP BIT(9) -#define STEPCONFIG_MODE_HWSYNC 0x2 -#define STEPCONFIG_SAMPLES_AVG (1 << 4) -#define STEPCONFIG_XPP (1 << 5) -#define STEPCONFIG_XNN (1 << 6) -#define STEPCONFIG_YPP (1 << 7) -#define STEPCONFIG_YNN (1 << 8) -#define STEPCONFIG_XNP (1 << 9) -#define STEPCONFIG_YPN (1 << 10) -#define STEPCONFIG_INM (1 << 18) -#define STEPCONFIG_INP (1 << 20) -#define STEPCONFIG_INP_5 (1 << 21) -#define STEPCONFIG_FIFO1 (1 << 26) -#define STEPCONFIG_OPENDLY 0xff -#define STEPCONFIG_Z1 (3 << 19) -#define STEPIDLE_INP (1 << 22) -#define STEPCHARGE_RFP (1 << 12) -#define STEPCHARGE_INM (1 << 15) -#define STEPCHARGE_INP (1 << 19) -#define STEPCHARGE_RFM (1 << 23) -#define STEPCHARGE_DELAY 0x1 -#define CNTRLREG_TSCSSENB (1 << 0) -#define CNTRLREG_STEPID (1 << 1) -#define CNTRLREG_STEPCONFIGWRT (1 << 2) -#define CNTRLREG_4WIRE (1 << 5) -#define CNTRLREG_5WIRE (1 << 6) -#define CNTRLREG_8WIRE (3 << 5) -#define CNTRLREG_TSCENB (1 << 7) -#define ADCFSM_STEPID 0x10 - -#define SEQ_SETTLE 275 -#define ADC_CLK 3000000 -#define MAX_12BIT ((1 << 12) - 1) -#define TSCADC_DELTA_X 15 -#define TSCADC_DELTA_Y 15 - -struct tscadc { - struct input_dev *input; - struct clk *tsc_ick; - void __iomem *tsc_base; - unsigned int irq; - unsigned int wires; - unsigned int x_plate_resistance; - bool pen_down; -}; - -static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg) -{ - return readl(ts->tsc_base + reg); -} - -static void tscadc_writel(struct tscadc *tsc, unsigned int reg, - unsigned int val) -{ - writel(val, tsc->tsc_base + reg); -} - -static void tscadc_step_config(struct tscadc *ts_dev) -{ - unsigned int config; - int i; - - /* Configure the Step registers */ - - config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP; - switch (ts_dev->wires) { - case 4: - config |= STEPCONFIG_INP | STEPCONFIG_XNN; - break; - case 5: - config |= STEPCONFIG_YNN | - STEPCONFIG_INP_5 | STEPCONFIG_XNN | - STEPCONFIG_YPP; - break; - case 8: - config |= STEPCONFIG_INP | STEPCONFIG_XNN; - break; - } - - for (i = 1; i < 7; i++) { - tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); - tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); - } - - config = 0; - config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN | - STEPCONFIG_INM | STEPCONFIG_FIFO1; - switch (ts_dev->wires) { - case 4: - config |= STEPCONFIG_YPP; - break; - case 5: - config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 | - STEPCONFIG_XNP | STEPCONFIG_YPN; - break; - case 8: - config |= STEPCONFIG_YPP; - break; - } - - for (i = 7; i < 13; i++) { - tscadc_writel(ts_dev, REG_STEPCONFIG(i), config); - tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); - } - - config = 0; - /* Charge step configuration */ - config = STEPCONFIG_XPP | STEPCONFIG_YNN | - STEPCHARGE_RFP | STEPCHARGE_RFM | - STEPCHARGE_INM | STEPCHARGE_INP; - - tscadc_writel(ts_dev, REG_CHARGECONFIG, config); - tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY); - - config = 0; - /* Configure to calculate pressure */ - config = STEPCONFIG_MODE_HWSYNC | - STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP | - STEPCONFIG_XNN | STEPCONFIG_INM; - tscadc_writel(ts_dev, REG_STEPCONFIG13, config); - tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY); - - config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1; - tscadc_writel(ts_dev, REG_STEPCONFIG14, config); - tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY); - - tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); -} - -static void tscadc_idle_config(struct tscadc *ts_config) -{ - unsigned int idleconfig; - - idleconfig = STEPCONFIG_YNN | - STEPCONFIG_INM | - STEPCONFIG_YPN | STEPIDLE_INP; - tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig); -} - -static void tscadc_read_coordinates(struct tscadc *ts_dev, - unsigned int *x, unsigned int *y) -{ - unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT); - unsigned int prev_val_x = ~0, prev_val_y = ~0; - unsigned int prev_diff_x = ~0, prev_diff_y = ~0; - unsigned int read, diff; - unsigned int i; - - /* - * Delta filter is used to remove large variations in sampled - * values from ADC. The filter tries to predict where the next - * coordinate could be. This is done by taking a previous - * coordinate and subtracting it form current one. Further the - * algorithm compares the difference with that of a present value, - * if true the value is reported to the sub system. - */ - for (i = 0; i < fifocount - 1; i++) { - read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; - diff = abs(read - prev_val_x); - if (diff < prev_diff_x) { - prev_diff_x = diff; - *x = read; - } - prev_val_x = read; - - read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; - diff = abs(read - prev_val_y); - if (diff < prev_diff_y) { - prev_diff_y = diff; - *y = read; - } - prev_val_y = read; - } -} - -static irqreturn_t tscadc_irq(int irq, void *dev) -{ - struct tscadc *ts_dev = dev; - struct input_dev *input_dev = ts_dev->input; - unsigned int status, irqclr = 0; - unsigned int x = 0, y = 0; - unsigned int z1, z2, z; - unsigned int fsm; - - status = tscadc_readl(ts_dev, REG_IRQSTATUS); - if (status & IRQENB_FIFO1THRES) { - tscadc_read_coordinates(ts_dev, &x, &y); - - z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff; - z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff; - - if (ts_dev->pen_down && z1 != 0 && z2 != 0) { - /* - * Calculate pressure using formula - * Resistance(touch) = x plate resistance * - * x postion/4096 * ((z2 / z1) - 1) - */ - z = z2 - z1; - z *= x; - z *= ts_dev->x_plate_resistance; - z /= z1; - z = (z + 2047) >> 12; - - if (z <= MAX_12BIT) { - input_report_abs(input_dev, ABS_X, x); - input_report_abs(input_dev, ABS_Y, y); - input_report_abs(input_dev, ABS_PRESSURE, z); - input_report_key(input_dev, BTN_TOUCH, 1); - input_sync(input_dev); - } - } - irqclr |= IRQENB_FIFO1THRES; - } - - /* - * Time for sequencer to settle, to read - * correct state of the sequencer. - */ - udelay(SEQ_SETTLE); - - status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS); - if (status & IRQENB_PENUP) { - /* Pen up event */ - fsm = tscadc_readl(ts_dev, REG_ADCFSM); - if (fsm == ADCFSM_STEPID) { - ts_dev->pen_down = false; - input_report_key(input_dev, BTN_TOUCH, 0); - input_report_abs(input_dev, ABS_PRESSURE, 0); - input_sync(input_dev); - } else { - ts_dev->pen_down = true; - } - irqclr |= IRQENB_PENUP; - } - - tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr); - /* check pending interrupts */ - tscadc_writel(ts_dev, REG_IRQEOI, 0x0); - - tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB); - return IRQ_HANDLED; -} - -/* - * The functions for inserting/removing driver as a module. - */ - -static int __devinit tscadc_probe(struct platform_device *pdev) -{ - const struct tsc_data *pdata = pdev->dev.platform_data; - struct resource *res; - struct tscadc *ts_dev; - struct input_dev *input_dev; - struct clk *clk; - int err; - int clk_value, ctrl, irq; - - if (!pdata) { - dev_err(&pdev->dev, "missing platform data.\n"); - return -EINVAL; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no memory resource defined.\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq ID is specified.\n"); - return -EINVAL; - } - - /* Allocate memory for device */ - ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ts_dev || !input_dev) { - dev_err(&pdev->dev, "failed to allocate memory.\n"); - err = -ENOMEM; - goto err_free_mem; - } - - ts_dev->input = input_dev; - ts_dev->irq = irq; - ts_dev->wires = pdata->wires; - ts_dev->x_plate_resistance = pdata->x_plate_resistance; - - res = request_mem_region(res->start, resource_size(res), pdev->name); - if (!res) { - dev_err(&pdev->dev, "failed to reserve registers.\n"); - err = -EBUSY; - goto err_free_mem; - } - - ts_dev->tsc_base = ioremap(res->start, resource_size(res)); - if (!ts_dev->tsc_base) { - dev_err(&pdev->dev, "failed to map registers.\n"); - err = -ENOMEM; - goto err_release_mem_region; - } - - err = request_irq(ts_dev->irq, tscadc_irq, - 0, pdev->dev.driver->name, ts_dev); - if (err) { - dev_err(&pdev->dev, "failed to allocate irq.\n"); - goto err_unmap_regs; - } - - ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick"); - if (IS_ERR(ts_dev->tsc_ick)) { - dev_err(&pdev->dev, "failed to get TSC ick\n"); - goto err_free_irq; - } - clk_enable(ts_dev->tsc_ick); - - clk = clk_get(&pdev->dev, "adc_tsc_fck"); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "failed to get TSC fck\n"); - err = PTR_ERR(clk); - goto err_disable_clk; - } - - clk_value = clk_get_rate(clk) / ADC_CLK; - clk_put(clk); - - if (clk_value < 7) { - dev_err(&pdev->dev, "clock input less than min clock requirement\n"); - goto err_disable_clk; - } - /* CLKDIV needs to be configured to the value minus 1 */ - tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1); - - /* Enable wake-up of the SoC using touchscreen */ - tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB); - - ctrl = CNTRLREG_STEPCONFIGWRT | - CNTRLREG_TSCENB | - CNTRLREG_STEPID; - switch (ts_dev->wires) { - case 4: - ctrl |= CNTRLREG_4WIRE; - break; - case 5: - ctrl |= CNTRLREG_5WIRE; - break; - case 8: - ctrl |= CNTRLREG_8WIRE; - break; - } - tscadc_writel(ts_dev, REG_CTRL, ctrl); - - tscadc_idle_config(ts_dev); - tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES); - tscadc_step_config(ts_dev); - tscadc_writel(ts_dev, REG_FIFO1THR, 6); - - ctrl |= CNTRLREG_TSCSSENB; - tscadc_writel(ts_dev, REG_CTRL, ctrl); - - input_dev->name = "ti-tsc-adc"; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0); - - /* register to the input system */ - err = input_register_device(input_dev); - if (err) - goto err_disable_clk; - - platform_set_drvdata(pdev, ts_dev); - return 0; - -err_disable_clk: - clk_disable(ts_dev->tsc_ick); - clk_put(ts_dev->tsc_ick); -err_free_irq: - free_irq(ts_dev->irq, ts_dev); -err_unmap_regs: - iounmap(ts_dev->tsc_base); -err_release_mem_region: - release_mem_region(res->start, resource_size(res)); -err_free_mem: - input_free_device(input_dev); - kfree(ts_dev); - return err; -} - -static int __devexit tscadc_remove(struct platform_device *pdev) -{ - struct tscadc *ts_dev = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(ts_dev->irq, ts_dev); - - input_unregister_device(ts_dev->input); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(ts_dev->tsc_base); - release_mem_region(res->start, resource_size(res)); - - clk_disable(ts_dev->tsc_ick); - clk_put(ts_dev->tsc_ick); - - kfree(ts_dev); - - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver ti_tsc_driver = { - .probe = tscadc_probe, - .remove = __devexit_p(tscadc_remove), - .driver = { - .name = "tsc", - .owner = THIS_MODULE, - }, -}; -module_platform_driver(ti_tsc_driver); - -MODULE_DESCRIPTION("TI touchscreen controller driver"); -MODULE_AUTHOR("Rachna Patil <rachna@ti.com>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index 368d2c6cf780..acfb87607b87 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -243,7 +243,7 @@ static void tsc_stop(struct input_dev *dev) clk_disable(ts->clk); } -static int __devinit tsc_probe(struct platform_device *pdev) +static int tsc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct tsc_data *ts; @@ -357,7 +357,7 @@ error_res: return error; } -static int __devexit tsc_remove(struct platform_device *pdev) +static int tsc_remove(struct platform_device *pdev) { struct tsc_data *ts = platform_get_drvdata(pdev); @@ -374,7 +374,7 @@ static int __devexit tsc_remove(struct platform_device *pdev) static struct platform_driver tsc_driver = { .probe = tsc_probe, - .remove = __devexit_p(tsc_remove), + .remove = tsc_remove, .driver.name = "tnetv107x-ts", .driver.owner = THIS_MODULE, }; diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c index f7eda3d00fad..820a066c3b8a 100644 --- a/drivers/input/touchscreen/tps6507x-ts.c +++ b/drivers/input/touchscreen/tps6507x-ts.c @@ -345,7 +345,7 @@ err0: return error; } -static int __devexit tps6507x_ts_remove(struct platform_device *pdev) +static int tps6507x_ts_remove(struct platform_device *pdev) { struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); struct tps6507x_ts *tsc = tps6507x_dev->ts; @@ -367,7 +367,7 @@ static struct platform_driver tps6507x_ts_driver = { .owner = THIS_MODULE, }, .probe = tps6507x_ts_probe, - .remove = __devexit_p(tps6507x_ts_remove), + .remove = tps6507x_ts_remove, }; module_platform_driver(tps6507x_ts_driver); diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index 5ce3fa8ce646..7213e8b07e79 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -555,7 +555,7 @@ static void tsc2005_close(struct input_dev *input) mutex_unlock(&ts->mutex); } -static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) +static void tsc2005_setup_spi_xfer(struct tsc2005 *ts) { tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false); tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false); @@ -569,7 +569,7 @@ static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts) spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg); } -static int __devinit tsc2005_probe(struct spi_device *spi) +static int tsc2005_probe(struct spi_device *spi) { const struct tsc2005_platform_data *pdata = spi->dev.platform_data; struct tsc2005 *ts; @@ -686,7 +686,7 @@ err_free_mem: return error; } -static int __devexit tsc2005_remove(struct spi_device *spi) +static int tsc2005_remove(struct spi_device *spi) { struct tsc2005 *ts = spi_get_drvdata(spi); @@ -745,7 +745,7 @@ static struct spi_driver tsc2005_driver = { .pm = &tsc2005_pm_ops, }, .probe = tsc2005_probe, - .remove = __devexit_p(tsc2005_remove), + .remove = tsc2005_remove, }; module_spi_driver(tsc2005_driver); @@ -753,3 +753,4 @@ module_spi_driver(tsc2005_driver); MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>"); MODULE_DESCRIPTION("TSC2005 Touchscreen Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("spi:tsc2005"); diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 1473d2382afd..0b67ba476b4c 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -273,7 +273,7 @@ static void tsc2007_close(struct input_dev *input_dev) tsc2007_stop(ts); } -static int __devinit tsc2007_probe(struct i2c_client *client, +static int tsc2007_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tsc2007 *ts; @@ -366,7 +366,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client, return err; } -static int __devexit tsc2007_remove(struct i2c_client *client) +static int tsc2007_remove(struct i2c_client *client) { struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; @@ -396,7 +396,7 @@ static struct i2c_driver tsc2007_driver = { }, .id_table = tsc2007_idtable, .probe = tsc2007_probe, - .remove = __devexit_p(tsc2007_remove), + .remove = tsc2007_remove, }; module_i2c_driver(tsc2007_driver); diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 46e83ad53f43..1271f97b4079 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c @@ -274,7 +274,7 @@ static void ucb1400_ts_close(struct input_dev *idev) * Try to probe our interrupt, rather than relying on lots of * hard-coded machine dependencies. */ -static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, +static int ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, struct platform_device *pdev) { unsigned long mask, timeout; @@ -318,7 +318,7 @@ static int __devinit ucb1400_ts_detect_irq(struct ucb1400_ts *ucb, return 0; } -static int __devinit ucb1400_ts_probe(struct platform_device *pdev) +static int ucb1400_ts_probe(struct platform_device *pdev) { struct ucb1400_ts *ucb = pdev->dev.platform_data; int error, x_res, y_res; @@ -397,7 +397,7 @@ err: return error; } -static int __devexit ucb1400_ts_remove(struct platform_device *pdev) +static int ucb1400_ts_remove(struct platform_device *pdev) { struct ucb1400_ts *ucb = pdev->dev.platform_data; @@ -442,7 +442,7 @@ static SIMPLE_DEV_PM_OPS(ucb1400_ts_pm_ops, static struct platform_driver ucb1400_ts_driver = { .probe = ucb1400_ts_probe, - .remove = __devexit_p(ucb1400_ts_remove), + .remove = ucb1400_ts_remove, .driver = { .name = "ucb1400_ts", .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 9396b21d0e8f..d2ef8f05c66e 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c @@ -215,7 +215,7 @@ static void w90p910_close(struct input_dev *dev) clk_disable(w90p910_ts->clk); } -static int __devinit w90x900ts_probe(struct platform_device *pdev) +static int w90x900ts_probe(struct platform_device *pdev) { struct w90p910_ts *w90p910_ts; struct input_dev *input_dev; @@ -301,7 +301,7 @@ fail1: input_free_device(input_dev); return err; } -static int __devexit w90x900ts_remove(struct platform_device *pdev) +static int w90x900ts_remove(struct platform_device *pdev) { struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev); struct resource *res; @@ -325,7 +325,7 @@ static int __devexit w90x900ts_remove(struct platform_device *pdev) static struct platform_driver w90x900ts_driver = { .probe = w90x900ts_probe, - .remove = __devexit_p(w90x900ts_remove), + .remove = w90x900ts_remove, .driver = { .name = "nuc900-ts", .owner = THIS_MODULE, diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index 0c01657132fd..bf0d07620bac 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -144,7 +144,7 @@ static void wacom_i2c_close(struct input_dev *dev) disable_irq(client->irq); } -static int __devinit wacom_i2c_probe(struct i2c_client *client, +static int wacom_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct wacom_i2c *wac_i2c; @@ -225,7 +225,7 @@ err_free_mem: return error; } -static int __devexit wacom_i2c_remove(struct i2c_client *client) +static int wacom_i2c_remove(struct i2c_client *client) { struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); @@ -272,7 +272,7 @@ static struct i2c_driver wacom_i2c_driver = { }, .probe = wacom_i2c_probe, - .remove = __devexit_p(wacom_i2c_remove), + .remove = wacom_i2c_remove, .id_table = wacom_i2c_id, }; module_i2c_driver(wacom_i2c_driver); diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 52abb98a8ae5..6be2eb6a153a 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -233,7 +233,7 @@ static void wm831x_ts_input_close(struct input_dev *idev) } } -static __devinit int wm831x_ts_probe(struct platform_device *pdev) +static int wm831x_ts_probe(struct platform_device *pdev) { struct wm831x_ts *wm831x_ts; struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); @@ -245,8 +245,9 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) if (core_pdata) pdata = core_pdata->touch; - wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL); - input_dev = input_allocate_device(); + wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts), + GFP_KERNEL); + input_dev = devm_input_allocate_device(&pdev->dev); if (!wm831x_ts || !input_dev) { error = -ENOMEM; goto err_alloc; @@ -375,22 +376,17 @@ err_pd_irq: err_data_irq: free_irq(wm831x_ts->data_irq, wm831x_ts); err_alloc: - input_free_device(input_dev); - kfree(wm831x_ts); return error; } -static __devexit int wm831x_ts_remove(struct platform_device *pdev) +static int wm831x_ts_remove(struct platform_device *pdev) { struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev); free_irq(wm831x_ts->pd_irq, wm831x_ts); free_irq(wm831x_ts->data_irq, wm831x_ts); - input_unregister_device(wm831x_ts->input_dev); - kfree(wm831x_ts); - platform_set_drvdata(pdev, NULL); return 0; } @@ -400,7 +396,7 @@ static struct platform_driver wm831x_ts_driver = { .owner = THIS_MODULE, }, .probe = wm831x_ts_probe, - .remove = __devexit_p(wm831x_ts_remove), + .remove = wm831x_ts_remove, }; module_platform_driver(wm831x_ts_driver); |
