aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
commit2dfea3803dcf70983d14ce1dcbb3e97a7459a28b (patch)
tree59bffc7389ff554585f79d7cc06021790dc2b317 /drivers/input/touchscreen
parentaed606e3bc1f10753254db308d3fd8c053c41328 (diff)
parent1881b68b8961a86d40c3c5c205e533515a2dc9c6 (diff)
Merge tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFS update from Samuel Ortiz: "This is the MFD patch set for the 3.8 merge window. We have several new drivers, most of the time coming with their sub devices drivers: - Austria Microsystem's AS3711 - Nano River's viperboard - TI's TPS80031, AM335x TS/ADC, - Realtek's MMC/memstick card reader - Nokia's retu We also got some notable cleanups and improvements: - tps6586x got converted to IRQ domains. - tps65910 and tps65090 moved to the regmap IRQ API. - STMPE is now Device Tree aware. - A general twl6040 and twl-core cleanup, with moves to the regmap I/O and IRQ APIs and a conversion to the recently added PWM framework. - sta2x11 gained regmap support. Then the rest is mostly tiny cleanups and fixes, among which we have Mark's wm5xxx and wm8xxx patchset." Far amount of annoying but largely trivial conflicts. Many due to __devinit/exit removal, others due to one or two of the new drivers also having come in through another tree. * tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (119 commits) mfd: tps6507x: Convert to devm_kzalloc mfd: stmpe: Update DT support for stmpe driver mfd: wm5102: Add readback of DSP status 3 register mfd: arizona: Log if we fail to create the primary IRQ domain mfd: tps80031: MFD_TPS80031 needs to select REGMAP_IRQ mfd: tps80031: Add terminating entry for tps80031_id_table mfd: sta2x11: Fix potential NULL pointer dereference in __sta2x11_mfd_mask() mfd: wm5102: Add tuning for revision B mfd: arizona: Defer patch initialistation until after first device boot mfd: tps65910: Fix wrong ack_base register mfd: tps65910: Remove unused data mfd: stmpe: Get rid of irq_invert_polarity mfd: ab8500-core: Fix invalid free of devm_ allocated data mfd: wm5102: Mark DSP memory regions as volatile mfd: wm5102: Correct default for LDO1_CONTROL_2 mfd: arizona: Register haptics devices mfd: wm8994: Make current device behaviour the default mfd: tps65090: MFD_TPS65090 needs to select REGMAP_IRQ mfd: Fix stmpe.c build when OF is not enabled mfd: jz4740-adc: Use devm_kzalloc ...
Diffstat (limited to 'drivers/input/touchscreen')
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/Makefile2
-rw-r--r--drivers/input/touchscreen/da9052_tsi.c59
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c398
-rw-r--r--drivers/input/touchscreen/ti_tscadc.c486
5 files changed, 422 insertions, 529 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index f7668b24c378..0c45caddd41c 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -529,9 +529,9 @@ config TOUCHSCREEN_TOUCHWIN
529 To compile this driver as a module, choose M here: the 529 To compile this driver as a module, choose M here: the
530 module will be called touchwin. 530 module will be called touchwin.
531 531
532config TOUCHSCREEN_TI_TSCADC 532config TOUCHSCREEN_TI_AM335X_TSC
533 tristate "TI Touchscreen Interface" 533 tristate "TI Touchscreen Interface"
534 depends on ARCH_OMAP2PLUS 534 depends on MFD_TI_AM335X_TSCADC
535 help 535 help
536 Say Y here if you have 4/5/8 wire touchscreen controller 536 Say Y here if you have 4/5/8 wire touchscreen controller
537 to be connected to the ADC controller on your TI AM335x SoC. 537 to be connected to the ADC controller on your TI AM335x SoC.
@@ -539,7 +539,7 @@ config TOUCHSCREEN_TI_TSCADC
539 If unsure, say N. 539 If unsure, say N.
540 540
541 To compile this driver as a module, choose M here: the 541 To compile this driver as a module, choose M here: the
542 module will be called ti_tscadc. 542 module will be called ti_am335x_tsc.
543 543
544config TOUCHSCREEN_ATMEL_TSADCC 544config TOUCHSCREEN_ATMEL_TSADCC
545 tristate "Atmel Touchscreen Interface" 545 tristate "Atmel Touchscreen Interface"
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 178eb128d90f..7c4c78ebe49e 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -52,7 +52,7 @@ obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
52obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o 52obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
53obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o 53obj-$(CONFIG_TOUCHSCREEN_ST1232) += st1232.o
54obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o 54obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
55obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o 55obj-$(CONFIG_TOUCHSCREEN_TI_AM335X_TSC) += ti_am335x_tsc.o
56obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o 56obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
57obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o 57obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
58obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o 58obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
diff --git a/drivers/input/touchscreen/da9052_tsi.c b/drivers/input/touchscreen/da9052_tsi.c
index e8df341090c0..53133efe0418 100644
--- a/drivers/input/touchscreen/da9052_tsi.c
+++ b/drivers/input/touchscreen/da9052_tsi.c
@@ -27,8 +27,6 @@ struct da9052_tsi {
27 struct input_dev *dev; 27 struct input_dev *dev;
28 struct delayed_work ts_pen_work; 28 struct delayed_work ts_pen_work;
29 struct mutex mutex; 29 struct mutex mutex;
30 unsigned int irq_pendwn;
31 unsigned int irq_datardy;
32 bool stopped; 30 bool stopped;
33 bool adc_on; 31 bool adc_on;
34}; 32};
@@ -45,8 +43,8 @@ static irqreturn_t da9052_ts_pendwn_irq(int irq, void *data)
45 43
46 if (!tsi->stopped) { 44 if (!tsi->stopped) {
47 /* Mask PEN_DOWN event and unmask TSI_READY event */ 45 /* Mask PEN_DOWN event and unmask TSI_READY event */
48 disable_irq_nosync(tsi->irq_pendwn); 46 da9052_disable_irq_nosync(tsi->da9052, DA9052_IRQ_PENDOWN);
49 enable_irq(tsi->irq_datardy); 47 da9052_enable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
50 48
51 da9052_ts_adc_toggle(tsi, true); 49 da9052_ts_adc_toggle(tsi, true);
52 50
@@ -137,8 +135,8 @@ static void da9052_ts_pen_work(struct work_struct *work)
137 return; 135 return;
138 136
139 /* Mask TSI_READY event and unmask PEN_DOWN event */ 137 /* Mask TSI_READY event and unmask PEN_DOWN event */
140 disable_irq(tsi->irq_datardy); 138 da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
141 enable_irq(tsi->irq_pendwn); 139 da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
142 } 140 }
143 } 141 }
144} 142}
@@ -197,7 +195,7 @@ static int da9052_ts_input_open(struct input_dev *input_dev)
197 mb(); 195 mb();
198 196
199 /* Unmask PEN_DOWN event */ 197 /* Unmask PEN_DOWN event */
200 enable_irq(tsi->irq_pendwn); 198 da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
201 199
202 /* Enable Pen Detect Circuit */ 200 /* Enable Pen Detect Circuit */
203 return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG, 201 return da9052_reg_update(tsi->da9052, DA9052_TSI_CONT_A_REG,
@@ -210,11 +208,11 @@ static void da9052_ts_input_close(struct input_dev *input_dev)
210 208
211 tsi->stopped = true; 209 tsi->stopped = true;
212 mb(); 210 mb();
213 disable_irq(tsi->irq_pendwn); 211 da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
214 cancel_delayed_work_sync(&tsi->ts_pen_work); 212 cancel_delayed_work_sync(&tsi->ts_pen_work);
215 213
216 if (tsi->adc_on) { 214 if (tsi->adc_on) {
217 disable_irq(tsi->irq_datardy); 215 da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
218 da9052_ts_adc_toggle(tsi, false); 216 da9052_ts_adc_toggle(tsi, false);
219 217
220 /* 218 /*
@@ -222,7 +220,7 @@ static void da9052_ts_input_close(struct input_dev *input_dev)
222 * twice and we need to enable it to keep enable/disable 220 * twice and we need to enable it to keep enable/disable
223 * counter balanced. IRQ is still off though. 221 * counter balanced. IRQ is still off though.
224 */ 222 */
225 enable_irq(tsi->irq_pendwn); 223 da9052_enable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
226 } 224 }
227 225
228 /* Disable Pen Detect Circuit */ 226 /* Disable Pen Detect Circuit */
@@ -234,21 +232,12 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
234 struct da9052 *da9052; 232 struct da9052 *da9052;
235 struct da9052_tsi *tsi; 233 struct da9052_tsi *tsi;
236 struct input_dev *input_dev; 234 struct input_dev *input_dev;
237 int irq_pendwn;
238 int irq_datardy;
239 int error; 235 int error;
240 236
241 da9052 = dev_get_drvdata(pdev->dev.parent); 237 da9052 = dev_get_drvdata(pdev->dev.parent);
242 if (!da9052) 238 if (!da9052)
243 return -EINVAL; 239 return -EINVAL;
244 240
245 irq_pendwn = platform_get_irq_byname(pdev, "PENDWN");
246 irq_datardy = platform_get_irq_byname(pdev, "TSIRDY");
247 if (irq_pendwn < 0 || irq_datardy < 0) {
248 dev_err(da9052->dev, "Unable to determine device interrupts\n");
249 return -ENXIO;
250 }
251
252 tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL); 241 tsi = kzalloc(sizeof(struct da9052_tsi), GFP_KERNEL);
253 input_dev = input_allocate_device(); 242 input_dev = input_allocate_device();
254 if (!tsi || !input_dev) { 243 if (!tsi || !input_dev) {
@@ -258,8 +247,6 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
258 247
259 tsi->da9052 = da9052; 248 tsi->da9052 = da9052;
260 tsi->dev = input_dev; 249 tsi->dev = input_dev;
261 tsi->irq_pendwn = da9052->irq_base + irq_pendwn;
262 tsi->irq_datardy = da9052->irq_base + irq_datardy;
263 tsi->stopped = true; 250 tsi->stopped = true;
264 INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work); 251 INIT_DELAYED_WORK(&tsi->ts_pen_work, da9052_ts_pen_work);
265 252
@@ -287,31 +274,25 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
287 /* Disable ADC */ 274 /* Disable ADC */
288 da9052_ts_adc_toggle(tsi, false); 275 da9052_ts_adc_toggle(tsi, false);
289 276
290 error = request_threaded_irq(tsi->irq_pendwn, 277 error = da9052_request_irq(tsi->da9052, DA9052_IRQ_PENDOWN,
291 NULL, da9052_ts_pendwn_irq, 278 "pendown-irq", da9052_ts_pendwn_irq, tsi);
292 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
293 "PENDWN", tsi);
294 if (error) { 279 if (error) {
295 dev_err(tsi->da9052->dev, 280 dev_err(tsi->da9052->dev,
296 "Failed to register PENDWN IRQ %d, error = %d\n", 281 "Failed to register PENDWN IRQ: %d\n", error);
297 tsi->irq_pendwn, error);
298 goto err_free_mem; 282 goto err_free_mem;
299 } 283 }
300 284
301 error = request_threaded_irq(tsi->irq_datardy, 285 error = da9052_request_irq(tsi->da9052, DA9052_IRQ_TSIREADY,
302 NULL, da9052_ts_datardy_irq, 286 "tsiready-irq", da9052_ts_datardy_irq, tsi);
303 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
304 "TSIRDY", tsi);
305 if (error) { 287 if (error) {
306 dev_err(tsi->da9052->dev, 288 dev_err(tsi->da9052->dev,
307 "Failed to register TSIRDY IRQ %d, error = %d\n", 289 "Failed to register TSIRDY IRQ :%d\n", error);
308 tsi->irq_datardy, error);
309 goto err_free_pendwn_irq; 290 goto err_free_pendwn_irq;
310 } 291 }
311 292
312 /* Mask PEN_DOWN and TSI_READY events */ 293 /* Mask PEN_DOWN and TSI_READY events */
313 disable_irq(tsi->irq_pendwn); 294 da9052_disable_irq(tsi->da9052, DA9052_IRQ_PENDOWN);
314 disable_irq(tsi->irq_datardy); 295 da9052_disable_irq(tsi->da9052, DA9052_IRQ_TSIREADY);
315 296
316 error = da9052_configure_tsi(tsi); 297 error = da9052_configure_tsi(tsi);
317 if (error) 298 if (error)
@@ -326,9 +307,9 @@ static int __devinit da9052_ts_probe(struct platform_device *pdev)
326 return 0; 307 return 0;
327 308
328err_free_datardy_irq: 309err_free_datardy_irq:
329 free_irq(tsi->irq_datardy, tsi); 310 da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi);
330err_free_pendwn_irq: 311err_free_pendwn_irq:
331 free_irq(tsi->irq_pendwn, tsi); 312 da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi);
332err_free_mem: 313err_free_mem:
333 kfree(tsi); 314 kfree(tsi);
334 input_free_device(input_dev); 315 input_free_device(input_dev);
@@ -342,8 +323,8 @@ static int __devexit da9052_ts_remove(struct platform_device *pdev)
342 323
343 da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19); 324 da9052_reg_write(tsi->da9052, DA9052_LDO9_REG, 0x19);
344 325
345 free_irq(tsi->irq_pendwn, tsi); 326 da9052_free_irq(tsi->da9052, DA9052_IRQ_TSIREADY, tsi);
346 free_irq(tsi->irq_datardy, tsi); 327 da9052_free_irq(tsi->da9052, DA9052_IRQ_PENDOWN, tsi);
347 328
348 input_unregister_device(tsi->dev); 329 input_unregister_device(tsi->dev);
349 kfree(tsi); 330 kfree(tsi);
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
new file mode 100644
index 000000000000..7a18a8a15228
--- /dev/null
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -0,0 +1,398 @@
1/*
2 * TI Touch Screen driver
3 *
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/err.h>
20#include <linux/module.h>
21#include <linux/input.h>
22#include <linux/slab.h>
23#include <linux/interrupt.h>
24#include <linux/clk.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/input/ti_am335x_tsc.h>
28#include <linux/delay.h>
29
30#include <linux/mfd/ti_am335x_tscadc.h>
31
32#define ADCFSM_STEPID 0x10
33#define SEQ_SETTLE 275
34#define MAX_12BIT ((1 << 12) - 1)
35
36struct titsc {
37 struct input_dev *input;
38 struct ti_tscadc_dev *mfd_tscadc;
39 unsigned int irq;
40 unsigned int wires;
41 unsigned int x_plate_resistance;
42 bool pen_down;
43 int steps_to_configure;
44};
45
46static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
47{
48 return readl(ts->mfd_tscadc->tscadc_base + reg);
49}
50
51static void titsc_writel(struct titsc *tsc, unsigned int reg,
52 unsigned int val)
53{
54 writel(val, tsc->mfd_tscadc->tscadc_base + reg);
55}
56
57static void titsc_step_config(struct titsc *ts_dev)
58{
59 unsigned int config;
60 int i, total_steps;
61
62 /* Configure the Step registers */
63 total_steps = 2 * ts_dev->steps_to_configure;
64
65 config = STEPCONFIG_MODE_HWSYNC |
66 STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
67 switch (ts_dev->wires) {
68 case 4:
69 config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
70 break;
71 case 5:
72 config |= STEPCONFIG_YNN |
73 STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
74 STEPCONFIG_YPP;
75 break;
76 case 8:
77 config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
78 break;
79 }
80
81 for (i = 1; i <= ts_dev->steps_to_configure; i++) {
82 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
83 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
84 }
85
86 config = 0;
87 config = STEPCONFIG_MODE_HWSYNC |
88 STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
89 STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
90 switch (ts_dev->wires) {
91 case 4:
92 config |= STEPCONFIG_YPP;
93 break;
94 case 5:
95 config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
96 STEPCONFIG_XNP | STEPCONFIG_YPN;
97 break;
98 case 8:
99 config |= STEPCONFIG_YPP;
100 break;
101 }
102
103 for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
104 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
105 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
106 }
107
108 config = 0;
109 /* Charge step configuration */
110 config = STEPCONFIG_XPP | STEPCONFIG_YNN |
111 STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
112 STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
113
114 titsc_writel(ts_dev, REG_CHARGECONFIG, config);
115 titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
116
117 config = 0;
118 /* Configure to calculate pressure */
119 config = STEPCONFIG_MODE_HWSYNC |
120 STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
121 STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
122 titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
123 titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
124 STEPCONFIG_OPENDLY);
125
126 config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
127 titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
128 titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
129 STEPCONFIG_OPENDLY);
130
131 titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
132}
133
134static void titsc_read_coordinates(struct titsc *ts_dev,
135 unsigned int *x, unsigned int *y)
136{
137 unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
138 unsigned int prev_val_x = ~0, prev_val_y = ~0;
139 unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
140 unsigned int read, diff;
141 unsigned int i, channel;
142
143 /*
144 * Delta filter is used to remove large variations in sampled
145 * values from ADC. The filter tries to predict where the next
146 * coordinate could be. This is done by taking a previous
147 * coordinate and subtracting it form current one. Further the
148 * algorithm compares the difference with that of a present value,
149 * if true the value is reported to the sub system.
150 */
151 for (i = 0; i < fifocount - 1; i++) {
152 read = titsc_readl(ts_dev, REG_FIFO0);
153 channel = read & 0xf0000;
154 channel = channel >> 0x10;
155 if ((channel >= 0) && (channel < ts_dev->steps_to_configure)) {
156 read &= 0xfff;
157 diff = abs(read - prev_val_x);
158 if (diff < prev_diff_x) {
159 prev_diff_x = diff;
160 *x = read;
161 }
162 prev_val_x = read;
163 }
164
165 read = titsc_readl(ts_dev, REG_FIFO1);
166 channel = read & 0xf0000;
167 channel = channel >> 0x10;
168 if ((channel >= ts_dev->steps_to_configure) &&
169 (channel < (2 * ts_dev->steps_to_configure - 1))) {
170 read &= 0xfff;
171 diff = abs(read - prev_val_y);
172 if (diff < prev_diff_y) {
173 prev_diff_y = diff;
174 *y = read;
175 }
176 prev_val_y = read;
177 }
178 }
179}
180
181static irqreturn_t titsc_irq(int irq, void *dev)
182{
183 struct titsc *ts_dev = dev;
184 struct input_dev *input_dev = ts_dev->input;
185 unsigned int status, irqclr = 0;
186 unsigned int x = 0, y = 0;
187 unsigned int z1, z2, z;
188 unsigned int fsm;
189 unsigned int fifo1count, fifo0count;
190 int i;
191
192 status = titsc_readl(ts_dev, REG_IRQSTATUS);
193 if (status & IRQENB_FIFO0THRES) {
194 titsc_read_coordinates(ts_dev, &x, &y);
195
196 z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
197 z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
198
199 fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
200 for (i = 0; i < fifo1count; i++)
201 titsc_readl(ts_dev, REG_FIFO1);
202
203 fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
204 for (i = 0; i < fifo0count; i++)
205 titsc_readl(ts_dev, REG_FIFO0);
206
207 if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
208 /*
209 * Calculate pressure using formula
210 * Resistance(touch) = x plate resistance *
211 * x postion/4096 * ((z2 / z1) - 1)
212 */
213 z = z2 - z1;
214 z *= x;
215 z *= ts_dev->x_plate_resistance;
216 z /= z1;
217 z = (z + 2047) >> 12;
218
219 if (z <= MAX_12BIT) {
220 input_report_abs(input_dev, ABS_X, x);
221 input_report_abs(input_dev, ABS_Y, y);
222 input_report_abs(input_dev, ABS_PRESSURE, z);
223 input_report_key(input_dev, BTN_TOUCH, 1);
224 input_sync(input_dev);
225 }
226 }
227 irqclr |= IRQENB_FIFO0THRES;
228 }
229
230 /*
231 * Time for sequencer to settle, to read
232 * correct state of the sequencer.
233 */
234 udelay(SEQ_SETTLE);
235
236 status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
237 if (status & IRQENB_PENUP) {
238 /* Pen up event */
239 fsm = titsc_readl(ts_dev, REG_ADCFSM);
240 if (fsm == ADCFSM_STEPID) {
241 ts_dev->pen_down = false;
242 input_report_key(input_dev, BTN_TOUCH, 0);
243 input_report_abs(input_dev, ABS_PRESSURE, 0);
244 input_sync(input_dev);
245 } else {
246 ts_dev->pen_down = true;
247 }
248 irqclr |= IRQENB_PENUP;
249 }
250
251 titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
252
253 titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
254 return IRQ_HANDLED;
255}
256
257/*
258 * The functions for inserting/removing driver as a module.
259 */
260
261static int __devinit titsc_probe(struct platform_device *pdev)
262{
263 struct titsc *ts_dev;
264 struct input_dev *input_dev;
265 struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
266 struct mfd_tscadc_board *pdata;
267 int err;
268
269 pdata = tscadc_dev->dev->platform_data;
270
271 if (!pdata) {
272 dev_err(&pdev->dev, "Could not find platform data\n");
273 return -EINVAL;
274 }
275
276 /* Allocate memory for device */
277 ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
278 input_dev = input_allocate_device();
279 if (!ts_dev || !input_dev) {
280 dev_err(&pdev->dev, "failed to allocate memory.\n");
281 err = -ENOMEM;
282 goto err_free_mem;
283 }
284
285 tscadc_dev->tsc = ts_dev;
286 ts_dev->mfd_tscadc = tscadc_dev;
287 ts_dev->input = input_dev;
288 ts_dev->irq = tscadc_dev->irq;
289 ts_dev->wires = pdata->tsc_init->wires;
290 ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
291 ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
292
293 err = request_irq(ts_dev->irq, titsc_irq,
294 0, pdev->dev.driver->name, ts_dev);
295 if (err) {
296 dev_err(&pdev->dev, "failed to allocate irq.\n");
297 goto err_free_mem;
298 }
299
300 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
301 titsc_step_config(ts_dev);
302 titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
303
304 input_dev->name = "ti-tsc";
305 input_dev->dev.parent = &pdev->dev;
306
307 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
308 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
309
310 input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
311 input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
312 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
313
314 /* register to the input system */
315 err = input_register_device(input_dev);
316 if (err)
317 goto err_free_irq;
318
319 platform_set_drvdata(pdev, ts_dev);
320 return 0;
321
322err_free_irq:
323 free_irq(ts_dev->irq, ts_dev);
324err_free_mem:
325 input_free_device(input_dev);
326 kfree(ts_dev);
327 return err;
328}
329
330static int __devexit titsc_remove(struct platform_device *pdev)
331{
332 struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
333 struct titsc *ts_dev = tscadc_dev->tsc;
334
335 free_irq(ts_dev->irq, ts_dev);
336
337 input_unregister_device(ts_dev->input);
338
339 platform_set_drvdata(pdev, NULL);
340 kfree(ts_dev);
341 return 0;
342}
343
344#ifdef CONFIG_PM
345static int titsc_suspend(struct device *dev)
346{
347 struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
348 struct titsc *ts_dev = tscadc_dev->tsc;
349 unsigned int idle;
350
351 if (device_may_wakeup(tscadc_dev->dev)) {
352 idle = titsc_readl(ts_dev, REG_IRQENABLE);
353 titsc_writel(ts_dev, REG_IRQENABLE,
354 (idle | IRQENB_HW_PEN));
355 titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
356 }
357 return 0;
358}
359
360static int titsc_resume(struct device *dev)
361{
362 struct ti_tscadc_dev *tscadc_dev = dev->platform_data;
363 struct titsc *ts_dev = tscadc_dev->tsc;
364
365 if (device_may_wakeup(tscadc_dev->dev)) {
366 titsc_writel(ts_dev, REG_IRQWAKEUP,
367 0x00);
368 titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
369 }
370 titsc_step_config(ts_dev);
371 titsc_writel(ts_dev, REG_FIFO0THR,
372 ts_dev->steps_to_configure);
373 return 0;
374}
375
376static const struct dev_pm_ops titsc_pm_ops = {
377 .suspend = titsc_suspend,
378 .resume = titsc_resume,
379};
380#define TITSC_PM_OPS (&titsc_pm_ops)
381#else
382#define TITSC_PM_OPS NULL
383#endif
384
385static struct platform_driver ti_tsc_driver = {
386 .probe = titsc_probe,
387 .remove = __devexit_p(titsc_remove),
388 .driver = {
389 .name = "tsc",
390 .owner = THIS_MODULE,
391 .pm = TITSC_PM_OPS,
392 },
393};
394module_platform_driver(ti_tsc_driver);
395
396MODULE_DESCRIPTION("TI touchscreen controller driver");
397MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
398MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
deleted file mode 100644
index d229c741d544..000000000000
--- a/drivers/input/touchscreen/ti_tscadc.c
+++ /dev/null
@@ -1,486 +0,0 @@
1/*
2 * TI Touch Screen driver
3 *
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation version 2.
9 *
10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
11 * kind, whether express or implied; without even the implied warranty
12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16
17#include <linux/init.h>
18#include <linux/kernel.h>
19#include <linux/err.h>
20#include <linux/module.h>
21#include <linux/input.h>
22#include <linux/slab.h>
23#include <linux/interrupt.h>
24#include <linux/clk.h>
25#include <linux/platform_device.h>
26#include <linux/io.h>
27#include <linux/input/ti_tscadc.h>
28#include <linux/delay.h>
29
30#define REG_IRQEOI 0x020
31#define REG_RAWIRQSTATUS 0x024
32#define REG_IRQSTATUS 0x028
33#define REG_IRQENABLE 0x02C
34#define REG_IRQWAKEUP 0x034
35#define REG_CTRL 0x040
36#define REG_ADCFSM 0x044
37#define REG_CLKDIV 0x04C
38#define REG_SE 0x054
39#define REG_IDLECONFIG 0x058
40#define REG_CHARGECONFIG 0x05C
41#define REG_CHARGEDELAY 0x060
42#define REG_STEPCONFIG(n) (0x64 + ((n - 1) * 8))
43#define REG_STEPDELAY(n) (0x68 + ((n - 1) * 8))
44#define REG_STEPCONFIG13 0x0C4
45#define REG_STEPDELAY13 0x0C8
46#define REG_STEPCONFIG14 0x0CC
47#define REG_STEPDELAY14 0x0D0
48#define REG_FIFO0CNT 0xE4
49#define REG_FIFO1THR 0xF4
50#define REG_FIFO0 0x100
51#define REG_FIFO1 0x200
52
53/* Register Bitfields */
54#define IRQWKUP_ENB BIT(0)
55#define STPENB_STEPENB 0x7FFF
56#define IRQENB_FIFO1THRES BIT(5)
57#define IRQENB_PENUP BIT(9)
58#define STEPCONFIG_MODE_HWSYNC 0x2
59#define STEPCONFIG_SAMPLES_AVG (1 << 4)
60#define STEPCONFIG_XPP (1 << 5)
61#define STEPCONFIG_XNN (1 << 6)
62#define STEPCONFIG_YPP (1 << 7)
63#define STEPCONFIG_YNN (1 << 8)
64#define STEPCONFIG_XNP (1 << 9)
65#define STEPCONFIG_YPN (1 << 10)
66#define STEPCONFIG_INM (1 << 18)
67#define STEPCONFIG_INP (1 << 20)
68#define STEPCONFIG_INP_5 (1 << 21)
69#define STEPCONFIG_FIFO1 (1 << 26)
70#define STEPCONFIG_OPENDLY 0xff
71#define STEPCONFIG_Z1 (3 << 19)
72#define STEPIDLE_INP (1 << 22)
73#define STEPCHARGE_RFP (1 << 12)
74#define STEPCHARGE_INM (1 << 15)
75#define STEPCHARGE_INP (1 << 19)
76#define STEPCHARGE_RFM (1 << 23)
77#define STEPCHARGE_DELAY 0x1
78#define CNTRLREG_TSCSSENB (1 << 0)
79#define CNTRLREG_STEPID (1 << 1)
80#define CNTRLREG_STEPCONFIGWRT (1 << 2)
81#define CNTRLREG_4WIRE (1 << 5)
82#define CNTRLREG_5WIRE (1 << 6)
83#define CNTRLREG_8WIRE (3 << 5)
84#define CNTRLREG_TSCENB (1 << 7)
85#define ADCFSM_STEPID 0x10
86
87#define SEQ_SETTLE 275
88#define ADC_CLK 3000000
89#define MAX_12BIT ((1 << 12) - 1)
90#define TSCADC_DELTA_X 15
91#define TSCADC_DELTA_Y 15
92
93struct tscadc {
94 struct input_dev *input;
95 struct clk *tsc_ick;
96 void __iomem *tsc_base;
97 unsigned int irq;
98 unsigned int wires;
99 unsigned int x_plate_resistance;
100 bool pen_down;
101};
102
103static unsigned int tscadc_readl(struct tscadc *ts, unsigned int reg)
104{
105 return readl(ts->tsc_base + reg);
106}
107
108static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
109 unsigned int val)
110{
111 writel(val, tsc->tsc_base + reg);
112}
113
114static void tscadc_step_config(struct tscadc *ts_dev)
115{
116 unsigned int config;
117 int i;
118
119 /* Configure the Step registers */
120
121 config = STEPCONFIG_MODE_HWSYNC |
122 STEPCONFIG_SAMPLES_AVG | STEPCONFIG_XPP;
123 switch (ts_dev->wires) {
124 case 4:
125 config |= STEPCONFIG_INP | STEPCONFIG_XNN;
126 break;
127 case 5:
128 config |= STEPCONFIG_YNN |
129 STEPCONFIG_INP_5 | STEPCONFIG_XNN |
130 STEPCONFIG_YPP;
131 break;
132 case 8:
133 config |= STEPCONFIG_INP | STEPCONFIG_XNN;
134 break;
135 }
136
137 for (i = 1; i < 7; i++) {
138 tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
139 tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
140 }
141
142 config = 0;
143 config = STEPCONFIG_MODE_HWSYNC |
144 STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YNN |
145 STEPCONFIG_INM | STEPCONFIG_FIFO1;
146 switch (ts_dev->wires) {
147 case 4:
148 config |= STEPCONFIG_YPP;
149 break;
150 case 5:
151 config |= STEPCONFIG_XPP | STEPCONFIG_INP_5 |
152 STEPCONFIG_XNP | STEPCONFIG_YPN;
153 break;
154 case 8:
155 config |= STEPCONFIG_YPP;
156 break;
157 }
158
159 for (i = 7; i < 13; i++) {
160 tscadc_writel(ts_dev, REG_STEPCONFIG(i), config);
161 tscadc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
162 }
163
164 config = 0;
165 /* Charge step configuration */
166 config = STEPCONFIG_XPP | STEPCONFIG_YNN |
167 STEPCHARGE_RFP | STEPCHARGE_RFM |
168 STEPCHARGE_INM | STEPCHARGE_INP;
169
170 tscadc_writel(ts_dev, REG_CHARGECONFIG, config);
171 tscadc_writel(ts_dev, REG_CHARGEDELAY, STEPCHARGE_DELAY);
172
173 config = 0;
174 /* Configure to calculate pressure */
175 config = STEPCONFIG_MODE_HWSYNC |
176 STEPCONFIG_SAMPLES_AVG | STEPCONFIG_YPP |
177 STEPCONFIG_XNN | STEPCONFIG_INM;
178 tscadc_writel(ts_dev, REG_STEPCONFIG13, config);
179 tscadc_writel(ts_dev, REG_STEPDELAY13, STEPCONFIG_OPENDLY);
180
181 config |= STEPCONFIG_Z1 | STEPCONFIG_FIFO1;
182 tscadc_writel(ts_dev, REG_STEPCONFIG14, config);
183 tscadc_writel(ts_dev, REG_STEPDELAY14, STEPCONFIG_OPENDLY);
184
185 tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
186}
187
188static void tscadc_idle_config(struct tscadc *ts_config)
189{
190 unsigned int idleconfig;
191
192 idleconfig = STEPCONFIG_YNN |
193 STEPCONFIG_INM |
194 STEPCONFIG_YPN | STEPIDLE_INP;
195 tscadc_writel(ts_config, REG_IDLECONFIG, idleconfig);
196}
197
198static void tscadc_read_coordinates(struct tscadc *ts_dev,
199 unsigned int *x, unsigned int *y)
200{
201 unsigned int fifocount = tscadc_readl(ts_dev, REG_FIFO0CNT);
202 unsigned int prev_val_x = ~0, prev_val_y = ~0;
203 unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
204 unsigned int read, diff;
205 unsigned int i;
206
207 /*
208 * Delta filter is used to remove large variations in sampled
209 * values from ADC. The filter tries to predict where the next
210 * coordinate could be. This is done by taking a previous
211 * coordinate and subtracting it form current one. Further the
212 * algorithm compares the difference with that of a present value,
213 * if true the value is reported to the sub system.
214 */
215 for (i = 0; i < fifocount - 1; i++) {
216 read = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
217 diff = abs(read - prev_val_x);
218 if (diff < prev_diff_x) {
219 prev_diff_x = diff;
220 *x = read;
221 }
222 prev_val_x = read;
223
224 read = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
225 diff = abs(read - prev_val_y);
226 if (diff < prev_diff_y) {
227 prev_diff_y = diff;
228 *y = read;
229 }
230 prev_val_y = read;
231 }
232}
233
234static irqreturn_t tscadc_irq(int irq, void *dev)
235{
236 struct tscadc *ts_dev = dev;
237 struct input_dev *input_dev = ts_dev->input;
238 unsigned int status, irqclr = 0;
239 unsigned int x = 0, y = 0;
240 unsigned int z1, z2, z;
241 unsigned int fsm;
242
243 status = tscadc_readl(ts_dev, REG_IRQSTATUS);
244 if (status & IRQENB_FIFO1THRES) {
245 tscadc_read_coordinates(ts_dev, &x, &y);
246
247 z1 = tscadc_readl(ts_dev, REG_FIFO0) & 0xfff;
248 z2 = tscadc_readl(ts_dev, REG_FIFO1) & 0xfff;
249
250 if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
251 /*
252 * Calculate pressure using formula
253 * Resistance(touch) = x plate resistance *
254 * x postion/4096 * ((z2 / z1) - 1)
255 */
256 z = z2 - z1;
257 z *= x;
258 z *= ts_dev->x_plate_resistance;
259 z /= z1;
260 z = (z + 2047) >> 12;
261
262 if (z <= MAX_12BIT) {
263 input_report_abs(input_dev, ABS_X, x);
264 input_report_abs(input_dev, ABS_Y, y);
265 input_report_abs(input_dev, ABS_PRESSURE, z);
266 input_report_key(input_dev, BTN_TOUCH, 1);
267 input_sync(input_dev);
268 }
269 }
270 irqclr |= IRQENB_FIFO1THRES;
271 }
272
273 /*
274 * Time for sequencer to settle, to read
275 * correct state of the sequencer.
276 */
277 udelay(SEQ_SETTLE);
278
279 status = tscadc_readl(ts_dev, REG_RAWIRQSTATUS);
280 if (status & IRQENB_PENUP) {
281 /* Pen up event */
282 fsm = tscadc_readl(ts_dev, REG_ADCFSM);
283 if (fsm == ADCFSM_STEPID) {
284 ts_dev->pen_down = false;
285 input_report_key(input_dev, BTN_TOUCH, 0);
286 input_report_abs(input_dev, ABS_PRESSURE, 0);
287 input_sync(input_dev);
288 } else {
289 ts_dev->pen_down = true;
290 }
291 irqclr |= IRQENB_PENUP;
292 }
293
294 tscadc_writel(ts_dev, REG_IRQSTATUS, irqclr);
295 /* check pending interrupts */
296 tscadc_writel(ts_dev, REG_IRQEOI, 0x0);
297
298 tscadc_writel(ts_dev, REG_SE, STPENB_STEPENB);
299 return IRQ_HANDLED;
300}
301
302/*
303 * The functions for inserting/removing driver as a module.
304 */
305
306static int __devinit tscadc_probe(struct platform_device *pdev)
307{
308 const struct tsc_data *pdata = pdev->dev.platform_data;
309 struct resource *res;
310 struct tscadc *ts_dev;
311 struct input_dev *input_dev;
312 struct clk *clk;
313 int err;
314 int clk_value, ctrl, irq;
315
316 if (!pdata) {
317 dev_err(&pdev->dev, "missing platform data.\n");
318 return -EINVAL;
319 }
320
321 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
322 if (!res) {
323 dev_err(&pdev->dev, "no memory resource defined.\n");
324 return -EINVAL;
325 }
326
327 irq = platform_get_irq(pdev, 0);
328 if (irq < 0) {
329 dev_err(&pdev->dev, "no irq ID is specified.\n");
330 return -EINVAL;
331 }
332
333 /* Allocate memory for device */
334 ts_dev = kzalloc(sizeof(struct tscadc), GFP_KERNEL);
335 input_dev = input_allocate_device();
336 if (!ts_dev || !input_dev) {
337 dev_err(&pdev->dev, "failed to allocate memory.\n");
338 err = -ENOMEM;
339 goto err_free_mem;
340 }
341
342 ts_dev->input = input_dev;
343 ts_dev->irq = irq;
344 ts_dev->wires = pdata->wires;
345 ts_dev->x_plate_resistance = pdata->x_plate_resistance;
346
347 res = request_mem_region(res->start, resource_size(res), pdev->name);
348 if (!res) {
349 dev_err(&pdev->dev, "failed to reserve registers.\n");
350 err = -EBUSY;
351 goto err_free_mem;
352 }
353
354 ts_dev->tsc_base = ioremap(res->start, resource_size(res));
355 if (!ts_dev->tsc_base) {
356 dev_err(&pdev->dev, "failed to map registers.\n");
357 err = -ENOMEM;
358 goto err_release_mem_region;
359 }
360
361 err = request_irq(ts_dev->irq, tscadc_irq,
362 0, pdev->dev.driver->name, ts_dev);
363 if (err) {
364 dev_err(&pdev->dev, "failed to allocate irq.\n");
365 goto err_unmap_regs;
366 }
367
368 ts_dev->tsc_ick = clk_get(&pdev->dev, "adc_tsc_ick");
369 if (IS_ERR(ts_dev->tsc_ick)) {
370 dev_err(&pdev->dev, "failed to get TSC ick\n");
371 goto err_free_irq;
372 }
373 clk_enable(ts_dev->tsc_ick);
374
375 clk = clk_get(&pdev->dev, "adc_tsc_fck");
376 if (IS_ERR(clk)) {
377 dev_err(&pdev->dev, "failed to get TSC fck\n");
378 err = PTR_ERR(clk);
379 goto err_disable_clk;
380 }
381
382 clk_value = clk_get_rate(clk) / ADC_CLK;
383 clk_put(clk);
384
385 if (clk_value < 7) {
386 dev_err(&pdev->dev, "clock input less than min clock requirement\n");
387 goto err_disable_clk;
388 }
389 /* CLKDIV needs to be configured to the value minus 1 */
390 tscadc_writel(ts_dev, REG_CLKDIV, clk_value - 1);
391
392 /* Enable wake-up of the SoC using touchscreen */
393 tscadc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
394
395 ctrl = CNTRLREG_STEPCONFIGWRT |
396 CNTRLREG_TSCENB |
397 CNTRLREG_STEPID;
398 switch (ts_dev->wires) {
399 case 4:
400 ctrl |= CNTRLREG_4WIRE;
401 break;
402 case 5:
403 ctrl |= CNTRLREG_5WIRE;
404 break;
405 case 8:
406 ctrl |= CNTRLREG_8WIRE;
407 break;
408 }
409 tscadc_writel(ts_dev, REG_CTRL, ctrl);
410
411 tscadc_idle_config(ts_dev);
412 tscadc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO1THRES);
413 tscadc_step_config(ts_dev);
414 tscadc_writel(ts_dev, REG_FIFO1THR, 6);
415
416 ctrl |= CNTRLREG_TSCSSENB;
417 tscadc_writel(ts_dev, REG_CTRL, ctrl);
418
419 input_dev->name = "ti-tsc-adc";
420 input_dev->dev.parent = &pdev->dev;
421
422 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
423 input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
424
425 input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
426 input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
427 input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
428
429 /* register to the input system */
430 err = input_register_device(input_dev);
431 if (err)
432 goto err_disable_clk;
433
434 platform_set_drvdata(pdev, ts_dev);
435 return 0;
436
437err_disable_clk:
438 clk_disable(ts_dev->tsc_ick);
439 clk_put(ts_dev->tsc_ick);
440err_free_irq:
441 free_irq(ts_dev->irq, ts_dev);
442err_unmap_regs:
443 iounmap(ts_dev->tsc_base);
444err_release_mem_region:
445 release_mem_region(res->start, resource_size(res));
446err_free_mem:
447 input_free_device(input_dev);
448 kfree(ts_dev);
449 return err;
450}
451
452static int __devexit tscadc_remove(struct platform_device *pdev)
453{
454 struct tscadc *ts_dev = platform_get_drvdata(pdev);
455 struct resource *res;
456
457 free_irq(ts_dev->irq, ts_dev);
458
459 input_unregister_device(ts_dev->input);
460
461 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
462 iounmap(ts_dev->tsc_base);
463 release_mem_region(res->start, resource_size(res));
464
465 clk_disable(ts_dev->tsc_ick);
466 clk_put(ts_dev->tsc_ick);
467
468 kfree(ts_dev);
469
470 platform_set_drvdata(pdev, NULL);
471 return 0;
472}
473
474static struct platform_driver ti_tsc_driver = {
475 .probe = tscadc_probe,
476 .remove = __devexit_p(tscadc_remove),
477 .driver = {
478 .name = "tsc",
479 .owner = THIS_MODULE,
480 },
481};
482module_platform_driver(ti_tsc_driver);
483
484MODULE_DESCRIPTION("TI touchscreen controller driver");
485MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
486MODULE_LICENSE("GPL");