1ffa458c1SDavid Brownell /* 2ffa458c1SDavid Brownell * ADS7846 based touchscreen and sensor driver 3ffa458c1SDavid Brownell * 4ffa458c1SDavid Brownell * Copyright (c) 2005 David Brownell 57de90a8cSImre Deak * Copyright (c) 2006 Nokia Corporation 67de90a8cSImre Deak * Various changes: Imre Deak <imre.deak@nokia.com> 7ffa458c1SDavid Brownell * 8ffa458c1SDavid Brownell * Using code from: 9ffa458c1SDavid Brownell * - corgi_ts.c 10ffa458c1SDavid Brownell * Copyright (C) 2004-2005 Richard Purdie 11ffa458c1SDavid Brownell * - omap_ts.[hc], ads7846.h, ts_osk.c 12ffa458c1SDavid Brownell * Copyright (C) 2002 MontaVista Software 13ffa458c1SDavid Brownell * Copyright (C) 2004 Texas Instruments 14ffa458c1SDavid Brownell * Copyright (C) 2005 Dirk Behme 15ffa458c1SDavid Brownell * 16ffa458c1SDavid Brownell * This program is free software; you can redistribute it and/or modify 17ffa458c1SDavid Brownell * it under the terms of the GNU General Public License version 2 as 18ffa458c1SDavid Brownell * published by the Free Software Foundation. 19ffa458c1SDavid Brownell */ 20ffa458c1SDavid Brownell #include <linux/device.h> 21ffa458c1SDavid Brownell #include <linux/init.h> 22ffa458c1SDavid Brownell #include <linux/delay.h> 23ffa458c1SDavid Brownell #include <linux/input.h> 24ffa458c1SDavid Brownell #include <linux/interrupt.h> 25ffa458c1SDavid Brownell #include <linux/slab.h> 26ffa458c1SDavid Brownell #include <linux/spi/spi.h> 27ffa458c1SDavid Brownell #include <linux/spi/ads7846.h> 283ac8bf07SAndrew Morton #include <asm/irq.h> 29ffa458c1SDavid Brownell 30ffa458c1SDavid Brownell #ifdef CONFIG_ARM 31ffa458c1SDavid Brownell #include <asm/mach-types.h> 32ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 33ffa458c1SDavid Brownell #include <asm/arch/gpio.h> 34ffa458c1SDavid Brownell #endif 35ffa458c1SDavid Brownell #endif 36ffa458c1SDavid Brownell 37ffa458c1SDavid Brownell 38ffa458c1SDavid Brownell /* 399084533eSDavid Brownell * This code has been heavily tested on a Nokia 770, and lightly 409084533eSDavid Brownell * tested on other ads7846 devices (OSK/Mistral, Lubbock). 41ffa458c1SDavid Brownell * Support for ads7843 and ads7845 has only been stubbed in. 42ffa458c1SDavid Brownell * 437de90a8cSImre Deak * IRQ handling needs a workaround because of a shortcoming in handling 447de90a8cSImre Deak * edge triggered IRQs on some platforms like the OMAP1/2. These 457de90a8cSImre Deak * platforms don't handle the ARM lazy IRQ disabling properly, thus we 467de90a8cSImre Deak * have to maintain our own SW IRQ disabled status. This should be 477de90a8cSImre Deak * removed as soon as the affected platform's IRQ handling is fixed. 487de90a8cSImre Deak * 49ffa458c1SDavid Brownell * app note sbaa036 talks in more detail about accurate sampling... 50ffa458c1SDavid Brownell * that ought to help in situations like LCDs inducing noise (which 51ffa458c1SDavid Brownell * can also be helped by using synch signals) and more generally. 527de90a8cSImre Deak * This driver tries to utilize the measures described in the app 537de90a8cSImre Deak * note. The strength of filtering can be set in the board-* specific 547de90a8cSImre Deak * files. 55ffa458c1SDavid Brownell */ 56ffa458c1SDavid Brownell 57ffa458c1SDavid Brownell #define TS_POLL_PERIOD msecs_to_jiffies(10) 58ffa458c1SDavid Brownell 59d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */ 60d93f70b2SDavid Brownell #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) 61d93f70b2SDavid Brownell 62ffa458c1SDavid Brownell struct ts_event { 63ffa458c1SDavid Brownell /* For portability, we can't read 12 bit values using SPI (which 64ffa458c1SDavid Brownell * would make the controller deliver them as native byteorder u16 65d93f70b2SDavid Brownell * with msbs zeroed). Instead, we read them as two 8-bit values, 66da970e69SImre Deak * *** WHICH NEED BYTESWAPPING *** and range adjustment. 67ffa458c1SDavid Brownell */ 68da970e69SImre Deak u16 x; 69da970e69SImre Deak u16 y; 70da970e69SImre Deak u16 z1, z2; 71d5b415c9SImre Deak int ignore; 72ffa458c1SDavid Brownell }; 73ffa458c1SDavid Brownell 74ffa458c1SDavid Brownell struct ads7846 { 75a90f7e98SDmitry Torokhov struct input_dev *input; 76ffa458c1SDavid Brownell char phys[32]; 77ffa458c1SDavid Brownell 78ffa458c1SDavid Brownell struct spi_device *spi; 798dd51650SDmitry Torokhov struct attribute_group *attr_group; 80ffa458c1SDavid Brownell u16 model; 81ffa458c1SDavid Brownell u16 vref_delay_usecs; 82ffa458c1SDavid Brownell u16 x_plate_ohms; 83d5b415c9SImre Deak u16 pressure_max; 84ffa458c1SDavid Brownell 8553a0ef89SImre Deak u8 read_x, read_y, read_z1, read_z2, pwrdown; 8653a0ef89SImre Deak u16 dummy; /* for the pwrdown read */ 87ffa458c1SDavid Brownell struct ts_event tc; 88ffa458c1SDavid Brownell 8953a0ef89SImre Deak struct spi_transfer xfer[10]; 900b7018aaSImre Deak struct spi_message msg[5]; 91d5b415c9SImre Deak struct spi_message *last_msg; 920b7018aaSImre Deak int msg_idx; 930b7018aaSImre Deak int read_cnt; 94d5b415c9SImre Deak int read_rep; 950b7018aaSImre Deak int last_read; 960b7018aaSImre Deak 970b7018aaSImre Deak u16 debounce_max; 980b7018aaSImre Deak u16 debounce_tol; 99d5b415c9SImre Deak u16 debounce_rep; 100ffa458c1SDavid Brownell 101ffa458c1SDavid Brownell spinlock_t lock; 102ffa458c1SDavid Brownell struct timer_list timer; /* P: lock */ 103ffa458c1SDavid Brownell unsigned pendown:1; /* P: lock */ 104ffa458c1SDavid Brownell unsigned pending:1; /* P: lock */ 105ffa458c1SDavid Brownell // FIXME remove "irq_disabled" 106ffa458c1SDavid Brownell unsigned irq_disabled:1; /* P: lock */ 1077de90a8cSImre Deak unsigned disabled:1; 108c9e617a5SImre Deak 109da970e69SImre Deak int (*filter)(void *data, int data_idx, int *val); 110da970e69SImre Deak void *filter_data; 111da970e69SImre Deak void (*filter_cleanup)(void *data); 112c9e617a5SImre Deak int (*get_pendown_state)(void); 113ffa458c1SDavid Brownell }; 114ffa458c1SDavid Brownell 115ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */ 116ffa458c1SDavid Brownell #if 0 117ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 1) 118ffa458c1SDavid Brownell #else 119ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 0) 120ffa458c1SDavid Brownell #endif 121ffa458c1SDavid Brownell 122ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 123ffa458c1SDavid Brownell 124ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors. 125ffa458c1SDavid Brownell * Earlier ads784x chips are somewhat compatible. 126ffa458c1SDavid Brownell */ 127ffa458c1SDavid Brownell #define ADS_START (1 << 7) 128ffa458c1SDavid Brownell #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 129ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 130ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 131ffa458c1SDavid Brownell #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 132ffa458c1SDavid Brownell #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 133ffa458c1SDavid Brownell #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 134ffa458c1SDavid Brownell #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 135ffa458c1SDavid Brownell #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 136ffa458c1SDavid Brownell #define ADS_8_BIT (1 << 3) 137ffa458c1SDavid Brownell #define ADS_12_BIT (0 << 3) 138ffa458c1SDavid Brownell #define ADS_SER (1 << 2) /* non-differential */ 139ffa458c1SDavid Brownell #define ADS_DFR (0 << 2) /* differential */ 140ffa458c1SDavid Brownell #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ 141ffa458c1SDavid Brownell #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 142ffa458c1SDavid Brownell #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 143ffa458c1SDavid Brownell #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 144ffa458c1SDavid Brownell 145ffa458c1SDavid Brownell #define MAX_12BIT ((1<<12)-1) 146ffa458c1SDavid Brownell 147ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */ 148*de2defd9SImre Deak #define READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \ 149*de2defd9SImre Deak | ADS_12_BIT | ADS_DFR | \ 150*de2defd9SImre Deak (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) 151ffa458c1SDavid Brownell 152*de2defd9SImre Deak #define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) 153*de2defd9SImre Deak #define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) 154*de2defd9SImre Deak #define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) 15553a0ef89SImre Deak 156*de2defd9SImre Deak #define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) 157*de2defd9SImre Deak #define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ 158ffa458c1SDavid Brownell 159ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage; 160ffa458c1SDavid Brownell * we leave both ADC and VREF powered 161ffa458c1SDavid Brownell */ 162ffa458c1SDavid Brownell #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ 163ffa458c1SDavid Brownell | ADS_12_BIT | ADS_SER) 164ffa458c1SDavid Brownell 165*de2defd9SImre Deak #define REF_ON (READ_12BIT_DFR(x, 1, 1)) 166*de2defd9SImre Deak #define REF_OFF (READ_12BIT_DFR(y, 0, 0)) 167ffa458c1SDavid Brownell 168ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 169ffa458c1SDavid Brownell 170ffa458c1SDavid Brownell /* 171ffa458c1SDavid Brownell * Non-touchscreen sensors only use single-ended conversions. 172ffa458c1SDavid Brownell */ 173ffa458c1SDavid Brownell 174ffa458c1SDavid Brownell struct ser_req { 175d93f70b2SDavid Brownell u8 ref_on; 176ffa458c1SDavid Brownell u8 command; 177d93f70b2SDavid Brownell u8 ref_off; 178ffa458c1SDavid Brownell u16 scratch; 179ffa458c1SDavid Brownell __be16 sample; 180ffa458c1SDavid Brownell struct spi_message msg; 181ffa458c1SDavid Brownell struct spi_transfer xfer[6]; 182ffa458c1SDavid Brownell }; 183ffa458c1SDavid Brownell 1847de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts); 1857de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts); 1867de90a8cSImre Deak 187c9e617a5SImre Deak static int device_suspended(struct device *dev) 188c9e617a5SImre Deak { 189c9e617a5SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 190c9e617a5SImre Deak return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; 191c9e617a5SImre Deak } 192c9e617a5SImre Deak 193ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command) 194ffa458c1SDavid Brownell { 195ffa458c1SDavid Brownell struct spi_device *spi = to_spi_device(dev); 196ffa458c1SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); 197e94b1766SChristoph Lameter struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); 198ffa458c1SDavid Brownell int status; 199ffa458c1SDavid Brownell int sample; 2008275c642SVitaly Wool int i; 201ffa458c1SDavid Brownell 202ffa458c1SDavid Brownell if (!req) 203ffa458c1SDavid Brownell return -ENOMEM; 204ffa458c1SDavid Brownell 2050b7018aaSImre Deak spi_message_init(&req->msg); 2068275c642SVitaly Wool 207ffa458c1SDavid Brownell /* activate reference, so it has time to settle; */ 208d93f70b2SDavid Brownell req->ref_on = REF_ON; 209d93f70b2SDavid Brownell req->xfer[0].tx_buf = &req->ref_on; 210ffa458c1SDavid Brownell req->xfer[0].len = 1; 211ffa458c1SDavid Brownell req->xfer[1].rx_buf = &req->scratch; 212ffa458c1SDavid Brownell req->xfer[1].len = 2; 213ffa458c1SDavid Brownell 214ffa458c1SDavid Brownell /* 215ffa458c1SDavid Brownell * for external VREF, 0 usec (and assume it's always on); 216ffa458c1SDavid Brownell * for 1uF, use 800 usec; 217ffa458c1SDavid Brownell * no cap, 100 usec. 218ffa458c1SDavid Brownell */ 219ffa458c1SDavid Brownell req->xfer[1].delay_usecs = ts->vref_delay_usecs; 220ffa458c1SDavid Brownell 221ffa458c1SDavid Brownell /* take sample */ 222ffa458c1SDavid Brownell req->command = (u8) command; 223ffa458c1SDavid Brownell req->xfer[2].tx_buf = &req->command; 224ffa458c1SDavid Brownell req->xfer[2].len = 1; 225ffa458c1SDavid Brownell req->xfer[3].rx_buf = &req->sample; 226ffa458c1SDavid Brownell req->xfer[3].len = 2; 227ffa458c1SDavid Brownell 228ffa458c1SDavid Brownell /* REVISIT: take a few more samples, and compare ... */ 229ffa458c1SDavid Brownell 230ffa458c1SDavid Brownell /* turn off reference */ 231d93f70b2SDavid Brownell req->ref_off = REF_OFF; 232d93f70b2SDavid Brownell req->xfer[4].tx_buf = &req->ref_off; 233ffa458c1SDavid Brownell req->xfer[4].len = 1; 234ffa458c1SDavid Brownell req->xfer[5].rx_buf = &req->scratch; 235ffa458c1SDavid Brownell req->xfer[5].len = 2; 236ffa458c1SDavid Brownell 237ffa458c1SDavid Brownell CS_CHANGE(req->xfer[5]); 238ffa458c1SDavid Brownell 239ffa458c1SDavid Brownell /* group all the transfers together, so we can't interfere with 240ffa458c1SDavid Brownell * reading touchscreen state; disable penirq while sampling 241ffa458c1SDavid Brownell */ 2428275c642SVitaly Wool for (i = 0; i < 6; i++) 2438275c642SVitaly Wool spi_message_add_tail(&req->xfer[i], &req->msg); 244ffa458c1SDavid Brownell 245c9e617a5SImre Deak ts->irq_disabled = 1; 246ffa458c1SDavid Brownell disable_irq(spi->irq); 247ffa458c1SDavid Brownell status = spi_sync(spi, &req->msg); 248c9e617a5SImre Deak ts->irq_disabled = 0; 249ffa458c1SDavid Brownell enable_irq(spi->irq); 250ffa458c1SDavid Brownell 251ffa458c1SDavid Brownell if (req->msg.status) 252ffa458c1SDavid Brownell status = req->msg.status; 253ffa458c1SDavid Brownell 2549084533eSDavid Brownell /* on-wire is a must-ignore bit, a BE12 value, then padding */ 2559084533eSDavid Brownell sample = be16_to_cpu(req->sample); 2569084533eSDavid Brownell sample = sample >> 3; 2579084533eSDavid Brownell sample &= 0x0fff; 2589084533eSDavid Brownell 2599084533eSDavid Brownell kfree(req); 260ffa458c1SDavid Brownell return status ? status : sample; 261ffa458c1SDavid Brownell } 262ffa458c1SDavid Brownell 263ffa458c1SDavid Brownell #define SHOW(name) static ssize_t \ 264ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ 265ffa458c1SDavid Brownell { \ 266ffa458c1SDavid Brownell ssize_t v = ads7846_read12_ser(dev, \ 267ffa458c1SDavid Brownell READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ 268ffa458c1SDavid Brownell if (v < 0) \ 269ffa458c1SDavid Brownell return v; \ 270ffa458c1SDavid Brownell return sprintf(buf, "%u\n", (unsigned) v); \ 271ffa458c1SDavid Brownell } \ 272ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); 273ffa458c1SDavid Brownell 274ffa458c1SDavid Brownell SHOW(temp0) 275ffa458c1SDavid Brownell SHOW(temp1) 276ffa458c1SDavid Brownell SHOW(vaux) 277ffa458c1SDavid Brownell SHOW(vbatt) 278ffa458c1SDavid Brownell 279438f2a74SImre Deak static int is_pen_down(struct device *dev) 280438f2a74SImre Deak { 281438f2a74SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 282438f2a74SImre Deak 283438f2a74SImre Deak return ts->pendown; 284438f2a74SImre Deak } 285438f2a74SImre Deak 286438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev, 287438f2a74SImre Deak struct device_attribute *attr, char *buf) 288438f2a74SImre Deak { 289438f2a74SImre Deak return sprintf(buf, "%u\n", is_pen_down(dev)); 290438f2a74SImre Deak } 291438f2a74SImre Deak 292438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 293438f2a74SImre Deak 2947de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev, 2957de90a8cSImre Deak struct device_attribute *attr, char *buf) 2967de90a8cSImre Deak { 2977de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 2987de90a8cSImre Deak 2997de90a8cSImre Deak return sprintf(buf, "%u\n", ts->disabled); 3007de90a8cSImre Deak } 3017de90a8cSImre Deak 3027de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev, 3037de90a8cSImre Deak struct device_attribute *attr, 3047de90a8cSImre Deak const char *buf, size_t count) 3057de90a8cSImre Deak { 3067de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 3077de90a8cSImre Deak char *endp; 3087de90a8cSImre Deak int i; 3097de90a8cSImre Deak 3107de90a8cSImre Deak i = simple_strtoul(buf, &endp, 10); 3117de90a8cSImre Deak spin_lock_irq(&ts->lock); 3127de90a8cSImre Deak 3137de90a8cSImre Deak if (i) 3147de90a8cSImre Deak ads7846_disable(ts); 3157de90a8cSImre Deak else 3167de90a8cSImre Deak ads7846_enable(ts); 3177de90a8cSImre Deak 3187de90a8cSImre Deak spin_unlock_irq(&ts->lock); 3197de90a8cSImre Deak 3207de90a8cSImre Deak return count; 3217de90a8cSImre Deak } 3227de90a8cSImre Deak 3237de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); 3247de90a8cSImre Deak 3258dd51650SDmitry Torokhov static struct attribute *ads7846_attributes[] = { 3268dd51650SDmitry Torokhov &dev_attr_temp0.attr, 3278dd51650SDmitry Torokhov &dev_attr_temp1.attr, 3288dd51650SDmitry Torokhov &dev_attr_vbatt.attr, 3298dd51650SDmitry Torokhov &dev_attr_vaux.attr, 3308dd51650SDmitry Torokhov &dev_attr_pen_down.attr, 3318dd51650SDmitry Torokhov &dev_attr_disable.attr, 3328dd51650SDmitry Torokhov NULL, 3338dd51650SDmitry Torokhov }; 3348dd51650SDmitry Torokhov 3358dd51650SDmitry Torokhov static struct attribute_group ads7846_attr_group = { 3368dd51650SDmitry Torokhov .attrs = ads7846_attributes, 3378dd51650SDmitry Torokhov }; 3388dd51650SDmitry Torokhov 3398dd51650SDmitry Torokhov /* 3408dd51650SDmitry Torokhov * ads7843/7845 don't have temperature sensors, and 3418dd51650SDmitry Torokhov * use the other sensors a bit differently too 3428dd51650SDmitry Torokhov */ 3438dd51650SDmitry Torokhov 3448dd51650SDmitry Torokhov static struct attribute *ads7843_attributes[] = { 3458dd51650SDmitry Torokhov &dev_attr_vbatt.attr, 3468dd51650SDmitry Torokhov &dev_attr_vaux.attr, 3478dd51650SDmitry Torokhov &dev_attr_pen_down.attr, 3488dd51650SDmitry Torokhov &dev_attr_disable.attr, 3498dd51650SDmitry Torokhov NULL, 3508dd51650SDmitry Torokhov }; 3518dd51650SDmitry Torokhov 3528dd51650SDmitry Torokhov static struct attribute_group ads7843_attr_group = { 3538dd51650SDmitry Torokhov .attrs = ads7843_attributes, 3548dd51650SDmitry Torokhov }; 3558dd51650SDmitry Torokhov 3568dd51650SDmitry Torokhov static struct attribute *ads7845_attributes[] = { 3578dd51650SDmitry Torokhov &dev_attr_vaux.attr, 3588dd51650SDmitry Torokhov &dev_attr_pen_down.attr, 3598dd51650SDmitry Torokhov &dev_attr_disable.attr, 3608dd51650SDmitry Torokhov NULL, 3618dd51650SDmitry Torokhov }; 3628dd51650SDmitry Torokhov 3638dd51650SDmitry Torokhov static struct attribute_group ads7845_attr_group = { 3648dd51650SDmitry Torokhov .attrs = ads7845_attributes, 3658dd51650SDmitry Torokhov }; 3668dd51650SDmitry Torokhov 367ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 368ffa458c1SDavid Brownell 369ffa458c1SDavid Brownell /* 370ffa458c1SDavid Brownell * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, 371ffa458c1SDavid Brownell * to retrieve touchscreen status. 372ffa458c1SDavid Brownell * 373ffa458c1SDavid Brownell * The SPI transfer completion callback does the real work. It reports 374ffa458c1SDavid Brownell * touchscreen events and reactivates the timer (or IRQ) as appropriate. 375ffa458c1SDavid Brownell */ 376ffa458c1SDavid Brownell 377ffa458c1SDavid Brownell static void ads7846_rx(void *ads) 378ffa458c1SDavid Brownell { 379ffa458c1SDavid Brownell struct ads7846 *ts = ads; 380a90f7e98SDmitry Torokhov struct input_dev *input_dev = ts->input; 381ffa458c1SDavid Brownell unsigned Rt; 382ffa458c1SDavid Brownell unsigned sync = 0; 383ffa458c1SDavid Brownell u16 x, y, z1, z2; 384ffa458c1SDavid Brownell unsigned long flags; 385ffa458c1SDavid Brownell 386da970e69SImre Deak /* ads7846_rx_val() did in-place conversion (including byteswap) from 387da970e69SImre Deak * on-the-wire format as part of debouncing to get stable readings. 388ffa458c1SDavid Brownell */ 389da970e69SImre Deak x = ts->tc.x; 390da970e69SImre Deak y = ts->tc.y; 391da970e69SImre Deak z1 = ts->tc.z1; 392da970e69SImre Deak z2 = ts->tc.z2; 393ffa458c1SDavid Brownell 394ffa458c1SDavid Brownell /* range filtering */ 395ffa458c1SDavid Brownell if (x == MAX_12BIT) 396ffa458c1SDavid Brownell x = 0; 397ffa458c1SDavid Brownell 398c9e617a5SImre Deak if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { 399ffa458c1SDavid Brownell /* compute touch pressure resistance using equation #2 */ 400ffa458c1SDavid Brownell Rt = z2; 401ffa458c1SDavid Brownell Rt -= z1; 402ffa458c1SDavid Brownell Rt *= x; 403ffa458c1SDavid Brownell Rt *= ts->x_plate_ohms; 404ffa458c1SDavid Brownell Rt /= z1; 405ffa458c1SDavid Brownell Rt = (Rt + 2047) >> 12; 406ffa458c1SDavid Brownell } else 407ffa458c1SDavid Brownell Rt = 0; 408ffa458c1SDavid Brownell 409d5b415c9SImre Deak /* Sample found inconsistent by debouncing or pressure is beyond 410d5b415c9SImre Deak * the maximum. Don't report it to user space, repeat at least 411d5b415c9SImre Deak * once more the measurement */ 412d5b415c9SImre Deak if (ts->tc.ignore || Rt > ts->pressure_max) { 413d5b415c9SImre Deak mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 414d5b415c9SImre Deak return; 415d5b415c9SImre Deak } 416d5b415c9SImre Deak 417ffa458c1SDavid Brownell /* NOTE: "pendown" is inferred from pressure; we don't rely on 418ffa458c1SDavid Brownell * being able to check nPENIRQ status, or "friendly" trigger modes 419ffa458c1SDavid Brownell * (both-edges is much better than just-falling or low-level). 420ffa458c1SDavid Brownell * 421ffa458c1SDavid Brownell * REVISIT: some boards may require reading nPENIRQ; it's 422ffa458c1SDavid Brownell * needed on 7843. and 7845 reads pressure differently... 423ffa458c1SDavid Brownell * 424ffa458c1SDavid Brownell * REVISIT: the touchscreen might not be connected; this code 425ffa458c1SDavid Brownell * won't notice that, even if nPENIRQ never fires ... 426ffa458c1SDavid Brownell */ 427ffa458c1SDavid Brownell if (!ts->pendown && Rt != 0) { 428a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 1); 429ffa458c1SDavid Brownell sync = 1; 430ffa458c1SDavid Brownell } else if (ts->pendown && Rt == 0) { 431a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 0); 432ffa458c1SDavid Brownell sync = 1; 433ffa458c1SDavid Brownell } 434ffa458c1SDavid Brownell 435ffa458c1SDavid Brownell if (Rt) { 436a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_X, x); 437a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_Y, y); 438ffa458c1SDavid Brownell sync = 1; 439ffa458c1SDavid Brownell } 440ae82d5abSImre Deak 441ae82d5abSImre Deak if (sync) { 442ae82d5abSImre Deak input_report_abs(input_dev, ABS_PRESSURE, Rt); 443a90f7e98SDmitry Torokhov input_sync(input_dev); 444ae82d5abSImre Deak } 445ffa458c1SDavid Brownell 446ffa458c1SDavid Brownell #ifdef VERBOSE 447ffa458c1SDavid Brownell if (Rt || ts->pendown) 448ffa458c1SDavid Brownell pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, 449ffa458c1SDavid Brownell x, y, Rt, Rt ? "" : " UP"); 450ffa458c1SDavid Brownell #endif 451ffa458c1SDavid Brownell 452ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 453ffa458c1SDavid Brownell 454ffa458c1SDavid Brownell ts->pendown = (Rt != 0); 455ffa458c1SDavid Brownell mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 456ffa458c1SDavid Brownell 457ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 458ffa458c1SDavid Brownell } 459ffa458c1SDavid Brownell 460da970e69SImre Deak static int ads7846_debounce(void *ads, int data_idx, int *val) 461ffa458c1SDavid Brownell { 4620b7018aaSImre Deak struct ads7846 *ts = ads; 463ffa458c1SDavid Brownell 464da970e69SImre Deak if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) { 465da970e69SImre Deak /* Start over collecting consistent readings. */ 466da970e69SImre Deak ts->read_rep = 0; 467d5b415c9SImre Deak /* Repeat it, if this was the first read or the read 468d5b415c9SImre Deak * wasn't consistent enough. */ 469d5b415c9SImre Deak if (ts->read_cnt < ts->debounce_max) { 470da970e69SImre Deak ts->last_read = *val; 471d5b415c9SImre Deak ts->read_cnt++; 472da970e69SImre Deak return ADS7846_FILTER_REPEAT; 4730b7018aaSImre Deak } else { 474d5b415c9SImre Deak /* Maximum number of debouncing reached and still 475d5b415c9SImre Deak * not enough number of consistent readings. Abort 476d5b415c9SImre Deak * the whole sample, repeat it in the next sampling 477d5b415c9SImre Deak * period. 478d5b415c9SImre Deak */ 479d5b415c9SImre Deak ts->read_cnt = 0; 480da970e69SImre Deak return ADS7846_FILTER_IGNORE; 481d5b415c9SImre Deak } 482d5b415c9SImre Deak } else { 483d5b415c9SImre Deak if (++ts->read_rep > ts->debounce_rep) { 484d5b415c9SImre Deak /* Got a good reading for this coordinate, 485d5b415c9SImre Deak * go for the next one. */ 4860b7018aaSImre Deak ts->read_cnt = 0; 487d5b415c9SImre Deak ts->read_rep = 0; 488da970e69SImre Deak return ADS7846_FILTER_OK; 489da970e69SImre Deak } else { 490d5b415c9SImre Deak /* Read more values that are consistent. */ 491d5b415c9SImre Deak ts->read_cnt++; 492da970e69SImre Deak return ADS7846_FILTER_REPEAT; 493da970e69SImre Deak } 494da970e69SImre Deak } 495da970e69SImre Deak } 496da970e69SImre Deak 497da970e69SImre Deak static int ads7846_no_filter(void *ads, int data_idx, int *val) 498da970e69SImre Deak { 499da970e69SImre Deak return ADS7846_FILTER_OK; 500da970e69SImre Deak } 501da970e69SImre Deak 502da970e69SImre Deak static void ads7846_rx_val(void *ads) 503da970e69SImre Deak { 504da970e69SImre Deak struct ads7846 *ts = ads; 505da970e69SImre Deak struct spi_message *m; 506da970e69SImre Deak struct spi_transfer *t; 507da970e69SImre Deak u16 *rx_val; 508da970e69SImre Deak int val; 509da970e69SImre Deak int action; 510da970e69SImre Deak int status; 511da970e69SImre Deak 512da970e69SImre Deak m = &ts->msg[ts->msg_idx]; 513da970e69SImre Deak t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); 514da970e69SImre Deak rx_val = t->rx_buf; 515da970e69SImre Deak 516da970e69SImre Deak /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; 517da970e69SImre Deak * built from two 8 bit values written msb-first. 518da970e69SImre Deak */ 519da970e69SImre Deak val = be16_to_cpu(*rx_val) >> 3; 520da970e69SImre Deak 521da970e69SImre Deak action = ts->filter(ts->filter_data, ts->msg_idx, &val); 522da970e69SImre Deak switch (action) { 523da970e69SImre Deak case ADS7846_FILTER_REPEAT: 524da970e69SImre Deak break; 525da970e69SImre Deak case ADS7846_FILTER_IGNORE: 526da970e69SImre Deak ts->tc.ignore = 1; 527da970e69SImre Deak /* Last message will contain ads7846_rx() as the 528da970e69SImre Deak * completion function. 529da970e69SImre Deak */ 530da970e69SImre Deak m = ts->last_msg; 531da970e69SImre Deak break; 532da970e69SImre Deak case ADS7846_FILTER_OK: 533da970e69SImre Deak *rx_val = val; 534da970e69SImre Deak ts->tc.ignore = 0; 535da970e69SImre Deak m = &ts->msg[++ts->msg_idx]; 536da970e69SImre Deak break; 537da970e69SImre Deak default: 538da970e69SImre Deak BUG(); 539ffa458c1SDavid Brownell } 5400b7018aaSImre Deak status = spi_async(ts->spi, m); 541ffa458c1SDavid Brownell if (status) 542ffa458c1SDavid Brownell dev_err(&ts->spi->dev, "spi_async --> %d\n", 543ffa458c1SDavid Brownell status); 544ffa458c1SDavid Brownell } 5450b7018aaSImre Deak 5460b7018aaSImre Deak static void ads7846_timer(unsigned long handle) 5470b7018aaSImre Deak { 5480b7018aaSImre Deak struct ads7846 *ts = (void *)handle; 5490b7018aaSImre Deak int status = 0; 5500b7018aaSImre Deak 551c9e617a5SImre Deak spin_lock_irq(&ts->lock); 552c9e617a5SImre Deak 553c9e617a5SImre Deak if (unlikely(ts->msg_idx && !ts->pendown)) { 5549084533eSDavid Brownell /* measurement cycle ended */ 555c9e617a5SImre Deak if (!device_suspended(&ts->spi->dev)) { 556c9e617a5SImre Deak ts->irq_disabled = 0; 557c9e617a5SImre Deak enable_irq(ts->spi->irq); 558c9e617a5SImre Deak } 559c9e617a5SImre Deak ts->pending = 0; 560c9e617a5SImre Deak ts->msg_idx = 0; 561c9e617a5SImre Deak } else { 562c9e617a5SImre Deak /* pen is still down, continue with the measurement */ 5630b7018aaSImre Deak ts->msg_idx = 0; 5640b7018aaSImre Deak status = spi_async(ts->spi, &ts->msg[0]); 5650b7018aaSImre Deak if (status) 5660b7018aaSImre Deak dev_err(&ts->spi->dev, "spi_async --> %d\n", status); 567ffa458c1SDavid Brownell } 568ffa458c1SDavid Brownell 569c9e617a5SImre Deak spin_unlock_irq(&ts->lock); 570c9e617a5SImre Deak } 571c9e617a5SImre Deak 5727d12e780SDavid Howells static irqreturn_t ads7846_irq(int irq, void *handle) 573ffa458c1SDavid Brownell { 5740b7018aaSImre Deak struct ads7846 *ts = handle; 5750b7018aaSImre Deak unsigned long flags; 5760b7018aaSImre Deak 5770b7018aaSImre Deak spin_lock_irqsave(&ts->lock, flags); 578c9e617a5SImre Deak if (likely(ts->get_pendown_state())) { 5790b7018aaSImre Deak if (!ts->irq_disabled) { 5809084533eSDavid Brownell /* The ARM do_simple_IRQ() dispatcher doesn't act 5819084533eSDavid Brownell * like the other dispatchers: it will report IRQs 5829084533eSDavid Brownell * even after they've been disabled. We work around 5839084533eSDavid Brownell * that here. (The "generic irq" framework may help...) 5840b7018aaSImre Deak */ 5850b7018aaSImre Deak ts->irq_disabled = 1; 5860b7018aaSImre Deak disable_irq(ts->spi->irq); 5870b7018aaSImre Deak ts->pending = 1; 5880b7018aaSImre Deak mod_timer(&ts->timer, jiffies); 5890b7018aaSImre Deak } 5900b7018aaSImre Deak } 5910b7018aaSImre Deak spin_unlock_irqrestore(&ts->lock, flags); 5927de90a8cSImre Deak 5937de90a8cSImre Deak return IRQ_HANDLED; 594ffa458c1SDavid Brownell } 595ffa458c1SDavid Brownell 596ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 597ffa458c1SDavid Brownell 5987de90a8cSImre Deak /* Must be called with ts->lock held */ 5997de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts) 600ffa458c1SDavid Brownell { 6017de90a8cSImre Deak if (ts->disabled) 6027de90a8cSImre Deak return; 603ffa458c1SDavid Brownell 604c9e617a5SImre Deak ts->disabled = 1; 605c9e617a5SImre Deak 606ffa458c1SDavid Brownell /* are we waiting for IRQ, or polling? */ 607c9e617a5SImre Deak if (!ts->pending) { 608ffa458c1SDavid Brownell ts->irq_disabled = 1; 609ffa458c1SDavid Brownell disable_irq(ts->spi->irq); 610ffa458c1SDavid Brownell } else { 611c9e617a5SImre Deak /* the timer will run at least once more, and 612c9e617a5SImre Deak * leave everything in a clean state, IRQ disabled 613ffa458c1SDavid Brownell */ 614c9e617a5SImre Deak while (ts->pending) { 6157de90a8cSImre Deak spin_unlock_irq(&ts->lock); 616c4febb94SJuha Yrjola msleep(1); 6177de90a8cSImre Deak spin_lock_irq(&ts->lock); 618ffa458c1SDavid Brownell } 619ffa458c1SDavid Brownell } 620ffa458c1SDavid Brownell 621ffa458c1SDavid Brownell /* we know the chip's in lowpower mode since we always 622ffa458c1SDavid Brownell * leave it that way after every request 623ffa458c1SDavid Brownell */ 624ffa458c1SDavid Brownell 6257de90a8cSImre Deak } 6267de90a8cSImre Deak 6277de90a8cSImre Deak /* Must be called with ts->lock held */ 6287de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts) 6297de90a8cSImre Deak { 6307de90a8cSImre Deak if (!ts->disabled) 6317de90a8cSImre Deak return; 6327de90a8cSImre Deak 6337de90a8cSImre Deak ts->disabled = 0; 6347de90a8cSImre Deak ts->irq_disabled = 0; 6357de90a8cSImre Deak enable_irq(ts->spi->irq); 6367de90a8cSImre Deak } 6377de90a8cSImre Deak 6387de90a8cSImre Deak static int ads7846_suspend(struct spi_device *spi, pm_message_t message) 6397de90a8cSImre Deak { 6407de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(&spi->dev); 6417de90a8cSImre Deak 6427de90a8cSImre Deak spin_lock_irq(&ts->lock); 6437de90a8cSImre Deak 6447de90a8cSImre Deak spi->dev.power.power_state = message; 6457de90a8cSImre Deak ads7846_disable(ts); 6467de90a8cSImre Deak 6477de90a8cSImre Deak spin_unlock_irq(&ts->lock); 6487de90a8cSImre Deak 649ffa458c1SDavid Brownell return 0; 6507de90a8cSImre Deak 651ffa458c1SDavid Brownell } 652ffa458c1SDavid Brownell 6532e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi) 654ffa458c1SDavid Brownell { 6552e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 656ffa458c1SDavid Brownell 6577de90a8cSImre Deak spin_lock_irq(&ts->lock); 6587de90a8cSImre Deak 6592e5a7bd9SDavid Brownell spi->dev.power.power_state = PMSG_ON; 6607de90a8cSImre Deak ads7846_enable(ts); 6617de90a8cSImre Deak 6627de90a8cSImre Deak spin_unlock_irq(&ts->lock); 6637de90a8cSImre Deak 664ffa458c1SDavid Brownell return 0; 665ffa458c1SDavid Brownell } 666ffa458c1SDavid Brownell 6672e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi) 668ffa458c1SDavid Brownell { 669ffa458c1SDavid Brownell struct ads7846 *ts; 670a90f7e98SDmitry Torokhov struct input_dev *input_dev; 6712e5a7bd9SDavid Brownell struct ads7846_platform_data *pdata = spi->dev.platform_data; 6720b7018aaSImre Deak struct spi_message *m; 673ffa458c1SDavid Brownell struct spi_transfer *x; 674*de2defd9SImre Deak int vref; 675a90f7e98SDmitry Torokhov int err; 676ffa458c1SDavid Brownell 677ffa458c1SDavid Brownell if (!spi->irq) { 6782e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no IRQ?\n"); 679ffa458c1SDavid Brownell return -ENODEV; 680ffa458c1SDavid Brownell } 681ffa458c1SDavid Brownell 682ffa458c1SDavid Brownell if (!pdata) { 6832e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no platform data?\n"); 684ffa458c1SDavid Brownell return -ENODEV; 685ffa458c1SDavid Brownell } 686ffa458c1SDavid Brownell 687ffa458c1SDavid Brownell /* don't exceed max specified sample rate */ 688d93f70b2SDavid Brownell if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { 6892e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "f(sample) %d KHz?\n", 690d93f70b2SDavid Brownell (spi->max_speed_hz/SAMPLE_BITS)/1000); 691ffa458c1SDavid Brownell return -EINVAL; 692ffa458c1SDavid Brownell } 693ffa458c1SDavid Brownell 6949084533eSDavid Brownell /* REVISIT when the irq can be triggered active-low, or if for some 6959084533eSDavid Brownell * reason the touchscreen isn't hooked up, we don't need to access 6969084533eSDavid Brownell * the pendown state. 6979084533eSDavid Brownell */ 698c9e617a5SImre Deak if (pdata->get_pendown_state == NULL) { 699c9e617a5SImre Deak dev_dbg(&spi->dev, "no get_pendown_state function?\n"); 700c9e617a5SImre Deak return -EINVAL; 701c9e617a5SImre Deak } 702c9e617a5SImre Deak 7039084533eSDavid Brownell /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except 7049084533eSDavid Brownell * that even if the hardware can do that, the SPI controller driver 7059084533eSDavid Brownell * may not. So we stick to very-portable 8 bit words, both RX and TX. 706ffa458c1SDavid Brownell */ 7079084533eSDavid Brownell spi->bits_per_word = 8; 708ffa458c1SDavid Brownell 709a90f7e98SDmitry Torokhov ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); 710a90f7e98SDmitry Torokhov input_dev = input_allocate_device(); 711a90f7e98SDmitry Torokhov if (!ts || !input_dev) { 712a90f7e98SDmitry Torokhov err = -ENOMEM; 713a90f7e98SDmitry Torokhov goto err_free_mem; 714a90f7e98SDmitry Torokhov } 715ffa458c1SDavid Brownell 7162e5a7bd9SDavid Brownell dev_set_drvdata(&spi->dev, ts); 717a90f7e98SDmitry Torokhov spi->dev.power.power_state = PMSG_ON; 718ffa458c1SDavid Brownell 719ffa458c1SDavid Brownell ts->spi = spi; 720a90f7e98SDmitry Torokhov ts->input = input_dev; 721ffa458c1SDavid Brownell 722ffa458c1SDavid Brownell init_timer(&ts->timer); 723ffa458c1SDavid Brownell ts->timer.data = (unsigned long) ts; 724ffa458c1SDavid Brownell ts->timer.function = ads7846_timer; 725ffa458c1SDavid Brownell 7267de90a8cSImre Deak spin_lock_init(&ts->lock); 7277de90a8cSImre Deak 728ffa458c1SDavid Brownell ts->model = pdata->model ? : 7846; 729ffa458c1SDavid Brownell ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; 730ffa458c1SDavid Brownell ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 731d5b415c9SImre Deak ts->pressure_max = pdata->pressure_max ? : ~0; 732da970e69SImre Deak 733da970e69SImre Deak if (pdata->filter != NULL) { 734da970e69SImre Deak if (pdata->filter_init != NULL) { 735da970e69SImre Deak err = pdata->filter_init(pdata, &ts->filter_data); 736da970e69SImre Deak if (err < 0) 737da970e69SImre Deak goto err_free_mem; 738da970e69SImre Deak } 739da970e69SImre Deak ts->filter = pdata->filter; 740da970e69SImre Deak ts->filter_cleanup = pdata->filter_cleanup; 741da970e69SImre Deak } else if (pdata->debounce_max) { 742d5b415c9SImre Deak ts->debounce_max = pdata->debounce_max; 743da970e69SImre Deak if (ts->debounce_max < 2) 744da970e69SImre Deak ts->debounce_max = 2; 745d5b415c9SImre Deak ts->debounce_tol = pdata->debounce_tol; 746d5b415c9SImre Deak ts->debounce_rep = pdata->debounce_rep; 747da970e69SImre Deak ts->filter = ads7846_debounce; 748da970e69SImre Deak ts->filter_data = ts; 749d5b415c9SImre Deak } else 750da970e69SImre Deak ts->filter = ads7846_no_filter; 751c9e617a5SImre Deak ts->get_pendown_state = pdata->get_pendown_state; 752ffa458c1SDavid Brownell 753a90f7e98SDmitry Torokhov snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 754ffa458c1SDavid Brownell 755a90f7e98SDmitry Torokhov input_dev->name = "ADS784x Touchscreen"; 756a90f7e98SDmitry Torokhov input_dev->phys = ts->phys; 757a90f7e98SDmitry Torokhov input_dev->cdev.dev = &spi->dev; 758ffa458c1SDavid Brownell 759a90f7e98SDmitry Torokhov input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 760a90f7e98SDmitry Torokhov input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 761a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 762ffa458c1SDavid Brownell pdata->x_min ? : 0, 763ffa458c1SDavid Brownell pdata->x_max ? : MAX_12BIT, 764ffa458c1SDavid Brownell 0, 0); 765a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 766ffa458c1SDavid Brownell pdata->y_min ? : 0, 767ffa458c1SDavid Brownell pdata->y_max ? : MAX_12BIT, 768ffa458c1SDavid Brownell 0, 0); 769a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 770ffa458c1SDavid Brownell pdata->pressure_min, pdata->pressure_max, 0, 0); 771ffa458c1SDavid Brownell 772*de2defd9SImre Deak vref = pdata->keep_vref_on; 773*de2defd9SImre Deak 774ffa458c1SDavid Brownell /* set up the transfers to read touchscreen state; this assumes we 775ffa458c1SDavid Brownell * use formula #2 for pressure, not #3. 776ffa458c1SDavid Brownell */ 7770b7018aaSImre Deak m = &ts->msg[0]; 778ffa458c1SDavid Brownell x = ts->xfer; 779ffa458c1SDavid Brownell 7800b7018aaSImre Deak spi_message_init(m); 7810b7018aaSImre Deak 782ffa458c1SDavid Brownell /* y- still on; turn on only y+ (and ADC) */ 783*de2defd9SImre Deak ts->read_y = READ_Y(vref); 784d93f70b2SDavid Brownell x->tx_buf = &ts->read_y; 785ffa458c1SDavid Brownell x->len = 1; 7860b7018aaSImre Deak spi_message_add_tail(x, m); 787d93f70b2SDavid Brownell 788ffa458c1SDavid Brownell x++; 789ffa458c1SDavid Brownell x->rx_buf = &ts->tc.y; 790ffa458c1SDavid Brownell x->len = 2; 7910b7018aaSImre Deak spi_message_add_tail(x, m); 792ffa458c1SDavid Brownell 793da970e69SImre Deak m->complete = ads7846_rx_val; 7940b7018aaSImre Deak m->context = ts; 795d93f70b2SDavid Brownell 7960b7018aaSImre Deak m++; 7970b7018aaSImre Deak spi_message_init(m); 798ffa458c1SDavid Brownell 799ffa458c1SDavid Brownell /* turn y- off, x+ on, then leave in lowpower */ 800d93f70b2SDavid Brownell x++; 801*de2defd9SImre Deak ts->read_x = READ_X(vref); 802d93f70b2SDavid Brownell x->tx_buf = &ts->read_x; 803ffa458c1SDavid Brownell x->len = 1; 8040b7018aaSImre Deak spi_message_add_tail(x, m); 805d93f70b2SDavid Brownell 806ffa458c1SDavid Brownell x++; 807ffa458c1SDavid Brownell x->rx_buf = &ts->tc.x; 808ffa458c1SDavid Brownell x->len = 2; 8090b7018aaSImre Deak spi_message_add_tail(x, m); 8100b7018aaSImre Deak 811da970e69SImre Deak m->complete = ads7846_rx_val; 8120b7018aaSImre Deak m->context = ts; 8130b7018aaSImre Deak 8140b7018aaSImre Deak /* turn y+ off, x- on; we'll use formula #2 */ 8150b7018aaSImre Deak if (ts->model == 7846) { 8160b7018aaSImre Deak m++; 8170b7018aaSImre Deak spi_message_init(m); 8180b7018aaSImre Deak 8190b7018aaSImre Deak x++; 820*de2defd9SImre Deak ts->read_z1 = READ_Z1(vref); 8210b7018aaSImre Deak x->tx_buf = &ts->read_z1; 8220b7018aaSImre Deak x->len = 1; 8230b7018aaSImre Deak spi_message_add_tail(x, m); 8240b7018aaSImre Deak 8250b7018aaSImre Deak x++; 8260b7018aaSImre Deak x->rx_buf = &ts->tc.z1; 8270b7018aaSImre Deak x->len = 2; 8280b7018aaSImre Deak spi_message_add_tail(x, m); 8290b7018aaSImre Deak 830da970e69SImre Deak m->complete = ads7846_rx_val; 8310b7018aaSImre Deak m->context = ts; 8320b7018aaSImre Deak 8330b7018aaSImre Deak m++; 8340b7018aaSImre Deak spi_message_init(m); 8350b7018aaSImre Deak 8360b7018aaSImre Deak x++; 837*de2defd9SImre Deak ts->read_z2 = READ_Z2(vref); 8380b7018aaSImre Deak x->tx_buf = &ts->read_z2; 8390b7018aaSImre Deak x->len = 1; 8400b7018aaSImre Deak spi_message_add_tail(x, m); 8410b7018aaSImre Deak 8420b7018aaSImre Deak x++; 8430b7018aaSImre Deak x->rx_buf = &ts->tc.z2; 8440b7018aaSImre Deak x->len = 2; 8450b7018aaSImre Deak spi_message_add_tail(x, m); 8460b7018aaSImre Deak 847da970e69SImre Deak m->complete = ads7846_rx_val; 8480b7018aaSImre Deak m->context = ts; 8490b7018aaSImre Deak } 85053a0ef89SImre Deak 85153a0ef89SImre Deak /* power down */ 8520b7018aaSImre Deak m++; 8530b7018aaSImre Deak spi_message_init(m); 8540b7018aaSImre Deak 85553a0ef89SImre Deak x++; 85653a0ef89SImre Deak ts->pwrdown = PWRDOWN; 85753a0ef89SImre Deak x->tx_buf = &ts->pwrdown; 85853a0ef89SImre Deak x->len = 1; 8590b7018aaSImre Deak spi_message_add_tail(x, m); 86053a0ef89SImre Deak 86153a0ef89SImre Deak x++; 86253a0ef89SImre Deak x->rx_buf = &ts->dummy; 86353a0ef89SImre Deak x->len = 2; 864d93f70b2SDavid Brownell CS_CHANGE(*x); 8650b7018aaSImre Deak spi_message_add_tail(x, m); 866ffa458c1SDavid Brownell 8670b7018aaSImre Deak m->complete = ads7846_rx; 8680b7018aaSImre Deak m->context = ts; 869ffa458c1SDavid Brownell 870d5b415c9SImre Deak ts->last_msg = m; 871d5b415c9SImre Deak 872dace1453SThomas Gleixner if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, 8739084533eSDavid Brownell spi->dev.driver->name, ts)) { 8742e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); 875a90f7e98SDmitry Torokhov err = -EBUSY; 876da970e69SImre Deak goto err_cleanup_filter; 877ffa458c1SDavid Brownell } 878ffa458c1SDavid Brownell 8792e5a7bd9SDavid Brownell dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); 880ffa458c1SDavid Brownell 881ffa458c1SDavid Brownell /* take a first sample, leaving nPENIRQ active; avoid 882ffa458c1SDavid Brownell * the touchscreen, in case it's not connected. 883ffa458c1SDavid Brownell */ 8842e5a7bd9SDavid Brownell (void) ads7846_read12_ser(&spi->dev, 885ffa458c1SDavid Brownell READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); 886ffa458c1SDavid Brownell 8878dd51650SDmitry Torokhov switch (ts->model) { 8888dd51650SDmitry Torokhov case 7846: 8898dd51650SDmitry Torokhov ts->attr_group = &ads7846_attr_group; 8908dd51650SDmitry Torokhov break; 8918dd51650SDmitry Torokhov case 7845: 8928dd51650SDmitry Torokhov ts->attr_group = &ads7845_attr_group; 8938dd51650SDmitry Torokhov break; 8948dd51650SDmitry Torokhov default: 8958dd51650SDmitry Torokhov ts->attr_group = &ads7843_attr_group; 8968dd51650SDmitry Torokhov break; 897ffa458c1SDavid Brownell } 8988dd51650SDmitry Torokhov err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); 8998dd51650SDmitry Torokhov if (err) 9008dd51650SDmitry Torokhov goto err_free_irq; 9017de90a8cSImre Deak 902a90f7e98SDmitry Torokhov err = input_register_device(input_dev); 903a90f7e98SDmitry Torokhov if (err) 9048dd51650SDmitry Torokhov goto err_remove_attr_group; 905a90f7e98SDmitry Torokhov 906ffa458c1SDavid Brownell return 0; 907a90f7e98SDmitry Torokhov 9088dd51650SDmitry Torokhov err_remove_attr_group: 9098dd51650SDmitry Torokhov sysfs_remove_group(&spi->dev.kobj, ts->attr_group); 9108dd51650SDmitry Torokhov err_free_irq: 911a90f7e98SDmitry Torokhov free_irq(spi->irq, ts); 912da970e69SImre Deak err_cleanup_filter: 913da970e69SImre Deak if (ts->filter_cleanup) 914da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 915a90f7e98SDmitry Torokhov err_free_mem: 916a90f7e98SDmitry Torokhov input_free_device(input_dev); 917a90f7e98SDmitry Torokhov kfree(ts); 918a90f7e98SDmitry Torokhov return err; 919ffa458c1SDavid Brownell } 920ffa458c1SDavid Brownell 9212e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi) 922ffa458c1SDavid Brownell { 9232e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 924ffa458c1SDavid Brownell 9257de90a8cSImre Deak input_unregister_device(ts->input); 9267de90a8cSImre Deak 9272e5a7bd9SDavid Brownell ads7846_suspend(spi, PMSG_SUSPEND); 928ffa458c1SDavid Brownell 9298dd51650SDmitry Torokhov sysfs_remove_group(&spi->dev.kobj, ts->attr_group); 930ffa458c1SDavid Brownell 9317de90a8cSImre Deak free_irq(ts->spi->irq, ts); 932c9e617a5SImre Deak /* suspend left the IRQ disabled */ 9337de90a8cSImre Deak enable_irq(ts->spi->irq); 9347de90a8cSImre Deak 935da970e69SImre Deak if (ts->filter_cleanup) 936da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 937da970e69SImre Deak 938ffa458c1SDavid Brownell kfree(ts); 939ffa458c1SDavid Brownell 9402e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "unregistered touchscreen\n"); 941ffa458c1SDavid Brownell return 0; 942ffa458c1SDavid Brownell } 943ffa458c1SDavid Brownell 9442e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = { 9452e5a7bd9SDavid Brownell .driver = { 946ffa458c1SDavid Brownell .name = "ads7846", 947ffa458c1SDavid Brownell .bus = &spi_bus_type, 9482e5a7bd9SDavid Brownell .owner = THIS_MODULE, 9492e5a7bd9SDavid Brownell }, 950ffa458c1SDavid Brownell .probe = ads7846_probe, 9512e5a7bd9SDavid Brownell .remove = __devexit_p(ads7846_remove), 952ffa458c1SDavid Brownell .suspend = ads7846_suspend, 953ffa458c1SDavid Brownell .resume = ads7846_resume, 954ffa458c1SDavid Brownell }; 955ffa458c1SDavid Brownell 956ffa458c1SDavid Brownell static int __init ads7846_init(void) 957ffa458c1SDavid Brownell { 958ffa458c1SDavid Brownell /* grr, board-specific init should stay out of drivers!! */ 959ffa458c1SDavid Brownell 960ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 961ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 962ffa458c1SDavid Brownell /* GPIO4 = PENIRQ; GPIO6 = BUSY */ 963ffa458c1SDavid Brownell omap_request_gpio(4); 964ffa458c1SDavid Brownell omap_set_gpio_direction(4, 1); 965ffa458c1SDavid Brownell omap_request_gpio(6); 966ffa458c1SDavid Brownell omap_set_gpio_direction(6, 1); 967ffa458c1SDavid Brownell } 968ffa458c1SDavid Brownell // also TI 1510 Innovator, bitbanging through FPGA 969ffa458c1SDavid Brownell // also Nokia 770 970ffa458c1SDavid Brownell // also Palm Tungsten T2 971ffa458c1SDavid Brownell #endif 972ffa458c1SDavid Brownell 973ffa458c1SDavid Brownell // PXA: 974ffa458c1SDavid Brownell // also Dell Axim X50 975ffa458c1SDavid Brownell // also HP iPaq H191x/H192x/H415x/H435x 9762e5a7bd9SDavid Brownell // also Intel Lubbock (additional to UCB1400; as temperature sensor) 977ffa458c1SDavid Brownell // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) 978ffa458c1SDavid Brownell 9792e5a7bd9SDavid Brownell // Atmel at91sam9261-EK uses ads7843 9802e5a7bd9SDavid Brownell 981ffa458c1SDavid Brownell // also various AMD Au1x00 devel boards 982ffa458c1SDavid Brownell 9832e5a7bd9SDavid Brownell return spi_register_driver(&ads7846_driver); 984ffa458c1SDavid Brownell } 985ffa458c1SDavid Brownell module_init(ads7846_init); 986ffa458c1SDavid Brownell 987ffa458c1SDavid Brownell static void __exit ads7846_exit(void) 988ffa458c1SDavid Brownell { 9892e5a7bd9SDavid Brownell spi_unregister_driver(&ads7846_driver); 990ffa458c1SDavid Brownell 991ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 992ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 993ffa458c1SDavid Brownell omap_free_gpio(4); 994ffa458c1SDavid Brownell omap_free_gpio(6); 995ffa458c1SDavid Brownell } 996ffa458c1SDavid Brownell #endif 997ffa458c1SDavid Brownell 998ffa458c1SDavid Brownell } 999ffa458c1SDavid Brownell module_exit(ads7846_exit); 1000ffa458c1SDavid Brownell 1001ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); 1002ffa458c1SDavid Brownell MODULE_LICENSE("GPL"); 1003