aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 20:14:01 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-06 20:14:01 -0500
commitdb30c70575822cc84d87b5613c19cac24734b99f (patch)
tree82945ad5813bfe6633698233981d270b5f0a310b /drivers/input/touchscreen
parentc861ea2cb2c25c1698734d9b0540a09e253690a1 (diff)
parent9334e90d5ac5ee1fa6d8b75acb7c64a8907787d1 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (29 commits) Input: i8042 - add Dell Vostro 1510 to nomux list Input: gtco - use USB endpoint API Input: add support for Maple controller as a joystick Input: atkbd - broaden the Dell DMI signatures Input: HIL drivers - add MODULE_ALIAS() Input: map_to_7segment.h - convert to __inline__ for userspace Input: add support for enhanced rotary controller on pxa930 and pxa935 Input: add support for trackball on pxa930 and pxa935 Input: add da9034 touchscreen support Input: ads7846 - strict_strtoul takes unsigned long Input: make some variables and functions static Input: add tsc2007 based touchscreen driver Input: psmouse - add module parameters to control OLPC touchpad delays Input: i8042 - add Gigabyte M912 netbook to noloop exception table Input: atkbd - Samsung NC10 key repeat fix Input: atkbd - add keyboard quirk for HP Pavilion ZV6100 laptop Input: libps2 - handle 0xfc responses from devices Input: add support for Wacom W8001 penabled serial touchscreen Input: synaptics - report multi-taps only if supported by the device Input: add joystick driver for Walkera WK-0701 RC transmitter ...
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig32
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/ads7846.c6
-rw-r--r--drivers/input/touchscreen/da9034-ts.c389
-rw-r--r--drivers/input/touchscreen/tsc2007.c381
-rw-r--r--drivers/input/touchscreen/usbtouchscreen.c5
-rw-r--r--drivers/input/touchscreen/wacom_w8001.c325
7 files changed, 1135 insertions, 6 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3d1ab8fa9acc..bb6486a8c070 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -58,6 +58,14 @@ config TOUCHSCREEN_CORGI
58 NOTE: this driver is deprecated, try enable SPI and generic 58 NOTE: this driver is deprecated, try enable SPI and generic
59 ADS7846-based touchscreen driver. 59 ADS7846-based touchscreen driver.
60 60
61config TOUCHSCREEN_DA9034
62 tristate "Touchscreen support for Dialog Semiconductor DA9034"
63 depends on PMIC_DA903X
64 default y
65 help
66 Say Y here to enable the support for the touchscreen found
67 on Dialog Semiconductor DA9034 PMIC.
68
61config TOUCHSCREEN_FUJITSU 69config TOUCHSCREEN_FUJITSU
62 tristate "Fujitsu serial touchscreen" 70 tristate "Fujitsu serial touchscreen"
63 select SERIO 71 select SERIO
@@ -95,6 +103,19 @@ config TOUCHSCREEN_ELO
95 To compile this driver as a module, choose M here: the 103 To compile this driver as a module, choose M here: the
96 module will be called elo. 104 module will be called elo.
97 105
106config TOUCHSCREEN_WACOM_W8001
107 tristate "Wacom W8001 penabled serial touchscreen"
108 select SERIO
109 help
110 Say Y here if you have an Wacom W8001 penabled serial touchscreen
111 connected to your system.
112
113 If unsure, say N.
114
115 To compile this driver as a module, choose M here: the
116 module will be called wacom_w8001.
117
118
98config TOUCHSCREEN_MTOUCH 119config TOUCHSCREEN_MTOUCH
99 tristate "MicroTouch serial touchscreens" 120 tristate "MicroTouch serial touchscreens"
100 select SERIO 121 select SERIO
@@ -376,4 +397,15 @@ config TOUCHSCREEN_TOUCHIT213
376 To compile this driver as a module, choose M here: the 397 To compile this driver as a module, choose M here: the
377 module will be called touchit213. 398 module will be called touchit213.
378 399
400config TOUCHSCREEN_TSC2007
401 tristate "TSC2007 based touchscreens"
402 depends on I2C
403 help
404 Say Y here if you have a TSC2007 based touchscreen.
405
406 If unsure, say N.
407
408 To compile this driver as a module, choose M here: the
409 module will be called tsc2007.
410
379endif 411endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 15cf29079489..d3375aff46fe 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -25,8 +25,11 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
25obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o 25obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
26obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o 26obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
27obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o 27obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
28obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
28obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o 29obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
30obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
29obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o 31obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
32obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
30wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o 33wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
31wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o 34wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
32wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o 35wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index e1ece89fe922..7c27c8b9b6d0 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -472,7 +472,7 @@ static ssize_t ads7846_disable_store(struct device *dev,
472 const char *buf, size_t count) 472 const char *buf, size_t count)
473{ 473{
474 struct ads7846 *ts = dev_get_drvdata(dev); 474 struct ads7846 *ts = dev_get_drvdata(dev);
475 long i; 475 unsigned long i;
476 476
477 if (strict_strtoul(buf, 10, &i)) 477 if (strict_strtoul(buf, 10, &i))
478 return -EINVAL; 478 return -EINVAL;
@@ -559,7 +559,7 @@ static void ads7846_rx(void *ads)
559 if (packet->tc.ignore || Rt > ts->pressure_max) { 559 if (packet->tc.ignore || Rt > ts->pressure_max) {
560#ifdef VERBOSE 560#ifdef VERBOSE
561 pr_debug("%s: ignored %d pressure %d\n", 561 pr_debug("%s: ignored %d pressure %d\n",
562 ts->spi->dev.bus_id, packet->tc.ignore, Rt); 562 dev_name(&ts->spi->dev), packet->tc.ignore, Rt);
563#endif 563#endif
564 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 564 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
565 HRTIMER_MODE_REL); 565 HRTIMER_MODE_REL);
@@ -947,7 +947,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
947 ts->penirq_recheck_delay_usecs = 947 ts->penirq_recheck_delay_usecs =
948 pdata->penirq_recheck_delay_usecs; 948 pdata->penirq_recheck_delay_usecs;
949 949
950 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 950 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
951 951
952 input_dev->name = "ADS784x Touchscreen"; 952 input_dev->name = "ADS784x Touchscreen";
953 input_dev->phys = ts->phys; 953 input_dev->phys = ts->phys;
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c
new file mode 100644
index 000000000000..4342e77814b5
--- /dev/null
+++ b/drivers/input/touchscreen/da9034-ts.c
@@ -0,0 +1,389 @@
1/*
2 * Touchscreen driver for Dialog Semiconductor DA9034
3 *
4 * Copyright (C) 2006-2008 Marvell International Ltd.
5 * Fengwei Yin <fengwei.yin@marvell.com>
6 * Eric Miao <eric.miao@marvell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/platform_device.h>
18#include <linux/input.h>
19#include <linux/mfd/da903x.h>
20
21#define DA9034_MANUAL_CTRL 0x50
22#define DA9034_LDO_ADC_EN (1 << 4)
23
24#define DA9034_AUTO_CTRL1 0x51
25
26#define DA9034_AUTO_CTRL2 0x52
27#define DA9034_AUTO_TSI_EN (1 << 3)
28#define DA9034_PEN_DETECT (1 << 4)
29
30#define DA9034_TSI_CTRL1 0x53
31#define DA9034_TSI_CTRL2 0x54
32#define DA9034_TSI_X_MSB 0x6c
33#define DA9034_TSI_Y_MSB 0x6d
34#define DA9034_TSI_XY_LSB 0x6e
35
36enum {
37 STATE_IDLE, /* wait for pendown */
38 STATE_BUSY, /* TSI busy sampling */
39 STATE_STOP, /* sample available */
40 STATE_WAIT, /* Wait to start next sample */
41};
42
43enum {
44 EVENT_PEN_DOWN,
45 EVENT_PEN_UP,
46 EVENT_TSI_READY,
47 EVENT_TIMEDOUT,
48};
49
50struct da9034_touch {
51 struct device *da9034_dev;
52 struct input_dev *input_dev;
53
54 struct delayed_work tsi_work;
55 struct notifier_block notifier;
56
57 int state;
58
59 int interval_ms;
60 int x_inverted;
61 int y_inverted;
62
63 int last_x;
64 int last_y;
65};
66
67static inline int is_pen_down(struct da9034_touch *touch)
68{
69 return da903x_query_status(touch->da9034_dev, DA9034_STATUS_PEN_DOWN);
70}
71
72static inline int detect_pen_down(struct da9034_touch *touch, int on)
73{
74 if (on)
75 return da903x_set_bits(touch->da9034_dev,
76 DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
77 else
78 return da903x_clr_bits(touch->da9034_dev,
79 DA9034_AUTO_CTRL2, DA9034_PEN_DETECT);
80}
81
82static int read_tsi(struct da9034_touch *touch)
83{
84 uint8_t _x, _y, _v;
85 int ret;
86
87 ret = da903x_read(touch->da9034_dev, DA9034_TSI_X_MSB, &_x);
88 if (ret)
89 return ret;
90
91 ret = da903x_read(touch->da9034_dev, DA9034_TSI_Y_MSB, &_y);
92 if (ret)
93 return ret;
94
95 ret = da903x_read(touch->da9034_dev, DA9034_TSI_XY_LSB, &_v);
96 if (ret)
97 return ret;
98
99 touch->last_x = ((_x << 2) & 0x3fc) | (_v & 0x3);
100 touch->last_y = ((_y << 2) & 0x3fc) | ((_v & 0xc) >> 2);
101
102 return 0;
103}
104
105static inline int start_tsi(struct da9034_touch *touch)
106{
107 return da903x_set_bits(touch->da9034_dev,
108 DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
109}
110
111static inline int stop_tsi(struct da9034_touch *touch)
112{
113 return da903x_clr_bits(touch->da9034_dev,
114 DA9034_AUTO_CTRL2, DA9034_AUTO_TSI_EN);
115}
116
117static inline void report_pen_down(struct da9034_touch *touch)
118{
119 int x = touch->last_x;
120 int y = touch->last_y;
121
122 x &= 0xfff;
123 if (touch->x_inverted)
124 x = 1024 - x;
125 y &= 0xfff;
126 if (touch->y_inverted)
127 y = 1024 - y;
128
129 input_report_abs(touch->input_dev, ABS_X, x);
130 input_report_abs(touch->input_dev, ABS_Y, y);
131 input_report_key(touch->input_dev, BTN_TOUCH, 1);
132
133 input_sync(touch->input_dev);
134}
135
136static inline void report_pen_up(struct da9034_touch *touch)
137{
138 input_report_key(touch->input_dev, BTN_TOUCH, 0);
139 input_sync(touch->input_dev);
140}
141
142static void da9034_event_handler(struct da9034_touch *touch, int event)
143{
144 int err;
145
146 switch (touch->state) {
147 case STATE_IDLE:
148 if (event != EVENT_PEN_DOWN)
149 break;
150
151 /* Enable auto measurement of the TSI, this will
152 * automatically disable pen down detection
153 */
154 err = start_tsi(touch);
155 if (err)
156 goto err_reset;
157
158 touch->state = STATE_BUSY;
159 break;
160
161 case STATE_BUSY:
162 if (event != EVENT_TSI_READY)
163 break;
164
165 err = read_tsi(touch);
166 if (err)
167 goto err_reset;
168
169 /* Disable auto measurement of the TSI, so that
170 * pen down status will be available
171 */
172 err = stop_tsi(touch);
173 if (err)
174 goto err_reset;
175
176 touch->state = STATE_STOP;
177 break;
178
179 case STATE_STOP:
180 if (event == EVENT_PEN_DOWN) {
181 report_pen_down(touch);
182 schedule_delayed_work(&touch->tsi_work,
183 msecs_to_jiffies(touch->interval_ms));
184 touch->state = STATE_WAIT;
185 }
186
187 if (event == EVENT_PEN_UP) {
188 report_pen_up(touch);
189 touch->state = STATE_IDLE;
190 }
191
192 input_sync(touch->input_dev);
193 break;
194
195 case STATE_WAIT:
196 if (event != EVENT_TIMEDOUT)
197 break;
198
199 if (is_pen_down(touch)) {
200 start_tsi(touch);
201 touch->state = STATE_BUSY;
202 } else
203 touch->state = STATE_IDLE;
204 break;
205 }
206 return;
207
208err_reset:
209 touch->state = STATE_IDLE;
210 stop_tsi(touch);
211 detect_pen_down(touch, 1);
212}
213
214static void da9034_tsi_work(struct work_struct *work)
215{
216 struct da9034_touch *touch =
217 container_of(work, struct da9034_touch, tsi_work.work);
218
219 da9034_event_handler(touch, EVENT_TIMEDOUT);
220}
221
222static int da9034_touch_notifier(struct notifier_block *nb,
223 unsigned long event, void *data)
224{
225 struct da9034_touch *touch =
226 container_of(nb, struct da9034_touch, notifier);
227
228 if (event & DA9034_EVENT_PEN_DOWN) {
229 if (is_pen_down(touch))
230 da9034_event_handler(touch, EVENT_PEN_DOWN);
231 else
232 da9034_event_handler(touch, EVENT_PEN_UP);
233 }
234
235 if (event & DA9034_EVENT_TSI_READY)
236 da9034_event_handler(touch, EVENT_TSI_READY);
237
238 return 0;
239}
240
241static int da9034_touch_open(struct input_dev *dev)
242{
243 struct da9034_touch *touch = input_get_drvdata(dev);
244 int ret;
245
246 ret = da903x_register_notifier(touch->da9034_dev, &touch->notifier,
247 DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
248 if (ret)
249 return -EBUSY;
250
251 /* Enable ADC LDO */
252 ret = da903x_set_bits(touch->da9034_dev,
253 DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
254 if (ret)
255 return ret;
256
257 /* TSI_DELAY: 3 slots, TSI_SKIP: 3 slots */
258 ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL1, 0x1b);
259 if (ret)
260 return ret;
261
262 ret = da903x_write(touch->da9034_dev, DA9034_TSI_CTRL2, 0x00);
263 if (ret)
264 return ret;
265
266 touch->state = STATE_IDLE;
267 detect_pen_down(touch, 1);
268
269 return 0;
270}
271
272static void da9034_touch_close(struct input_dev *dev)
273{
274 struct da9034_touch *touch = input_get_drvdata(dev);
275
276 da903x_unregister_notifier(touch->da9034_dev, &touch->notifier,
277 DA9034_EVENT_PEN_DOWN | DA9034_EVENT_TSI_READY);
278
279 cancel_delayed_work_sync(&touch->tsi_work);
280
281 touch->state = STATE_IDLE;
282 stop_tsi(touch);
283 detect_pen_down(touch, 0);
284
285 /* Disable ADC LDO */
286 da903x_clr_bits(touch->da9034_dev,
287 DA9034_MANUAL_CTRL, DA9034_LDO_ADC_EN);
288}
289
290
291static int __devinit da9034_touch_probe(struct platform_device *pdev)
292{
293 struct da9034_touch_pdata *pdata = pdev->dev.platform_data;
294 struct da9034_touch *touch;
295 struct input_dev *input_dev;
296 int ret;
297
298 touch = kzalloc(sizeof(struct da9034_touch), GFP_KERNEL);
299 if (touch == NULL) {
300 dev_err(&pdev->dev, "failed to allocate driver data\n");
301 return -ENOMEM;
302 }
303
304 touch->da9034_dev = pdev->dev.parent;
305
306 if (pdata) {
307 touch->interval_ms = pdata->interval_ms;
308 touch->x_inverted = pdata->x_inverted;
309 touch->y_inverted = pdata->y_inverted;
310 } else
311 /* fallback into default */
312 touch->interval_ms = 10;
313
314 INIT_DELAYED_WORK(&touch->tsi_work, da9034_tsi_work);
315 touch->notifier.notifier_call = da9034_touch_notifier;
316
317 input_dev = input_allocate_device();
318 if (!input_dev) {
319 dev_err(&pdev->dev, "failed to allocate input device\n");
320 ret = -ENOMEM;
321 goto err_free_touch;
322 }
323
324 input_dev->name = pdev->name;
325 input_dev->open = da9034_touch_open;
326 input_dev->close = da9034_touch_close;
327 input_dev->dev.parent = &pdev->dev;
328
329 __set_bit(EV_ABS, input_dev->evbit);
330 __set_bit(ABS_X, input_dev->absbit);
331 __set_bit(ABS_Y, input_dev->absbit);
332 input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0);
333 input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0);
334
335 __set_bit(EV_KEY, input_dev->evbit);
336 __set_bit(BTN_TOUCH, input_dev->keybit);
337
338 touch->input_dev = input_dev;
339 input_set_drvdata(input_dev, touch);
340
341 ret = input_register_device(input_dev);
342 if (ret)
343 goto err_free_input;
344
345 platform_set_drvdata(pdev, touch);
346 return 0;
347
348err_free_input:
349 input_free_device(input_dev);
350err_free_touch:
351 kfree(touch);
352 return ret;
353}
354
355static int __devexit da9034_touch_remove(struct platform_device *pdev)
356{
357 struct da9034_touch *touch = platform_get_drvdata(pdev);
358
359 input_unregister_device(touch->input_dev);
360 kfree(touch);
361
362 return 0;
363}
364
365static struct platform_driver da9034_touch_driver = {
366 .driver = {
367 .name = "da9034-touch",
368 .owner = THIS_MODULE,
369 },
370 .probe = da9034_touch_probe,
371 .remove = __devexit_p(da9034_touch_remove),
372};
373
374static int __init da9034_touch_init(void)
375{
376 return platform_driver_register(&da9034_touch_driver);
377}
378module_init(da9034_touch_init);
379
380static void __exit da9034_touch_exit(void)
381{
382 platform_driver_unregister(&da9034_touch_driver);
383}
384module_exit(da9034_touch_exit);
385
386MODULE_DESCRIPTION("Touchscreen driver for Dialog Semiconductor DA9034");
387MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
388MODULE_LICENSE("GPL");
389MODULE_ALIAS("platform:da9034-touch");
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
new file mode 100644
index 000000000000..b75dc2990574
--- /dev/null
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -0,0 +1,381 @@
1/*
2 * drivers/input/touchscreen/tsc2007.c
3 *
4 * Copyright (c) 2008 MtekVision Co., Ltd.
5 * Kwangwoo Lee <kwlee@mtekvision.com>
6 *
7 * Using code from:
8 * - ads7846.c
9 * Copyright (c) 2005 David Brownell
10 * Copyright (c) 2006 Nokia Corporation
11 * - corgi_ts.c
12 * Copyright (C) 2004-2005 Richard Purdie
13 * - omap_ts.[hc], ads7846.h, ts_osk.c
14 * Copyright (C) 2002 MontaVista Software
15 * Copyright (C) 2004 Texas Instruments
16 * Copyright (C) 2005 Dirk Behme
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2 as
20 * published by the Free Software Foundation.
21 */
22
23#include <linux/module.h>
24#include <linux/hrtimer.h>
25#include <linux/slab.h>
26#include <linux/input.h>
27#include <linux/interrupt.h>
28#include <linux/i2c.h>
29#include <linux/i2c/tsc2007.h>
30
31#define TS_POLL_DELAY (10 * 1000) /* ns delay before the first sample */
32#define TS_POLL_PERIOD (5 * 1000) /* ns delay between samples */
33
34#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
35#define TSC2007_MEASURE_AUX (0x2 << 4)
36#define TSC2007_MEASURE_TEMP1 (0x4 << 4)
37#define TSC2007_ACTIVATE_XN (0x8 << 4)
38#define TSC2007_ACTIVATE_YN (0x9 << 4)
39#define TSC2007_ACTIVATE_YP_XN (0xa << 4)
40#define TSC2007_SETUP (0xb << 4)
41#define TSC2007_MEASURE_X (0xc << 4)
42#define TSC2007_MEASURE_Y (0xd << 4)
43#define TSC2007_MEASURE_Z1 (0xe << 4)
44#define TSC2007_MEASURE_Z2 (0xf << 4)
45
46#define TSC2007_POWER_OFF_IRQ_EN (0x0 << 2)
47#define TSC2007_ADC_ON_IRQ_DIS0 (0x1 << 2)
48#define TSC2007_ADC_OFF_IRQ_EN (0x2 << 2)
49#define TSC2007_ADC_ON_IRQ_DIS1 (0x3 << 2)
50
51#define TSC2007_12BIT (0x0 << 1)
52#define TSC2007_8BIT (0x1 << 1)
53
54#define MAX_12BIT ((1 << 12) - 1)
55
56#define ADC_ON_12BIT (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0)
57
58#define READ_Y (ADC_ON_12BIT | TSC2007_MEASURE_Y)
59#define READ_Z1 (ADC_ON_12BIT | TSC2007_MEASURE_Z1)
60#define READ_Z2 (ADC_ON_12BIT | TSC2007_MEASURE_Z2)
61#define READ_X (ADC_ON_12BIT | TSC2007_MEASURE_X)
62#define PWRDOWN (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
63
64struct ts_event {
65 u16 x;
66 u16 y;
67 u16 z1, z2;
68};
69
70struct tsc2007 {
71 struct input_dev *input;
72 char phys[32];
73 struct hrtimer timer;
74 struct ts_event tc;
75
76 struct i2c_client *client;
77
78 spinlock_t lock;
79
80 u16 model;
81 u16 x_plate_ohms;
82
83 unsigned pendown;
84 int irq;
85
86 int (*get_pendown_state)(void);
87 void (*clear_penirq)(void);
88};
89
90static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
91{
92 s32 data;
93 u16 val;
94
95 data = i2c_smbus_read_word_data(tsc->client, cmd);
96 if (data < 0) {
97 dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
98 return data;
99 }
100
101 /* The protocol and raw data format from i2c interface:
102 * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
103 * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
104 */
105 val = swab16(data) >> 4;
106
107 dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
108
109 return val;
110}
111
112static void tsc2007_send_event(void *tsc)
113{
114 struct tsc2007 *ts = tsc;
115 u32 rt;
116 u16 x, y, z1, z2;
117
118 x = ts->tc.x;
119 y = ts->tc.y;
120 z1 = ts->tc.z1;
121 z2 = ts->tc.z2;
122
123 /* range filtering */
124 if (x == MAX_12BIT)
125 x = 0;
126
127 if (likely(x && z1)) {
128 /* compute touch pressure resistance using equation #1 */
129 rt = z2;
130 rt -= z1;
131 rt *= x;
132 rt *= ts->x_plate_ohms;
133 rt /= z1;
134 rt = (rt + 2047) >> 12;
135 } else
136 rt = 0;
137
138 /* Sample found inconsistent by debouncing or pressure is beyond
139 * the maximum. Don't report it to user space, repeat at least
140 * once more the measurement
141 */
142 if (rt > MAX_12BIT) {
143 dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
144
145 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
146 HRTIMER_MODE_REL);
147 return;
148 }
149
150 /* NOTE: We can't rely on the pressure to determine the pen down
151 * state, even this controller has a pressure sensor. The pressure
152 * value can fluctuate for quite a while after lifting the pen and
153 * in some cases may not even settle at the expected value.
154 *
155 * The only safe way to check for the pen up condition is in the
156 * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
157 */
158 if (rt) {
159 struct input_dev *input = ts->input;
160
161 if (!ts->pendown) {
162 dev_dbg(&ts->client->dev, "DOWN\n");
163
164 input_report_key(input, BTN_TOUCH, 1);
165 ts->pendown = 1;
166 }
167
168 input_report_abs(input, ABS_X, x);
169 input_report_abs(input, ABS_Y, y);
170 input_report_abs(input, ABS_PRESSURE, rt);
171
172 input_sync(input);
173
174 dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
175 x, y, rt);
176 }
177
178 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
179 HRTIMER_MODE_REL);
180}
181
182static int tsc2007_read_values(struct tsc2007 *tsc)
183{
184 /* y- still on; turn on only y+ (and ADC) */
185 tsc->tc.y = tsc2007_xfer(tsc, READ_Y);
186
187 /* turn y- off, x+ on, then leave in lowpower */
188 tsc->tc.x = tsc2007_xfer(tsc, READ_X);
189
190 /* turn y+ off, x- on; we'll use formula #1 */
191 tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1);
192 tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2);
193
194 /* power down */
195 tsc2007_xfer(tsc, PWRDOWN);
196
197 return 0;
198}
199
200static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
201{
202 struct tsc2007 *ts = container_of(handle, struct tsc2007, timer);
203
204 spin_lock_irq(&ts->lock);
205
206 if (unlikely(!ts->get_pendown_state() && ts->pendown)) {
207 struct input_dev *input = ts->input;
208
209 dev_dbg(&ts->client->dev, "UP\n");
210
211 input_report_key(input, BTN_TOUCH, 0);
212 input_report_abs(input, ABS_PRESSURE, 0);
213 input_sync(input);
214
215 ts->pendown = 0;
216 enable_irq(ts->irq);
217 } else {
218 /* pen is still down, continue with the measurement */
219 dev_dbg(&ts->client->dev, "pen is still down\n");
220
221 tsc2007_read_values(ts);
222 tsc2007_send_event(ts);
223 }
224
225 spin_unlock_irq(&ts->lock);
226
227 return HRTIMER_NORESTART;
228}
229
230static irqreturn_t tsc2007_irq(int irq, void *handle)
231{
232 struct tsc2007 *ts = handle;
233 unsigned long flags;
234
235 spin_lock_irqsave(&ts->lock, flags);
236
237 if (likely(ts->get_pendown_state())) {
238 disable_irq(ts->irq);
239 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
240 HRTIMER_MODE_REL);
241 }
242
243 if (ts->clear_penirq)
244 ts->clear_penirq();
245
246 spin_unlock_irqrestore(&ts->lock, flags);
247
248 return IRQ_HANDLED;
249}
250
251static int tsc2007_probe(struct i2c_client *client,
252 const struct i2c_device_id *id)
253{
254 struct tsc2007 *ts;
255 struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
256 struct input_dev *input_dev;
257 int err;
258
259 if (!pdata) {
260 dev_err(&client->dev, "platform data is required!\n");
261 return -EINVAL;
262 }
263
264 if (!i2c_check_functionality(client->adapter,
265 I2C_FUNC_SMBUS_READ_WORD_DATA))
266 return -EIO;
267
268 ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
269 input_dev = input_allocate_device();
270 if (!ts || !input_dev) {
271 err = -ENOMEM;
272 goto err_free_mem;
273 }
274
275 ts->client = client;
276 i2c_set_clientdata(client, ts);
277
278 ts->input = input_dev;
279
280 hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
281 ts->timer.function = tsc2007_timer;
282
283 spin_lock_init(&ts->lock);
284
285 ts->model = pdata->model;
286 ts->x_plate_ohms = pdata->x_plate_ohms;
287 ts->get_pendown_state = pdata->get_pendown_state;
288 ts->clear_penirq = pdata->clear_penirq;
289
290 pdata->init_platform_hw();
291
292 snprintf(ts->phys, sizeof(ts->phys), "%s/input0", client->dev.bus_id);
293
294 input_dev->name = "TSC2007 Touchscreen";
295 input_dev->phys = ts->phys;
296 input_dev->id.bustype = BUS_I2C;
297
298 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
299 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
300
301 input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
302 input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
303 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
304
305 tsc2007_read_values(ts);
306
307 ts->irq = client->irq;
308
309 err = request_irq(ts->irq, tsc2007_irq, 0,
310 client->dev.driver->name, ts);
311 if (err < 0) {
312 dev_err(&client->dev, "irq %d busy?\n", ts->irq);
313 goto err_free_mem;
314 }
315
316 err = input_register_device(input_dev);
317 if (err)
318 goto err_free_irq;
319
320 dev_info(&client->dev, "registered with irq (%d)\n", ts->irq);
321
322 return 0;
323
324 err_free_irq:
325 free_irq(ts->irq, ts);
326 hrtimer_cancel(&ts->timer);
327 err_free_mem:
328 input_free_device(input_dev);
329 kfree(ts);
330 return err;
331}
332
333static int tsc2007_remove(struct i2c_client *client)
334{
335 struct tsc2007 *ts = i2c_get_clientdata(client);
336 struct tsc2007_platform_data *pdata;
337
338 pdata = client->dev.platform_data;
339 pdata->exit_platform_hw();
340
341 free_irq(ts->irq, ts);
342 hrtimer_cancel(&ts->timer);
343 input_unregister_device(ts->input);
344 kfree(ts);
345
346 return 0;
347}
348
349static struct i2c_device_id tsc2007_idtable[] = {
350 { "tsc2007", 0 },
351 { }
352};
353
354MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
355
356static struct i2c_driver tsc2007_driver = {
357 .driver = {
358 .owner = THIS_MODULE,
359 .name = "tsc2007"
360 },
361 .id_table = tsc2007_idtable,
362 .probe = tsc2007_probe,
363 .remove = tsc2007_remove,
364};
365
366static int __init tsc2007_init(void)
367{
368 return i2c_add_driver(&tsc2007_driver);
369}
370
371static void __exit tsc2007_exit(void)
372{
373 i2c_del_driver(&tsc2007_driver);
374}
375
376module_init(tsc2007_init);
377module_exit(tsc2007_exit);
378
379MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
380MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");
381MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index fdd645c214a2..5080b26ba160 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -424,7 +424,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
424 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 424 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
425 if (ret < 0) 425 if (ret < 0)
426 goto err_out; 426 goto err_out;
427 if (buf[0] != 0x06 || buf[1] != 0x00) { 427 if (buf[0] != 0x06) {
428 ret = -ENODEV; 428 ret = -ENODEV;
429 goto err_out; 429 goto err_out;
430 } 430 }
@@ -437,8 +437,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
437 TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); 437 TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
438 if (ret < 0) 438 if (ret < 0)
439 goto err_out; 439 goto err_out;
440 if ((buf[0] != 0x06 || buf[1] != 0x00) && 440 if ((buf[0] != 0x06) && (buf[0] != 0x15 || buf[1] != 0x01)) {
441 (buf[0] != 0x15 || buf[1] != 0x01)) {
442 ret = -ENODEV; 441 ret = -ENODEV;
443 goto err_out; 442 goto err_out;
444 } 443 }
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
new file mode 100644
index 000000000000..2f33a0167644
--- /dev/null
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -0,0 +1,325 @@
1/*
2 * Wacom W8001 penabled serial touchscreen driver
3 *
4 * Copyright (c) 2008 Jaya Kumar
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
8 * more details.
9 *
10 * Layout based on Elo serial touchscreen driver by Vojtech Pavlik
11 */
12
13#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/slab.h>
17#include <linux/input.h>
18#include <linux/serio.h>
19#include <linux/init.h>
20#include <linux/ctype.h>
21
22#define DRIVER_DESC "Wacom W8001 serial touchscreen driver"
23
24MODULE_AUTHOR("Jaya Kumar <jayakumar.lkml@gmail.com>");
25MODULE_DESCRIPTION(DRIVER_DESC);
26MODULE_LICENSE("GPL");
27
28/*
29 * Definitions & global arrays.
30 */
31
32#define W8001_MAX_LENGTH 11
33#define W8001_PACKET_LEN 11
34#define W8001_LEAD_MASK 0x80
35#define W8001_LEAD_BYTE 0x80
36#define W8001_TAB_MASK 0x40
37#define W8001_TAB_BYTE 0x40
38
39#define W8001_QUERY_PACKET 0x20
40
41struct w8001_coord {
42 u8 rdy;
43 u8 tsw;
44 u8 f1;
45 u8 f2;
46 u16 x;
47 u16 y;
48 u16 pen_pressure;
49 u8 tilt_x;
50 u8 tilt_y;
51};
52
53/*
54 * Per-touchscreen data.
55 */
56
57struct w8001 {
58 struct input_dev *dev;
59 struct serio *serio;
60 struct mutex cmd_mutex;
61 struct completion cmd_done;
62 int id;
63 int idx;
64 unsigned char expected_packet;
65 unsigned char data[W8001_MAX_LENGTH];
66 unsigned char response[W8001_PACKET_LEN];
67 char phys[32];
68};
69
70static int parse_data(u8 *data, struct w8001_coord *coord)
71{
72 coord->rdy = data[0] & 0x20;
73 coord->tsw = data[0] & 0x01;
74 coord->f1 = data[0] & 0x02;
75 coord->f2 = data[0] & 0x04;
76
77 coord->x = (data[1] & 0x7F) << 9;
78 coord->x |= (data[2] & 0x7F) << 2;
79 coord->x |= (data[6] & 0x60) >> 5;
80
81 coord->y = (data[3] & 0x7F) << 9;
82 coord->y |= (data[4] & 0x7F) << 2;
83 coord->y |= (data[6] & 0x18) >> 3;
84
85 coord->pen_pressure = data[5] & 0x7F;
86 coord->pen_pressure |= (data[6] & 0x07) << 7 ;
87
88 coord->tilt_x = data[7] & 0x7F;
89 coord->tilt_y = data[8] & 0x7F;
90
91 return 0;
92}
93
94static void w8001_process_data(struct w8001 *w8001, unsigned char data)
95{
96 struct input_dev *dev = w8001->dev;
97 u8 tmp;
98 struct w8001_coord coord;
99
100 w8001->data[w8001->idx] = data;
101 switch (w8001->idx++) {
102 case 0:
103 if ((data & W8001_LEAD_MASK) != W8001_LEAD_BYTE) {
104 pr_debug("w8001: unsynchronized data: 0x%02x\n", data);
105 w8001->idx = 0;
106 }
107 break;
108 case 8:
109 tmp = w8001->data[0] & W8001_TAB_MASK;
110 if (unlikely(tmp == W8001_TAB_BYTE))
111 break;
112 w8001->idx = 0;
113 memset(&coord, 0, sizeof(coord));
114 parse_data(w8001->data, &coord);
115 input_report_abs(dev, ABS_X, coord.x);
116 input_report_abs(dev, ABS_Y, coord.y);
117 input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
118 input_report_key(dev, BTN_TOUCH, coord.tsw);
119 input_sync(dev);
120 break;
121 case 10:
122 w8001->idx = 0;
123 memcpy(w8001->response, &w8001->data, W8001_PACKET_LEN);
124 w8001->expected_packet = W8001_QUERY_PACKET;
125 complete(&w8001->cmd_done);
126 break;
127 }
128}
129
130
131static irqreturn_t w8001_interrupt(struct serio *serio,
132 unsigned char data, unsigned int flags)
133{
134 struct w8001 *w8001 = serio_get_drvdata(serio);
135
136 w8001_process_data(w8001, data);
137
138 return IRQ_HANDLED;
139}
140
141static int w8001_async_command(struct w8001 *w8001, unsigned char *packet,
142 int len)
143{
144 int rc = -1;
145 int i;
146
147 mutex_lock(&w8001->cmd_mutex);
148
149 for (i = 0; i < len; i++) {
150 if (serio_write(w8001->serio, packet[i]))
151 goto out;
152 }
153 rc = 0;
154
155out:
156 mutex_unlock(&w8001->cmd_mutex);
157 return rc;
158}
159
160static int w8001_command(struct w8001 *w8001, unsigned char *packet, int len)
161{
162 int rc = -1;
163 int i;
164
165 mutex_lock(&w8001->cmd_mutex);
166
167 serio_pause_rx(w8001->serio);
168 init_completion(&w8001->cmd_done);
169 serio_continue_rx(w8001->serio);
170
171 for (i = 0; i < len; i++) {
172 if (serio_write(w8001->serio, packet[i]))
173 goto out;
174 }
175
176 wait_for_completion_timeout(&w8001->cmd_done, HZ);
177
178 if (w8001->expected_packet == W8001_QUERY_PACKET) {
179 /* We are back in reporting mode, the query was ACKed */
180 memcpy(packet, w8001->response, W8001_PACKET_LEN);
181 rc = 0;
182 }
183
184out:
185 mutex_unlock(&w8001->cmd_mutex);
186 return rc;
187}
188
189static int w8001_setup(struct w8001 *w8001)
190{
191 struct w8001_coord coord;
192 struct input_dev *dev = w8001->dev;
193 unsigned char start[1] = { '1' };
194 unsigned char query[11] = { '*' };
195
196 if (w8001_command(w8001, query, 1))
197 return -1;
198
199 memset(&coord, 0, sizeof(coord));
200 parse_data(query, &coord);
201
202 input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0);
203 input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0);
204 input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0);
205 input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
206 input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
207
208 if (w8001_async_command(w8001, start, 1))
209 return -1;
210
211 return 0;
212}
213
214/*
215 * w8001_disconnect() is the opposite of w8001_connect()
216 */
217
218static void w8001_disconnect(struct serio *serio)
219{
220 struct w8001 *w8001 = serio_get_drvdata(serio);
221
222 input_get_device(w8001->dev);
223 input_unregister_device(w8001->dev);
224 serio_close(serio);
225 serio_set_drvdata(serio, NULL);
226 input_put_device(w8001->dev);
227 kfree(w8001);
228}
229
230/*
231 * w8001_connect() is the routine that is called when someone adds a
232 * new serio device that supports the w8001 protocol and registers it as
233 * an input device.
234 */
235
236static int w8001_connect(struct serio *serio, struct serio_driver *drv)
237{
238 struct w8001 *w8001;
239 struct input_dev *input_dev;
240 int err;
241
242 w8001 = kzalloc(sizeof(struct w8001), GFP_KERNEL);
243 input_dev = input_allocate_device();
244 if (!w8001 || !input_dev) {
245 err = -ENOMEM;
246 goto fail1;
247 }
248
249 w8001->serio = serio;
250 w8001->id = serio->id.id;
251 w8001->dev = input_dev;
252 mutex_init(&w8001->cmd_mutex);
253 init_completion(&w8001->cmd_done);
254 snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
255
256 input_dev->name = "Wacom W8001 Penabled Serial TouchScreen";
257 input_dev->phys = w8001->phys;
258 input_dev->id.bustype = BUS_RS232;
259 input_dev->id.vendor = SERIO_W8001;
260 input_dev->id.product = w8001->id;
261 input_dev->id.version = 0x0100;
262 input_dev->dev.parent = &serio->dev;
263
264 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
265 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
266
267 serio_set_drvdata(serio, w8001);
268 err = serio_open(serio, drv);
269 if (err)
270 goto fail2;
271
272 if (w8001_setup(w8001))
273 goto fail3;
274
275 err = input_register_device(w8001->dev);
276 if (err)
277 goto fail3;
278
279 return 0;
280
281fail3:
282 serio_close(serio);
283fail2:
284 serio_set_drvdata(serio, NULL);
285fail1:
286 input_free_device(input_dev);
287 kfree(w8001);
288 return err;
289}
290
291static struct serio_device_id w8001_serio_ids[] = {
292 {
293 .type = SERIO_RS232,
294 .proto = SERIO_W8001,
295 .id = SERIO_ANY,
296 .extra = SERIO_ANY,
297 },
298 { 0 }
299};
300
301MODULE_DEVICE_TABLE(serio, w8001_serio_ids);
302
303static struct serio_driver w8001_drv = {
304 .driver = {
305 .name = "w8001",
306 },
307 .description = DRIVER_DESC,
308 .id_table = w8001_serio_ids,
309 .interrupt = w8001_interrupt,
310 .connect = w8001_connect,
311 .disconnect = w8001_disconnect,
312};
313
314static int __init w8001_init(void)
315{
316 return serio_register_driver(&w8001_drv);
317}
318
319static void __exit w8001_exit(void)
320{
321 serio_unregister_driver(&w8001_drv);
322}
323
324module_init(w8001_init);
325module_exit(w8001_exit);