Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / input / touchscreen / ti_am335x_tsc.c
CommitLineData
1b8be32e
RP
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>
55c04de5 27#include <linux/input/ti_am335x_tsc.h>
1b8be32e
RP
28#include <linux/delay.h>
29
2b99bafa 30#include <linux/mfd/ti_am335x_tscadc.h>
33f5cc60
PR
31
32#define ADCFSM_STEPID 0x10
1b8be32e 33#define SEQ_SETTLE 275
1b8be32e 34#define MAX_12BIT ((1 << 12) - 1)
1b8be32e 35
55c04de5 36struct titsc {
1b8be32e 37 struct input_dev *input;
2b99bafa 38 struct ti_tscadc_dev *mfd_tscadc;
1b8be32e
RP
39 unsigned int irq;
40 unsigned int wires;
41 unsigned int x_plate_resistance;
42 bool pen_down;
d1fb5743 43 int steps_to_configure;
1b8be32e
RP
44};
45
55c04de5 46static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
1b8be32e 47{
2b99bafa 48 return readl(ts->mfd_tscadc->tscadc_base + reg);
1b8be32e
RP
49}
50
55c04de5 51static void titsc_writel(struct titsc *tsc, unsigned int reg,
1b8be32e
RP
52 unsigned int val)
53{
2b99bafa 54 writel(val, tsc->mfd_tscadc->tscadc_base + reg);
1b8be32e
RP
55}
56
55c04de5 57static void titsc_step_config(struct titsc *ts_dev)
1b8be32e
RP
58{
59 unsigned int config;
d1fb5743 60 int i, total_steps;
1b8be32e
RP
61
62 /* Configure the Step registers */
d1fb5743 63 total_steps = 2 * ts_dev->steps_to_configure;
1b8be32e
RP
64
65 config = STEPCONFIG_MODE_HWSYNC |
33f5cc60 66 STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
1b8be32e
RP
67 switch (ts_dev->wires) {
68 case 4:
33f5cc60 69 config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
1b8be32e
RP
70 break;
71 case 5:
72 config |= STEPCONFIG_YNN |
33f5cc60 73 STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
1b8be32e
RP
74 STEPCONFIG_YPP;
75 break;
76 case 8:
33f5cc60 77 config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
1b8be32e
RP
78 break;
79 }
80
d1fb5743 81 for (i = 1; i <= ts_dev->steps_to_configure; i++) {
55c04de5
PR
82 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
83 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
1b8be32e
RP
84 }
85
86 config = 0;
87 config = STEPCONFIG_MODE_HWSYNC |
33f5cc60
PR
88 STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
89 STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
1b8be32e
RP
90 switch (ts_dev->wires) {
91 case 4:
92 config |= STEPCONFIG_YPP;
93 break;
94 case 5:
33f5cc60 95 config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
1b8be32e
RP
96 STEPCONFIG_XNP | STEPCONFIG_YPN;
97 break;
98 case 8:
99 config |= STEPCONFIG_YPP;
100 break;
101 }
102
d1fb5743 103 for (i = (ts_dev->steps_to_configure + 1); i <= total_steps; i++) {
55c04de5
PR
104 titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
105 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
1b8be32e
RP
106 }
107
108 config = 0;
109 /* Charge step configuration */
110 config = STEPCONFIG_XPP | STEPCONFIG_YNN |
33f5cc60
PR
111 STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
112 STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
1b8be32e 113
55c04de5
PR
114 titsc_writel(ts_dev, REG_CHARGECONFIG, config);
115 titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
1b8be32e
RP
116
117 config = 0;
118 /* Configure to calculate pressure */
119 config = STEPCONFIG_MODE_HWSYNC |
33f5cc60
PR
120 STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
121 STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
55c04de5
PR
122 titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
123 titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
d1fb5743 124 STEPCONFIG_OPENDLY);
1b8be32e 125
33f5cc60 126 config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
55c04de5
PR
127 titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
128 titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
d1fb5743 129 STEPCONFIG_OPENDLY);
1b8be32e 130
2b99bafa 131 titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
1b8be32e
RP
132}
133
55c04de5 134static void titsc_read_coordinates(struct titsc *ts_dev,
1b8be32e
RP
135 unsigned int *x, unsigned int *y)
136{
55c04de5 137 unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
1b8be32e
RP
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;
2b99bafa 141 unsigned int i, channel;
1b8be32e
RP
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++) {
2b99bafa
PR
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;
1b8be32e 163 }
1b8be32e 164
2b99bafa
PR
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;
1b8be32e 177 }
1b8be32e
RP
178 }
179}
180
55c04de5 181static irqreturn_t titsc_irq(int irq, void *dev)
1b8be32e 182{
55c04de5 183 struct titsc *ts_dev = dev;
1b8be32e
RP
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;
2b99bafa
PR
189 unsigned int fifo1count, fifo0count;
190 int i;
1b8be32e 191
55c04de5 192 status = titsc_readl(ts_dev, REG_IRQSTATUS);
30af55f9 193 if (status & IRQENB_FIFO0THRES) {
55c04de5 194 titsc_read_coordinates(ts_dev, &x, &y);
1b8be32e 195
55c04de5
PR
196 z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
197 z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
1b8be32e 198
2b99bafa
PR
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
1b8be32e
RP
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 }
30af55f9 227 irqclr |= IRQENB_FIFO0THRES;
1b8be32e
RP
228 }
229
230 /*
231 * Time for sequencer to settle, to read
232 * correct state of the sequencer.
233 */
234 udelay(SEQ_SETTLE);
235
55c04de5 236 status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
1b8be32e
RP
237 if (status & IRQENB_PENUP) {
238 /* Pen up event */
55c04de5 239 fsm = titsc_readl(ts_dev, REG_ADCFSM);
1b8be32e
RP
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
55c04de5 251 titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
1b8be32e 252
2b99bafa 253 titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
1b8be32e
RP
254 return IRQ_HANDLED;
255}
256
257/*
258 * The functions for inserting/removing driver as a module.
259 */
260
55c04de5 261static int __devinit titsc_probe(struct platform_device *pdev)
1b8be32e 262{
55c04de5 263 struct titsc *ts_dev;
1b8be32e 264 struct input_dev *input_dev;
2b99bafa
PR
265 struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
266 struct mfd_tscadc_board *pdata;
1b8be32e 267 int err;
1b8be32e 268
2b99bafa 269 pdata = tscadc_dev->dev->platform_data;
1b8be32e 270
2b99bafa
PR
271 if (!pdata) {
272 dev_err(&pdev->dev, "Could not find platform data\n");
1b8be32e
RP
273 return -EINVAL;
274 }
275
276 /* Allocate memory for device */
55c04de5 277 ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
1b8be32e
RP
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
2b99bafa
PR
285 tscadc_dev->tsc = ts_dev;
286 ts_dev->mfd_tscadc = tscadc_dev;
1b8be32e 287 ts_dev->input = input_dev;
2b99bafa
PR
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;
1b8be32e 292
55c04de5 293 err = request_irq(ts_dev->irq, titsc_irq,
1b8be32e
RP
294 0, pdev->dev.driver->name, ts_dev);
295 if (err) {
296 dev_err(&pdev->dev, "failed to allocate irq.\n");
2b99bafa 297 goto err_free_mem;
1b8be32e 298 }
1b8be32e 299
55c04de5
PR
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);
1b8be32e 303
2b99bafa 304 input_dev->name = "ti-tsc";
1b8be32e
RP
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)
2b99bafa 317 goto err_free_irq;
1b8be32e
RP
318
319 platform_set_drvdata(pdev, ts_dev);
320 return 0;
321
1b8be32e
RP
322err_free_irq:
323 free_irq(ts_dev->irq, ts_dev);
1b8be32e
RP
324err_free_mem:
325 input_free_device(input_dev);
326 kfree(ts_dev);
327 return err;
328}
329
55c04de5 330static int __devexit titsc_remove(struct platform_device *pdev)
1b8be32e 331{
2b99bafa
PR
332 struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
333 struct titsc *ts_dev = tscadc_dev->tsc;
1b8be32e
RP
334
335 free_irq(ts_dev->irq, ts_dev);
336
337 input_unregister_device(ts_dev->input);
338
2b99bafa
PR
339 platform_set_drvdata(pdev, NULL);
340 kfree(ts_dev);
341 return 0;
342}
1b8be32e 343
2b99bafa
PR
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}
1b8be32e 359
2b99bafa
PR
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;
1b8be32e 364
2b99bafa
PR
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);
1b8be32e
RP
373 return 0;
374}
375
2b99bafa
PR
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
1b8be32e 385static struct platform_driver ti_tsc_driver = {
55c04de5
PR
386 .probe = titsc_probe,
387 .remove = __devexit_p(titsc_remove),
1b8be32e
RP
388 .driver = {
389 .name = "tsc",
390 .owner = THIS_MODULE,
2b99bafa 391 .pm = TITSC_PM_OPS,
1b8be32e
RP
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");