Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: ads7846 - miscellaneous fixes

- Add disable attribute to support device locking mode where
unintentional touch event shouldn't wake up the system;
- Update comments;
- Add missing spin_lock_init;
- Do device resume with the lock held;
- Do cleanup calls / free memory in the reverse order of initialization.

Signed-off-by: Imre Deak <imre.deak@nokia.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Imre Deak and committed by
Dmitry Torokhov
7de90a8c c4febb94

+114 -30
+114 -30
drivers/input/touchscreen/ads7846.c
··· 2 2 * ADS7846 based touchscreen and sensor driver 3 3 * 4 4 * Copyright (c) 2005 David Brownell 5 + * Copyright (c) 2006 Nokia Corporation 6 + * Various changes: Imre Deak <imre.deak@nokia.com> 5 7 * 6 8 * Using code from: 7 9 * - corgi_ts.c ··· 36 34 37 35 38 36 /* 39 - * This code has been lightly tested on an ads7846. 37 + * This code has been tested on an ads7846 / N770 device. 40 38 * Support for ads7843 and ads7845 has only been stubbed in. 41 39 * 42 - * Not yet done: investigate the values reported. Are x/y/pressure 43 - * event values sane enough for X11? How accurate are the temperature 44 - * and voltage readings? (System-specific calibration should support 40 + * Not yet done: How accurate are the temperature and voltage 41 + * readings? (System-specific calibration should support 45 42 * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) 43 + * 44 + * IRQ handling needs a workaround because of a shortcoming in handling 45 + * edge triggered IRQs on some platforms like the OMAP1/2. These 46 + * platforms don't handle the ARM lazy IRQ disabling properly, thus we 47 + * have to maintain our own SW IRQ disabled status. This should be 48 + * removed as soon as the affected platform's IRQ handling is fixed. 46 49 * 47 50 * app note sbaa036 talks in more detail about accurate sampling... 48 51 * that ought to help in situations like LCDs inducing noise (which 49 52 * can also be helped by using synch signals) and more generally. 53 + * This driver tries to utilize the measures described in the app 54 + * note. The strength of filtering can be set in the board-* specific 55 + * files. 50 56 */ 51 57 52 58 #define TS_POLL_PERIOD msecs_to_jiffies(10) ··· 101 91 unsigned pending:1; /* P: lock */ 102 92 // FIXME remove "irq_disabled" 103 93 unsigned irq_disabled:1; /* P: lock */ 94 + unsigned disabled:1; 104 95 }; 105 96 106 97 /* leave chip selected when we're done, for quicker re-select? */ ··· 171 160 struct spi_message msg; 172 161 struct spi_transfer xfer[6]; 173 162 }; 163 + 164 + static void ads7846_enable(struct ads7846 *ts); 165 + static void ads7846_disable(struct ads7846 *ts); 174 166 175 167 static int ads7846_read12_ser(struct device *dev, unsigned command) 176 168 { ··· 270 256 } 271 257 272 258 static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 259 + 260 + static ssize_t ads7846_disable_show(struct device *dev, 261 + struct device_attribute *attr, char *buf) 262 + { 263 + struct ads7846 *ts = dev_get_drvdata(dev); 264 + 265 + return sprintf(buf, "%u\n", ts->disabled); 266 + } 267 + 268 + static ssize_t ads7846_disable_store(struct device *dev, 269 + struct device_attribute *attr, 270 + const char *buf, size_t count) 271 + { 272 + struct ads7846 *ts = dev_get_drvdata(dev); 273 + char *endp; 274 + int i; 275 + 276 + i = simple_strtoul(buf, &endp, 10); 277 + spin_lock_irq(&ts->lock); 278 + 279 + if (i) 280 + ads7846_disable(ts); 281 + else 282 + ads7846_enable(ts); 283 + 284 + spin_unlock_irq(&ts->lock); 285 + 286 + return count; 287 + } 288 + 289 + static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); 273 290 274 291 /*--------------------------------------------------------------------------*/ 275 292 ··· 441 396 { 442 397 struct ads7846 *ts = handle; 443 398 unsigned long flags; 444 - int r = IRQ_HANDLED; 445 399 446 400 spin_lock_irqsave(&ts->lock, flags); 447 - if (ts->irq_disabled) 448 - r = IRQ_HANDLED; 449 - else { 401 + if (likely(!ts->irq_disabled && !ts->disabled)) { 450 402 if (!ts->irq_disabled) { 451 403 /* REVISIT irq logic for many ARM chips has cloned a 452 404 * bug wherein disabling an irq in its handler won't ··· 461 419 } 462 420 } 463 421 spin_unlock_irqrestore(&ts->lock, flags); 464 - return r; 422 + 423 + return IRQ_HANDLED; 465 424 } 466 425 467 426 /*--------------------------------------------------------------------------*/ 468 427 469 - static int 470 - ads7846_suspend(struct spi_device *spi, pm_message_t message) 428 + /* Must be called with ts->lock held */ 429 + static void ads7846_disable(struct ads7846 *ts) 471 430 { 472 - struct ads7846 *ts = dev_get_drvdata(&spi->dev); 473 - unsigned long flags; 474 - 475 - spin_lock_irqsave(&ts->lock, flags); 476 - 477 - spi->dev.power.power_state = message; 431 + if (ts->disabled) 432 + return; 478 433 479 434 /* are we waiting for IRQ, or polling? */ 480 435 if (!ts->pendown) { ··· 487 448 mod_timer(&ts->timer, jiffies); 488 449 489 450 while (ts->pendown || ts->pending) { 490 - spin_unlock_irqrestore(&ts->lock, flags); 451 + spin_unlock_irq(&ts->lock); 491 452 msleep(1); 492 - spin_lock_irqsave(&ts->lock, flags); 453 + spin_lock_irq(&ts->lock); 493 454 } 494 455 } 495 456 ··· 497 458 * leave it that way after every request 498 459 */ 499 460 500 - spin_unlock_irqrestore(&ts->lock, flags); 461 + ts->disabled = 1; 462 + } 463 + 464 + /* Must be called with ts->lock held */ 465 + static void ads7846_enable(struct ads7846 *ts) 466 + { 467 + if (!ts->disabled) 468 + return; 469 + 470 + ts->disabled = 0; 471 + ts->irq_disabled = 0; 472 + enable_irq(ts->spi->irq); 473 + } 474 + 475 + static int ads7846_suspend(struct spi_device *spi, pm_message_t message) 476 + { 477 + struct ads7846 *ts = dev_get_drvdata(&spi->dev); 478 + 479 + spin_lock_irq(&ts->lock); 480 + 481 + spi->dev.power.power_state = message; 482 + ads7846_disable(ts); 483 + 484 + spin_unlock_irq(&ts->lock); 485 + 501 486 return 0; 487 + 502 488 } 503 489 504 490 static int ads7846_resume(struct spi_device *spi) 505 491 { 506 492 struct ads7846 *ts = dev_get_drvdata(&spi->dev); 507 493 508 - ts->irq_disabled = 0; 509 - enable_irq(ts->spi->irq); 494 + spin_lock_irq(&ts->lock); 495 + 510 496 spi->dev.power.power_state = PMSG_ON; 497 + ads7846_enable(ts); 498 + 499 + spin_unlock_irq(&ts->lock); 500 + 511 501 return 0; 512 502 } 513 503 ··· 588 520 init_timer(&ts->timer); 589 521 ts->timer.data = (unsigned long) ts; 590 522 ts->timer.function = ads7846_timer; 523 + 524 + spin_lock_init(&ts->lock); 591 525 592 526 ts->model = pdata->model ? : 7846; 593 527 ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; ··· 741 671 742 672 device_create_file(&spi->dev, &dev_attr_pen_down); 743 673 674 + device_create_file(&spi->dev, &dev_attr_disable); 675 + 744 676 err = input_register_device(input_dev); 745 677 if (err) 746 - goto err_free_irq; 678 + goto err_remove_attr; 747 679 748 680 return 0; 749 681 750 - err_free_irq: 682 + err_remove_attr: 683 + device_remove_file(&spi->dev, &dev_attr_disable); 684 + device_remove_file(&spi->dev, &dev_attr_pen_down); 685 + if (ts->model == 7846) { 686 + device_remove_file(&spi->dev, &dev_attr_temp1); 687 + device_remove_file(&spi->dev, &dev_attr_temp0); 688 + } 689 + if (ts->model != 7845) 690 + device_remove_file(&spi->dev, &dev_attr_vbatt); 691 + device_remove_file(&spi->dev, &dev_attr_vaux); 692 + 751 693 free_irq(spi->irq, ts); 752 694 err_free_mem: 753 695 input_free_device(input_dev); ··· 771 689 { 772 690 struct ads7846 *ts = dev_get_drvdata(&spi->dev); 773 691 692 + input_unregister_device(ts->input); 693 + 774 694 ads7846_suspend(spi, PMSG_SUSPEND); 775 - free_irq(ts->spi->irq, ts); 776 - if (ts->irq_disabled) 777 - enable_irq(ts->spi->irq); 778 695 696 + device_remove_file(&spi->dev, &dev_attr_disable); 779 697 device_remove_file(&spi->dev, &dev_attr_pen_down); 780 - 781 698 if (ts->model == 7846) { 782 - device_remove_file(&spi->dev, &dev_attr_temp0); 783 699 device_remove_file(&spi->dev, &dev_attr_temp1); 700 + device_remove_file(&spi->dev, &dev_attr_temp0); 784 701 } 785 702 if (ts->model != 7845) 786 703 device_remove_file(&spi->dev, &dev_attr_vbatt); 787 704 device_remove_file(&spi->dev, &dev_attr_vaux); 788 705 789 - input_unregister_device(ts->input); 706 + free_irq(ts->spi->irq, ts); 707 + if (ts->irq_disabled) 708 + enable_irq(ts->spi->irq); 709 + 790 710 kfree(ts); 791 711 792 712 dev_dbg(&spi->dev, "unregistered touchscreen\n");