aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen/ads7846.c
diff options
context:
space:
mode:
authorImre Deak <imre.deak@solidboot.com>2007-01-18 00:45:43 -0500
committerDmitry Torokhov <dtor@insightbb.com>2007-01-18 00:45:43 -0500
commit15e3589e59c35ed33823dda3d38ad171222b83b4 (patch)
tree11e2cad189b9fae914b497d360a65f80674b7042 /drivers/input/touchscreen/ads7846.c
parent7937e86a70235e1584486654687dc9908a11e00a (diff)
Input: ads7846 - detect pen up from GPIO state
We can't depend on the pressure value to determine when the pen was lifted, so use the GPIO line state instead. This also helps with chips (like ads7843) that don't have pressure sensors. Signed-off-by: Imre Deak <imre.deak@solidboot.com> Signed-off-by: Juha Yrjola <juha.yrjola@solidboot.com> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/touchscreen/ads7846.c')
-rw-r--r--drivers/input/touchscreen/ads7846.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 11979be33589..b18c63a3f2ab 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -378,11 +378,8 @@ static struct attribute_group ads7845_attr_group = {
378static void ads7846_rx(void *ads) 378static void ads7846_rx(void *ads)
379{ 379{
380 struct ads7846 *ts = ads; 380 struct ads7846 *ts = ads;
381 struct input_dev *input_dev = ts->input;
382 unsigned Rt; 381 unsigned Rt;
383 unsigned sync = 0;
384 u16 x, y, z1, z2; 382 u16 x, y, z1, z2;
385 unsigned long flags;
386 383
387 /* ads7846_rx_val() did in-place conversion (including byteswap) from 384 /* ads7846_rx_val() did in-place conversion (including byteswap) from
388 * on-the-wire format as part of debouncing to get stable readings. 385 * on-the-wire format as part of debouncing to get stable readings.
@@ -396,7 +393,7 @@ static void ads7846_rx(void *ads)
396 if (x == MAX_12BIT) 393 if (x == MAX_12BIT)
397 x = 0; 394 x = 0;
398 395
399 if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { 396 if (likely(x && z1)) {
400 /* compute touch pressure resistance using equation #2 */ 397 /* compute touch pressure resistance using equation #2 */
401 Rt = z2; 398 Rt = z2;
402 Rt -= z1; 399 Rt -= z1;
@@ -412,52 +409,44 @@ static void ads7846_rx(void *ads)
412 * once more the measurement 409 * once more the measurement
413 */ 410 */
414 if (ts->tc.ignore || Rt > ts->pressure_max) { 411 if (ts->tc.ignore || Rt > ts->pressure_max) {
412#ifdef VERBOSE
413 pr_debug("%s: ignored %d pressure %d\n",
414 ts->spi->dev.bus_id, ts->tc.ignore, Rt);
415#endif
415 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 416 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
416 HRTIMER_REL); 417 HRTIMER_REL);
417 return; 418 return;
418 } 419 }
419 420
420 /* NOTE: "pendown" is inferred from pressure; we don't rely on 421 /* NOTE: We can't rely on the pressure to determine the pen down
421 * being able to check nPENIRQ status, or "friendly" trigger modes 422 * state, even this controller has a pressure sensor. The pressure
422 * (both-edges is much better than just-falling or low-level). 423 * value can fluctuate for quite a while after lifting the pen and
423 * 424 * in some cases may not even settle at the expected value.
424 * REVISIT: some boards may require reading nPENIRQ; it's
425 * needed on 7843. and 7845 reads pressure differently...
426 * 425 *
427 * REVISIT: the touchscreen might not be connected; this code 426 * The only safe way to check for the pen up condition is in the
428 * won't notice that, even if nPENIRQ never fires ... 427 * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
429 */ 428 */
430 if (!ts->pendown && Rt != 0) {
431 input_report_key(input_dev, BTN_TOUCH, 1);
432 sync = 1;
433 } else if (ts->pendown && Rt == 0) {
434 input_report_key(input_dev, BTN_TOUCH, 0);
435 sync = 1;
436 }
437
438 if (Rt) { 429 if (Rt) {
439 input_report_abs(input_dev, ABS_X, x); 430 struct input_dev *input = ts->input;
440 input_report_abs(input_dev, ABS_Y, y);
441 sync = 1;
442 }
443 431
444 if (sync) { 432 if (!ts->pendown) {
445 input_report_abs(input_dev, ABS_PRESSURE, Rt); 433 input_report_key(input, BTN_TOUCH, 1);
446 input_sync(input_dev); 434 ts->pendown = 1;
447 } 435#ifdef VERBOSE
448 436 dev_dbg(&ts->spi->dev, "DOWN\n");
449#ifdef VERBOSE
450 if (Rt || ts->pendown)
451 pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
452 x, y, Rt, Rt ? "" : " UP");
453#endif 437#endif
438 }
439 input_report_abs(input, ABS_X, x);
440 input_report_abs(input, ABS_Y, y);
441 input_report_abs(input, ABS_PRESSURE, Rt);
454 442
455 spin_lock_irqsave(&ts->lock, flags); 443 input_sync(input);
444#ifdef VERBOSE
445 dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
446#endif
447 }
456 448
457 ts->pendown = (Rt != 0);
458 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL); 449 hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_REL);
459
460 spin_unlock_irqrestore(&ts->lock, flags);
461} 450}
462 451
463static int ads7846_debounce(void *ads, int data_idx, int *val) 452static int ads7846_debounce(void *ads, int data_idx, int *val)
@@ -553,14 +542,27 @@ static int ads7846_timer(struct hrtimer *handle)
553 542
554 spin_lock_irq(&ts->lock); 543 spin_lock_irq(&ts->lock);
555 544
556 if (unlikely(ts->msg_idx && !ts->pendown)) { 545 if (unlikely(!ts->get_pendown_state() ||
546 device_suspended(&ts->spi->dev))) {
547 if (ts->pendown) {
548 struct input_dev *input = ts->input;
549
550 input_report_key(input, BTN_TOUCH, 0);
551 input_report_abs(input, ABS_PRESSURE, 0);
552 input_sync(input);
553
554 ts->pendown = 0;
555#ifdef VERBOSE
556 dev_dbg(&ts->spi->dev, "UP\n");
557#endif
558 }
559
557 /* measurement cycle ended */ 560 /* measurement cycle ended */
558 if (!device_suspended(&ts->spi->dev)) { 561 if (!device_suspended(&ts->spi->dev)) {
559 ts->irq_disabled = 0; 562 ts->irq_disabled = 0;
560 enable_irq(ts->spi->irq); 563 enable_irq(ts->spi->irq);
561 } 564 }
562 ts->pending = 0; 565 ts->pending = 0;
563 ts->msg_idx = 0;
564 } else { 566 } else {
565 /* pen is still down, continue with the measurement */ 567 /* pen is still down, continue with the measurement */
566 ts->msg_idx = 0; 568 ts->msg_idx = 0;