2 * TI Touch Screen driver
4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
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.
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.
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>
27 #include <linux/input/ti_am335x_tsc.h>
28 #include <linux/delay.h>
30 #include <linux/mfd/ti_am335x_tscadc.h>
32 #define ADCFSM_STEPID 0x10
33 #define SEQ_SETTLE 275
34 #define MAX_12BIT ((1 << 12) - 1)
37 struct input_dev
*input
;
38 struct ti_tscadc_dev
*mfd_tscadc
;
41 unsigned int x_plate_resistance
;
43 int steps_to_configure
;
46 static unsigned int titsc_readl(struct titsc
*ts
, unsigned int reg
)
48 return readl(ts
->mfd_tscadc
->tscadc_base
+ reg
);
51 static void titsc_writel(struct titsc
*tsc
, unsigned int reg
,
54 writel(val
, tsc
->mfd_tscadc
->tscadc_base
+ reg
);
57 static void titsc_step_config(struct titsc
*ts_dev
)
62 /* Configure the Step registers */
63 total_steps
= 2 * ts_dev
->steps_to_configure
;
65 config
= STEPCONFIG_MODE_HWSYNC
|
66 STEPCONFIG_AVG_16
| STEPCONFIG_XPP
;
67 switch (ts_dev
->wires
) {
69 config
|= STEPCONFIG_INP_AN2
| STEPCONFIG_XNN
;
72 config
|= STEPCONFIG_YNN
|
73 STEPCONFIG_INP_AN4
| STEPCONFIG_XNN
|
77 config
|= STEPCONFIG_INP_AN2
| STEPCONFIG_XNN
;
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
);
87 config
= STEPCONFIG_MODE_HWSYNC
|
88 STEPCONFIG_AVG_16
| STEPCONFIG_YNN
|
89 STEPCONFIG_INM_ADCREFM
| STEPCONFIG_FIFO1
;
90 switch (ts_dev
->wires
) {
92 config
|= STEPCONFIG_YPP
;
95 config
|= STEPCONFIG_XPP
| STEPCONFIG_INP_AN4
|
96 STEPCONFIG_XNP
| STEPCONFIG_YPN
;
99 config
|= STEPCONFIG_YPP
;
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
);
109 /* Charge step configuration */
110 config
= STEPCONFIG_XPP
| STEPCONFIG_YNN
|
111 STEPCHARGE_RFP_XPUL
| STEPCHARGE_RFM_XNUR
|
112 STEPCHARGE_INM_AN1
| STEPCHARGE_INP_AN1
;
114 titsc_writel(ts_dev
, REG_CHARGECONFIG
, config
);
115 titsc_writel(ts_dev
, REG_CHARGEDELAY
, CHARGEDLY_OPENDLY
);
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),
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),
131 titsc_writel(ts_dev
, REG_SE
, STPENB_STEPENB_TC
);
134 static void titsc_read_coordinates(struct titsc
*ts_dev
,
135 unsigned int *x
, unsigned int *y
)
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
;
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.
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
)) {
157 diff
= abs(read
- prev_val_x
);
158 if (diff
< prev_diff_x
) {
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))) {
171 diff
= abs(read
- prev_val_y
);
172 if (diff
< prev_diff_y
) {
181 static irqreturn_t
titsc_irq(int irq
, void *dev
)
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
;
189 unsigned int fifo1count
, fifo0count
;
192 status
= titsc_readl(ts_dev
, REG_IRQSTATUS
);
193 if (status
& IRQENB_FIFO0THRES
) {
194 titsc_read_coordinates(ts_dev
, &x
, &y
);
196 z1
= titsc_readl(ts_dev
, REG_FIFO0
) & 0xfff;
197 z2
= titsc_readl(ts_dev
, REG_FIFO1
) & 0xfff;
199 fifo1count
= titsc_readl(ts_dev
, REG_FIFO1CNT
);
200 for (i
= 0; i
< fifo1count
; i
++)
201 titsc_readl(ts_dev
, REG_FIFO1
);
203 fifo0count
= titsc_readl(ts_dev
, REG_FIFO0CNT
);
204 for (i
= 0; i
< fifo0count
; i
++)
205 titsc_readl(ts_dev
, REG_FIFO0
);
207 if (ts_dev
->pen_down
&& z1
!= 0 && z2
!= 0) {
209 * Calculate pressure using formula
210 * Resistance(touch) = x plate resistance *
211 * x postion/4096 * ((z2 / z1) - 1)
215 z
*= ts_dev
->x_plate_resistance
;
217 z
= (z
+ 2047) >> 12;
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
);
227 irqclr
|= IRQENB_FIFO0THRES
;
231 * Time for sequencer to settle, to read
232 * correct state of the sequencer.
236 status
= titsc_readl(ts_dev
, REG_RAWIRQSTATUS
);
237 if (status
& IRQENB_PENUP
) {
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
);
246 ts_dev
->pen_down
= true;
248 irqclr
|= IRQENB_PENUP
;
251 titsc_writel(ts_dev
, REG_IRQSTATUS
, irqclr
);
253 titsc_writel(ts_dev
, REG_SE
, STPENB_STEPENB_TC
);
258 * The functions for inserting/removing driver as a module.
261 static int titsc_probe(struct platform_device
*pdev
)
263 struct titsc
*ts_dev
;
264 struct input_dev
*input_dev
;
265 struct ti_tscadc_dev
*tscadc_dev
= ti_tscadc_dev_get(pdev
);
266 struct mfd_tscadc_board
*pdata
;
269 pdata
= tscadc_dev
->dev
->platform_data
;
272 dev_err(&pdev
->dev
, "Could not find platform data\n");
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");
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
;
293 err
= request_irq(ts_dev
->irq
, titsc_irq
,
294 0, pdev
->dev
.driver
->name
, ts_dev
);
296 dev_err(&pdev
->dev
, "failed to allocate irq.\n");
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
);
304 input_dev
->name
= "ti-tsc";
305 input_dev
->dev
.parent
= &pdev
->dev
;
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
);
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);
314 /* register to the input system */
315 err
= input_register_device(input_dev
);
319 platform_set_drvdata(pdev
, ts_dev
);
323 free_irq(ts_dev
->irq
, ts_dev
);
325 input_free_device(input_dev
);
330 static int titsc_remove(struct platform_device
*pdev
)
332 struct titsc
*ts_dev
= platform_get_drvdata(pdev
);
335 free_irq(ts_dev
->irq
, ts_dev
);
337 input_unregister_device(ts_dev
->input
);
339 platform_set_drvdata(pdev
, NULL
);
345 static int titsc_suspend(struct device
*dev
)
347 struct titsc
*ts_dev
= dev_get_drvdata(dev
);
348 struct ti_tscadc_dev
*tscadc_dev
;
351 tscadc_dev
= ti_tscadc_dev_get(to_platform_device(dev
));
352 if (device_may_wakeup(tscadc_dev
->dev
)) {
353 idle
= titsc_readl(ts_dev
, REG_IRQENABLE
);
354 titsc_writel(ts_dev
, REG_IRQENABLE
,
355 (idle
| IRQENB_HW_PEN
));
356 titsc_writel(ts_dev
, REG_IRQWAKEUP
, IRQWKUP_ENB
);
361 static int titsc_resume(struct device
*dev
)
363 struct titsc
*ts_dev
= dev_get_drvdata(dev
);
364 struct ti_tscadc_dev
*tscadc_dev
;
366 tscadc_dev
= ti_tscadc_dev_get(to_platform_device(dev
));
367 if (device_may_wakeup(tscadc_dev
->dev
)) {
368 titsc_writel(ts_dev
, REG_IRQWAKEUP
,
370 titsc_writel(ts_dev
, REG_IRQCLR
, IRQENB_HW_PEN
);
372 titsc_step_config(ts_dev
);
373 titsc_writel(ts_dev
, REG_FIFO0THR
,
374 ts_dev
->steps_to_configure
);
378 static const struct dev_pm_ops titsc_pm_ops
= {
379 .suspend
= titsc_suspend
,
380 .resume
= titsc_resume
,
382 #define TITSC_PM_OPS (&titsc_pm_ops)
384 #define TITSC_PM_OPS NULL
387 static struct platform_driver ti_tsc_driver
= {
388 .probe
= titsc_probe
,
389 .remove
= titsc_remove
,
392 .owner
= THIS_MODULE
,
396 module_platform_driver(ti_tsc_driver
);
398 MODULE_DESCRIPTION("TI touchscreen controller driver");
399 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
400 MODULE_LICENSE("GPL");