1ffa458c1SDavid Brownell /* 2ffa458c1SDavid Brownell * ADS7846 based touchscreen and sensor driver 3ffa458c1SDavid Brownell * 4ffa458c1SDavid Brownell * Copyright (c) 2005 David Brownell 5ffa458c1SDavid Brownell * 6ffa458c1SDavid Brownell * Using code from: 7ffa458c1SDavid Brownell * - corgi_ts.c 8ffa458c1SDavid Brownell * Copyright (C) 2004-2005 Richard Purdie 9ffa458c1SDavid Brownell * - omap_ts.[hc], ads7846.h, ts_osk.c 10ffa458c1SDavid Brownell * Copyright (C) 2002 MontaVista Software 11ffa458c1SDavid Brownell * Copyright (C) 2004 Texas Instruments 12ffa458c1SDavid Brownell * Copyright (C) 2005 Dirk Behme 13ffa458c1SDavid Brownell * 14ffa458c1SDavid Brownell * This program is free software; you can redistribute it and/or modify 15ffa458c1SDavid Brownell * it under the terms of the GNU General Public License version 2 as 16ffa458c1SDavid Brownell * published by the Free Software Foundation. 17ffa458c1SDavid Brownell */ 18ffa458c1SDavid Brownell #include <linux/device.h> 19ffa458c1SDavid Brownell #include <linux/init.h> 20ffa458c1SDavid Brownell #include <linux/delay.h> 21ffa458c1SDavid Brownell #include <linux/input.h> 22ffa458c1SDavid Brownell #include <linux/interrupt.h> 23ffa458c1SDavid Brownell #include <linux/slab.h> 24ffa458c1SDavid Brownell #include <linux/spi/spi.h> 25ffa458c1SDavid Brownell #include <linux/spi/ads7846.h> 263ac8bf07SAndrew Morton #include <asm/irq.h> 27ffa458c1SDavid Brownell 28ffa458c1SDavid Brownell #ifdef CONFIG_ARM 29ffa458c1SDavid Brownell #include <asm/mach-types.h> 30ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 31ffa458c1SDavid Brownell #include <asm/arch/gpio.h> 32ffa458c1SDavid Brownell #endif 33ffa458c1SDavid Brownell #endif 34ffa458c1SDavid Brownell 35ffa458c1SDavid Brownell 36ffa458c1SDavid Brownell /* 37ffa458c1SDavid Brownell * This code has been lightly tested on an ads7846. 38ffa458c1SDavid Brownell * Support for ads7843 and ads7845 has only been stubbed in. 39ffa458c1SDavid Brownell * 40ffa458c1SDavid Brownell * Not yet done: investigate the values reported. Are x/y/pressure 41ffa458c1SDavid Brownell * event values sane enough for X11? How accurate are the temperature 42ffa458c1SDavid Brownell * and voltage readings? (System-specific calibration should support 43ffa458c1SDavid Brownell * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) 44ffa458c1SDavid Brownell * 45ffa458c1SDavid Brownell * app note sbaa036 talks in more detail about accurate sampling... 46ffa458c1SDavid Brownell * that ought to help in situations like LCDs inducing noise (which 47ffa458c1SDavid Brownell * can also be helped by using synch signals) and more generally. 48ffa458c1SDavid Brownell */ 49ffa458c1SDavid Brownell 50ffa458c1SDavid Brownell #define TS_POLL_PERIOD msecs_to_jiffies(10) 51ffa458c1SDavid Brownell 52d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */ 53d93f70b2SDavid Brownell #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) 54d93f70b2SDavid Brownell 55ffa458c1SDavid Brownell struct ts_event { 56ffa458c1SDavid Brownell /* For portability, we can't read 12 bit values using SPI (which 57ffa458c1SDavid Brownell * would make the controller deliver them as native byteorder u16 58d93f70b2SDavid Brownell * with msbs zeroed). Instead, we read them as two 8-bit values, 59ffa458c1SDavid Brownell * which need byteswapping then range adjustment. 60ffa458c1SDavid Brownell */ 61ffa458c1SDavid Brownell __be16 x; 62ffa458c1SDavid Brownell __be16 y; 63ffa458c1SDavid Brownell __be16 z1, z2; 64ffa458c1SDavid Brownell }; 65ffa458c1SDavid Brownell 66ffa458c1SDavid Brownell struct ads7846 { 67a90f7e98SDmitry Torokhov struct input_dev *input; 68ffa458c1SDavid Brownell char phys[32]; 69ffa458c1SDavid Brownell 70ffa458c1SDavid Brownell struct spi_device *spi; 71ffa458c1SDavid Brownell u16 model; 72ffa458c1SDavid Brownell u16 vref_delay_usecs; 73ffa458c1SDavid Brownell u16 x_plate_ohms; 74ffa458c1SDavid Brownell 75d93f70b2SDavid Brownell u8 read_x, read_y, read_z1, read_z2; 76ffa458c1SDavid Brownell struct ts_event tc; 77ffa458c1SDavid Brownell 78ffa458c1SDavid Brownell struct spi_transfer xfer[8]; 79ffa458c1SDavid Brownell struct spi_message msg; 80ffa458c1SDavid Brownell 81ffa458c1SDavid Brownell spinlock_t lock; 82ffa458c1SDavid Brownell struct timer_list timer; /* P: lock */ 83ffa458c1SDavid Brownell unsigned pendown:1; /* P: lock */ 84ffa458c1SDavid Brownell unsigned pending:1; /* P: lock */ 85ffa458c1SDavid Brownell // FIXME remove "irq_disabled" 86ffa458c1SDavid Brownell unsigned irq_disabled:1; /* P: lock */ 87ffa458c1SDavid Brownell }; 88ffa458c1SDavid Brownell 89ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */ 90ffa458c1SDavid Brownell #if 0 91ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 1) 92ffa458c1SDavid Brownell #else 93ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 0) 94ffa458c1SDavid Brownell #endif 95ffa458c1SDavid Brownell 96ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 97ffa458c1SDavid Brownell 98ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors. 99ffa458c1SDavid Brownell * Earlier ads784x chips are somewhat compatible. 100ffa458c1SDavid Brownell */ 101ffa458c1SDavid Brownell #define ADS_START (1 << 7) 102ffa458c1SDavid Brownell #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 103ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 104ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 105ffa458c1SDavid Brownell #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 106ffa458c1SDavid Brownell #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 107ffa458c1SDavid Brownell #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 108ffa458c1SDavid Brownell #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 109ffa458c1SDavid Brownell #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 110ffa458c1SDavid Brownell #define ADS_8_BIT (1 << 3) 111ffa458c1SDavid Brownell #define ADS_12_BIT (0 << 3) 112ffa458c1SDavid Brownell #define ADS_SER (1 << 2) /* non-differential */ 113ffa458c1SDavid Brownell #define ADS_DFR (0 << 2) /* differential */ 114ffa458c1SDavid Brownell #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ 115ffa458c1SDavid Brownell #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 116ffa458c1SDavid Brownell #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 117ffa458c1SDavid Brownell #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 118ffa458c1SDavid Brownell 119ffa458c1SDavid Brownell #define MAX_12BIT ((1<<12)-1) 120ffa458c1SDavid Brownell 121ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */ 122ffa458c1SDavid Brownell #define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ 123ffa458c1SDavid Brownell | ADS_12_BIT | ADS_DFR) 124ffa458c1SDavid Brownell 125d93f70b2SDavid Brownell #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) 126d93f70b2SDavid Brownell #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) 127d93f70b2SDavid Brownell #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) 128d93f70b2SDavid Brownell #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_PDOWN) /* LAST */ 129ffa458c1SDavid Brownell 130ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage; 131ffa458c1SDavid Brownell * we leave both ADC and VREF powered 132ffa458c1SDavid Brownell */ 133ffa458c1SDavid Brownell #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ 134ffa458c1SDavid Brownell | ADS_12_BIT | ADS_SER) 135ffa458c1SDavid Brownell 136d93f70b2SDavid Brownell #define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON) 137d93f70b2SDavid Brownell #define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) 138ffa458c1SDavid Brownell 139ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 140ffa458c1SDavid Brownell 141ffa458c1SDavid Brownell /* 142ffa458c1SDavid Brownell * Non-touchscreen sensors only use single-ended conversions. 143ffa458c1SDavid Brownell */ 144ffa458c1SDavid Brownell 145ffa458c1SDavid Brownell struct ser_req { 146d93f70b2SDavid Brownell u8 ref_on; 147ffa458c1SDavid Brownell u8 command; 148d93f70b2SDavid Brownell u8 ref_off; 149ffa458c1SDavid Brownell u16 scratch; 150ffa458c1SDavid Brownell __be16 sample; 151ffa458c1SDavid Brownell struct spi_message msg; 152ffa458c1SDavid Brownell struct spi_transfer xfer[6]; 153ffa458c1SDavid Brownell }; 154ffa458c1SDavid Brownell 155ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command) 156ffa458c1SDavid Brownell { 157ffa458c1SDavid Brownell struct spi_device *spi = to_spi_device(dev); 158ffa458c1SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); 159ffa458c1SDavid Brownell struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); 160ffa458c1SDavid Brownell int status; 161ffa458c1SDavid Brownell int sample; 1628275c642SVitaly Wool int i; 163ffa458c1SDavid Brownell 164ffa458c1SDavid Brownell if (!req) 165ffa458c1SDavid Brownell return -ENOMEM; 166ffa458c1SDavid Brownell 1678275c642SVitaly Wool INIT_LIST_HEAD(&req->msg.transfers); 1688275c642SVitaly Wool 169ffa458c1SDavid Brownell /* activate reference, so it has time to settle; */ 170d93f70b2SDavid Brownell req->ref_on = REF_ON; 171d93f70b2SDavid Brownell req->xfer[0].tx_buf = &req->ref_on; 172ffa458c1SDavid Brownell req->xfer[0].len = 1; 173ffa458c1SDavid Brownell req->xfer[1].rx_buf = &req->scratch; 174ffa458c1SDavid Brownell req->xfer[1].len = 2; 175ffa458c1SDavid Brownell 176ffa458c1SDavid Brownell /* 177ffa458c1SDavid Brownell * for external VREF, 0 usec (and assume it's always on); 178ffa458c1SDavid Brownell * for 1uF, use 800 usec; 179ffa458c1SDavid Brownell * no cap, 100 usec. 180ffa458c1SDavid Brownell */ 181ffa458c1SDavid Brownell req->xfer[1].delay_usecs = ts->vref_delay_usecs; 182ffa458c1SDavid Brownell 183ffa458c1SDavid Brownell /* take sample */ 184ffa458c1SDavid Brownell req->command = (u8) command; 185ffa458c1SDavid Brownell req->xfer[2].tx_buf = &req->command; 186ffa458c1SDavid Brownell req->xfer[2].len = 1; 187ffa458c1SDavid Brownell req->xfer[3].rx_buf = &req->sample; 188ffa458c1SDavid Brownell req->xfer[3].len = 2; 189ffa458c1SDavid Brownell 190ffa458c1SDavid Brownell /* REVISIT: take a few more samples, and compare ... */ 191ffa458c1SDavid Brownell 192ffa458c1SDavid Brownell /* turn off reference */ 193d93f70b2SDavid Brownell req->ref_off = REF_OFF; 194d93f70b2SDavid Brownell req->xfer[4].tx_buf = &req->ref_off; 195ffa458c1SDavid Brownell req->xfer[4].len = 1; 196ffa458c1SDavid Brownell req->xfer[5].rx_buf = &req->scratch; 197ffa458c1SDavid Brownell req->xfer[5].len = 2; 198ffa458c1SDavid Brownell 199ffa458c1SDavid Brownell CS_CHANGE(req->xfer[5]); 200ffa458c1SDavid Brownell 201ffa458c1SDavid Brownell /* group all the transfers together, so we can't interfere with 202ffa458c1SDavid Brownell * reading touchscreen state; disable penirq while sampling 203ffa458c1SDavid Brownell */ 2048275c642SVitaly Wool for (i = 0; i < 6; i++) 2058275c642SVitaly Wool spi_message_add_tail(&req->xfer[i], &req->msg); 206ffa458c1SDavid Brownell 207ffa458c1SDavid Brownell disable_irq(spi->irq); 208ffa458c1SDavid Brownell status = spi_sync(spi, &req->msg); 209ffa458c1SDavid Brownell enable_irq(spi->irq); 210ffa458c1SDavid Brownell 211ffa458c1SDavid Brownell if (req->msg.status) 212ffa458c1SDavid Brownell status = req->msg.status; 213ffa458c1SDavid Brownell sample = be16_to_cpu(req->sample); 214ffa458c1SDavid Brownell sample = sample >> 4; 215ffa458c1SDavid Brownell kfree(req); 216ffa458c1SDavid Brownell 217ffa458c1SDavid Brownell return status ? status : sample; 218ffa458c1SDavid Brownell } 219ffa458c1SDavid Brownell 220ffa458c1SDavid Brownell #define SHOW(name) static ssize_t \ 221ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ 222ffa458c1SDavid Brownell { \ 223ffa458c1SDavid Brownell ssize_t v = ads7846_read12_ser(dev, \ 224ffa458c1SDavid Brownell READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ 225ffa458c1SDavid Brownell if (v < 0) \ 226ffa458c1SDavid Brownell return v; \ 227ffa458c1SDavid Brownell return sprintf(buf, "%u\n", (unsigned) v); \ 228ffa458c1SDavid Brownell } \ 229ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); 230ffa458c1SDavid Brownell 231ffa458c1SDavid Brownell SHOW(temp0) 232ffa458c1SDavid Brownell SHOW(temp1) 233ffa458c1SDavid Brownell SHOW(vaux) 234ffa458c1SDavid Brownell SHOW(vbatt) 235ffa458c1SDavid Brownell 236*438f2a74SImre Deak static int is_pen_down(struct device *dev) 237*438f2a74SImre Deak { 238*438f2a74SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 239*438f2a74SImre Deak 240*438f2a74SImre Deak return ts->pendown; 241*438f2a74SImre Deak } 242*438f2a74SImre Deak 243*438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev, 244*438f2a74SImre Deak struct device_attribute *attr, char *buf) 245*438f2a74SImre Deak { 246*438f2a74SImre Deak return sprintf(buf, "%u\n", is_pen_down(dev)); 247*438f2a74SImre Deak } 248*438f2a74SImre Deak 249*438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 250*438f2a74SImre Deak 251ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 252ffa458c1SDavid Brownell 253ffa458c1SDavid Brownell /* 254ffa458c1SDavid Brownell * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, 255ffa458c1SDavid Brownell * to retrieve touchscreen status. 256ffa458c1SDavid Brownell * 257ffa458c1SDavid Brownell * The SPI transfer completion callback does the real work. It reports 258ffa458c1SDavid Brownell * touchscreen events and reactivates the timer (or IRQ) as appropriate. 259ffa458c1SDavid Brownell */ 260ffa458c1SDavid Brownell 261ffa458c1SDavid Brownell static void ads7846_rx(void *ads) 262ffa458c1SDavid Brownell { 263ffa458c1SDavid Brownell struct ads7846 *ts = ads; 264a90f7e98SDmitry Torokhov struct input_dev *input_dev = ts->input; 265ffa458c1SDavid Brownell unsigned Rt; 266ffa458c1SDavid Brownell unsigned sync = 0; 267ffa458c1SDavid Brownell u16 x, y, z1, z2; 268ffa458c1SDavid Brownell unsigned long flags; 269ffa458c1SDavid Brownell 270ffa458c1SDavid Brownell /* adjust: 12 bit samples (left aligned), built from 271ffa458c1SDavid Brownell * two 8 bit values writen msb-first. 272ffa458c1SDavid Brownell */ 273ffa458c1SDavid Brownell x = be16_to_cpu(ts->tc.x) >> 4; 274ffa458c1SDavid Brownell y = be16_to_cpu(ts->tc.y) >> 4; 275ffa458c1SDavid Brownell z1 = be16_to_cpu(ts->tc.z1) >> 4; 276ffa458c1SDavid Brownell z2 = be16_to_cpu(ts->tc.z2) >> 4; 277ffa458c1SDavid Brownell 278ffa458c1SDavid Brownell /* range filtering */ 279ffa458c1SDavid Brownell if (x == MAX_12BIT) 280ffa458c1SDavid Brownell x = 0; 281ffa458c1SDavid Brownell 282ffa458c1SDavid Brownell if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { 283ffa458c1SDavid Brownell /* compute touch pressure resistance using equation #2 */ 284ffa458c1SDavid Brownell Rt = z2; 285ffa458c1SDavid Brownell Rt -= z1; 286ffa458c1SDavid Brownell Rt *= x; 287ffa458c1SDavid Brownell Rt *= ts->x_plate_ohms; 288ffa458c1SDavid Brownell Rt /= z1; 289ffa458c1SDavid Brownell Rt = (Rt + 2047) >> 12; 290ffa458c1SDavid Brownell } else 291ffa458c1SDavid Brownell Rt = 0; 292ffa458c1SDavid Brownell 293ffa458c1SDavid Brownell /* NOTE: "pendown" is inferred from pressure; we don't rely on 294ffa458c1SDavid Brownell * being able to check nPENIRQ status, or "friendly" trigger modes 295ffa458c1SDavid Brownell * (both-edges is much better than just-falling or low-level). 296ffa458c1SDavid Brownell * 297ffa458c1SDavid Brownell * REVISIT: some boards may require reading nPENIRQ; it's 298ffa458c1SDavid Brownell * needed on 7843. and 7845 reads pressure differently... 299ffa458c1SDavid Brownell * 300ffa458c1SDavid Brownell * REVISIT: the touchscreen might not be connected; this code 301ffa458c1SDavid Brownell * won't notice that, even if nPENIRQ never fires ... 302ffa458c1SDavid Brownell */ 303ffa458c1SDavid Brownell if (!ts->pendown && Rt != 0) { 304a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 1); 305ffa458c1SDavid Brownell sync = 1; 306ffa458c1SDavid Brownell } else if (ts->pendown && Rt == 0) { 307a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 0); 308ffa458c1SDavid Brownell sync = 1; 309ffa458c1SDavid Brownell } 310ffa458c1SDavid Brownell 311ffa458c1SDavid Brownell if (Rt) { 312a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_X, x); 313a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_Y, y); 314a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_PRESSURE, Rt); 315ffa458c1SDavid Brownell sync = 1; 316ffa458c1SDavid Brownell } 317ffa458c1SDavid Brownell if (sync) 318a90f7e98SDmitry Torokhov input_sync(input_dev); 319ffa458c1SDavid Brownell 320ffa458c1SDavid Brownell #ifdef VERBOSE 321ffa458c1SDavid Brownell if (Rt || ts->pendown) 322ffa458c1SDavid Brownell pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, 323ffa458c1SDavid Brownell x, y, Rt, Rt ? "" : " UP"); 324ffa458c1SDavid Brownell #endif 325ffa458c1SDavid Brownell 326ffa458c1SDavid Brownell /* don't retrigger while we're suspended */ 327ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 328ffa458c1SDavid Brownell 329ffa458c1SDavid Brownell ts->pendown = (Rt != 0); 330ffa458c1SDavid Brownell ts->pending = 0; 331ffa458c1SDavid Brownell 332ffa458c1SDavid Brownell if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { 333ffa458c1SDavid Brownell if (ts->pendown) 334ffa458c1SDavid Brownell mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 335ffa458c1SDavid Brownell else if (ts->irq_disabled) { 336ffa458c1SDavid Brownell ts->irq_disabled = 0; 337ffa458c1SDavid Brownell enable_irq(ts->spi->irq); 338ffa458c1SDavid Brownell } 339ffa458c1SDavid Brownell } 340ffa458c1SDavid Brownell 341ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 342ffa458c1SDavid Brownell } 343ffa458c1SDavid Brownell 344ffa458c1SDavid Brownell static void ads7846_timer(unsigned long handle) 345ffa458c1SDavid Brownell { 346ffa458c1SDavid Brownell struct ads7846 *ts = (void *)handle; 347ffa458c1SDavid Brownell int status = 0; 348ffa458c1SDavid Brownell unsigned long flags; 349ffa458c1SDavid Brownell 350ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 351ffa458c1SDavid Brownell if (!ts->pending) { 352ffa458c1SDavid Brownell ts->pending = 1; 353ffa458c1SDavid Brownell if (!ts->irq_disabled) { 354ffa458c1SDavid Brownell ts->irq_disabled = 1; 355ffa458c1SDavid Brownell disable_irq(ts->spi->irq); 356ffa458c1SDavid Brownell } 357ffa458c1SDavid Brownell status = spi_async(ts->spi, &ts->msg); 358ffa458c1SDavid Brownell if (status) 359ffa458c1SDavid Brownell dev_err(&ts->spi->dev, "spi_async --> %d\n", 360ffa458c1SDavid Brownell status); 361ffa458c1SDavid Brownell } 362ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 363ffa458c1SDavid Brownell } 364ffa458c1SDavid Brownell 365ffa458c1SDavid Brownell static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) 366ffa458c1SDavid Brownell { 367ffa458c1SDavid Brownell ads7846_timer((unsigned long) handle); 368ffa458c1SDavid Brownell return IRQ_HANDLED; 369ffa458c1SDavid Brownell } 370ffa458c1SDavid Brownell 371ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 372ffa458c1SDavid Brownell 373ffa458c1SDavid Brownell static int 3742e5a7bd9SDavid Brownell ads7846_suspend(struct spi_device *spi, pm_message_t message) 375ffa458c1SDavid Brownell { 3762e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 377ffa458c1SDavid Brownell unsigned long flags; 378ffa458c1SDavid Brownell 379ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 380ffa458c1SDavid Brownell 3812e5a7bd9SDavid Brownell spi->dev.power.power_state = message; 382ffa458c1SDavid Brownell 383ffa458c1SDavid Brownell /* are we waiting for IRQ, or polling? */ 384ffa458c1SDavid Brownell if (!ts->pendown) { 385ffa458c1SDavid Brownell if (!ts->irq_disabled) { 386ffa458c1SDavid Brownell ts->irq_disabled = 1; 387ffa458c1SDavid Brownell disable_irq(ts->spi->irq); 388ffa458c1SDavid Brownell } 389ffa458c1SDavid Brownell } else { 390ffa458c1SDavid Brownell /* polling; force a final SPI completion; 391ffa458c1SDavid Brownell * that will clean things up neatly 392ffa458c1SDavid Brownell */ 393ffa458c1SDavid Brownell if (!ts->pending) 394ffa458c1SDavid Brownell mod_timer(&ts->timer, jiffies); 395ffa458c1SDavid Brownell 396ffa458c1SDavid Brownell while (ts->pendown || ts->pending) { 397ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 398ffa458c1SDavid Brownell udelay(10); 399ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 400ffa458c1SDavid Brownell } 401ffa458c1SDavid Brownell } 402ffa458c1SDavid Brownell 403ffa458c1SDavid Brownell /* we know the chip's in lowpower mode since we always 404ffa458c1SDavid Brownell * leave it that way after every request 405ffa458c1SDavid Brownell */ 406ffa458c1SDavid Brownell 407ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 408ffa458c1SDavid Brownell return 0; 409ffa458c1SDavid Brownell } 410ffa458c1SDavid Brownell 4112e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi) 412ffa458c1SDavid Brownell { 4132e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 414ffa458c1SDavid Brownell 415ffa458c1SDavid Brownell ts->irq_disabled = 0; 416ffa458c1SDavid Brownell enable_irq(ts->spi->irq); 4172e5a7bd9SDavid Brownell spi->dev.power.power_state = PMSG_ON; 418ffa458c1SDavid Brownell return 0; 419ffa458c1SDavid Brownell } 420ffa458c1SDavid Brownell 4212e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi) 422ffa458c1SDavid Brownell { 423ffa458c1SDavid Brownell struct ads7846 *ts; 424a90f7e98SDmitry Torokhov struct input_dev *input_dev; 4252e5a7bd9SDavid Brownell struct ads7846_platform_data *pdata = spi->dev.platform_data; 426ffa458c1SDavid Brownell struct spi_transfer *x; 427a90f7e98SDmitry Torokhov int err; 428ffa458c1SDavid Brownell 429ffa458c1SDavid Brownell if (!spi->irq) { 4302e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no IRQ?\n"); 431ffa458c1SDavid Brownell return -ENODEV; 432ffa458c1SDavid Brownell } 433ffa458c1SDavid Brownell 434ffa458c1SDavid Brownell if (!pdata) { 4352e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no platform data?\n"); 436ffa458c1SDavid Brownell return -ENODEV; 437ffa458c1SDavid Brownell } 438ffa458c1SDavid Brownell 439ffa458c1SDavid Brownell /* don't exceed max specified sample rate */ 440d93f70b2SDavid Brownell if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { 4412e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "f(sample) %d KHz?\n", 442d93f70b2SDavid Brownell (spi->max_speed_hz/SAMPLE_BITS)/1000); 443ffa458c1SDavid Brownell return -EINVAL; 444ffa458c1SDavid Brownell } 445ffa458c1SDavid Brownell 446ffa458c1SDavid Brownell /* We'd set the wordsize to 12 bits ... except that some controllers 447ffa458c1SDavid Brownell * will then treat the 8 bit command words as 12 bits (and drop the 448ffa458c1SDavid Brownell * four MSBs of the 12 bit result). Result: inputs must be shifted 449ffa458c1SDavid Brownell * to discard the four garbage LSBs. 450ffa458c1SDavid Brownell */ 451ffa458c1SDavid Brownell 452a90f7e98SDmitry Torokhov ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); 453a90f7e98SDmitry Torokhov input_dev = input_allocate_device(); 454a90f7e98SDmitry Torokhov if (!ts || !input_dev) { 455a90f7e98SDmitry Torokhov err = -ENOMEM; 456a90f7e98SDmitry Torokhov goto err_free_mem; 457a90f7e98SDmitry Torokhov } 458ffa458c1SDavid Brownell 4592e5a7bd9SDavid Brownell dev_set_drvdata(&spi->dev, ts); 460a90f7e98SDmitry Torokhov spi->dev.power.power_state = PMSG_ON; 461ffa458c1SDavid Brownell 462ffa458c1SDavid Brownell ts->spi = spi; 463a90f7e98SDmitry Torokhov ts->input = input_dev; 464ffa458c1SDavid Brownell 465ffa458c1SDavid Brownell init_timer(&ts->timer); 466ffa458c1SDavid Brownell ts->timer.data = (unsigned long) ts; 467ffa458c1SDavid Brownell ts->timer.function = ads7846_timer; 468ffa458c1SDavid Brownell 469ffa458c1SDavid Brownell ts->model = pdata->model ? : 7846; 470ffa458c1SDavid Brownell ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; 471ffa458c1SDavid Brownell ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 472ffa458c1SDavid Brownell 473a90f7e98SDmitry Torokhov snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 474ffa458c1SDavid Brownell 475a90f7e98SDmitry Torokhov input_dev->name = "ADS784x Touchscreen"; 476a90f7e98SDmitry Torokhov input_dev->phys = ts->phys; 477a90f7e98SDmitry Torokhov input_dev->cdev.dev = &spi->dev; 478ffa458c1SDavid Brownell 479a90f7e98SDmitry Torokhov input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 480a90f7e98SDmitry Torokhov input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 481a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 482ffa458c1SDavid Brownell pdata->x_min ? : 0, 483ffa458c1SDavid Brownell pdata->x_max ? : MAX_12BIT, 484ffa458c1SDavid Brownell 0, 0); 485a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 486ffa458c1SDavid Brownell pdata->y_min ? : 0, 487ffa458c1SDavid Brownell pdata->y_max ? : MAX_12BIT, 488ffa458c1SDavid Brownell 0, 0); 489a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 490ffa458c1SDavid Brownell pdata->pressure_min, pdata->pressure_max, 0, 0); 491ffa458c1SDavid Brownell 492ffa458c1SDavid Brownell /* set up the transfers to read touchscreen state; this assumes we 493ffa458c1SDavid Brownell * use formula #2 for pressure, not #3. 494ffa458c1SDavid Brownell */ 495d93f70b2SDavid Brownell INIT_LIST_HEAD(&ts->msg.transfers); 496ffa458c1SDavid Brownell x = ts->xfer; 497ffa458c1SDavid Brownell 498ffa458c1SDavid Brownell /* y- still on; turn on only y+ (and ADC) */ 499d93f70b2SDavid Brownell ts->read_y = READ_Y; 500d93f70b2SDavid Brownell x->tx_buf = &ts->read_y; 501ffa458c1SDavid Brownell x->len = 1; 502d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 503d93f70b2SDavid Brownell 504ffa458c1SDavid Brownell x++; 505ffa458c1SDavid Brownell x->rx_buf = &ts->tc.y; 506ffa458c1SDavid Brownell x->len = 2; 507d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 508ffa458c1SDavid Brownell 509ffa458c1SDavid Brownell /* turn y+ off, x- on; we'll use formula #2 */ 510ffa458c1SDavid Brownell if (ts->model == 7846) { 511d93f70b2SDavid Brownell x++; 512d93f70b2SDavid Brownell ts->read_z1 = READ_Z1; 513d93f70b2SDavid Brownell x->tx_buf = &ts->read_z1; 514ffa458c1SDavid Brownell x->len = 1; 515d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 516d93f70b2SDavid Brownell 517ffa458c1SDavid Brownell x++; 518ffa458c1SDavid Brownell x->rx_buf = &ts->tc.z1; 519ffa458c1SDavid Brownell x->len = 2; 520d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 521ffa458c1SDavid Brownell 522d93f70b2SDavid Brownell x++; 523d93f70b2SDavid Brownell ts->read_z2 = READ_Z2; 524d93f70b2SDavid Brownell x->tx_buf = &ts->read_z2; 525ffa458c1SDavid Brownell x->len = 1; 526d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 527d93f70b2SDavid Brownell 528ffa458c1SDavid Brownell x++; 529ffa458c1SDavid Brownell x->rx_buf = &ts->tc.z2; 530ffa458c1SDavid Brownell x->len = 2; 531d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 532ffa458c1SDavid Brownell } 533ffa458c1SDavid Brownell 534ffa458c1SDavid Brownell /* turn y- off, x+ on, then leave in lowpower */ 535d93f70b2SDavid Brownell x++; 536d93f70b2SDavid Brownell ts->read_x = READ_X; 537d93f70b2SDavid Brownell x->tx_buf = &ts->read_x; 538ffa458c1SDavid Brownell x->len = 1; 539d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 540d93f70b2SDavid Brownell 541ffa458c1SDavid Brownell x++; 542ffa458c1SDavid Brownell x->rx_buf = &ts->tc.x; 543ffa458c1SDavid Brownell x->len = 2; 544d93f70b2SDavid Brownell CS_CHANGE(*x); 545d93f70b2SDavid Brownell spi_message_add_tail(x, &ts->msg); 546ffa458c1SDavid Brownell 547ffa458c1SDavid Brownell ts->msg.complete = ads7846_rx; 548ffa458c1SDavid Brownell ts->msg.context = ts; 549ffa458c1SDavid Brownell 550f43aaba1SRussell King if (request_irq(spi->irq, ads7846_irq, 551f43aaba1SRussell King SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, 5522e5a7bd9SDavid Brownell spi->dev.bus_id, ts)) { 5532e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); 554a90f7e98SDmitry Torokhov err = -EBUSY; 555a90f7e98SDmitry Torokhov goto err_free_mem; 556ffa458c1SDavid Brownell } 557ffa458c1SDavid Brownell 5582e5a7bd9SDavid Brownell dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); 559ffa458c1SDavid Brownell 560ffa458c1SDavid Brownell /* take a first sample, leaving nPENIRQ active; avoid 561ffa458c1SDavid Brownell * the touchscreen, in case it's not connected. 562ffa458c1SDavid Brownell */ 5632e5a7bd9SDavid Brownell (void) ads7846_read12_ser(&spi->dev, 564ffa458c1SDavid Brownell READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); 565ffa458c1SDavid Brownell 566ffa458c1SDavid Brownell /* ads7843/7845 don't have temperature sensors, and 567ffa458c1SDavid Brownell * use the other sensors a bit differently too 568ffa458c1SDavid Brownell */ 569ffa458c1SDavid Brownell if (ts->model == 7846) { 5702e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_temp0); 5712e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_temp1); 572ffa458c1SDavid Brownell } 573ffa458c1SDavid Brownell if (ts->model != 7845) 5742e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_vbatt); 5752e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_vaux); 576ffa458c1SDavid Brownell 577*438f2a74SImre Deak device_create_file(&spi->dev, &dev_attr_pen_down); 578*438f2a74SImre Deak 579a90f7e98SDmitry Torokhov err = input_register_device(input_dev); 580a90f7e98SDmitry Torokhov if (err) 581a90f7e98SDmitry Torokhov goto err_free_irq; 582a90f7e98SDmitry Torokhov 583ffa458c1SDavid Brownell return 0; 584a90f7e98SDmitry Torokhov 585a90f7e98SDmitry Torokhov err_free_irq: 586a90f7e98SDmitry Torokhov free_irq(spi->irq, ts); 587a90f7e98SDmitry Torokhov err_free_mem: 588a90f7e98SDmitry Torokhov input_free_device(input_dev); 589a90f7e98SDmitry Torokhov kfree(ts); 590a90f7e98SDmitry Torokhov return err; 591ffa458c1SDavid Brownell } 592ffa458c1SDavid Brownell 5932e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi) 594ffa458c1SDavid Brownell { 5952e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 596ffa458c1SDavid Brownell 5972e5a7bd9SDavid Brownell ads7846_suspend(spi, PMSG_SUSPEND); 598ffa458c1SDavid Brownell free_irq(ts->spi->irq, ts); 599ffa458c1SDavid Brownell if (ts->irq_disabled) 600ffa458c1SDavid Brownell enable_irq(ts->spi->irq); 601ffa458c1SDavid Brownell 602*438f2a74SImre Deak device_remove_file(&spi->dev, &dev_attr_pen_down); 603*438f2a74SImre Deak 604ffa458c1SDavid Brownell if (ts->model == 7846) { 6052e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_temp0); 6062e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_temp1); 607ffa458c1SDavid Brownell } 608ffa458c1SDavid Brownell if (ts->model != 7845) 6092e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_vbatt); 6102e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_vaux); 611ffa458c1SDavid Brownell 612a90f7e98SDmitry Torokhov input_unregister_device(ts->input); 613ffa458c1SDavid Brownell kfree(ts); 614ffa458c1SDavid Brownell 6152e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "unregistered touchscreen\n"); 616ffa458c1SDavid Brownell return 0; 617ffa458c1SDavid Brownell } 618ffa458c1SDavid Brownell 6192e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = { 6202e5a7bd9SDavid Brownell .driver = { 621ffa458c1SDavid Brownell .name = "ads7846", 622ffa458c1SDavid Brownell .bus = &spi_bus_type, 6232e5a7bd9SDavid Brownell .owner = THIS_MODULE, 6242e5a7bd9SDavid Brownell }, 625ffa458c1SDavid Brownell .probe = ads7846_probe, 6262e5a7bd9SDavid Brownell .remove = __devexit_p(ads7846_remove), 627ffa458c1SDavid Brownell .suspend = ads7846_suspend, 628ffa458c1SDavid Brownell .resume = ads7846_resume, 629ffa458c1SDavid Brownell }; 630ffa458c1SDavid Brownell 631ffa458c1SDavid Brownell static int __init ads7846_init(void) 632ffa458c1SDavid Brownell { 633ffa458c1SDavid Brownell /* grr, board-specific init should stay out of drivers!! */ 634ffa458c1SDavid Brownell 635ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 636ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 637ffa458c1SDavid Brownell /* GPIO4 = PENIRQ; GPIO6 = BUSY */ 638ffa458c1SDavid Brownell omap_request_gpio(4); 639ffa458c1SDavid Brownell omap_set_gpio_direction(4, 1); 640ffa458c1SDavid Brownell omap_request_gpio(6); 641ffa458c1SDavid Brownell omap_set_gpio_direction(6, 1); 642ffa458c1SDavid Brownell } 643ffa458c1SDavid Brownell // also TI 1510 Innovator, bitbanging through FPGA 644ffa458c1SDavid Brownell // also Nokia 770 645ffa458c1SDavid Brownell // also Palm Tungsten T2 646ffa458c1SDavid Brownell #endif 647ffa458c1SDavid Brownell 648ffa458c1SDavid Brownell // PXA: 649ffa458c1SDavid Brownell // also Dell Axim X50 650ffa458c1SDavid Brownell // also HP iPaq H191x/H192x/H415x/H435x 6512e5a7bd9SDavid Brownell // also Intel Lubbock (additional to UCB1400; as temperature sensor) 652ffa458c1SDavid Brownell // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) 653ffa458c1SDavid Brownell 6542e5a7bd9SDavid Brownell // Atmel at91sam9261-EK uses ads7843 6552e5a7bd9SDavid Brownell 656ffa458c1SDavid Brownell // also various AMD Au1x00 devel boards 657ffa458c1SDavid Brownell 6582e5a7bd9SDavid Brownell return spi_register_driver(&ads7846_driver); 659ffa458c1SDavid Brownell } 660ffa458c1SDavid Brownell module_init(ads7846_init); 661ffa458c1SDavid Brownell 662ffa458c1SDavid Brownell static void __exit ads7846_exit(void) 663ffa458c1SDavid Brownell { 6642e5a7bd9SDavid Brownell spi_unregister_driver(&ads7846_driver); 665ffa458c1SDavid Brownell 666ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 667ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 668ffa458c1SDavid Brownell omap_free_gpio(4); 669ffa458c1SDavid Brownell omap_free_gpio(6); 670ffa458c1SDavid Brownell } 671ffa458c1SDavid Brownell #endif 672ffa458c1SDavid Brownell 673ffa458c1SDavid Brownell } 674ffa458c1SDavid Brownell module_exit(ads7846_exit); 675ffa458c1SDavid Brownell 676ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); 677ffa458c1SDavid Brownell MODULE_LICENSE("GPL"); 678