From 5a966261c0dfb836f54444ff3893638802183cac Mon Sep 17 00:00:00 2001 From: Tatsunosuke Tobita Date: Sun, 25 Mar 2012 17:23:19 -0700 Subject: Input: add support for Wacom Stylus device with I2C interface This adds support for Wacom Stylus device with I2C interface. [Dan Carpenter : fix NULL-pointer dereference in error handling path.] Signed-off-by: Tatsunosuke Tobita Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 12 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/wacom_i2c.c | 315 ++++++++++++++++++++++++++++++++++ 3 files changed, 328 insertions(+) create mode 100644 drivers/input/touchscreen/wacom_i2c.c (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 97b31a0e052..c5eb2b925be 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -306,6 +306,18 @@ config TOUCHSCREEN_WACOM_W8001 To compile this driver as a module, choose M here: the module will be called wacom_w8001. +config TOUCHSCREEN_WACOM_I2C + tristate "Wacom Tablet support (I2C)" + depends on I2C + help + Say Y here if you want to use the I2C version of the Wacom + Pen Tablet. + + If unsure, say N. + + To compile this driver as a module, choose M here: the module + will be called wacom_i2c. + config TOUCHSCREEN_LPC32XX tristate "LPC32XX touchscreen controller" depends on ARCH_LPC32XX diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 3d5cf8cbf89..7cca7ddb464 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o +obj-$(CONFIG_TOUCHSCREEN_WACOM_I2C) += wacom_i2c.o obj-$(CONFIG_TOUCHSCREEN_WM831X) += wm831x-ts.o obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c new file mode 100644 index 00000000000..b8ca4a6bc91 --- /dev/null +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -0,0 +1,315 @@ +/* + * Wacom Penabled Driver for I2C + * + * Copyright (c) 2011 Tatsunosuke Tobita, Wacom. + * + * + * 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 of 2 of the License, + * or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define WACOM_CMD_QUERY0 0x04 +#define WACOM_CMD_QUERY1 0x00 +#define WACOM_CMD_QUERY2 0x33 +#define WACOM_CMD_QUERY3 0x02 +#define WACOM_CMD_THROW0 0x05 +#define WACOM_CMD_THROW1 0x00 +#define WACOM_QUERY_SIZE 19 +#define WACOM_RETRY_CNT 100 + +struct wacom_features { + int x_max; + int y_max; + int pressure_max; + char fw_version; +}; + +struct wacom_i2c { + struct i2c_client *client; + struct input_dev *input; + unsigned int gpio; + u8 data[WACOM_QUERY_SIZE]; +}; + +static int wacom_query_device(struct i2c_client *client, + struct wacom_features *features) +{ + int ret; + u8 cmd1[] = { WACOM_CMD_QUERY0, WACOM_CMD_QUERY1, + WACOM_CMD_QUERY2, WACOM_CMD_QUERY3 }; + u8 cmd2[] = { WACOM_CMD_THROW0, WACOM_CMD_THROW1 }; + u8 data[WACOM_QUERY_SIZE]; + struct i2c_msg msgs[] = { + { + .addr = client->addr, + .flags = 0, + .len = sizeof(cmd1), + .buf = cmd1, + }, + { + .addr = client->addr, + .flags = 0, + .len = sizeof(cmd2), + .buf = cmd2, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = sizeof(data), + .buf = data, + }, + }; + + ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret < 0) + return ret; + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + features->x_max = get_unaligned_le16(&data[3]); + features->y_max = get_unaligned_le16(&data[5]); + features->pressure_max = get_unaligned_le16(&data[11]); + features->fw_version = get_unaligned_le16(&data[13]); + + dev_dbg(&client->dev, + "x_max:%d, y_max:%d, pressure:%d, fw:%d\n", + features->x_max, features->y_max, + features->pressure_max, features->fw_version); + + return 0; +} + +static int wacom_i2c_fetch_data(struct wacom_i2c *wac_i2c) +{ + int retries = 0; + int ret; + + do { + ret = i2c_master_recv(wac_i2c->client, + wac_i2c->data, sizeof(wac_i2c->data)); + } while (gpio_get_value(wac_i2c->gpio) == 0 && + retries++ < WACOM_RETRY_CNT); + + if (retries >= WACOM_RETRY_CNT) + ret = -EIO; + + return ret < 0 ? ret : 0; +} + +static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) +{ + struct wacom_i2c *wac_i2c = dev_id; + struct input_dev *input = wac_i2c->input; + u8 *data = wac_i2c->data; + unsigned int x, y, pressure; + unsigned char tsw, f1, f2, ers; + int error; + + error = wacom_i2c_fetch_data(wac_i2c); + if (error) + goto out; + + tsw = data[3] & 0x01; + ers = data[3] & 0x04; + f1 = data[3] & 0x02; + f2 = data[3] & 0x10; + x = le16_to_cpup((__le16 *)&data[4]); + y = le16_to_cpup((__le16 *)&data[6]); + pressure = le16_to_cpup((__le16 *)&data[8]); + + input_report_key(input, BTN_TOUCH, tsw || ers); + input_report_key(input, BTN_TOOL_PEN, tsw); + input_report_key(input, BTN_TOOL_RUBBER, ers); + input_report_key(input, BTN_STYLUS, f1); + input_report_key(input, BTN_STYLUS2, f2); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, pressure); + input_sync(input); + +out: + return IRQ_HANDLED; +} + +static int wacom_i2c_open(struct input_dev *dev) +{ + struct wacom_i2c *wac_i2c = input_get_drvdata(dev); + struct i2c_client *client = wac_i2c->client; + int error; + + /* Clear the device buffer */ + error = wacom_i2c_fetch_data(wac_i2c); + if (error) + return error; + + enable_irq(client->irq); + + return 0; +} + +static void wacom_i2c_close(struct input_dev *dev) +{ + struct wacom_i2c *wac_i2c = input_get_drvdata(dev); + struct i2c_client *client = wac_i2c->client; + + disable_irq(client->irq); +} + +static int __devinit wacom_i2c_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct wacom_i2c *wac_i2c; + struct input_dev *input; + struct wacom_features features; + int gpio; + int error; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "i2c_check_functionality error\n"); + return -EIO; + } + + gpio = irq_to_gpio(client->irq); + if (gpio < 0) { + error = gpio; + dev_err(&client->dev, + "irq_to_gpio() failed, error: %d\n", error); + return error; + } + + error = wacom_query_device(client, &features); + if (error) + return error; + + wac_i2c = kzalloc(sizeof(*wac_i2c), GFP_KERNEL); + input = input_allocate_device(); + if (!wac_i2c || !input) { + error = -ENOMEM; + goto err_free_mem; + } + + wac_i2c->client = client; + wac_i2c->input = input; + wac_i2c->gpio = gpio; + + input->name = "Wacom I2C Digitizer"; + input->id.bustype = BUS_I2C; + input->id.vendor = 0x56a; + input->id.version = features.fw_version; + input->dev.parent = &client->dev; + input->open = wacom_i2c_open; + input->close = wacom_i2c_close; + + input->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + __set_bit(BTN_TOOL_PEN, input->keybit); + __set_bit(BTN_TOOL_RUBBER, input->keybit); + __set_bit(BTN_STYLUS, input->keybit); + __set_bit(BTN_STYLUS2, input->keybit); + __set_bit(BTN_TOUCH, input->keybit); + + input_set_abs_params(input, ABS_X, 0, features.x_max, 0, 0); + input_set_abs_params(input, ABS_Y, 0, features.y_max, 0, 0); + input_set_abs_params(input, ABS_PRESSURE, + 0, features.pressure_max, 0, 0); + + input_set_drvdata(input, wac_i2c); + + error = request_threaded_irq(client->irq, NULL, wacom_i2c_irq, + IRQF_TRIGGER_FALLING, + "wacom_i2c", wac_i2c); + if (error) { + dev_err(&client->dev, + "Failed to enable IRQ, error: %d\n", error); + goto err_free_mem; + } + + /* Disable the IRQ, we'll enable it in wac_i2c_open() */ + disable_irq(client->irq); + + error = input_register_device(wac_i2c->input); + if (error) { + dev_err(&client->dev, + "Failed to register input device, error: %d\n", error); + goto err_free_irq; + } + + i2c_set_clientdata(client, wac_i2c); + return 0; + +err_free_irq: + free_irq(client->irq, wac_i2c); +err_free_mem: + input_free_device(input); + kfree(wac_i2c); + + return error; +} + +static int __devexit wacom_i2c_remove(struct i2c_client *client) +{ + struct wacom_i2c *wac_i2c = i2c_get_clientdata(client); + + free_irq(client->irq, wac_i2c); + input_unregister_device(wac_i2c->input); + kfree(wac_i2c); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int wacom_i2c_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + disable_irq(client->irq); + + return 0; +} + +static int wacom_i2c_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + + enable_irq(client->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(wacom_i2c_pm, wacom_i2c_suspend, wacom_i2c_resume); + +static const struct i2c_device_id wacom_i2c_id[] = { + { "WAC_I2C_EMR", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(i2c, wacom_i2c_id); + +static struct i2c_driver wacom_i2c_driver = { + .driver = { + .name = "wacom_i2c", + .owner = THIS_MODULE, + .pm = &wacom_i2c_pm, + }, + + .probe = wacom_i2c_probe, + .remove = __devexit_p(wacom_i2c_remove), + .id_table = wacom_i2c_id, +}; +module_i2c_driver(wacom_i2c_driver); + +MODULE_AUTHOR("Tatsunosuke Tobita "); +MODULE_DESCRIPTION("WACOM EMR I2C Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-18-g5258 From e6293d2f8a6cd427a1ef4ddecb16b1d5ae1929cd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 3 Apr 2012 11:30:28 -0700 Subject: Input: st1232 - add device tree support This patch enables DT support for the st1232 driver which is primarily used on the sh7372 Mackerel board. [dtor@mail.ru: chnaged to use CONFIG_OF and of_match_ptr] Signed-off-by: Magnus Damm Acked-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index cbbf71b2269..216fabb5acc 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -255,6 +255,14 @@ 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 = { + { .compatible = "sitronix,st1232", }, + { } +}; +MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); +#endif + static struct i2c_driver st1232_ts_driver = { .probe = st1232_ts_probe, .remove = __devexit_p(st1232_ts_remove), @@ -262,6 +270,7 @@ static struct i2c_driver st1232_ts_driver = { .driver = { .name = ST1232_TS_NAME, .owner = THIS_MODULE, + .of_match_table = of_match_ptr(st1232_ts_dt_ids), #ifdef CONFIG_PM .pm = &st1232_ts_pm_ops, #endif -- cgit v1.2.3-18-g5258 From b3571400395e318306165eabbfbe05a4c3e4366c Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 3 Apr 2012 11:30:28 -0700 Subject: Input: st1232 - switch to using SIMPLE_DEV_PM_OPS Acked-by: Rafael J. Wysocki Reviewed-by: Simon Horman Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/st1232.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index 216fabb5acc..6cb68a1981b 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -218,7 +218,7 @@ static int __devexit st1232_ts_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int st1232_ts_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -243,12 +243,11 @@ static int st1232_ts_resume(struct device *dev) return 0; } -static const struct dev_pm_ops st1232_ts_pm_ops = { - .suspend = st1232_ts_suspend, - .resume = st1232_ts_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, + st1232_ts_suspend, st1232_ts_resume); + static const struct i2c_device_id st1232_ts_id[] = { { ST1232_TS_NAME, 0 }, { } @@ -271,9 +270,7 @@ static struct i2c_driver st1232_ts_driver = { .name = ST1232_TS_NAME, .owner = THIS_MODULE, .of_match_table = of_match_ptr(st1232_ts_dt_ids), -#ifdef CONFIG_PM .pm = &st1232_ts_pm_ops, -#endif }, }; -- cgit v1.2.3-18-g5258 From 65ac9f7a23c934ee8c40dc20955e75db4924bfea Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 3 Apr 2012 23:50:17 -0700 Subject: Input: serio - use module_serio_driver This patch converts the drivers in drivers/input/* to use module_serio_driver() macro which makes the code smaller and a bit simpler. Signed-off-by: Axel Lin Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/dynapro.c | 17 +---------------- drivers/input/touchscreen/elo.c | 17 +---------------- drivers/input/touchscreen/fujitsu_ts.c | 13 +------------ drivers/input/touchscreen/gunze.c | 17 +---------------- drivers/input/touchscreen/h3600_ts_input.c | 17 +---------------- drivers/input/touchscreen/hampshire.c | 17 +---------------- drivers/input/touchscreen/inexio.c | 17 +---------------- drivers/input/touchscreen/mtouch.c | 17 +---------------- drivers/input/touchscreen/penmount.c | 17 +---------------- drivers/input/touchscreen/touchit213.c | 17 +---------------- drivers/input/touchscreen/touchright.c | 17 +---------------- drivers/input/touchscreen/touchwin.c | 17 +---------------- drivers/input/touchscreen/tsc40.c | 12 +----------- drivers/input/touchscreen/wacom_w8001.c | 13 +------------ 14 files changed, 14 insertions(+), 211 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c index 455353908bd..1809677a651 100644 --- a/drivers/input/touchscreen/dynapro.c +++ b/drivers/input/touchscreen/dynapro.c @@ -188,19 +188,4 @@ static struct serio_driver dynapro_drv = { .disconnect = dynapro_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init dynapro_init(void) -{ - return serio_register_driver(&dynapro_drv); -} - -static void __exit dynapro_exit(void) -{ - serio_unregister_driver(&dynapro_drv); -} - -module_init(dynapro_init); -module_exit(dynapro_exit); +module_serio_driver(dynapro_drv); diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 486d31ba9c0..957423d1471 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -405,19 +405,4 @@ static struct serio_driver elo_drv = { .disconnect = elo_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init elo_init(void) -{ - return serio_register_driver(&elo_drv); -} - -static void __exit elo_exit(void) -{ - serio_unregister_driver(&elo_drv); -} - -module_init(elo_init); -module_exit(elo_exit); +module_serio_driver(elo_drv); diff --git a/drivers/input/touchscreen/fujitsu_ts.c b/drivers/input/touchscreen/fujitsu_ts.c index 80b21800355..10794ddbdf5 100644 --- a/drivers/input/touchscreen/fujitsu_ts.c +++ b/drivers/input/touchscreen/fujitsu_ts.c @@ -175,15 +175,4 @@ static struct serio_driver fujitsu_drv = { .disconnect = fujitsu_disconnect, }; -static int __init fujitsu_init(void) -{ - return serio_register_driver(&fujitsu_drv); -} - -static void __exit fujitsu_exit(void) -{ - serio_unregister_driver(&fujitsu_drv); -} - -module_init(fujitsu_init); -module_exit(fujitsu_exit); +module_serio_driver(fujitsu_drv); diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c index a54f90e02ab..41c71766bf1 100644 --- a/drivers/input/touchscreen/gunze.c +++ b/drivers/input/touchscreen/gunze.c @@ -186,19 +186,4 @@ static struct serio_driver gunze_drv = { .disconnect = gunze_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init gunze_init(void) -{ - return serio_register_driver(&gunze_drv); -} - -static void __exit gunze_exit(void) -{ - serio_unregister_driver(&gunze_drv); -} - -module_init(gunze_init); -module_exit(gunze_exit); +module_serio_driver(gunze_drv); diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 6107e563e68..b9e8686a6f1 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -476,19 +476,4 @@ static struct serio_driver h3600ts_drv = { .disconnect = h3600ts_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init h3600ts_init(void) -{ - return serio_register_driver(&h3600ts_drv); -} - -static void __exit h3600ts_exit(void) -{ - serio_unregister_driver(&h3600ts_drv); -} - -module_init(h3600ts_init); -module_exit(h3600ts_exit); +module_serio_driver(h3600ts_drv); diff --git a/drivers/input/touchscreen/hampshire.c b/drivers/input/touchscreen/hampshire.c index 2da6cc31bb2..0cc47ea98ac 100644 --- a/drivers/input/touchscreen/hampshire.c +++ b/drivers/input/touchscreen/hampshire.c @@ -187,19 +187,4 @@ static struct serio_driver hampshire_drv = { .disconnect = hampshire_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init hampshire_init(void) -{ - return serio_register_driver(&hampshire_drv); -} - -static void __exit hampshire_exit(void) -{ - serio_unregister_driver(&hampshire_drv); -} - -module_init(hampshire_init); -module_exit(hampshire_exit); +module_serio_driver(hampshire_drv); diff --git a/drivers/input/touchscreen/inexio.c b/drivers/input/touchscreen/inexio.c index 192ade0a0fb..a29c99c3224 100644 --- a/drivers/input/touchscreen/inexio.c +++ b/drivers/input/touchscreen/inexio.c @@ -189,19 +189,4 @@ static struct serio_driver inexio_drv = { .disconnect = inexio_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init inexio_init(void) -{ - return serio_register_driver(&inexio_drv); -} - -static void __exit inexio_exit(void) -{ - serio_unregister_driver(&inexio_drv); -} - -module_init(inexio_init); -module_exit(inexio_exit); +module_serio_driver(inexio_drv); diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c index 9077228418b..eb66b7c37c2 100644 --- a/drivers/input/touchscreen/mtouch.c +++ b/drivers/input/touchscreen/mtouch.c @@ -202,19 +202,4 @@ static struct serio_driver mtouch_drv = { .disconnect = mtouch_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init mtouch_init(void) -{ - return serio_register_driver(&mtouch_drv); -} - -static void __exit mtouch_exit(void) -{ - serio_unregister_driver(&mtouch_drv); -} - -module_init(mtouch_init); -module_exit(mtouch_exit); +module_serio_driver(mtouch_drv); diff --git a/drivers/input/touchscreen/penmount.c b/drivers/input/touchscreen/penmount.c index 4c012fb2b01..4ccde45b9da 100644 --- a/drivers/input/touchscreen/penmount.c +++ b/drivers/input/touchscreen/penmount.c @@ -317,19 +317,4 @@ static struct serio_driver pm_drv = { .disconnect = pm_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init pm_init(void) -{ - return serio_register_driver(&pm_drv); -} - -static void __exit pm_exit(void) -{ - serio_unregister_driver(&pm_drv); -} - -module_init(pm_init); -module_exit(pm_exit); +module_serio_driver(pm_drv); diff --git a/drivers/input/touchscreen/touchit213.c b/drivers/input/touchscreen/touchit213.c index d1297ba19da..5f29e5b8e1c 100644 --- a/drivers/input/touchscreen/touchit213.c +++ b/drivers/input/touchscreen/touchit213.c @@ -216,19 +216,4 @@ static struct serio_driver touchit213_drv = { .disconnect = touchit213_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init touchit213_init(void) -{ - return serio_register_driver(&touchit213_drv); -} - -static void __exit touchit213_exit(void) -{ - serio_unregister_driver(&touchit213_drv); -} - -module_init(touchit213_init); -module_exit(touchit213_exit); +module_serio_driver(touchit213_drv); diff --git a/drivers/input/touchscreen/touchright.c b/drivers/input/touchscreen/touchright.c index 3a5c142c2a7..8a2887daf19 100644 --- a/drivers/input/touchscreen/touchright.c +++ b/drivers/input/touchscreen/touchright.c @@ -176,19 +176,4 @@ static struct serio_driver tr_drv = { .disconnect = tr_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init tr_init(void) -{ - return serio_register_driver(&tr_drv); -} - -static void __exit tr_exit(void) -{ - serio_unregister_driver(&tr_drv); -} - -module_init(tr_init); -module_exit(tr_exit); +module_serio_driver(tr_drv); diff --git a/drivers/input/touchscreen/touchwin.c b/drivers/input/touchscreen/touchwin.c index 763a656a59f..588cdcb839d 100644 --- a/drivers/input/touchscreen/touchwin.c +++ b/drivers/input/touchscreen/touchwin.c @@ -183,19 +183,4 @@ static struct serio_driver tw_drv = { .disconnect = tw_disconnect, }; -/* - * The functions for inserting/removing us as a module. - */ - -static int __init tw_init(void) -{ - return serio_register_driver(&tw_drv); -} - -static void __exit tw_exit(void) -{ - serio_unregister_driver(&tw_drv); -} - -module_init(tw_init); -module_exit(tw_exit); +module_serio_driver(tw_drv); diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 29d5ed4dd31..63209aaa55f 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -167,17 +167,7 @@ static struct serio_driver tsc_drv = { .disconnect = tsc_disconnect, }; -static int __init tsc_ser_init(void) -{ - return serio_register_driver(&tsc_drv); -} -module_init(tsc_ser_init); - -static void __exit tsc_exit(void) -{ - serio_unregister_driver(&tsc_drv); -} -module_exit(tsc_exit); +module_serio_driver(tsc_drv); MODULE_AUTHOR("Sebastian Andrzej Siewior "); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 1569a3934ab..8f9ad2f893b 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -594,15 +594,4 @@ static struct serio_driver w8001_drv = { .disconnect = w8001_disconnect, }; -static int __init w8001_init(void) -{ - return serio_register_driver(&w8001_drv); -} - -static void __exit w8001_exit(void) -{ - serio_unregister_driver(&w8001_drv); -} - -module_init(w8001_init); -module_exit(w8001_exit); +module_serio_driver(w8001_drv); -- cgit v1.2.3-18-g5258 From d568778298f58330bcc8cc23845676d1143c8d33 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 10 Apr 2012 00:21:09 -0700 Subject: Input: wacom_i2c - do not use irq_to_gpio Because irq_to_gpio() is not available on many platforms let's switch to level-triggered one-shot IRQs that will stay active as long as there is data to be read. Tested-by: Tobita Tatsunosuke Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_i2c.c | 41 ++++------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/wacom_i2c.c b/drivers/input/touchscreen/wacom_i2c.c index b8ca4a6bc91..35572575d34 100644 --- a/drivers/input/touchscreen/wacom_i2c.c +++ b/drivers/input/touchscreen/wacom_i2c.c @@ -39,7 +39,6 @@ struct wacom_features { struct wacom_i2c { struct i2c_client *client; struct input_dev *input; - unsigned int gpio; u8 data[WACOM_QUERY_SIZE]; }; @@ -91,23 +90,6 @@ static int wacom_query_device(struct i2c_client *client, return 0; } -static int wacom_i2c_fetch_data(struct wacom_i2c *wac_i2c) -{ - int retries = 0; - int ret; - - do { - ret = i2c_master_recv(wac_i2c->client, - wac_i2c->data, sizeof(wac_i2c->data)); - } while (gpio_get_value(wac_i2c->gpio) == 0 && - retries++ < WACOM_RETRY_CNT); - - if (retries >= WACOM_RETRY_CNT) - ret = -EIO; - - return ret < 0 ? ret : 0; -} - static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) { struct wacom_i2c *wac_i2c = dev_id; @@ -117,8 +99,9 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id) unsigned char tsw, f1, f2, ers; int error; - error = wacom_i2c_fetch_data(wac_i2c); - if (error) + error = i2c_master_recv(wac_i2c->client, + wac_i2c->data, sizeof(wac_i2c->data)); + if (error < 0) goto out; tsw = data[3] & 0x01; @@ -147,12 +130,6 @@ static int wacom_i2c_open(struct input_dev *dev) { struct wacom_i2c *wac_i2c = input_get_drvdata(dev); struct i2c_client *client = wac_i2c->client; - int error; - - /* Clear the device buffer */ - error = wacom_i2c_fetch_data(wac_i2c); - if (error) - return error; enable_irq(client->irq); @@ -173,7 +150,6 @@ static int __devinit wacom_i2c_probe(struct i2c_client *client, struct wacom_i2c *wac_i2c; struct input_dev *input; struct wacom_features features; - int gpio; int error; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { @@ -181,14 +157,6 @@ static int __devinit wacom_i2c_probe(struct i2c_client *client, return -EIO; } - gpio = irq_to_gpio(client->irq); - if (gpio < 0) { - error = gpio; - dev_err(&client->dev, - "irq_to_gpio() failed, error: %d\n", error); - return error; - } - error = wacom_query_device(client, &features); if (error) return error; @@ -202,7 +170,6 @@ static int __devinit wacom_i2c_probe(struct i2c_client *client, wac_i2c->client = client; wac_i2c->input = input; - wac_i2c->gpio = gpio; input->name = "Wacom I2C Digitizer"; input->id.bustype = BUS_I2C; @@ -228,7 +195,7 @@ static int __devinit wacom_i2c_probe(struct i2c_client *client, input_set_drvdata(input, wac_i2c); error = request_threaded_irq(client->irq, NULL, wacom_i2c_irq, - IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, "wacom_i2c", wac_i2c); if (error) { dev_err(&client->dev, -- cgit v1.2.3-18-g5258 From 5cb727a86780fcac34de871cd12bea3f744d6be2 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Fri, 20 Apr 2012 23:02:49 -0700 Subject: Input: lpc32xx_ts - add device tree support This change implements device tree support for the LPC32xx SoC's touchscreen controller. Signed-off-by: Roland Stigge Reviewed-by: Thierry Reding Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/lpc32xx_ts.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index afcd0691ec6..e8fccbc452d 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -22,6 +22,7 @@ #include #include #include +#include /* * Touchscreen controller register offsets @@ -383,6 +384,14 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = { #define LPC32XX_TS_PM_OPS NULL #endif +#ifdef CONFIG_OF +static struct of_device_id lpc32xx_tsc_of_match[] = { + { .compatible = "nxp,lpc32xx-tsc", }, + { }, +}; +MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); +#endif + static struct platform_driver lpc32xx_ts_driver = { .probe = lpc32xx_ts_probe, .remove = __devexit_p(lpc32xx_ts_remove), @@ -390,6 +399,7 @@ static struct platform_driver lpc32xx_ts_driver = { .name = MOD_NAME, .owner = THIS_MODULE, .pm = LPC32XX_TS_PM_OPS, + .of_match_table = of_match_ptr(lpc32xx_tsc_of_match), }, }; module_platform_driver(lpc32xx_ts_driver); -- cgit v1.2.3-18-g5258 From 34604086bea11f1f4d7ff124c84dab9b89956837 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 23 Apr 2012 22:26:38 -0700 Subject: Input: lpc32xx_ts - fix device tree compatible string During the device tree integration of the various LPC32xx drivers, we agreed on using non-wildcard "compatible" strings. This change switches lpc32xx_ts touchscreen driver to use "nxp,lpc3220-tsc". Signed-off-by: Roland Stigge Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/lpc32xx_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c index e8fccbc452d..4c2b8ed3bf1 100644 --- a/drivers/input/touchscreen/lpc32xx_ts.c +++ b/drivers/input/touchscreen/lpc32xx_ts.c @@ -386,7 +386,7 @@ static const struct dev_pm_ops lpc32xx_ts_pm_ops = { #ifdef CONFIG_OF static struct of_device_id lpc32xx_tsc_of_match[] = { - { .compatible = "nxp,lpc32xx-tsc", }, + { .compatible = "nxp,lpc3220-tsc", }, { }, }; MODULE_DEVICE_TABLE(of, lpc32xx_tsc_of_match); -- cgit v1.2.3-18-g5258 From 41baf6368ea2c2ad9eca44dbb07490a46202f474 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sun, 29 Apr 2012 22:53:35 -0700 Subject: Input: usbtouchscreen - fix typo Signed-off-by: Shawn Landden Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index ba7c56567ee..148774e03ae 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -756,7 +756,7 @@ config TOUCHSCREEN_USB_EASYTOUCH bool "EasyTouch USB Touch controller device support" if EMBEDDED depends on TOUCHSCREEN_USB_COMPOSITE help - Say Y here if you have a EasyTouch USB Touch controller device support. + Say Y here if you have an EasyTouch USB Touch controller. If unsure, say N. config TOUCHSCREEN_TOUCHIT213 -- cgit v1.2.3-18-g5258 From df052676e534092138f8712c389aa7750d05ba15 Mon Sep 17 00:00:00 2001 From: Shawn Landden Date: Sun, 29 Apr 2012 22:53:35 -0700 Subject: Input: usbtouchscreen - only expose e2i configure option in expert mode as is the case of all other devices supported by usbtouchscreen.c Also list e2i under the composite configure option (TOUCHSCREEN_USB_COMPOSITE) Signed-off-by: Shawn Landden Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 148774e03ae..229135c1dfe 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -647,6 +647,7 @@ config TOUCHSCREEN_USB_COMPOSITE - Zytronic controllers - Elo TouchSystems 2700 IntelliTouch - EasyTouch USB Touch Controller from Data Modul + - e2i (Mimo monitors) Have a look at for a usage description and the required user-space stuff. @@ -733,7 +734,7 @@ config TOUCHSCREEN_USB_ELO config TOUCHSCREEN_USB_E2I default y - bool "e2i Touchscreen controller (e.g. from Mimo 740)" + bool "e2i Touchscreen controller (e.g. from Mimo 740)" if EXPERT depends on TOUCHSCREEN_USB_COMPOSITE config TOUCHSCREEN_USB_ZYTRONIC -- cgit v1.2.3-18-g5258 From eead75a2b4cd635ef2ba399018623358d67343cf Mon Sep 17 00:00:00 2001 From: Ashish Jangam Date: Sun, 29 Apr 2012 23:33:41 -0700 Subject: Input: add support for DA9052/53 touch screen controller This driver adds support for DA9052/53 4-wire resistive ADC interfaced touchscreen controller. DA9052/53 is a multi-function device, therefore this driver depends on DA9052/53 core. This patch is functionally tested on Samsung SMDKV6410. Signed-off-by: David Dajun Chen Signed-off-by: Ashish Jangam Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/Kconfig | 17 ++ drivers/input/touchscreen/Makefile | 1 + drivers/input/touchscreen/da9052_tsi.c | 370 +++++++++++++++++++++++++++++++++ 3 files changed, 388 insertions(+) create mode 100644 drivers/input/touchscreen/da9052_tsi.c (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 229135c1dfe..f67657b2fd5 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -187,6 +187,23 @@ config TOUCHSCREEN_DA9034 Say Y here to enable the support for the touchscreen found on Dialog Semiconductor DA9034 PMIC. + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called da9034-ts. + +config TOUCHSCREEN_DA9052 + tristate "Dialog DA9052/DA9053 TSI" + depends on PMIC_DA9052 + help + Say Y here to support the touchscreen found on Dialog Semiconductor + DA9052-BC and DA9053-AA/Bx PMICs. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called da9052_tsi. + config TOUCHSCREEN_DYNAPRO tristate "Dynapro serial touchscreen" select SERIO diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7cca7ddb464..eb8bfe1c1a4 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C) += cyttsp_i2c.o obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o +obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c new file mode 100644 index 00000000000..e8df341090c --- /dev/null +++ b/drivers/input/touchscreen/da9052_tsi.c @@ -0,0 +1,370 @@ +/* + * TSI driver for Dialog DA9052 + * + * Copyright(c) 2012 Dialog Semiconductor Ltd. + * + * Author: David Dajun Chen + * + * 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 +#include +#include +#include +#include + +#include +#include + +#define TSI_PEN_DOWN_STATUS 0x40 + +struct da9052_tsi { + struct da9052 *da9052; + 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; +}; + +static void da9052_ts_adc_toggle(struct da9052_tsi *tsi, bool on) +{ + da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 0, on); + tsi->adc_on = on; +} + +static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data) +{ + struct da9052_tsi *tsi = 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_ts_adc_toggle(tsi, true); + + schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); + } + + return IRQ_HANDLED; +} + +static void da9052_ts_read(struct da9052_tsi *tsi) +{ + struct input_dev *input = tsi->dev; + int ret; + u16 x, y, z; + u8 v; + + ret = da9052_reg_read(tsi->da9052, DA9052_TSI_X_MSB_REG); + if (ret < 0) + return; + + x = (u16) ret; + + ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Y_MSB_REG); + if (ret < 0) + return; + + y = (u16) ret; + + ret = da9052_reg_read(tsi->da9052, DA9052_TSI_Z_MSB_REG); + if (ret < 0) + return; + + z = (u16) ret; + + ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); + if (ret < 0) + return; + + v = (u8) ret; + + x = ((x << 2) & 0x3fc) | (v & 0x3); + y = ((y << 2) & 0x3fc) | ((v & 0xc) >> 2); + z = ((z << 2) & 0x3fc) | ((v & 0x30) >> 4); + + input_report_key(input, BTN_TOUCH, 1); + input_report_abs(input, ABS_X, x); + input_report_abs(input, ABS_Y, y); + input_report_abs(input, ABS_PRESSURE, z); + input_sync(input); +} + +static irqreturn_t da9052_ts_datardy_irq(int irq, void *data) +{ + struct da9052_tsi *tsi = data; + + da9052_ts_read(tsi); + + return IRQ_HANDLED; +} + +static void da9052_ts_pen_work(struct work_struct *work) +{ + struct da9052_tsi *tsi = container_of(work, struct da9052_tsi, + ts_pen_work.work); + if (!tsi->stopped) { + int ret = da9052_reg_read(tsi->da9052, DA9052_TSI_LSB_REG); + if (ret < 0 || (ret & TSI_PEN_DOWN_STATUS)) { + /* Pen is still DOWN (or read error) */ + schedule_delayed_work(&tsi->ts_pen_work, HZ / 50); + } else { + struct input_dev *input = tsi->dev; + + /* Pen UP */ + da9052_ts_adc_toggle(tsi, false); + + /* Report Pen UP */ + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_sync(input); + + /* + * FIXME: Fixes the unhandled irq issue when quick + * pen down and pen up events occurs + */ + ret = da9052_reg_update(tsi->da9052, + DA9052_EVENT_B_REG, 0xC0, 0xC0); + if (ret < 0) + return; + + /* Mask TSI_READY event and unmask PEN_DOWN event */ + disable_irq(tsi->irq_datardy); + enable_irq(tsi->irq_pendwn); + } + } +} + +static int __devinit da9052_ts_configure_gpio(struct da9052 *da9052) +{ + int error; + + error = da9052_reg_update(da9052, DA9052_GPIO_2_3_REG, 0x30, 0); + if (error < 0) + return error; + + error = da9052_reg_update(da9052, DA9052_GPIO_4_5_REG, 0x33, 0); + if (error < 0) + return error; + + error = da9052_reg_update(da9052, DA9052_GPIO_6_7_REG, 0x33, 0); + if (error < 0) + return error; + + return 0; +} + +static int __devinit da9052_configure_tsi(struct da9052_tsi *tsi) +{ + int error; + + error = da9052_ts_configure_gpio(tsi->da9052); + if (error) + return error; + + /* Measure TSI sample every 1ms */ + error = da9052_reg_update(tsi->da9052, DA9052_ADC_CONT_REG, + 1 << 6, 1 << 6); + if (error < 0) + return error; + + /* TSI_DELAY: 3 slots, TSI_SKIP: 0 slots, TSI_MODE: XYZP */ + error = da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 0xFC, 0xC0); + if (error < 0) + return error; + + /* Supply TSIRef through LD09 */ + error = da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x59); + if (error < 0) + return error; + + return 0; +} + +static int da9052_ts_input_open(struct input_dev *input_dev) +{ + struct da9052_tsi *tsi = input_get_drvdata(input_dev); + + tsi->stopped = false; + mb(); + + /* Unmask PEN_DOWN event */ + enable_irq(tsi->irq_pendwn); + + /* Enable Pen Detect Circuit */ + return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, + 1 << 1, 1 << 1); +} + +static void da9052_ts_input_close(struct input_dev *input_dev) +{ + struct da9052_tsi *tsi = input_get_drvdata(input_dev); + + tsi->stopped = true; + mb(); + disable_irq(tsi->irq_pendwn); + cancel_delayed_work_sync(&tsi->ts_pen_work); + + if (tsi->adc_on) { + disable_irq(tsi->irq_datardy); + da9052_ts_adc_toggle(tsi, false); + + /* + * If ADC was on that means that pendwn IRQ was disabled + * twice and we need to enable it to keep enable/disable + * counter balanced. IRQ is still off though. + */ + enable_irq(tsi->irq_pendwn); + } + + /* 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) +{ + 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) { + error = -ENOMEM; + goto err_free_mem; + } + + 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); + + input_dev->id.version = 0x0101; + input_dev->id.vendor = 0x15B6; + input_dev->id.product = 0x9052; + input_dev->name = "Dialog DA9052 TouchScreen Driver"; + input_dev->dev.parent = &pdev->dev; + input_dev->open = da9052_ts_input_open; + input_dev->close = da9052_ts_input_close; + + __set_bit(EV_ABS, input_dev->evbit); + __set_bit(EV_KEY, input_dev->evbit); + __set_bit(BTN_TOUCH, input_dev->keybit); + + input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); + input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1023, 0, 0); + + input_set_drvdata(input_dev, tsi); + + /* Disable Pen Detect Circuit */ + da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 1 << 1, 0); + + /* 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); + if (error) { + dev_err(tsi->da9052->dev, + "Failed to register PENDWN IRQ %d, error = %d\n", + tsi->irq_pendwn, error); + goto err_free_mem; + } + + error = request_threaded_irq(tsi->irq_datardy, + NULL, da9052_ts_datardy_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + "TSIRDY", tsi); + if (error) { + dev_err(tsi->da9052->dev, + "Failed to register TSIRDY IRQ %d, error = %d\n", + tsi->irq_datardy, error); + goto err_free_pendwn_irq; + } + + /* Mask PEN_DOWN and TSI_READY events */ + disable_irq(tsi->irq_pendwn); + disable_irq(tsi->irq_datardy); + + error = da9052_configure_tsi(tsi); + if (error) + goto err_free_datardy_irq; + + error = input_register_device(tsi->dev); + if (error) + goto err_free_datardy_irq; + + platform_set_drvdata(pdev, tsi); + + return 0; + +err_free_datardy_irq: + free_irq(tsi->irq_datardy, tsi); +err_free_pendwn_irq: + free_irq(tsi->irq_pendwn, tsi); +err_free_mem: + kfree(tsi); + input_free_device(input_dev); + + return error; +} + +static int __devexit 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); + + input_unregister_device(tsi->dev); + kfree(tsi); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver da9052_tsi_driver = { + .probe = da9052_ts_probe, + .remove = __devexit_p(da9052_ts_remove), + .driver = { + .name = "da9052-tsi", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(da9052_tsi_driver); + +MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9052"); +MODULE_AUTHOR("Anthony Olech "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da9052-tsi"); -- cgit v1.2.3-18-g5258 From 3a73c8169e4f56c1161a95985b8489dd04a7bcbe Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Tue, 8 May 2012 22:29:14 -0700 Subject: Input: atmel_mxt_ts - use CONFIG_PM_SLEEP Simple cleanup to use newer PM APIs. Signed-off-by: Daniel Kurtz Reviewed-by: Joonyoung Shim Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 19d4ea65ea0..0a6e368a5a9 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1201,7 +1201,7 @@ static int __devexit mxt_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int mxt_suspend(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -1239,13 +1239,10 @@ static int mxt_resume(struct device *dev) return 0; } - -static const struct dev_pm_ops mxt_pm_ops = { - .suspend = mxt_suspend, - .resume = mxt_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); + static const struct i2c_device_id mxt_id[] = { { "qt602240_ts", 0 }, { "atmel_mxt_ts", 0 }, @@ -1258,9 +1255,7 @@ static struct i2c_driver mxt_driver = { .driver = { .name = "atmel_mxt_ts", .owner = THIS_MODULE, -#ifdef CONFIG_PM .pm = &mxt_pm_ops, -#endif }, .probe = mxt_probe, .remove = __devexit_p(mxt_remove), -- cgit v1.2.3-18-g5258 From 71b3e938cb97f6cf324fb5aaca46d8e400dc38f0 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Tue, 8 May 2012 22:30:14 -0700 Subject: Input: atmel_mxt_ts - only allow root to update firmware Restrict permissions on the update_fw sysfs entry to read only for root only. Also, update object permission to use a macro S_IRUGO macro instead of hard coded 0444. Signed-off-by: Daniel Kurtz Reviewed-by: Joonyoung Shim Acked-by: Nick Dyer Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 0a6e368a5a9..15ae6fd575b 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -1049,8 +1049,8 @@ static ssize_t mxt_update_fw_store(struct device *dev, return count; } -static DEVICE_ATTR(object, 0444, mxt_object_show, NULL); -static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store); +static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL); +static DEVICE_ATTR(update_fw, S_IWUSR, NULL, mxt_update_fw_store); static struct attribute *mxt_attrs[] = { &dev_attr_object.attr, -- cgit v1.2.3-18-g5258 From d1ff320f0a9766a53ae412d96f72bd861a889af6 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Tue, 8 May 2012 22:38:52 -0700 Subject: Input: atmel_mxt_ts - verify object size in mxt_write_object Don't allow writing past the length of an object. Signed-off-by: Daniel Kurtz Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 15ae6fd575b..8f0dc7776e7 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -506,7 +506,7 @@ static int mxt_write_object(struct mxt_data *data, u16 reg; object = mxt_get_object(data, type); - if (!object) + if (!object || offset >= object->size + 1) return -EINVAL; reg = object->start_address; -- cgit v1.2.3-18-g5258 From 822115ff4bd7141a6069dcc17b35dfd823a44dff Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Tue, 8 May 2012 22:40:26 -0700 Subject: Input: atmel_mxt_ts - do not read extra (checksum) byte atmel_mxt devices will send a checksum byte at the end of a message if the MSB of the object address is set. However, since this driver does not set this bit, the checksum byte isn't actually sent, so don't even try to read it. Signed-off-by: Daniel Kurtz Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 8f0dc7776e7..12a6ba2792a 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -236,7 +236,6 @@ struct mxt_object { struct mxt_message { u8 reportid; u8 message[7]; - u8 checksum; }; struct mxt_finger { @@ -336,7 +335,6 @@ static void mxt_dump_message(struct device *dev, dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); - dev_dbg(dev, "checksum:\t0x%x\n", message->checksum); } static int mxt_check_bootloader(struct i2c_client *client, -- cgit v1.2.3-18-g5258 From 6ee3dbf93a895fce7c11d4d79e12beab1beb7860 Mon Sep 17 00:00:00 2001 From: Daniel Kurtz Date: Tue, 8 May 2012 22:40:29 -0700 Subject: Input: atmel_mxt_ts - dump each message on just 1 line Helps ensure all bytes for a single message together in the system log. Signed-off-by: Daniel Kurtz Reviewed-by: Joonyoung Shim Acked-by: Nick Dyer Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/atmel_mxt_ts.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 12a6ba2792a..42e645062c2 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -325,16 +325,12 @@ static bool mxt_object_writable(unsigned int type) } static void mxt_dump_message(struct device *dev, - struct mxt_message *message) + struct mxt_message *message) { - dev_dbg(dev, "reportid:\t0x%x\n", message->reportid); - dev_dbg(dev, "message1:\t0x%x\n", message->message[0]); - dev_dbg(dev, "message2:\t0x%x\n", message->message[1]); - dev_dbg(dev, "message3:\t0x%x\n", message->message[2]); - dev_dbg(dev, "message4:\t0x%x\n", message->message[3]); - dev_dbg(dev, "message5:\t0x%x\n", message->message[4]); - dev_dbg(dev, "message6:\t0x%x\n", message->message[5]); - dev_dbg(dev, "message7:\t0x%x\n", message->message[6]); + dev_dbg(dev, "reportid: %u\tmessage: %02x %02x %02x %02x %02x %02x %02x\n", + message->reportid, message->message[0], message->message[1], + message->message[2], message->message[3], message->message[4], + message->message[5], message->message[6]); } static int mxt_check_bootloader(struct i2c_client *client, -- cgit v1.2.3-18-g5258 From cd99758ba3bde64347a8ece381cbae2fb5c745b2 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 14 May 2012 23:14:24 +0200 Subject: mfd: Convert wm831x to irq_domain The modern idiom is to use irq_domain to allocate interrupts. This is useful partly to allow further infrastructure to be based on the domains and partly because it makes it much easier to allocate virtual interrupts to devices as we don't need to allocate a contiguous range of interrupt numbers. Convert the wm831x driver over to this infrastructure, using a legacy IRQ mapping if an irq_base is specified in platform data and otherwise using a linear mapping, always registering the interrupts even if they won't ever be used. Only boards which need to use the GPIOs as interrupts should need to use an irq_base. This means that we can't use the MFD irq_base management since the unless we're using an explicit irq_base from platform data we can't rely on a linear mapping of interrupts. Instead we need to map things via the irq_domain - provide a conveniencem function wm831x_irq() to save a small amount of typing when doing so. Looking at this I couldn't clearly see anything the MFD core could do to make this nicer. Since we're not supporting device tree yet there's no meaningful advantage if we don't do this conversion in one, the fact that the interrupt resources are used for repeated IP blocks makes accessor functions for the irq_domain more trouble to do than they're worth. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz --- drivers/input/touchscreen/wm831x-ts.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/input/touchscreen') diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 4bc851a9dc3..e83410721e3 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -260,15 +260,16 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) * If we have a direct IRQ use it, otherwise use the interrupt * from the WM831x IRQ controller. */ + wm831x_ts->data_irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, + "TCHDATA")); if (pdata && pdata->data_irq) wm831x_ts->data_irq = pdata->data_irq; - else - wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); + wm831x_ts->pd_irq = wm831x_irq(wm831x, + platform_get_irq_byname(pdev, "TCHPD")); if (pdata && pdata->pd_irq) wm831x_ts->pd_irq = pdata->pd_irq; - else - wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); if (pdata) wm831x_ts->pressure = pdata->pressure; -- cgit v1.2.3-18-g5258