diff options
author | Imre Deak <imre.deak@solidboot.com> | 2007-01-18 00:45:43 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2007-01-18 00:45:43 -0500 |
commit | 15e3589e59c35ed33823dda3d38ad171222b83b4 (patch) | |
tree | 11e2cad189b9fae914b497d360a65f80674b7042 /drivers/input | |
parent | 7937e86a70235e1584486654687dc9908a11e00a (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')
-rw-r--r-- | drivers/input/touchscreen/ads7846.c | 80 |
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 = { | |||
378 | static void ads7846_rx(void *ads) | 378 | static 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 | ||
463 | static int ads7846_debounce(void *ads, int data_idx, int *val) | 452 | static 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; |