Add support for the ads7843 touchscreen controller to the ads7846
driver code.
The "pen down" information is managed quite differently as we
do not have a touch-pressure measurement on the ads7843.

Signed-off-by: Nicolas Ferre <[EMAIL PROTECTED]>
---

I add a ads7843_rx function to manage the end of a measurement cycle.
As for ads7846_rx, it does the real work and communicates with the
input subsystem.
The timer function is responsible of taking the pen up/pen down state
through the board specific get_pendown_state() callback.

As the SPI underlying code behaves quite differently from a controller
driver to another while not having a tx_buf filled, I have add a
zeroed buffer to give to the SPI layer while receiving data.

===================================================================
--- a/input/touchscreen/ads7846.c       (.../linux-2.6.19-at91/drivers) 
(revision 634)
+++ b/input/touchscreen/ads7846.c       (.../linux-2.6.19-atmel-devel/drivers)  
(revision 634)
@@ -4,6 +4,7 @@
 * Copyright (c) 2005 David Brownell
 * Copyright (c) 2006 Nokia Corporation
 * Various changes: Imre Deak <[EMAIL PROTECTED]>
+ * Ads7843 support: Atmel, Nicolas Ferre <[EMAIL PROTECTED]>
 *
 * Using code from:
 *  - corgi_ts.c
@@ -38,7 +39,8 @@
/*
 * This code has been heavily tested on a Nokia 770, and lightly
 * tested on other ads7846 devices (OSK/Mistral, Lubbock).
- * Support for ads7843 and ads7845 has only been stubbed in.
+ * Support for ads7843 tested on Atmel at91sam926x-EK.
+ * Support for ads7845 has only been stubbed in.
 *
 * IRQ handling needs a workaround because of a shortcoming in handling
 * edge triggered IRQs on some platforms like the OMAP1/2. These
@@ -82,6 +84,7 @@ struct ads7846 {
        u16                     pressure_max;

        u8                      read_x, read_y, read_z1, read_z2, pwrdown;
+       u16                     zerro;          /* to send zerros while 
receiving */
        u16                     dummy;          /* for the pwrdown read */
        struct ts_event         tc;

@@ -151,6 +154,10 @@ struct ads7846 {
#define READ_X  (READ_12BIT_DFR(x)  | ADS_PD10_ADC_ON)
#define PWRDOWN (READ_12BIT_DFR(y)  | ADS_PD10_PDOWN)   /* LAST */

+/* alternate ads7843 commands */
+#define        ALT_READ_Y      (READ_12BIT_DFR(y)  | ADS_PD10_ALL_ON)
+#define        ALT_READ_X      (READ_12BIT_DFR(x)  | ADS_PD10_ALL_ON)
+
/* single-ended samples need to first power up reference voltage;
 * we leave both ADC and VREF powered
 */
@@ -171,6 +178,7 @@ struct ser_req {
        u8                      command;
        u8                      ref_off;
        u16                     scratch;
+       u16                     zerro;
        __be16                  sample;
        struct spi_message      msg;
        struct spi_transfer     xfer[6];
@@ -203,6 +211,7 @@ static int ads7846_read12_ser(struct dev
        req->ref_on = REF_ON;
        req->xfer[0].tx_buf = &req->ref_on;
        req->xfer[0].len = 1;
+       req->xfer[1].tx_buf = &req->zerro;
        req->xfer[1].rx_buf = &req->scratch;
        req->xfer[1].len = 2;

@@ -217,6 +226,7 @@ static int ads7846_read12_ser(struct dev
        req->command = (u8) command;
        req->xfer[2].tx_buf = &req->command;
        req->xfer[2].len = 1;
+       req->xfer[3].tx_buf = &req->zerro;
        req->xfer[3].rx_buf = &req->sample;
        req->xfer[3].len = 2;

@@ -226,6 +236,7 @@ static int ads7846_read12_ser(struct dev
        req->ref_off = REF_OFF;
        req->xfer[4].tx_buf = &req->ref_off;
        req->xfer[4].len = 1;
+       req->xfer[3].tx_buf = &req->zerro;
        req->xfer[5].rx_buf = &req->scratch;
        req->xfer[5].len = 2;

@@ -410,6 +421,50 @@ static void ads7846_rx(void *ads)
        spin_unlock_irqrestore(&ts->lock, flags);
}

+static void ads7843_rx(void *ads)
+{
+       struct ads7846          *ts = ads;
+       struct input_dev        *input_dev = ts->input;
+       u16                     x, y;
+       unsigned long           flags;
+
+       
+       /* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
+        * built from two 8 bit values written msb-first.
+        */
+       x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
+       y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
+
+       /* range filtering */
+       if (x == MAX_12BIT)
+               x = 0;
+
+       if (ts->pendown) {
+               input_report_key(input_dev, BTN_TOUCH, 1);
+               input_report_abs(input_dev, ABS_PRESSURE, ts->pressure_max / 2);
+               input_report_abs(input_dev, ABS_X, x);
+               input_report_abs(input_dev, ABS_Y, y);
+       } else {
+               input_report_key(input_dev, BTN_TOUCH, 0);
+               input_report_abs(input_dev, ABS_PRESSURE, 0);
+       }
+
+       input_sync(input_dev);
+
+#ifdef VERBOSE
+       pr_debug("%s: %d/%d%s\n", ts->spi->dev.bus_id,
+               x, y, ts->pendown ? "" : " UP");
+#endif
+
+       if (ts->pendown) {
+               spin_lock_irqsave(&ts->lock, flags);
+
+               mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+
+               spin_unlock_irqrestore(&ts->lock, flags);
+       }
+}
+
static void ads7846_debounce(void *ads)
{
        struct ads7846          *ts = ads;
@@ -465,11 +520,25 @@ static void ads7846_timer(unsigned long {
        struct ads7846  *ts = (void *)handle;
        int             status = 0;
+       int             alt_end_cycle = 0; /* ads7843 alternative cycle end */
+
+       if (ts->model == 7843) {
+               /* get sample */
+               ts->pendown = ts->get_pendown_state();
+               alt_end_cycle = ts->pending;
+       }

        spin_lock_irq(&ts->lock);

-       if (unlikely(ts->msg_idx && !ts->pendown)) {
+       if (unlikely(!ts->pendown && (ts->msg_idx || alt_end_cycle))) {
                /* measurement cycle ended */
+               if (ts->model == 7843) {
+                       status = spi_async(ts->spi, ts->last_msg);
+                       if (status)
+                               dev_err(&ts->spi->dev,
+                                       "spi_async --> %d\n", status);
+               }
+
                if (!device_suspended(&ts->spi->dev)) {
                        ts->irq_disabled = 0;
                        enable_irq(ts->spi->irq);
@@ -684,12 +753,17 @@ static int __devinit ads7846_probe(struc
        spi_message_init(m);

        /* y- still on; turn on only y+ (and ADC) */
-       ts->read_y = READ_Y;
+       if (ts->model == 7843) {
+               ts->read_y = ALT_READ_Y;
+       } else {
+               ts->read_y = READ_Y;
+       }
        x->tx_buf = &ts->read_y;
        x->len = 1;
        spi_message_add_tail(x, m);

        x++;
+       x->tx_buf = &ts->zerro;
        x->rx_buf = &ts->tc.y;
        x->len = 2;
        spi_message_add_tail(x, m);
@@ -702,12 +776,17 @@ static int __devinit ads7846_probe(struc

        /* turn y- off, x+ on, then leave in lowpower */
        x++;
-       ts->read_x = READ_X;
+       if (ts->model == 7843) {
+               ts->read_x = ALT_READ_X;
+       } else {
+               ts->read_x = READ_X;
+       }
        x->tx_buf = &ts->read_x;
        x->len = 1;
        spi_message_add_tail(x, m);

        x++;
+       x->tx_buf = &ts->zerro;
        x->rx_buf = &ts->tc.x;
        x->len = 2;
        spi_message_add_tail(x, m);
@@ -763,12 +842,17 @@ static int __devinit ads7846_probe(struc
        spi_message_add_tail(x, m);

        x++;
+       x->tx_buf = &ts->zerro;
        x->rx_buf = &ts->dummy;
        x->len = 2;
        CS_CHANGE(*x);
        spi_message_add_tail(x, m);

-       m->complete = ads7846_rx;
+       if (ts->model == 7843) {
+               m->complete = ads7843_rx;
+       } else {
+               m->complete = ads7846_rx;
+       }
        m->context = ts;

        ts->last_msg = m;
@@ -782,11 +866,16 @@ static int __devinit ads7846_probe(struc

        dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);

-       /* take a first sample, leaving nPENIRQ active; avoid
-        * the touchscreen, in case it's not connected.
-        */
-       (void) ads7846_read12_ser(&spi->dev,
-                         READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+       if (ts->model != 7843) {
+               /* take a first sample, leaving nPENIRQ active; avoid
+                * the touchscreen, in case it's not connected.
+                */
+               (void) ads7846_read12_ser(&spi->dev,
+                                 READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+       } else {
+               (void) ads7846_read12_ser(&spi->dev,
+                                 READ_12BIT_DFR(y) | ADS_PD10_ALL_ON);
+       }

        /* ads7843/7845 don't have temperature sensors, and
         * use the other sensors a bit differently too
@@ -795,12 +884,14 @@ static int __devinit ads7846_probe(struc
                device_create_file(&spi->dev, &dev_attr_temp0);
                device_create_file(&spi->dev, &dev_attr_temp1);
        }
-       if (ts->model != 7845)
+       if (ts->model != 7845 && ts->model != 7843)
                device_create_file(&spi->dev, &dev_attr_vbatt);
-       device_create_file(&spi->dev, &dev_attr_vaux);

-       device_create_file(&spi->dev, &dev_attr_pen_down);
+       if (ts->model != 7843) {
+               device_create_file(&spi->dev, &dev_attr_vaux);
+       }

+       device_create_file(&spi->dev, &dev_attr_pen_down);
        device_create_file(&spi->dev, &dev_attr_disable);

        err = input_register_device(input_dev);
@@ -816,9 +907,12 @@ static int __devinit ads7846_probe(struc
                device_remove_file(&spi->dev, &dev_attr_temp1);
                device_remove_file(&spi->dev, &dev_attr_temp0);
        }
-       if (ts->model != 7845)
+       if (ts->model != 7845 && ts->model != 7843)
                device_remove_file(&spi->dev, &dev_attr_vbatt);
-       device_remove_file(&spi->dev, &dev_attr_vaux);
+
+       if (ts->model != 7843) {
+               device_remove_file(&spi->dev, &dev_attr_vaux);
+       }

        free_irq(spi->irq, ts);
 err_free_mem:
@@ -841,9 +935,12 @@ static int __devexit ads7846_remove(stru
                device_remove_file(&spi->dev, &dev_attr_temp1);
                device_remove_file(&spi->dev, &dev_attr_temp0);
        }
-       if (ts->model != 7845)
+       if (ts->model != 7845 && ts->model != 7843)
                device_remove_file(&spi->dev, &dev_attr_vbatt);
-       device_remove_file(&spi->dev, &dev_attr_vaux);
+
+       if (ts->model != 7843) {
+               device_remove_file(&spi->dev, &dev_attr_vaux);
+       }

        free_irq(ts->spi->irq, ts);
        /* suspend left the IRQ disabled */


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to