1 From c0960b696fbccc83925134aec007801073bcac54 Mon Sep 17 00:00:00 2001
2 From: Lauri Leukkunen <lauri.leukkunen@nokia.com>
3 Date: Fri, 12 Mar 2010 16:54:33 +0000
4 Subject: [PATCH 7/10] input: touchscreen: introduce tsc2005 driver
6 Patch-mainline: 2.6.35?
7 Discussions: http://www.mail-archive.com/linux-omap@vger.kernel.org/msg26748.html
9 Introduce a driver for the Texas Instruments TSC2005 touchscreen
10 controller (http://focus.ti.com/docs/prod/folders/print/tsc2005.html).
12 The patch is based on a driver by Lauri Leukkunen, with modifications
13 by David Brownell, Phil Carmody, Imre Deak, Hiroshi DOYU, Ari Kauppi,
14 Tony Lindgren, Jarkko Nikula, Eero Nurkkala and Roman Tereshonkov.
16 Signed-off-by: Lauri Leukkunen <lauri.leukkunen@nokia.com>
17 [aaro.koskinen@nokia.com: patch description, rebasing & cleanup]
18 Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
19 Cc: David Brownell <dbrownell@users.sourceforge.net>
20 Cc: Phil Carmody <ext-phil.2.carmody@nokia.com>
21 Cc: Imre Deak <imre.deak@nokia.com>
22 Cc: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
23 Cc: Ari Kauppi <Ext-Ari.Kauppi@nokia.com>
24 Cc: Tony Lindgren <tony@atomide.com>
25 Cc: Jarkko Nikula <jhnikula@gmail.com>
26 Cc: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
27 Cc: Roman Tereshonkov <roman.tereshonkov@nokia.com>
29 drivers/input/touchscreen/Kconfig | 11 +
30 drivers/input/touchscreen/Makefile | 1 +
31 drivers/input/touchscreen/tsc2005.c | 678 +++++++++++++++++++++++++++++++++++
32 include/linux/spi/tsc2005.h | 41 +++
33 4 files changed, 731 insertions(+), 0 deletions(-)
34 create mode 100644 drivers/input/touchscreen/tsc2005.c
35 create mode 100644 include/linux/spi/tsc2005.h
37 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
38 index dfafc76..72c1797 100644
39 --- a/drivers/input/touchscreen/Kconfig
40 +++ b/drivers/input/touchscreen/Kconfig
41 @@ -548,6 +548,17 @@ config TOUCHSCREEN_TOUCHIT213
42 To compile this driver as a module, choose M here: the
43 module will be called touchit213.
45 +config TOUCHSCREEN_TSC2005
46 + tristate "TSC2005 based touchscreens"
47 + depends on SPI_MASTER
49 + Say Y here if you have a TSC2005 based touchscreen.
53 + To compile this driver as a module, choose M here: the
54 + module will be called tsc2005.
56 config TOUCHSCREEN_TSC2007
57 tristate "TSC2007 based touchscreens"
59 diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
60 index d61a3b4..61fa8b5 100644
61 --- a/drivers/input/touchscreen/Makefile
62 +++ b/drivers/input/touchscreen/Makefile
63 @@ -33,6 +33,7 @@ obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
64 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
65 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
66 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
67 +obj-$(CONFIG_TOUCHSCREEN_TSC2005) += tsc2005.o
68 obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
69 obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
70 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
71 diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
73 index 0000000..27ee361
75 +++ b/drivers/input/touchscreen/tsc2005.c
78 + * TSC2005 touchscreen driver
80 + * Copyright (C) 2006-2010 Nokia Corporation
82 + * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
83 + * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
85 + * This program is free software; you can redistribute it and/or modify
86 + * it under the terms of the GNU General Public License as published by
87 + * the Free Software Foundation; either version 2 of the License, or
88 + * (at your option) any later version.
90 + * This program is distributed in the hope that it will be useful,
91 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
92 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
93 + * GNU General Public License for more details.
95 + * You should have received a copy of the GNU General Public License
96 + * along with this program; if not, write to the Free Software
97 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
101 +#include <linux/kernel.h>
102 +#include <linux/module.h>
103 +#include <linux/input.h>
104 +#include <linux/interrupt.h>
105 +#include <linux/delay.h>
106 +#include <linux/spi/spi.h>
107 +#include <linux/spi/tsc2005.h>
110 + * The touchscreen interface operates as follows:
112 + * 1) Pen is pressed against the touchscreen.
113 + * 2) TSC2005 performs AD conversion.
114 + * 3) After the conversion is done TSC2005 drives DAV line down.
115 + * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
116 + * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
118 + * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
119 + * tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
120 + * 7) When the penup timer expires, there have not been touch or DAV interrupts
121 + * during the last 40ms which means the pen has been lifted.
123 + * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
124 + * after a configurable period (in ms) of activity. If esd_timeout is 0, the
125 + * watchdog is disabled.
128 +/* control byte 1 */
129 +#define TSC2005_CMD 0x80
130 +#define TSC2005_CMD_NORMAL 0x00
131 +#define TSC2005_CMD_STOP 0x01
132 +#define TSC2005_CMD_12BIT 0x04
134 +/* control byte 0 */
135 +#define TSC2005_REG_READ 0x0001
136 +#define TSC2005_REG_PND0 0x0002
137 +#define TSC2005_REG_X 0x0000
138 +#define TSC2005_REG_Y 0x0008
139 +#define TSC2005_REG_Z1 0x0010
140 +#define TSC2005_REG_Z2 0x0018
141 +#define TSC2005_REG_TEMP_HIGH 0x0050
142 +#define TSC2005_REG_CFR0 0x0060
143 +#define TSC2005_REG_CFR1 0x0068
144 +#define TSC2005_REG_CFR2 0x0070
146 +/* configuration register 0 */
147 +#define TSC2005_CFR0_PRECHARGE_276US 0x0040
148 +#define TSC2005_CFR0_STABTIME_1MS 0x0300
149 +#define TSC2005_CFR0_CLOCK_1MHZ 0x1000
150 +#define TSC2005_CFR0_RESOLUTION12 0x2000
151 +#define TSC2005_CFR0_PENMODE 0x8000
152 +#define TSC2005_CFR0_INITVALUE (TSC2005_CFR0_STABTIME_1MS | \
153 + TSC2005_CFR0_CLOCK_1MHZ | \
154 + TSC2005_CFR0_RESOLUTION12 | \
155 + TSC2005_CFR0_PRECHARGE_276US | \
156 + TSC2005_CFR0_PENMODE)
158 +/* bits common to both read and write of configuration register 0 */
159 +#define TSC2005_CFR0_RW_MASK 0x3fff
161 +/* configuration register 1 */
162 +#define TSC2005_CFR1_BATCHDELAY_4MS 0x0003
163 +#define TSC2005_CFR1_INITVALUE TSC2005_CFR1_BATCHDELAY_4MS
165 +/* configuration register 2 */
166 +#define TSC2005_CFR2_MAVE_Z 0x0004
167 +#define TSC2005_CFR2_MAVE_Y 0x0008
168 +#define TSC2005_CFR2_MAVE_X 0x0010
169 +#define TSC2005_CFR2_AVG_7 0x0800
170 +#define TSC2005_CFR2_MEDIUM_15 0x3000
171 +#define TSC2005_CFR2_INITVALUE (TSC2005_CFR2_MAVE_X | \
172 + TSC2005_CFR2_MAVE_Y | \
173 + TSC2005_CFR2_MAVE_Z | \
174 + TSC2005_CFR2_MEDIUM_15 | \
175 + TSC2005_CFR2_AVG_7)
177 +#define MAX_12BIT 0xfff
178 +#define TSC2005_SPI_MAX_SPEED_HZ 10000000
179 +#define TSC2005_PENUP_TIME_MS 40
181 +struct tsc2005_spi_rd {
182 + struct spi_transfer spi_xfer;
188 + struct spi_device *spi;
190 + struct spi_message spi_read_msg;
191 + struct tsc2005_spi_rd spi_x;
192 + struct tsc2005_spi_rd spi_y;
193 + struct tsc2005_spi_rd spi_z1;
194 + struct tsc2005_spi_rd spi_z2;
196 + struct input_dev *idev;
199 + struct mutex mutex;
201 + struct timer_list penup_timer;
202 + struct work_struct penup_work;
204 + unsigned int esd_timeout;
205 + struct timer_list esd_timer;
206 + struct work_struct esd_work;
208 + unsigned int x_plate_ohm;
211 + unsigned int disable_depth;
213 + void (*set_reset)(bool enable);
216 +static void tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
219 + struct spi_message msg;
220 + struct spi_transfer xfer = { 0 };
222 + tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
225 + xfer.rx_buf = NULL;
227 + xfer.bits_per_word = 8;
229 + spi_message_init(&msg);
230 + spi_message_add_tail(&xfer, &msg);
231 + spi_sync(ts->spi, &msg);
234 +static void tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value)
237 + struct spi_message msg;
238 + struct spi_transfer xfer = { 0 };
240 + tx = (reg | TSC2005_REG_PND0) << 16;
244 + xfer.rx_buf = NULL;
246 + xfer.bits_per_word = 24;
248 + spi_message_init(&msg);
249 + spi_message_add_tail(&xfer, &msg);
250 + spi_sync(ts->spi, &msg);
253 +static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last)
255 + rd->spi_tx = (reg | TSC2005_REG_READ) << 16;
256 + rd->spi_xfer.tx_buf = &rd->spi_tx;
257 + rd->spi_xfer.rx_buf = &rd->spi_rx;
258 + rd->spi_xfer.len = 4;
259 + rd->spi_xfer.bits_per_word = 24;
260 + rd->spi_xfer.cs_change = !last;
263 +static void tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value)
265 + struct spi_message msg;
266 + struct tsc2005_spi_rd spi_rd = { { 0 }, 0, 0 };
268 + tsc2005_setup_read(&spi_rd, reg, 1);
270 + spi_message_init(&msg);
271 + spi_message_add_tail(&spi_rd.spi_xfer, &msg);
272 + spi_sync(ts->spi, &msg);
273 + *value = spi_rd.spi_rx;
276 +static void tsc2005_update_pen_state(struct tsc2005 *ts,
277 + int x, int y, int pressure)
280 + input_report_abs(ts->idev, ABS_X, x);
281 + input_report_abs(ts->idev, ABS_Y, y);
283 + input_report_abs(ts->idev, ABS_PRESSURE, pressure);
284 + input_report_key(ts->idev, BTN_TOUCH, !!pressure);
285 + input_sync(ts->idev);
286 + dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
290 +static irqreturn_t tsc2005_irq_handler(int irq, void *dev_id)
292 + struct tsc2005 *ts = dev_id;
294 + /* update the penup timer only if it's pending */
295 + mod_timer_pending(&ts->penup_timer,
296 + jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
298 + return IRQ_WAKE_THREAD;
301 +static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
303 + struct tsc2005 *ts = _ts;
304 + unsigned int pressure;
310 + mutex_lock(&ts->mutex);
312 + if (unlikely(ts->disable_depth))
315 + /* read the coordinates */
316 + spi_sync(ts->spi, &ts->spi_read_msg);
317 + x = ts->spi_x.spi_rx;
318 + y = ts->spi_y.spi_rx;
319 + z1 = ts->spi_z1.spi_rx;
320 + z2 = ts->spi_z2.spi_rx;
322 + /* validate position */
323 + if (unlikely(x > MAX_12BIT || y > MAX_12BIT))
326 + /* skip coords if the pressure components are out of range */
327 + if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2))
330 + /* compute touch pressure resistance using equation #1 */
331 + pressure = x * (z2 - z1) / z1;
332 + pressure = pressure * ts->x_plate_ohm / 4096;
333 + if (unlikely(pressure > MAX_12BIT))
336 + tsc2005_update_pen_state(ts, x, y, pressure);
338 + /* set the penup timer */
339 + mod_timer(&ts->penup_timer,
340 + jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
342 + if (!ts->esd_timeout)
345 + /* update the watchdog timer */
346 + mod_timer(&ts->esd_timer,
347 + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout)));
350 + mutex_unlock(&ts->mutex);
351 + return IRQ_HANDLED;
354 +static void tsc2005_penup_timer(unsigned long data)
356 + struct tsc2005 *ts = (struct tsc2005 *)data;
358 + schedule_work(&ts->penup_work);
361 +static void tsc2005_penup_work(struct work_struct *work)
363 + struct tsc2005 *ts = container_of(work, struct tsc2005, penup_work);
365 + mutex_lock(&ts->mutex);
366 + tsc2005_update_pen_state(ts, 0, 0, 0);
367 + mutex_unlock(&ts->mutex);
370 +static void tsc2005_start_scan(struct tsc2005 *ts)
372 + tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
373 + tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
374 + tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
375 + tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
378 +static void tsc2005_stop_scan(struct tsc2005 *ts)
380 + tsc2005_cmd(ts, TSC2005_CMD_STOP);
383 +/* must be called with mutex held */
384 +static void tsc2005_disable(struct tsc2005 *ts)
386 + if (ts->disable_depth++ != 0)
388 + disable_irq(ts->spi->irq);
389 + if (ts->esd_timeout)
390 + del_timer_sync(&ts->esd_timer);
391 + del_timer_sync(&ts->penup_timer);
392 + tsc2005_stop_scan(ts);
395 +/* must be called with mutex held */
396 +static void tsc2005_enable(struct tsc2005 *ts)
398 + if (--ts->disable_depth != 0)
400 + tsc2005_start_scan(ts);
401 + enable_irq(ts->spi->irq);
402 + if (!ts->esd_timeout)
404 + mod_timer(&ts->esd_timer,
405 + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout)));
408 +static ssize_t tsc2005_disable_show(struct device *dev,
409 + struct device_attribute *attr, char *buf)
411 + struct tsc2005 *ts = dev_get_drvdata(dev);
413 + return sprintf(buf, "%u\n", ts->disabled);
416 +static ssize_t tsc2005_disable_store(struct device *dev,
417 + struct device_attribute *attr,
418 + const char *buf, size_t count)
420 + struct tsc2005 *ts = dev_get_drvdata(dev);
424 + if (strict_strtoul(buf, 10, &res) < 0)
428 + mutex_lock(&ts->mutex);
429 + if (i == ts->disabled)
433 + tsc2005_disable(ts);
435 + tsc2005_enable(ts);
437 + mutex_unlock(&ts->mutex);
440 +static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store);
442 +static ssize_t tsc2005_selftest_show(struct device *dev,
443 + struct device_attribute *attr,
446 + struct tsc2005 *ts = dev_get_drvdata(dev);
448 + u16 temp_high_orig;
449 + u16 temp_high_test;
450 + unsigned int result;
452 + if (!ts->set_reset) {
453 + dev_warn(&ts->spi->dev,
454 + "unable to selftest: no reset function\n");
459 + mutex_lock(&ts->mutex);
462 + * Test TSC2005 communications via temp high register.
464 + tsc2005_disable(ts);
466 + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
467 + temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
468 + tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test);
469 + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
470 + if (temp_high != temp_high_test) {
471 + dev_warn(dev, "selftest failed: %d != %d\n",
472 + temp_high, temp_high_test);
476 + /* hardware reset */
478 + msleep(1); /* only 10us required */
480 + tsc2005_enable(ts);
482 + /* test that the reset really happened */
483 + tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
484 + if (temp_high != temp_high_orig) {
485 + dev_warn(dev, "selftest failed after reset: %d != %d\n",
486 + temp_high, temp_high_orig);
490 + mutex_unlock(&ts->mutex);
493 + return sprintf(buf, "%u\n", result);
495 +static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
497 +static void tsc2005_esd_timer(unsigned long data)
499 + struct tsc2005 *ts = (struct tsc2005 *)data;
501 + schedule_work(&ts->esd_work);
504 +static void tsc2005_esd_work(struct work_struct *work)
506 + struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work);
509 + mutex_lock(&ts->mutex);
511 + if (ts->disable_depth)
515 + * If we cannot read our known value from configuration register 0 then
516 + * reset the controller as if from power-up and start scanning again.
518 + tsc2005_read(ts, TSC2005_REG_CFR0, &r);
519 + if ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK) {
520 + dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
522 + msleep(1); /* only 10us required */
524 + tsc2005_start_scan(ts);
527 + /* re-arm the watchdog */
528 + mod_timer(&ts->esd_timer,
529 + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout)));
532 + mutex_unlock(&ts->mutex);
535 +static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
537 + tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, 0);
538 + tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, 0);
539 + tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, 0);
540 + tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, 1);
542 + spi_message_init(&ts->spi_read_msg);
543 + spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg);
544 + spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg);
545 + spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg);
546 + spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
549 +static struct attribute *tsc2005_attrs[] = {
550 + &dev_attr_disable.attr,
551 + &dev_attr_selftest.attr,
555 +static struct attribute_group tsc2005_attr_group = {
556 + .attrs = tsc2005_attrs,
559 +static int __devinit tsc2005_setup(struct tsc2005 *ts,
560 + struct tsc2005_platform_data *pdata)
570 + mutex_init(&ts->mutex);
572 + tsc2005_setup_spi_xfer(ts);
574 + init_timer(&ts->penup_timer);
575 + setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
576 + INIT_WORK(&ts->penup_work, tsc2005_penup_work);
578 + fudge_x = pdata->ts_x_fudge ? : 0;
579 + fudge_y = pdata->ts_y_fudge ? : 0;
580 + fudge_p = pdata->ts_pressure_fudge ? : 0;
581 + x_max = pdata->ts_x_max ? : MAX_12BIT;
582 + y_max = pdata->ts_y_max ? : MAX_12BIT;
583 + p_max = pdata->ts_pressure_max ? : MAX_12BIT;
584 + ts->x_plate_ohm = pdata->ts_x_plate_ohm ? : 0;
585 + ts->esd_timeout = pdata->esd_timeout_ms;
586 + ts->set_reset = pdata->set_reset;
588 + ts->idev = input_allocate_device();
589 + if (ts->idev == NULL)
591 + ts->idev->name = "TSC2005 touchscreen";
592 + snprintf(ts->phys, sizeof(ts->phys), "%s/input-ts",
593 + dev_name(&ts->spi->dev));
594 + ts->idev->phys = ts->phys;
595 + ts->idev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
596 + ts->idev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
597 + ts->idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
599 + input_set_abs_params(ts->idev, ABS_X, 0, x_max, fudge_x, 0);
600 + input_set_abs_params(ts->idev, ABS_Y, 0, y_max, fudge_y, 0);
601 + input_set_abs_params(ts->idev, ABS_PRESSURE, 0, p_max, fudge_p, 0);
603 + r = request_threaded_irq(ts->spi->irq, tsc2005_irq_handler,
604 + tsc2005_irq_thread, IRQF_TRIGGER_RISING,
607 + dev_err(&ts->spi->dev, "request_threaded_irq(): %d\n", r);
610 + set_irq_wake(ts->spi->irq, 1);
612 + r = input_register_device(ts->idev);
614 + dev_err(&ts->spi->dev, "input_register_device(): %d\n", r);
618 + r = sysfs_create_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
620 + dev_warn(&ts->spi->dev, "sysfs entry creation failed: %d\n", r);
622 + tsc2005_start_scan(ts);
624 + if (!ts->esd_timeout || !ts->set_reset)
627 + /* start the optional ESD watchdog */
628 + setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts);
629 + INIT_WORK(&ts->esd_work, tsc2005_esd_work);
630 + mod_timer(&ts->esd_timer,
631 + round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout)));
637 + free_irq(ts->spi->irq, ts);
640 + input_free_device(ts->idev);
644 +static int __devinit tsc2005_probe(struct spi_device *spi)
646 + struct tsc2005_platform_data *pdata = spi->dev.platform_data;
647 + struct tsc2005 *ts;
650 + if (spi->irq < 0) {
651 + dev_dbg(&spi->dev, "no irq\n");
656 + dev_dbg(&spi->dev, "no platform data\n");
660 + ts = kzalloc(sizeof(*ts), GFP_KERNEL);
664 + dev_set_drvdata(&spi->dev, ts);
666 + spi->dev.power.power_state = PMSG_ON;
667 + spi->mode = SPI_MODE_0;
668 + spi->bits_per_word = 8;
669 + if (!spi->max_speed_hz)
670 + spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
673 + r = tsc2005_setup(ts, pdata);
679 +static int __devexit tsc2005_remove(struct spi_device *spi)
681 + struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
683 + mutex_lock(&ts->mutex);
684 + tsc2005_disable(ts);
685 + mutex_unlock(&ts->mutex);
687 + if (ts->esd_timeout)
688 + del_timer_sync(&ts->esd_timer);
689 + del_timer_sync(&ts->penup_timer);
691 + flush_work(&ts->esd_work);
692 + flush_work(&ts->penup_work);
694 + sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
695 + free_irq(ts->spi->irq, ts);
696 + input_unregister_device(ts->idev);
703 +static int tsc2005_suspend(struct spi_device *spi, pm_message_t mesg)
705 + struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
707 + mutex_lock(&ts->mutex);
708 + tsc2005_disable(ts);
709 + mutex_unlock(&ts->mutex);
714 +static int tsc2005_resume(struct spi_device *spi)
716 + struct tsc2005 *ts = dev_get_drvdata(&spi->dev);
718 + mutex_lock(&ts->mutex);
719 + tsc2005_enable(ts);
720 + mutex_unlock(&ts->mutex);
726 +static struct spi_driver tsc2005_driver = {
729 + .owner = THIS_MODULE,
732 + .suspend = tsc2005_suspend,
733 + .resume = tsc2005_resume,
735 + .probe = tsc2005_probe,
736 + .remove = __devexit_p(tsc2005_remove),
739 +static int __init tsc2005_init(void)
741 + printk(KERN_INFO "TSC2005 driver initializing\n");
742 + return spi_register_driver(&tsc2005_driver);
744 +module_init(tsc2005_init);
746 +static void __exit tsc2005_exit(void)
748 + spi_unregister_driver(&tsc2005_driver);
750 +module_exit(tsc2005_exit);
752 +MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
753 +MODULE_LICENSE("GPL");
754 +MODULE_ALIAS("platform:tsc2005");
755 diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h
757 index 0000000..d9b0c84
759 +++ b/include/linux/spi/tsc2005.h
762 + * This file is part of TSC2005 touchscreen driver
764 + * Copyright (C) 2009-2010 Nokia Corporation
766 + * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
768 + * This program is free software; you can redistribute it and/or modify
769 + * it under the terms of the GNU General Public License as published by
770 + * the Free Software Foundation; either version 2 of the License, or
771 + * (at your option) any later version.
773 + * This program is distributed in the hope that it will be useful,
774 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
775 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
776 + * GNU General Public License for more details.
778 + * You should have received a copy of the GNU General Public License
779 + * along with this program; if not, write to the Free Software
780 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
784 +#ifndef _LINUX_SPI_TSC2005_H
785 +#define _LINUX_SPI_TSC2005_H
787 +#include <linux/types.h>
789 +struct tsc2005_platform_data {
790 + int ts_pressure_max;
791 + int ts_pressure_fudge;
796 + int ts_x_plate_ohm;
797 + unsigned int esd_timeout_ms;
798 + void (*set_reset)(bool enable);