]> err.no Git - linux-2.6/blobdiff - drivers/input/touchscreen/ads7846.c
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
[linux-2.6] / drivers / input / touchscreen / ads7846.c
index 1c9069cd3bae4228fe1ed142c8c6543b4467ad11..58934a40f5ce5ff90abfbe071327370598d0e631 100644 (file)
@@ -83,7 +83,7 @@ struct ads7846 {
 
 #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE)
        struct attribute_group  *attr_group;
-       struct class_device     *hwmon;
+       struct device           *hwmon;
 #endif
 
        u16                     model;
@@ -95,7 +95,7 @@ struct ads7846 {
        u16                     dummy;          /* for the pwrdown read */
        struct ts_event         tc;
 
-       struct spi_transfer     xfer[10];
+       struct spi_transfer     xfer[18];
        struct spi_message      msg[5];
        struct spi_message      *last_msg;
        int                     msg_idx;
@@ -107,6 +107,8 @@ struct ads7846 {
        u16                     debounce_tol;
        u16                     debounce_rep;
 
+       u16                     penirq_recheck_delay_usecs;
+
        spinlock_t              lock;
        struct hrtimer          timer;
        unsigned                pendown:1;      /* P: lock */
@@ -114,6 +116,7 @@ struct ads7846 {
 // FIXME remove "irq_disabled"
        unsigned                irq_disabled:1; /* P: lock */
        unsigned                disabled:1;
+       unsigned                is_suspended:1;
 
        int                     (*filter)(void *data, int data_idx, int *val);
        void                    *filter_data;
@@ -201,7 +204,7 @@ static void ads7846_disable(struct ads7846 *ts);
 static int device_suspended(struct device *dev)
 {
        struct ads7846 *ts = dev_get_drvdata(dev);
-       return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
+       return ts->is_suspended || ts->disabled;
 }
 
 static int ads7846_read12_ser(struct device *dev, unsigned command)
@@ -265,13 +268,12 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
        ts->irq_disabled = 0;
        enable_irq(spi->irq);
 
-       if (req->msg.status)
-               status = req->msg.status;
-
-       /* on-wire is a must-ignore bit, a BE12 value, then padding */
-       sample = be16_to_cpu(req->sample);
-       sample = sample >> 3;
-       sample &= 0x0fff;
+       if (status == 0) {
+               /* on-wire is a must-ignore bit, a BE12 value, then padding */
+               sample = be16_to_cpu(req->sample);
+               sample = sample >> 3;
+               sample &= 0x0fff;
+       }
 
        kfree(req);
        return status ? status : sample;
@@ -367,7 +369,7 @@ static struct attribute_group ads7845_attr_group = {
 
 static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts)
 {
-       struct class_device *hwmon;
+       struct device *hwmon;
        int err;
 
        /* hwmon sensors need a reference voltage */
@@ -553,6 +555,15 @@ static void ads7846_rx(void *ads)
                return;
        }
 
+       /* Maybe check the pendown state before reporting. This discards
+        * false readings when the pen is lifted.
+        */
+       if (ts->penirq_recheck_delay_usecs) {
+               udelay(ts->penirq_recheck_delay_usecs);
+               if (!ts->get_pendown_state())
+                       Rt = 0;
+       }
+
        /* NOTE: We can't rely on the pressure to determine the pen down
         * state, even this controller has a pressure sensor.  The pressure
         * value can fluctuate for quite a while after lifting the pen and
@@ -784,7 +795,7 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
 
        spin_lock_irq(&ts->lock);
 
-       spi->dev.power.power_state = message;
+       ts->is_suspended = 1;
        ads7846_disable(ts);
 
        spin_unlock_irq(&ts->lock);
@@ -799,7 +810,7 @@ static int ads7846_resume(struct spi_device *spi)
 
        spin_lock_irq(&ts->lock);
 
-       spi->dev.power.power_state = PMSG_ON;
+       ts->is_suspended = 0;
        ads7846_enable(ts);
 
        spin_unlock_irq(&ts->lock);
@@ -861,7 +872,6 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        }
 
        dev_set_drvdata(&spi->dev, ts);
-       spi->dev.power.power_state = PMSG_ON;
 
        ts->spi = spi;
        ts->input = input_dev;
@@ -896,14 +906,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                ts->filter = ads7846_no_filter;
        ts->get_pendown_state = pdata->get_pendown_state;
 
+       if (pdata->penirq_recheck_delay_usecs)
+               ts->penirq_recheck_delay_usecs =
+                               pdata->penirq_recheck_delay_usecs;
+
        snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
 
        input_dev->name = "ADS784x Touchscreen";
        input_dev->phys = ts->phys;
        input_dev->dev.parent = &spi->dev;
 
-       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
        input_set_abs_params(input_dev, ABS_X,
                        pdata->x_min ? : 0,
                        pdata->x_max ? : MAX_12BIT,
@@ -936,6 +950,24 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        x->len = 2;
        spi_message_add_tail(x, m);
 
+       /* the first sample after switching drivers can be low quality;
+        * optionally discard it, using a second one after the signals
+        * have had enough time to stabilize.
+        */
+       if (pdata->settle_delay_usecs) {
+               x->delay_usecs = pdata->settle_delay_usecs;
+
+               x++;
+               x->tx_buf = &ts->read_y;
+               x->len = 1;
+               spi_message_add_tail(x, m);
+
+               x++;
+               x->rx_buf = &ts->tc.y;
+               x->len = 2;
+               spi_message_add_tail(x, m);
+       }
+
        m->complete = ads7846_rx_val;
        m->context = ts;
 
@@ -954,6 +986,21 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        x->len = 2;
        spi_message_add_tail(x, m);
 
+       /* ... maybe discard first sample ... */
+       if (pdata->settle_delay_usecs) {
+               x->delay_usecs = pdata->settle_delay_usecs;
+
+               x++;
+               x->tx_buf = &ts->read_x;
+               x->len = 1;
+               spi_message_add_tail(x, m);
+
+               x++;
+               x->rx_buf = &ts->tc.x;
+               x->len = 2;
+               spi_message_add_tail(x, m);
+       }
+
        m->complete = ads7846_rx_val;
        m->context = ts;
 
@@ -973,6 +1020,21 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                x->len = 2;
                spi_message_add_tail(x, m);
 
+               /* ... maybe discard first sample ... */
+               if (pdata->settle_delay_usecs) {
+                       x->delay_usecs = pdata->settle_delay_usecs;
+
+                       x++;
+                       x->tx_buf = &ts->read_z1;
+                       x->len = 1;
+                       spi_message_add_tail(x, m);
+
+                       x++;
+                       x->rx_buf = &ts->tc.z1;
+                       x->len = 2;
+                       spi_message_add_tail(x, m);
+               }
+
                m->complete = ads7846_rx_val;
                m->context = ts;
 
@@ -990,6 +1052,21 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                x->len = 2;
                spi_message_add_tail(x, m);
 
+               /* ... maybe discard first sample ... */
+               if (pdata->settle_delay_usecs) {
+                       x->delay_usecs = pdata->settle_delay_usecs;
+
+                       x++;
+                       x->tx_buf = &ts->read_z2;
+                       x->len = 1;
+                       spi_message_add_tail(x, m);
+
+                       x++;
+                       x->rx_buf = &ts->tc.z2;
+                       x->len = 2;
+                       spi_message_add_tail(x, m);
+               }
+
                m->complete = ads7846_rx_val;
                m->context = ts;
        }