aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-17 01:11:34 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2011-03-17 02:29:29 -0400
commit0b950d3d7ce4c1e870b8efc4ae0faaf0ef53532c (patch)
tree4d6f36f7564fec7465546bba3377642e4675f0c9 /drivers
parent71f80045d48f259ea423bae3c14c2361e010a9ce (diff)
Input: tsc2005 - add open/close
Introduce open and close methods for the input device to keep the device powered down when it is not in use. Also rework interaction between interrupt thread and starting/shutting off/resetting the device: instead of taking a mutex in the intterrupt thread and elsewhere disable interrupts before transitioning the device in a new state. The ESD handling is also separated from the IRQ thread; we poll regularly at a given interval and simply skip reads if we see that valid interrupt happened not so long ago. This allows us not cancel and reschedule ESD work from interrupt context all the time. Tested-by: Aaro Koskinen <aaro.koskinen@nokia.com> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/tsc2005.c218
1 files changed, 124 insertions, 94 deletions
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
index 5a15919ec4c7..3e1c9c297f33 100644
--- a/drivers/input/touchscreen/tsc2005.c
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -133,13 +133,14 @@ struct tsc2005 {
133 struct timer_list penup_timer; 133 struct timer_list penup_timer;
134 134
135 unsigned int esd_timeout; 135 unsigned int esd_timeout;
136 struct timer_list esd_timer; 136 struct delayed_work esd_work;
137 struct work_struct esd_work; 137 unsigned long last_valid_interrupt;
138 138
139 unsigned int x_plate_ohm; 139 unsigned int x_plate_ohm;
140 140
141 bool disabled; 141 bool disabled;
142 unsigned int disable_depth; 142 bool opened;
143 bool suspended;
143 144
144 bool pen_down; 145 bool pen_down;
145 146
@@ -258,11 +259,6 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
258 u32 z1, z2; 259 u32 z1, z2;
259 int error; 260 int error;
260 261
261 mutex_lock(&ts->mutex);
262
263 if (unlikely(ts->disable_depth))
264 goto out;
265
266 /* read the coordinates */ 262 /* read the coordinates */
267 error = spi_sync(ts->spi, &ts->spi_read_msg); 263 error = spi_sync(ts->spi, &ts->spi_read_msg);
268 if (unlikely(error)) 264 if (unlikely(error))
@@ -309,21 +305,13 @@ static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
309 spin_lock_irqsave(&ts->lock, flags); 305 spin_lock_irqsave(&ts->lock, flags);
310 306
311 tsc2005_update_pen_state(ts, x, y, pressure); 307 tsc2005_update_pen_state(ts, x, y, pressure);
312
313 /* set the penup timer */
314 mod_timer(&ts->penup_timer, 308 mod_timer(&ts->penup_timer,
315 jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS)); 309 jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
316 310
317 if (ts->esd_timeout && ts->set_reset) {
318 /* update the watchdog timer */
319 mod_timer(&ts->esd_timer, round_jiffies(jiffies +
320 msecs_to_jiffies(ts->esd_timeout)));
321 }
322
323 spin_unlock_irqrestore(&ts->lock, flags); 311 spin_unlock_irqrestore(&ts->lock, flags);
324 312
313 ts->last_valid_interrupt = jiffies;
325out: 314out:
326 mutex_unlock(&ts->mutex);
327 return IRQ_HANDLED; 315 return IRQ_HANDLED;
328} 316}
329 317
@@ -350,29 +338,31 @@ static void tsc2005_stop_scan(struct tsc2005 *ts)
350 tsc2005_cmd(ts, TSC2005_CMD_STOP); 338 tsc2005_cmd(ts, TSC2005_CMD_STOP);
351} 339}
352 340
353/* must be called with mutex held */ 341/* must be called with ts->mutex held */
354static void tsc2005_disable(struct tsc2005 *ts) 342static void __tsc2005_disable(struct tsc2005 *ts)
355{ 343{
356 if (ts->disable_depth++ != 0) 344 tsc2005_stop_scan(ts);
357 return; 345
358 disable_irq(ts->spi->irq); 346 disable_irq(ts->spi->irq);
359 if (ts->esd_timeout)
360 del_timer_sync(&ts->esd_timer);
361 del_timer_sync(&ts->penup_timer); 347 del_timer_sync(&ts->penup_timer);
362 tsc2005_stop_scan(ts); 348
349 cancel_delayed_work_sync(&ts->esd_work);
350
351 enable_irq(ts->spi->irq);
363} 352}
364 353
365/* must be called with mutex held */ 354/* must be called with ts->mutex held */
366static void tsc2005_enable(struct tsc2005 *ts) 355static void __tsc2005_enable(struct tsc2005 *ts)
367{ 356{
368 if (--ts->disable_depth != 0)
369 return;
370 tsc2005_start_scan(ts); 357 tsc2005_start_scan(ts);
371 enable_irq(ts->spi->irq); 358
372 if (!ts->esd_timeout) 359 if (ts->esd_timeout && ts->set_reset) {
373 return; 360 ts->last_valid_interrupt = jiffies;
374 mod_timer(&ts->esd_timer, 361 schedule_delayed_work(&ts->esd_work,
375 round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); 362 round_jiffies(jiffies +
363 msecs_to_jiffies(ts->esd_timeout)));
364 }
365
376} 366}
377 367
378static ssize_t tsc2005_disable_show(struct device *dev, 368static ssize_t tsc2005_disable_show(struct device *dev,
@@ -390,23 +380,29 @@ static ssize_t tsc2005_disable_store(struct device *dev,
390{ 380{
391 struct spi_device *spi = to_spi_device(dev); 381 struct spi_device *spi = to_spi_device(dev);
392 struct tsc2005 *ts = spi_get_drvdata(spi); 382 struct tsc2005 *ts = spi_get_drvdata(spi);
393 unsigned long res; 383 unsigned long val;
394 int i; 384 int error;
395 385
396 if (strict_strtoul(buf, 10, &res) < 0) 386 error = strict_strtoul(buf, 10, &val);
397 return -EINVAL; 387 if (error)
398 i = res ? 1 : 0; 388 return error;
399 389
400 mutex_lock(&ts->mutex); 390 mutex_lock(&ts->mutex);
401 if (i == ts->disabled) 391
402 goto out; 392 if (!ts->suspended && ts->opened) {
403 ts->disabled = i; 393 if (val) {
404 if (i) 394 if (!ts->disabled)
405 tsc2005_disable(ts); 395 __tsc2005_disable(ts);
406 else 396 } else {
407 tsc2005_enable(ts); 397 if (ts->disabled)
408out: 398 __tsc2005_enable(ts);
399 }
400 }
401
402 ts->disabled = !!val;
403
409 mutex_unlock(&ts->mutex); 404 mutex_unlock(&ts->mutex);
405
410 return count; 406 return count;
411} 407}
412static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store); 408static DEVICE_ATTR(disable, 0664, tsc2005_disable_show, tsc2005_disable_store);
@@ -428,7 +424,7 @@ static ssize_t tsc2005_selftest_show(struct device *dev,
428 /* 424 /*
429 * Test TSC2005 communications via temp high register. 425 * Test TSC2005 communications via temp high register.
430 */ 426 */
431 tsc2005_disable(ts); 427 __tsc2005_disable(ts);
432 428
433 error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig); 429 error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
434 if (error) { 430 if (error) {
@@ -484,7 +480,7 @@ static ssize_t tsc2005_selftest_show(struct device *dev,
484 } 480 }
485 481
486out: 482out:
487 tsc2005_enable(ts); 483 __tsc2005_enable(ts);
488 mutex_unlock(&ts->mutex); 484 mutex_unlock(&ts->mutex);
489 485
490 return sprintf(buf, "%d\n", success); 486 return sprintf(buf, "%d\n", success);
@@ -519,44 +515,79 @@ static const struct attribute_group tsc2005_attr_group = {
519 .attrs = tsc2005_attrs, 515 .attrs = tsc2005_attrs,
520}; 516};
521 517
522static void tsc2005_esd_timer(unsigned long data)
523{
524 struct tsc2005 *ts = (struct tsc2005 *)data;
525
526 schedule_work(&ts->esd_work);
527}
528
529static void tsc2005_esd_work(struct work_struct *work) 518static void tsc2005_esd_work(struct work_struct *work)
530{ 519{
531 struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work); 520 struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
532 int error; 521 int error;
533 u16 r; 522 u16 r;
534 523
535 mutex_lock(&ts->mutex); 524 mutex_lock(&ts->mutex);
536 525
537 if (ts->disable_depth) 526 if (time_is_after_jiffies(ts->last_valid_interrupt +
527 msecs_to_jiffies(ts->esd_timeout)))
538 goto out; 528 goto out;
539 529
540 /* 530 /* We should be able to read register without disabling interrupts. */
541 * If we cannot read our known value from configuration register 0 then
542 * reset the controller as if from power-up and start scanning again.
543 */
544 error = tsc2005_read(ts, TSC2005_REG_CFR0, &r); 531 error = tsc2005_read(ts, TSC2005_REG_CFR0, &r);
545 if (error || 532 if (!error &&
546 ((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) { 533 !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
547 dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n"); 534 goto out;
548 ts->set_reset(false);
549 tsc2005_update_pen_state(ts, 0, 0, 0);
550 usleep_range(100, 500); /* only 10us required */
551 ts->set_reset(true);
552 tsc2005_start_scan(ts);
553 } 535 }
554 536
555 /* re-arm the watchdog */ 537 /*
556 mod_timer(&ts->esd_timer, 538 * If we could not read our known value from configuration register 0
557 round_jiffies(jiffies + msecs_to_jiffies(ts->esd_timeout))); 539 * then we should reset the controller as if from power-up and start
540 * scanning again.
541 */
542 dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
543
544 disable_irq(ts->spi->irq);
545 del_timer_sync(&ts->penup_timer);
546
547 tsc2005_update_pen_state(ts, 0, 0, 0);
548
549 ts->set_reset(false);
550 usleep_range(100, 500); /* only 10us required */
551 ts->set_reset(true);
552
553 enable_irq(ts->spi->irq);
554 tsc2005_start_scan(ts);
558 555
559out: 556out:
557 /* re-arm the watchdog */
558 schedule_delayed_work(&ts->esd_work,
559 round_jiffies(jiffies +
560 msecs_to_jiffies(ts->esd_timeout)));
561 mutex_unlock(&ts->mutex);
562}
563
564static int tsc2005_open(struct input_dev *input)
565{
566 struct tsc2005 *ts = input_get_drvdata(input);
567
568 mutex_lock(&ts->mutex);
569
570 if (!ts->suspended && !ts->disabled)
571 __tsc2005_enable(ts);
572
573 ts->opened = true;
574
575 mutex_unlock(&ts->mutex);
576
577 return 0;
578}
579
580static void tsc2005_close(struct input_dev *input)
581{
582 struct tsc2005 *ts = input_get_drvdata(input);
583
584 mutex_lock(&ts->mutex);
585
586 if (!ts->suspended && !ts->disabled)
587 __tsc2005_disable(ts);
588
589 ts->opened = false;
590
560 mutex_unlock(&ts->mutex); 591 mutex_unlock(&ts->mutex);
561} 592}
562 593
@@ -628,8 +659,7 @@ static int __devinit tsc2005_probe(struct spi_device *spi)
628 spin_lock_init(&ts->lock); 659 spin_lock_init(&ts->lock);
629 setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts); 660 setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
630 661
631 setup_timer(&ts->esd_timer, tsc2005_esd_timer, (unsigned long)ts); 662 INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
632 INIT_WORK(&ts->esd_work, tsc2005_esd_work);
633 663
634 tsc2005_setup_spi_xfer(ts); 664 tsc2005_setup_spi_xfer(ts);
635 665
@@ -647,6 +677,14 @@ static int __devinit tsc2005_probe(struct spi_device *spi)
647 input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0); 677 input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
648 input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0); 678 input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
649 679
680 input_dev->open = tsc2005_open;
681 input_dev->close = tsc2005_close;
682
683 input_set_drvdata(input_dev, ts);
684
685 /* Ensure the touchscreen is off */
686 tsc2005_stop_scan(ts);
687
650 error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread, 688 error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread,
651 IRQF_TRIGGER_RISING, "tsc2005", ts); 689 IRQF_TRIGGER_RISING, "tsc2005", ts);
652 if (error) { 690 if (error) {
@@ -669,14 +707,6 @@ static int __devinit tsc2005_probe(struct spi_device *spi)
669 goto err_remove_sysfs; 707 goto err_remove_sysfs;
670 } 708 }
671 709
672 tsc2005_start_scan(ts);
673
674 if (ts->esd_timeout && ts->set_reset) {
675 /* start the optional ESD watchdog */
676 mod_timer(&ts->esd_timer, round_jiffies(jiffies +
677 msecs_to_jiffies(ts->esd_timeout)));
678 }
679
680 set_irq_wake(spi->irq, 1); 710 set_irq_wake(spi->irq, 1);
681 return 0; 711 return 0;
682 712
@@ -697,16 +727,6 @@ static int __devexit tsc2005_remove(struct spi_device *spi)
697 727
698 sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group); 728 sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
699 729
700 mutex_lock(&ts->mutex);
701 tsc2005_disable(ts);
702 mutex_unlock(&ts->mutex);
703
704 if (ts->esd_timeout)
705 del_timer_sync(&ts->esd_timer);
706 del_timer_sync(&ts->penup_timer);
707
708 flush_work(&ts->esd_work);
709
710 free_irq(ts->spi->irq, ts); 730 free_irq(ts->spi->irq, ts);
711 input_unregister_device(ts->idev); 731 input_unregister_device(ts->idev);
712 kfree(ts); 732 kfree(ts);
@@ -722,7 +742,12 @@ static int tsc2005_suspend(struct device *dev)
722 struct tsc2005 *ts = spi_get_drvdata(spi); 742 struct tsc2005 *ts = spi_get_drvdata(spi);
723 743
724 mutex_lock(&ts->mutex); 744 mutex_lock(&ts->mutex);
725 tsc2005_disable(ts); 745
746 if (!ts->suspended && !ts->disabled && ts->opened)
747 __tsc2005_disable(ts);
748
749 ts->suspended = true;
750
726 mutex_unlock(&ts->mutex); 751 mutex_unlock(&ts->mutex);
727 752
728 return 0; 753 return 0;
@@ -734,7 +759,12 @@ static int tsc2005_resume(struct device *dev)
734 struct tsc2005 *ts = spi_get_drvdata(spi); 759 struct tsc2005 *ts = spi_get_drvdata(spi);
735 760
736 mutex_lock(&ts->mutex); 761 mutex_lock(&ts->mutex);
737 tsc2005_enable(ts); 762
763 if (ts->suspended && !ts->disabled && ts->opened)
764 __tsc2005_enable(ts);
765
766 ts->suspended = false;
767
738 mutex_unlock(&ts->mutex); 768 mutex_unlock(&ts->mutex);
739 769
740 return 0; 770 return 0;