aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/ti_am335x_tsc.c
diff options
context:
space:
mode:
authorBrad Griffis <bgriffis@ti.com>2015-02-03 14:44:12 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-02-03 14:50:38 -0500
commit344d635b9a41b19837ccf8083a99ea688027019c (patch)
treef1b09497f07b3d825a66ba14f793d41605eedfdd /drivers/input/touchscreen/ti_am335x_tsc.c
parent3a59684ccc5d529e7e9ce8b068889dbaa4c34e9b (diff)
Input: ti_am335x_tsc - remove udelay in interrupt handler
TSC interrupt handler had udelay to avoid reporting of false pen-up interrupt to user space. This patch implements workaround suggesting in Advisory 1.0.31 of silicon errata for am335x, thus eliminating udelay and touchscreen lag. This also improves performance of touchscreen and eliminates sudden jump of cursor at touch release. IDLECONFIG and CHARGECONFIG registers are to be configured with same values in order to eliminate false pen-up events. This workaround may result in false pen-down to be detected, hence considerable charge step delay needs to be added. The charge delay is set to 0xB000 (in terms of ADC clock cycles) by default. TSC steps are disabled at the end of every sampling cycle and EOS bit is set. Once the EOS bit is set, the TSC steps need to be re-enabled to begin next sampling cycle. Signed-off-by: Brad Griffis <bgriffis@ti.com> [vigneshr@ti.com: Ported the patch from v3.12 to v3.19rc1] Signed-off-by: Vignesh R <vigneshr@ti.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/touchscreen/ti_am335x_tsc.c')
-rw-r--r--drivers/input/touchscreen/ti_am335x_tsc.c67
1 files changed, 31 insertions, 36 deletions
diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index dfbb9fe6a270..0625c102a1d0 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -173,11 +173,9 @@ static void titsc_step_config(struct titsc *ts_dev)
173 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY); 173 titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
174 } 174 }
175 175
176 /* Charge step configuration */ 176 /* Make CHARGECONFIG same as IDLECONFIG */
177 config = ts_dev->bit_xp | ts_dev->bit_yn |
178 STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
179 STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
180 177
178 config = titsc_readl(ts_dev, REG_IDLECONFIG);
181 titsc_writel(ts_dev, REG_CHARGECONFIG, config); 179 titsc_writel(ts_dev, REG_CHARGECONFIG, config);
182 titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY); 180 titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
183 181
@@ -261,12 +259,34 @@ static irqreturn_t titsc_irq(int irq, void *dev)
261{ 259{
262 struct titsc *ts_dev = dev; 260 struct titsc *ts_dev = dev;
263 struct input_dev *input_dev = ts_dev->input; 261 struct input_dev *input_dev = ts_dev->input;
264 unsigned int status, irqclr = 0; 262 unsigned int fsm, status, irqclr = 0;
265 unsigned int x = 0, y = 0; 263 unsigned int x = 0, y = 0;
266 unsigned int z1, z2, z; 264 unsigned int z1, z2, z;
267 unsigned int fsm;
268 265
269 status = titsc_readl(ts_dev, REG_IRQSTATUS); 266 status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
267 if (status & IRQENB_HW_PEN) {
268 ts_dev->pen_down = true;
269 titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
270 titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
271 irqclr |= IRQENB_HW_PEN;
272 }
273
274 if (status & IRQENB_PENUP) {
275 fsm = titsc_readl(ts_dev, REG_ADCFSM);
276 if (fsm == ADCFSM_STEPID) {
277 ts_dev->pen_down = false;
278 input_report_key(input_dev, BTN_TOUCH, 0);
279 input_report_abs(input_dev, ABS_PRESSURE, 0);
280 input_sync(input_dev);
281 } else {
282 ts_dev->pen_down = true;
283 }
284 irqclr |= IRQENB_PENUP;
285 }
286
287 if (status & IRQENB_EOS)
288 irqclr |= IRQENB_EOS;
289
270 /* 290 /*
271 * ADC and touchscreen share the IRQ line. 291 * ADC and touchscreen share the IRQ line.
272 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only 292 * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
@@ -297,37 +317,11 @@ static irqreturn_t titsc_irq(int irq, void *dev)
297 } 317 }
298 irqclr |= IRQENB_FIFO0THRES; 318 irqclr |= IRQENB_FIFO0THRES;
299 } 319 }
300
301 /*
302 * Time for sequencer to settle, to read
303 * correct state of the sequencer.
304 */
305 udelay(SEQ_SETTLE);
306
307 status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
308 if (status & IRQENB_PENUP) {
309 /* Pen up event */
310 fsm = titsc_readl(ts_dev, REG_ADCFSM);
311 if (fsm == ADCFSM_STEPID) {
312 ts_dev->pen_down = false;
313 input_report_key(input_dev, BTN_TOUCH, 0);
314 input_report_abs(input_dev, ABS_PRESSURE, 0);
315 input_sync(input_dev);
316 } else {
317 ts_dev->pen_down = true;
318 }
319 irqclr |= IRQENB_PENUP;
320 }
321
322 if (status & IRQENB_HW_PEN) {
323
324 titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
325 titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
326 }
327
328 if (irqclr) { 320 if (irqclr) {
329 titsc_writel(ts_dev, REG_IRQSTATUS, irqclr); 321 titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
330 am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask); 322 if (status & IRQENB_EOS)
323 am335x_tsc_se_set_cache(ts_dev->mfd_tscadc,
324 ts_dev->step_mask);
331 return IRQ_HANDLED; 325 return IRQ_HANDLED;
332 } 326 }
333 return IRQ_NONE; 327 return IRQ_NONE;
@@ -417,6 +411,7 @@ static int titsc_probe(struct platform_device *pdev)
417 } 411 }
418 412
419 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES); 413 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
414 titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_EOS);
420 err = titsc_config_wires(ts_dev); 415 err = titsc_config_wires(ts_dev);
421 if (err) { 416 if (err) {
422 dev_err(&pdev->dev, "wrong i/p wire configuration\n"); 417 dev_err(&pdev->dev, "wrong i/p wire configuration\n");