aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/ads7846.c144
1 files changed, 114 insertions, 30 deletions
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index bdec112e89c4..fec3b9b22309 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -2,6 +2,8 @@
2 * ADS7846 based touchscreen and sensor driver 2 * ADS7846 based touchscreen and sensor driver
3 * 3 *
4 * Copyright (c) 2005 David Brownell 4 * Copyright (c) 2005 David Brownell
5 * Copyright (c) 2006 Nokia Corporation
6 * Various changes: Imre Deak <imre.deak@nokia.com>
5 * 7 *
6 * Using code from: 8 * Using code from:
7 * - corgi_ts.c 9 * - corgi_ts.c
@@ -34,17 +36,25 @@
34 36
35 37
36/* 38/*
37 * This code has been lightly tested on an ads7846. 39 * This code has been tested on an ads7846 / N770 device.
38 * Support for ads7843 and ads7845 has only been stubbed in. 40 * Support for ads7843 and ads7845 has only been stubbed in.
39 * 41 *
40 * Not yet done: investigate the values reported. Are x/y/pressure 42 * Not yet done: How accurate are the temperature and voltage
41 * event values sane enough for X11? How accurate are the temperature 43 * readings? (System-specific calibration should support
42 * and voltage readings? (System-specific calibration should support
43 * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) 44 * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.)
44 * 45 *
46 * IRQ handling needs a workaround because of a shortcoming in handling
47 * edge triggered IRQs on some platforms like the OMAP1/2. These
48 * platforms don't handle the ARM lazy IRQ disabling properly, thus we
49 * have to maintain our own SW IRQ disabled status. This should be
50 * removed as soon as the affected platform's IRQ handling is fixed.
51 *
45 * app note sbaa036 talks in more detail about accurate sampling... 52 * app note sbaa036 talks in more detail about accurate sampling...
46 * that ought to help in situations like LCDs inducing noise (which 53 * that ought to help in situations like LCDs inducing noise (which
47 * can also be helped by using synch signals) and more generally. 54 * can also be helped by using synch signals) and more generally.
55 * This driver tries to utilize the measures described in the app
56 * note. The strength of filtering can be set in the board-* specific
57 * files.
48 */ 58 */
49 59
50#define TS_POLL_PERIOD msecs_to_jiffies(10) 60#define TS_POLL_PERIOD msecs_to_jiffies(10)
@@ -91,6 +101,7 @@ struct ads7846 {
91 unsigned pending:1; /* P: lock */ 101 unsigned pending:1; /* P: lock */
92// FIXME remove "irq_disabled" 102// FIXME remove "irq_disabled"
93 unsigned irq_disabled:1; /* P: lock */ 103 unsigned irq_disabled:1; /* P: lock */
104 unsigned disabled:1;
94}; 105};
95 106
96/* leave chip selected when we're done, for quicker re-select? */ 107/* leave chip selected when we're done, for quicker re-select? */
@@ -161,6 +172,9 @@ struct ser_req {
161 struct spi_transfer xfer[6]; 172 struct spi_transfer xfer[6];
162}; 173};
163 174
175static void ads7846_enable(struct ads7846 *ts);
176static void ads7846_disable(struct ads7846 *ts);
177
164static int ads7846_read12_ser(struct device *dev, unsigned command) 178static int ads7846_read12_ser(struct device *dev, unsigned command)
165{ 179{
166 struct spi_device *spi = to_spi_device(dev); 180 struct spi_device *spi = to_spi_device(dev);
@@ -257,6 +271,37 @@ static ssize_t ads7846_pen_down_show(struct device *dev,
257 271
258static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 272static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
259 273
274static ssize_t ads7846_disable_show(struct device *dev,
275 struct device_attribute *attr, char *buf)
276{
277 struct ads7846 *ts = dev_get_drvdata(dev);
278
279 return sprintf(buf, "%u\n", ts->disabled);
280}
281
282static ssize_t ads7846_disable_store(struct device *dev,
283 struct device_attribute *attr,
284 const char *buf, size_t count)
285{
286 struct ads7846 *ts = dev_get_drvdata(dev);
287 char *endp;
288 int i;
289
290 i = simple_strtoul(buf, &endp, 10);
291 spin_lock_irq(&ts->lock);
292
293 if (i)
294 ads7846_disable(ts);
295 else
296 ads7846_enable(ts);
297
298 spin_unlock_irq(&ts->lock);
299
300 return count;
301}
302
303static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
304
260/*--------------------------------------------------------------------------*/ 305/*--------------------------------------------------------------------------*/
261 306
262/* 307/*
@@ -396,12 +441,9 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
396{ 441{
397 struct ads7846 *ts = handle; 442 struct ads7846 *ts = handle;
398 unsigned long flags; 443 unsigned long flags;
399 int r = IRQ_HANDLED;
400 444
401 spin_lock_irqsave(&ts->lock, flags); 445 spin_lock_irqsave(&ts->lock, flags);
402 if (ts->irq_disabled) 446 if (likely(!ts->irq_disabled && !ts->disabled)) {
403 r = IRQ_HANDLED;
404 else {
405 if (!ts->irq_disabled) { 447 if (!ts->irq_disabled) {
406 /* REVISIT irq logic for many ARM chips has cloned a 448 /* REVISIT irq logic for many ARM chips has cloned a
407 * bug wherein disabling an irq in its handler won't 449 * bug wherein disabling an irq in its handler won't
@@ -419,20 +461,17 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs)
419 } 461 }
420 } 462 }
421 spin_unlock_irqrestore(&ts->lock, flags); 463 spin_unlock_irqrestore(&ts->lock, flags);
422 return r; 464
465 return IRQ_HANDLED;
423} 466}
424 467
425/*--------------------------------------------------------------------------*/ 468/*--------------------------------------------------------------------------*/
426 469
427static int 470/* Must be called with ts->lock held */
428ads7846_suspend(struct spi_device *spi, pm_message_t message) 471static void ads7846_disable(struct ads7846 *ts)
429{ 472{
430 struct ads7846 *ts = dev_get_drvdata(&spi->dev); 473 if (ts->disabled)
431 unsigned long flags; 474 return;
432
433 spin_lock_irqsave(&ts->lock, flags);
434
435 spi->dev.power.power_state = message;
436 475
437 /* are we waiting for IRQ, or polling? */ 476 /* are we waiting for IRQ, or polling? */
438 if (!ts->pendown) { 477 if (!ts->pendown) {
@@ -448,9 +487,9 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message)
448 mod_timer(&ts->timer, jiffies); 487 mod_timer(&ts->timer, jiffies);
449 488
450 while (ts->pendown || ts->pending) { 489 while (ts->pendown || ts->pending) {
451 spin_unlock_irqrestore(&ts->lock, flags); 490 spin_unlock_irq(&ts->lock);
452 msleep(1); 491 msleep(1);
453 spin_lock_irqsave(&ts->lock, flags); 492 spin_lock_irq(&ts->lock);
454 } 493 }
455 } 494 }
456 495
@@ -458,17 +497,46 @@ ads7846_suspend(struct spi_device *spi, pm_message_t message)
458 * leave it that way after every request 497 * leave it that way after every request
459 */ 498 */
460 499
461 spin_unlock_irqrestore(&ts->lock, flags); 500 ts->disabled = 1;
501}
502
503/* Must be called with ts->lock held */
504static void ads7846_enable(struct ads7846 *ts)
505{
506 if (!ts->disabled)
507 return;
508
509 ts->disabled = 0;
510 ts->irq_disabled = 0;
511 enable_irq(ts->spi->irq);