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 /* 397de90a8cSImre Deak * This code has been tested on an ads7846 / N770 device. 40ffa458c1SDavid Brownell * Support for ads7843 and ads7845 has only been stubbed in. 41ffa458c1SDavid Brownell * 427de90a8cSImre Deak * Not yet done: How accurate are the temperature and voltage 437de90a8cSImre Deak * readings? (System-specific calibration should support 44ffa458c1SDavid Brownell * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) 45ffa458c1SDavid Brownell * 467de90a8cSImre Deak * IRQ handling needs a workaround because of a shortcoming in handling 477de90a8cSImre Deak * edge triggered IRQs on some platforms like the OMAP1/2. These 487de90a8cSImre Deak * platforms don't handle the ARM lazy IRQ disabling properly, thus we 497de90a8cSImre Deak * have to maintain our own SW IRQ disabled status. This should be 507de90a8cSImre Deak * removed as soon as the affected platform's IRQ handling is fixed. 517de90a8cSImre Deak * 52ffa458c1SDavid Brownell * app note sbaa036 talks in more detail about accurate sampling... 53ffa458c1SDavid Brownell * that ought to help in situations like LCDs inducing noise (which 54ffa458c1SDavid Brownell * can also be helped by using synch signals) and more generally. 557de90a8cSImre Deak * This driver tries to utilize the measures described in the app 567de90a8cSImre Deak * note. The strength of filtering can be set in the board-* specific 577de90a8cSImre Deak * files. 58ffa458c1SDavid Brownell */ 59ffa458c1SDavid Brownell 60ffa458c1SDavid Brownell #define TS_POLL_PERIOD msecs_to_jiffies(10) 61ffa458c1SDavid Brownell 62d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */ 63d93f70b2SDavid Brownell #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) 64d93f70b2SDavid Brownell 65ffa458c1SDavid Brownell struct ts_event { 66ffa458c1SDavid Brownell /* For portability, we can't read 12 bit values using SPI (which 67ffa458c1SDavid Brownell * would make the controller deliver them as native byteorder u16 68d93f70b2SDavid Brownell * with msbs zeroed). Instead, we read them as two 8-bit values, 69ffa458c1SDavid Brownell * which need byteswapping then range adjustment. 70ffa458c1SDavid Brownell */ 71ffa458c1SDavid Brownell __be16 x; 72ffa458c1SDavid Brownell __be16 y; 73ffa458c1SDavid Brownell __be16 z1, z2; 74ffa458c1SDavid Brownell }; 75ffa458c1SDavid Brownell 76ffa458c1SDavid Brownell struct ads7846 { 77a90f7e98SDmitry Torokhov struct input_dev *input; 78ffa458c1SDavid Brownell char phys[32]; 79ffa458c1SDavid Brownell 80ffa458c1SDavid Brownell struct spi_device *spi; 81ffa458c1SDavid Brownell u16 model; 82ffa458c1SDavid Brownell u16 vref_delay_usecs; 83ffa458c1SDavid Brownell u16 x_plate_ohms; 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]; 910b7018aaSImre Deak int msg_idx; 920b7018aaSImre Deak int read_cnt; 930b7018aaSImre Deak int last_read; 940b7018aaSImre Deak 950b7018aaSImre Deak u16 debounce_max; 960b7018aaSImre Deak u16 debounce_tol; 97ffa458c1SDavid Brownell 98ffa458c1SDavid Brownell spinlock_t lock; 99ffa458c1SDavid Brownell struct timer_list timer; /* P: lock */ 100ffa458c1SDavid Brownell unsigned pendown:1; /* P: lock */ 101ffa458c1SDavid Brownell unsigned pending:1; /* P: lock */ 102ffa458c1SDavid Brownell // FIXME remove "irq_disabled" 103ffa458c1SDavid Brownell unsigned irq_disabled:1; /* P: lock */ 1047de90a8cSImre Deak unsigned disabled:1; 105*c9e617a5SImre Deak 106*c9e617a5SImre Deak int (*get_pendown_state)(void); 107ffa458c1SDavid Brownell }; 108ffa458c1SDavid Brownell 109ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */ 110ffa458c1SDavid Brownell #if 0 111ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 1) 112ffa458c1SDavid Brownell #else 113ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 0) 114ffa458c1SDavid Brownell #endif 115ffa458c1SDavid Brownell 116ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 117ffa458c1SDavid Brownell 118ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors. 119ffa458c1SDavid Brownell * Earlier ads784x chips are somewhat compatible. 120ffa458c1SDavid Brownell */ 121ffa458c1SDavid Brownell #define ADS_START (1 << 7) 122ffa458c1SDavid Brownell #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 123ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 124ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 125ffa458c1SDavid Brownell #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 126ffa458c1SDavid Brownell #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 127ffa458c1SDavid Brownell #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 128ffa458c1SDavid Brownell #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 129ffa458c1SDavid Brownell #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 130ffa458c1SDavid Brownell #define ADS_8_BIT (1 << 3) 131ffa458c1SDavid Brownell #define ADS_12_BIT (0 << 3) 132ffa458c1SDavid Brownell #define ADS_SER (1 << 2) /* non-differential */ 133ffa458c1SDavid Brownell #define ADS_DFR (0 << 2) /* differential */ 134ffa458c1SDavid Brownell #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ 135ffa458c1SDavid Brownell #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 136ffa458c1SDavid Brownell #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 137ffa458c1SDavid Brownell #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 138ffa458c1SDavid Brownell 139ffa458c1SDavid Brownell #define MAX_12BIT ((1<<12)-1) 140ffa458c1SDavid Brownell 141ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */ 142ffa458c1SDavid Brownell #define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ 143ffa458c1SDavid Brownell | ADS_12_BIT | ADS_DFR) 144ffa458c1SDavid Brownell 145d93f70b2SDavid Brownell #define READ_Y (READ_12BIT_DFR(y) | ADS_PD10_ADC_ON) 146d93f70b2SDavid Brownell #define READ_Z1 (READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON) 147d93f70b2SDavid Brownell #define READ_Z2 (READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON) 14853a0ef89SImre Deak 14953a0ef89SImre Deak #define READ_X (READ_12BIT_DFR(x) | ADS_PD10_ADC_ON) 15053a0ef89SImre Deak #define PWRDOWN (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) /* LAST */ 151ffa458c1SDavid Brownell 152ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage; 153ffa458c1SDavid Brownell * we leave both ADC and VREF powered 154ffa458c1SDavid Brownell */ 155ffa458c1SDavid Brownell #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ 156ffa458c1SDavid Brownell | ADS_12_BIT | ADS_SER) 157ffa458c1SDavid Brownell 158d93f70b2SDavid Brownell #define REF_ON (READ_12BIT_DFR(x) | ADS_PD10_ALL_ON) 159d93f70b2SDavid Brownell #define REF_OFF (READ_12BIT_DFR(y) | ADS_PD10_PDOWN) 160ffa458c1SDavid Brownell 161ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 162ffa458c1SDavid Brownell 163ffa458c1SDavid Brownell /* 164ffa458c1SDavid Brownell * Non-touchscreen sensors only use single-ended conversions. 165ffa458c1SDavid Brownell */ 166ffa458c1SDavid Brownell 167ffa458c1SDavid Brownell struct ser_req { 168d93f70b2SDavid Brownell u8 ref_on; 169ffa458c1SDavid Brownell u8 command; 170d93f70b2SDavid Brownell u8 ref_off; 171ffa458c1SDavid Brownell u16 scratch; 172ffa458c1SDavid Brownell __be16 sample; 173ffa458c1SDavid Brownell struct spi_message msg; 174ffa458c1SDavid Brownell struct spi_transfer xfer[6]; 175ffa458c1SDavid Brownell }; 176ffa458c1SDavid Brownell 1777de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts); 1787de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts); 1797de90a8cSImre Deak 180*c9e617a5SImre Deak static int device_suspended(struct device *dev) 181*c9e617a5SImre Deak { 182*c9e617a5SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 183*c9e617a5SImre Deak return dev->power.power_state.event != PM_EVENT_ON || ts->disabled; 184*c9e617a5SImre Deak } 185*c9e617a5SImre Deak 186ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command) 187ffa458c1SDavid Brownell { 188ffa458c1SDavid Brownell struct spi_device *spi = to_spi_device(dev); 189ffa458c1SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); 190ffa458c1SDavid Brownell struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); 191ffa458c1SDavid Brownell int status; 192ffa458c1SDavid Brownell int sample; 1938275c642SVitaly Wool int i; 194ffa458c1SDavid Brownell 195ffa458c1SDavid Brownell if (!req) 196ffa458c1SDavid Brownell return -ENOMEM; 197ffa458c1SDavid Brownell 1980b7018aaSImre Deak spi_message_init(&req->msg); 1998275c642SVitaly Wool 200ffa458c1SDavid Brownell /* activate reference, so it has time to settle; */ 201d93f70b2SDavid Brownell req->ref_on = REF_ON; 202d93f70b2SDavid Brownell req->xfer[0].tx_buf = &req->ref_on; 203ffa458c1SDavid Brownell req->xfer[0].len = 1; 204ffa458c1SDavid Brownell req->xfer[1].rx_buf = &req->scratch; 205ffa458c1SDavid Brownell req->xfer[1].len = 2; 206ffa458c1SDavid Brownell 207ffa458c1SDavid Brownell /* 208ffa458c1SDavid Brownell * for external VREF, 0 usec (and assume it's always on); 209ffa458c1SDavid Brownell * for 1uF, use 800 usec; 210ffa458c1SDavid Brownell * no cap, 100 usec. 211ffa458c1SDavid Brownell */ 212ffa458c1SDavid Brownell req->xfer[1].delay_usecs = ts->vref_delay_usecs; 213ffa458c1SDavid Brownell 214ffa458c1SDavid Brownell /* take sample */ 215ffa458c1SDavid Brownell req->command = (u8) command; 216ffa458c1SDavid Brownell req->xfer[2].tx_buf = &req->command; 217ffa458c1SDavid Brownell req->xfer[2].len = 1; 218ffa458c1SDavid Brownell req->xfer[3].rx_buf = &req->sample; 219ffa458c1SDavid Brownell req->xfer[3].len = 2; 220ffa458c1SDavid Brownell 221ffa458c1SDavid Brownell /* REVISIT: take a few more samples, and compare ... */ 222ffa458c1SDavid Brownell 223ffa458c1SDavid Brownell /* turn off reference */ 224d93f70b2SDavid Brownell req->ref_off = REF_OFF; 225d93f70b2SDavid Brownell req->xfer[4].tx_buf = &req->ref_off; 226ffa458c1SDavid Brownell req->xfer[4].len = 1; 227ffa458c1SDavid Brownell req->xfer[5].rx_buf = &req->scratch; 228ffa458c1SDavid Brownell req->xfer[5].len = 2; 229ffa458c1SDavid Brownell 230ffa458c1SDavid Brownell CS_CHANGE(req->xfer[5]); 231ffa458c1SDavid Brownell 232ffa458c1SDavid Brownell /* group all the transfers together, so we can't interfere with 233ffa458c1SDavid Brownell * reading touchscreen state; disable penirq while sampling 234ffa458c1SDavid Brownell */ 2358275c642SVitaly Wool for (i = 0; i < 6; i++) 2368275c642SVitaly Wool spi_message_add_tail(&req->xfer[i], &req->msg); 237ffa458c1SDavid Brownell 238*c9e617a5SImre Deak ts->irq_disabled = 1; 239ffa458c1SDavid Brownell disable_irq(spi->irq); 240ffa458c1SDavid Brownell status = spi_sync(spi, &req->msg); 241*c9e617a5SImre Deak ts->irq_disabled = 0; 242ffa458c1SDavid Brownell enable_irq(spi->irq); 243ffa458c1SDavid Brownell 244ffa458c1SDavid Brownell if (req->msg.status) 245ffa458c1SDavid Brownell status = req->msg.status; 246ffa458c1SDavid Brownell sample = be16_to_cpu(req->sample); 247ffa458c1SDavid Brownell sample = sample >> 4; 248ffa458c1SDavid Brownell kfree(req); 249ffa458c1SDavid Brownell 250ffa458c1SDavid Brownell return status ? status : sample; 251ffa458c1SDavid Brownell } 252ffa458c1SDavid Brownell 253ffa458c1SDavid Brownell #define SHOW(name) static ssize_t \ 254ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ 255ffa458c1SDavid Brownell { \ 256ffa458c1SDavid Brownell ssize_t v = ads7846_read12_ser(dev, \ 257ffa458c1SDavid Brownell READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ 258ffa458c1SDavid Brownell if (v < 0) \ 259ffa458c1SDavid Brownell return v; \ 260ffa458c1SDavid Brownell return sprintf(buf, "%u\n", (unsigned) v); \ 261ffa458c1SDavid Brownell } \ 262ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); 263ffa458c1SDavid Brownell 264ffa458c1SDavid Brownell SHOW(temp0) 265ffa458c1SDavid Brownell SHOW(temp1) 266ffa458c1SDavid Brownell SHOW(vaux) 267ffa458c1SDavid Brownell SHOW(vbatt) 268ffa458c1SDavid Brownell 269438f2a74SImre Deak static int is_pen_down(struct device *dev) 270438f2a74SImre Deak { 271438f2a74SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 272438f2a74SImre Deak 273438f2a74SImre Deak return ts->pendown; 274438f2a74SImre Deak } 275438f2a74SImre Deak 276438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev, 277438f2a74SImre Deak struct device_attribute *attr, char *buf) 278438f2a74SImre Deak { 279438f2a74SImre Deak return sprintf(buf, "%u\n", is_pen_down(dev)); 280438f2a74SImre Deak } 281438f2a74SImre Deak 282438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 283438f2a74SImre Deak 2847de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev, 2857de90a8cSImre Deak struct device_attribute *attr, char *buf) 2867de90a8cSImre Deak { 2877de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 2887de90a8cSImre Deak 2897de90a8cSImre Deak return sprintf(buf, "%u\n", ts->disabled); 2907de90a8cSImre Deak } 2917de90a8cSImre Deak 2927de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev, 2937de90a8cSImre Deak struct device_attribute *attr, 2947de90a8cSImre Deak const char *buf, size_t count) 2957de90a8cSImre Deak { 2967de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 2977de90a8cSImre Deak char *endp; 2987de90a8cSImre Deak int i; 2997de90a8cSImre Deak 3007de90a8cSImre Deak i = simple_strtoul(buf, &endp, 10); 3017de90a8cSImre Deak spin_lock_irq(&ts->lock); 3027de90a8cSImre Deak 3037de90a8cSImre Deak if (i) 3047de90a8cSImre Deak ads7846_disable(ts); 3057de90a8cSImre Deak else 3067de90a8cSImre Deak ads7846_enable(ts); 3077de90a8cSImre Deak 3087de90a8cSImre Deak spin_unlock_irq(&ts->lock); 3097de90a8cSImre Deak 3107de90a8cSImre Deak return count; 3117de90a8cSImre Deak } 3127de90a8cSImre Deak 3137de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); 3147de90a8cSImre Deak 315ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 316ffa458c1SDavid Brownell 317ffa458c1SDavid Brownell /* 318ffa458c1SDavid Brownell * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, 319ffa458c1SDavid Brownell * to retrieve touchscreen status. 320ffa458c1SDavid Brownell * 321ffa458c1SDavid Brownell * The SPI transfer completion callback does the real work. It reports 322ffa458c1SDavid Brownell * touchscreen events and reactivates the timer (or IRQ) as appropriate. 323ffa458c1SDavid Brownell */ 324ffa458c1SDavid Brownell 325ffa458c1SDavid Brownell static void ads7846_rx(void *ads) 326ffa458c1SDavid Brownell { 327ffa458c1SDavid Brownell struct ads7846 *ts = ads; 328a90f7e98SDmitry Torokhov struct input_dev *input_dev = ts->input; 329ffa458c1SDavid Brownell unsigned Rt; 330ffa458c1SDavid Brownell unsigned sync = 0; 331ffa458c1SDavid Brownell u16 x, y, z1, z2; 332ffa458c1SDavid Brownell unsigned long flags; 333ffa458c1SDavid Brownell 334ffa458c1SDavid Brownell /* adjust: 12 bit samples (left aligned), built from 335ffa458c1SDavid Brownell * two 8 bit values writen msb-first. 336ffa458c1SDavid Brownell */ 337ffa458c1SDavid Brownell x = be16_to_cpu(ts->tc.x) >> 4; 338ffa458c1SDavid Brownell y = be16_to_cpu(ts->tc.y) >> 4; 339ffa458c1SDavid Brownell z1 = be16_to_cpu(ts->tc.z1) >> 4; 340ffa458c1SDavid Brownell z2 = be16_to_cpu(ts->tc.z2) >> 4; 341ffa458c1SDavid Brownell 342ffa458c1SDavid Brownell /* range filtering */ 343ffa458c1SDavid Brownell if (x == MAX_12BIT) 344ffa458c1SDavid Brownell x = 0; 345ffa458c1SDavid Brownell 346*c9e617a5SImre Deak if (likely(x && z1 && !device_suspended(&ts->spi->dev))) { 347ffa458c1SDavid Brownell /* compute touch pressure resistance using equation #2 */ 348ffa458c1SDavid Brownell Rt = z2; 349ffa458c1SDavid Brownell Rt -= z1; 350ffa458c1SDavid Brownell Rt *= x; 351ffa458c1SDavid Brownell Rt *= ts->x_plate_ohms; 352ffa458c1SDavid Brownell Rt /= z1; 353ffa458c1SDavid Brownell Rt = (Rt + 2047) >> 12; 354ffa458c1SDavid Brownell } else 355ffa458c1SDavid Brownell Rt = 0; 356ffa458c1SDavid Brownell 357ffa458c1SDavid Brownell /* NOTE: "pendown" is inferred from pressure; we don't rely on 358ffa458c1SDavid Brownell * being able to check nPENIRQ status, or "friendly" trigger modes 359ffa458c1SDavid Brownell * (both-edges is much better than just-falling or low-level). 360ffa458c1SDavid Brownell * 361ffa458c1SDavid Brownell * REVISIT: some boards may require reading nPENIRQ; it's 362ffa458c1SDavid Brownell * needed on 7843. and 7845 reads pressure differently... 363ffa458c1SDavid Brownell * 364ffa458c1SDavid Brownell * REVISIT: the touchscreen might not be connected; this code 365ffa458c1SDavid Brownell * won't notice that, even if nPENIRQ never fires ... 366ffa458c1SDavid Brownell */ 367ffa458c1SDavid Brownell if (!ts->pendown && Rt != 0) { 368a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 1); 369ffa458c1SDavid Brownell sync = 1; 370ffa458c1SDavid Brownell } else if (ts->pendown && Rt == 0) { 371a90f7e98SDmitry Torokhov input_report_key(input_dev, BTN_TOUCH, 0); 372ffa458c1SDavid Brownell sync = 1; 373ffa458c1SDavid Brownell } 374ffa458c1SDavid Brownell 375ffa458c1SDavid Brownell if (Rt) { 376a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_X, x); 377a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_Y, y); 378a90f7e98SDmitry Torokhov input_report_abs(input_dev, ABS_PRESSURE, Rt); 379ffa458c1SDavid Brownell sync = 1; 380ffa458c1SDavid Brownell } 381ffa458c1SDavid Brownell if (sync) 382a90f7e98SDmitry Torokhov input_sync(input_dev); 383ffa458c1SDavid Brownell 384ffa458c1SDavid Brownell #ifdef VERBOSE 385ffa458c1SDavid Brownell if (Rt || ts->pendown) 386ffa458c1SDavid Brownell pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, 387ffa458c1SDavid Brownell x, y, Rt, Rt ? "" : " UP"); 388ffa458c1SDavid Brownell #endif 389ffa458c1SDavid Brownell 390ffa458c1SDavid Brownell spin_lock_irqsave(&ts->lock, flags); 391ffa458c1SDavid Brownell 392ffa458c1SDavid Brownell ts->pendown = (Rt != 0); 393ffa458c1SDavid Brownell mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); 394ffa458c1SDavid Brownell 395ffa458c1SDavid Brownell spin_unlock_irqrestore(&ts->lock, flags); 396ffa458c1SDavid Brownell } 397ffa458c1SDavid Brownell 3980b7018aaSImre Deak static void ads7846_debounce(void *ads) 399ffa458c1SDavid Brownell { 4000b7018aaSImre Deak struct ads7846 *ts = ads; 4010b7018aaSImre Deak struct spi_message *m; 4020b7018aaSImre Deak struct spi_transfer *t; 4030b7018aaSImre Deak u16 val; 4040b7018aaSImre Deak int status; 405ffa458c1SDavid Brownell 4060b7018aaSImre Deak m = &ts->msg[ts->msg_idx]; 4070b7018aaSImre Deak t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); 4080b7018aaSImre Deak val = (*(u16 *)t->rx_buf) >> 3; 4090b7018aaSImre Deak 4100b7018aaSImre Deak if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol 4110b7018aaSImre Deak && ts->read_cnt < ts->debounce_max)) { 4120b7018aaSImre Deak /* Repeat it, if this was the first read or the read wasn't 4130b7018aaSImre Deak * consistent enough 4140b7018aaSImre Deak */ 4150b7018aaSImre Deak ts->read_cnt++; 4160b7018aaSImre Deak ts->last_read = val; 4170b7018aaSImre Deak } else { 4180b7018aaSImre Deak /* Go for the next read */ 4190b7018aaSImre Deak ts->msg_idx++; 4200b7018aaSImre Deak ts->read_cnt = 0; 4210b7018aaSImre Deak m++; 422ffa458c1SDavid Brownell } 4230b7018aaSImre Deak status = spi_async(ts->spi, m); 424ffa458c1SDavid Brownell if (status) 425ffa458c1SDavid Brownell dev_err(&ts->spi->dev, "spi_async --> %d\n", 426ffa458c1SDavid Brownell status); 427ffa458c1SDavid Brownell } 4280b7018aaSImre Deak 4290b7018aaSImre Deak static void ads7846_timer(unsigned long handle) 4300b7018aaSImre Deak { 4310b7018aaSImre Deak struct ads7846 *ts = (void *)handle; 4320b7018aaSImre Deak int status = 0; 4330b7018aaSImre Deak 434*c9e617a5SImre Deak spin_lock_irq(&ts->lock); 435*c9e617a5SImre Deak 436*c9e617a5SImre Deak if (unlikely(ts->msg_idx && !ts->pendown)) { 437*c9e617a5SImre Deak /* measurment cycle ended */ 438*c9e617a5SImre Deak if (!device_suspended(&ts->spi->dev)) { 439*c9e617a5SImre Deak ts->irq_disabled = 0; 440*c9e617a5SImre Deak enable_irq(ts->spi->irq); 441*c9e617a5SImre Deak } 442*c9e617a5SImre Deak ts->pending = 0; 443*c9e617a5SImre Deak ts->msg_idx = 0; 444*c9e617a5SImre Deak } else { 445*c9e617a5SImre Deak /* pen is still down, continue with the measurement */ 4460b7018aaSImre Deak ts->msg_idx = 0; 4470b7018aaSImre Deak status = spi_async(ts->spi, &ts->msg[0]); 4480b7018aaSImre Deak if (status) 4490b7018aaSImre Deak dev_err(&ts->spi->dev, "spi_async --> %d\n", status); 450ffa458c1SDavid Brownell } 451ffa458c1SDavid Brownell 452*c9e617a5SImre Deak spin_unlock_irq(&ts->lock); 453*c9e617a5SImre Deak } 454*c9e617a5SImre Deak 455ffa458c1SDavid Brownell static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) 456ffa458c1SDavid Brownell { 4570b7018aaSImre Deak struct ads7846 *ts = handle; 4580b7018aaSImre Deak unsigned long flags; 4590b7018aaSImre Deak 4600b7018aaSImre Deak spin_lock_irqsave(&ts->lock, flags); 461*c9e617a5SImre Deak if (likely(ts->get_pendown_state())) { 4620b7018aaSImre Deak if (!ts->irq_disabled) { 4630b7018aaSImre Deak /* REVISIT irq logic for many ARM chips has cloned a 4640b7018aaSImre Deak * bug wherein disabling an irq in its handler won't 4650b7018aaSImre Deak * work;(it's disabled lazily, and too late to work. 4660b7018aaSImre Deak * until all their irq logic is fixed, we must shadow 4670b7018aaSImre Deak * that state here. 4680b7018aaSImre Deak */ 4690b7018aaSImre Deak ts->irq_disabled = 1; 4700b7018aaSImre Deak disable_irq(ts->spi->irq); 4710b7018aaSImre Deak ts->pending = 1; 4720b7018aaSImre Deak mod_timer(&ts->timer, jiffies); 4730b7018aaSImre Deak } 4740b7018aaSImre Deak } 4750b7018aaSImre Deak spin_unlock_irqrestore(&ts->lock, flags); 4767de90a8cSImre Deak 4777de90a8cSImre Deak return IRQ_HANDLED; 478ffa458c1SDavid Brownell } 479ffa458c1SDavid Brownell 480ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 481ffa458c1SDavid Brownell 4827de90a8cSImre Deak /* Must be called with ts->lock held */ 4837de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts) 484ffa458c1SDavid Brownell { 4857de90a8cSImre Deak if (ts->disabled) 4867de90a8cSImre Deak return; 487ffa458c1SDavid Brownell 488*c9e617a5SImre Deak ts->disabled = 1; 489*c9e617a5SImre Deak 490ffa458c1SDavid Brownell /* are we waiting for IRQ, or polling? */ 491*c9e617a5SImre Deak if (!ts->pending) { 492ffa458c1SDavid Brownell ts->irq_disabled = 1; 493ffa458c1SDavid Brownell disable_irq(ts->spi->irq); 494ffa458c1SDavid Brownell } else { 495*c9e617a5SImre Deak /* the timer will run at least once more, and 496*c9e617a5SImre Deak * leave everything in a clean state, IRQ disabled 497ffa458c1SDavid Brownell */ 498*c9e617a5SImre Deak while (ts->pending) { 4997de90a8cSImre Deak spin_unlock_irq(&ts->lock); 500c4febb94SJuha Yrjola msleep(1); 5017de90a8cSImre Deak spin_lock_irq(&ts->lock); 502ffa458c1SDavid Brownell } 503ffa458c1SDavid Brownell } 504ffa458c1SDavid Brownell 505ffa458c1SDavid Brownell /* we know the chip's in lowpower mode since we always 506ffa458c1SDavid Brownell * leave it that way after every request 507ffa458c1SDavid Brownell */ 508ffa458c1SDavid Brownell 5097de90a8cSImre Deak } 5107de90a8cSImre Deak 5117de90a8cSImre Deak /* Must be called with ts->lock held */ 5127de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts) 5137de90a8cSImre Deak { 5147de90a8cSImre Deak if (!ts->disabled) 5157de90a8cSImre Deak return; 5167de90a8cSImre Deak 5177de90a8cSImre Deak ts->disabled = 0; 5187de90a8cSImre Deak ts->irq_disabled = 0; 5197de90a8cSImre Deak enable_irq(ts->spi->irq); 5207de90a8cSImre Deak } 5217de90a8cSImre Deak 5227de90a8cSImre Deak static int ads7846_suspend(struct spi_device *spi, pm_message_t message) 5237de90a8cSImre Deak { 5247de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(&spi->dev); 5257de90a8cSImre Deak 5267de90a8cSImre Deak spin_lock_irq(&ts->lock); 5277de90a8cSImre Deak 5287de90a8cSImre Deak spi->dev.power.power_state = message; 5297de90a8cSImre Deak ads7846_disable(ts); 5307de90a8cSImre Deak 5317de90a8cSImre Deak spin_unlock_irq(&ts->lock); 5327de90a8cSImre Deak 533ffa458c1SDavid Brownell return 0; 5347de90a8cSImre Deak 535ffa458c1SDavid Brownell } 536ffa458c1SDavid Brownell 5372e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi) 538ffa458c1SDavid Brownell { 5392e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 540ffa458c1SDavid Brownell 5417de90a8cSImre Deak spin_lock_irq(&ts->lock); 5427de90a8cSImre Deak 5432e5a7bd9SDavid Brownell spi->dev.power.power_state = PMSG_ON; 5447de90a8cSImre Deak ads7846_enable(ts); 5457de90a8cSImre Deak 5467de90a8cSImre Deak spin_unlock_irq(&ts->lock); 5477de90a8cSImre Deak 548ffa458c1SDavid Brownell return 0; 549ffa458c1SDavid Brownell } 550ffa458c1SDavid Brownell 5512e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi) 552ffa458c1SDavid Brownell { 553ffa458c1SDavid Brownell struct ads7846 *ts; 554a90f7e98SDmitry Torokhov struct input_dev *input_dev; 5552e5a7bd9SDavid Brownell struct ads7846_platform_data *pdata = spi->dev.platform_data; 5560b7018aaSImre Deak struct spi_message *m; 557ffa458c1SDavid Brownell struct spi_transfer *x; 558a90f7e98SDmitry Torokhov int err; 559ffa458c1SDavid Brownell 560ffa458c1SDavid Brownell if (!spi->irq) { 5612e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no IRQ?\n"); 562ffa458c1SDavid Brownell return -ENODEV; 563ffa458c1SDavid Brownell } 564ffa458c1SDavid Brownell 565ffa458c1SDavid Brownell if (!pdata) { 5662e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no platform data?\n"); 567ffa458c1SDavid Brownell return -ENODEV; 568ffa458c1SDavid Brownell } 569ffa458c1SDavid Brownell 570ffa458c1SDavid Brownell /* don't exceed max specified sample rate */ 571d93f70b2SDavid Brownell if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { 5722e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "f(sample) %d KHz?\n", 573d93f70b2SDavid Brownell (spi->max_speed_hz/SAMPLE_BITS)/1000); 574ffa458c1SDavid Brownell return -EINVAL; 575ffa458c1SDavid Brownell } 576ffa458c1SDavid Brownell 577*c9e617a5SImre Deak if (pdata->get_pendown_state == NULL) { 578*c9e617a5SImre Deak dev_dbg(&spi->dev, "no get_pendown_state function?\n"); 579*c9e617a5SImre Deak return -EINVAL; 580*c9e617a5SImre Deak } 581*c9e617a5SImre Deak 582ffa458c1SDavid Brownell /* We'd set the wordsize to 12 bits ... except that some controllers 583ffa458c1SDavid Brownell * will then treat the 8 bit command words as 12 bits (and drop the 584ffa458c1SDavid Brownell * four MSBs of the 12 bit result). Result: inputs must be shifted 585ffa458c1SDavid Brownell * to discard the four garbage LSBs. 586ffa458c1SDavid Brownell */ 587ffa458c1SDavid Brownell 588a90f7e98SDmitry Torokhov ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); 589a90f7e98SDmitry Torokhov input_dev = input_allocate_device(); 590a90f7e98SDmitry Torokhov if (!ts || !input_dev) { 591a90f7e98SDmitry Torokhov err = -ENOMEM; 592a90f7e98SDmitry Torokhov goto err_free_mem; 593a90f7e98SDmitry Torokhov } 594ffa458c1SDavid Brownell 5952e5a7bd9SDavid Brownell dev_set_drvdata(&spi->dev, ts); 596a90f7e98SDmitry Torokhov spi->dev.power.power_state = PMSG_ON; 597ffa458c1SDavid Brownell 598ffa458c1SDavid Brownell ts->spi = spi; 599a90f7e98SDmitry Torokhov ts->input = input_dev; 600ffa458c1SDavid Brownell 601ffa458c1SDavid Brownell init_timer(&ts->timer); 602ffa458c1SDavid Brownell ts->timer.data = (unsigned long) ts; 603ffa458c1SDavid Brownell ts->timer.function = ads7846_timer; 604ffa458c1SDavid Brownell 6057de90a8cSImre Deak spin_lock_init(&ts->lock); 6067de90a8cSImre Deak 607ffa458c1SDavid Brownell ts->model = pdata->model ? : 7846; 608ffa458c1SDavid Brownell ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; 609ffa458c1SDavid Brownell ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 6100b7018aaSImre Deak ts->debounce_max = pdata->debounce_max ? : 1; 6110b7018aaSImre Deak ts->debounce_tol = pdata->debounce_tol ? : 10; 612*c9e617a5SImre Deak ts->get_pendown_state = pdata->get_pendown_state; 613ffa458c1SDavid Brownell 614a90f7e98SDmitry Torokhov snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 615ffa458c1SDavid Brownell 616a90f7e98SDmitry Torokhov input_dev->name = "ADS784x Touchscreen"; 617a90f7e98SDmitry Torokhov input_dev->phys = ts->phys; 618a90f7e98SDmitry Torokhov input_dev->cdev.dev = &spi->dev; 619ffa458c1SDavid Brownell 620a90f7e98SDmitry Torokhov input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); 621a90f7e98SDmitry Torokhov input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); 622a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 623ffa458c1SDavid Brownell pdata->x_min ? : 0, 624ffa458c1SDavid Brownell pdata->x_max ? : MAX_12BIT, 625ffa458c1SDavid Brownell 0, 0); 626a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 627ffa458c1SDavid Brownell pdata->y_min ? : 0, 628ffa458c1SDavid Brownell pdata->y_max ? : MAX_12BIT, 629ffa458c1SDavid Brownell 0, 0); 630a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 631ffa458c1SDavid Brownell pdata->pressure_min, pdata->pressure_max, 0, 0); 632ffa458c1SDavid Brownell 633ffa458c1SDavid Brownell /* set up the transfers to read touchscreen state; this assumes we 634ffa458c1SDavid Brownell * use formula #2 for pressure, not #3. 635ffa458c1SDavid Brownell */ 6360b7018aaSImre Deak m = &ts->msg[0]; 637ffa458c1SDavid Brownell x = ts->xfer; 638ffa458c1SDavid Brownell 6390b7018aaSImre Deak spi_message_init(m); 6400b7018aaSImre Deak 641ffa458c1SDavid Brownell /* y- still on; turn on only y+ (and ADC) */ 642d93f70b2SDavid Brownell ts->read_y = READ_Y; 643d93f70b2SDavid Brownell x->tx_buf = &ts->read_y; 644ffa458c1SDavid Brownell x->len = 1; 6450b7018aaSImre Deak spi_message_add_tail(x, m); 646d93f70b2SDavid Brownell 647ffa458c1SDavid Brownell x++; 648ffa458c1SDavid Brownell x->rx_buf = &ts->tc.y; 649ffa458c1SDavid Brownell x->len = 2; 6500b7018aaSImre Deak spi_message_add_tail(x, m); 651ffa458c1SDavid Brownell 6520b7018aaSImre Deak m->complete = ads7846_debounce; 6530b7018aaSImre Deak m->context = ts; 654d93f70b2SDavid Brownell 6550b7018aaSImre Deak m++; 6560b7018aaSImre Deak spi_message_init(m); 657ffa458c1SDavid Brownell 658ffa458c1SDavid Brownell /* turn y- off, x+ on, then leave in lowpower */ 659d93f70b2SDavid Brownell x++; 660d93f70b2SDavid Brownell ts->read_x = READ_X; 661d93f70b2SDavid Brownell x->tx_buf = &ts->read_x; 662ffa458c1SDavid Brownell x->len = 1; 6630b7018aaSImre Deak spi_message_add_tail(x, m); 664d93f70b2SDavid Brownell 665ffa458c1SDavid Brownell x++; 666ffa458c1SDavid Brownell x->rx_buf = &ts->tc.x; 667ffa458c1SDavid Brownell x->len = 2; 6680b7018aaSImre Deak spi_message_add_tail(x, m); 6690b7018aaSImre Deak 6700b7018aaSImre Deak m->complete = ads7846_debounce; 6710b7018aaSImre Deak m->context = ts; 6720b7018aaSImre Deak 6730b7018aaSImre Deak /* turn y+ off, x- on; we'll use formula #2 */ 6740b7018aaSImre Deak if (ts->model == 7846) { 6750b7018aaSImre Deak m++; 6760b7018aaSImre Deak spi_message_init(m); 6770b7018aaSImre Deak 6780b7018aaSImre Deak x++; 6790b7018aaSImre Deak ts->read_z1 = READ_Z1; 6800b7018aaSImre Deak x->tx_buf = &ts->read_z1; 6810b7018aaSImre Deak x->len = 1; 6820b7018aaSImre Deak spi_message_add_tail(x, m); 6830b7018aaSImre Deak 6840b7018aaSImre Deak x++; 6850b7018aaSImre Deak x->rx_buf = &ts->tc.z1; 6860b7018aaSImre Deak x->len = 2; 6870b7018aaSImre Deak spi_message_add_tail(x, m); 6880b7018aaSImre Deak 6890b7018aaSImre Deak m->complete = ads7846_debounce; 6900b7018aaSImre Deak m->context = ts; 6910b7018aaSImre Deak 6920b7018aaSImre Deak m++; 6930b7018aaSImre Deak spi_message_init(m); 6940b7018aaSImre Deak 6950b7018aaSImre Deak x++; 6960b7018aaSImre Deak ts->read_z2 = READ_Z2; 6970b7018aaSImre Deak x->tx_buf = &ts->read_z2; 6980b7018aaSImre Deak x->len = 1; 6990b7018aaSImre Deak spi_message_add_tail(x, m); 7000b7018aaSImre Deak 7010b7018aaSImre Deak x++; 7020b7018aaSImre Deak x->rx_buf = &ts->tc.z2; 7030b7018aaSImre Deak x->len = 2; 7040b7018aaSImre Deak spi_message_add_tail(x, m); 7050b7018aaSImre Deak 7060b7018aaSImre Deak m->complete = ads7846_debounce; 7070b7018aaSImre Deak m->context = ts; 7080b7018aaSImre Deak } 70953a0ef89SImre Deak 71053a0ef89SImre Deak /* power down */ 7110b7018aaSImre Deak m++; 7120b7018aaSImre Deak spi_message_init(m); 7130b7018aaSImre Deak 71453a0ef89SImre Deak x++; 71553a0ef89SImre Deak ts->pwrdown = PWRDOWN; 71653a0ef89SImre Deak x->tx_buf = &ts->pwrdown; 71753a0ef89SImre Deak x->len = 1; 7180b7018aaSImre Deak spi_message_add_tail(x, m); 71953a0ef89SImre Deak 72053a0ef89SImre Deak x++; 72153a0ef89SImre Deak x->rx_buf = &ts->dummy; 72253a0ef89SImre Deak x->len = 2; 723d93f70b2SDavid Brownell CS_CHANGE(*x); 7240b7018aaSImre Deak spi_message_add_tail(x, m); 725ffa458c1SDavid Brownell 7260b7018aaSImre Deak m->complete = ads7846_rx; 7270b7018aaSImre Deak m->context = ts; 728ffa458c1SDavid Brownell 729f43aaba1SRussell King if (request_irq(spi->irq, ads7846_irq, 730f43aaba1SRussell King SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, 7312e5a7bd9SDavid Brownell spi->dev.bus_id, ts)) { 7322e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); 733a90f7e98SDmitry Torokhov err = -EBUSY; 734a90f7e98SDmitry Torokhov goto err_free_mem; 735ffa458c1SDavid Brownell } 736ffa458c1SDavid Brownell 7372e5a7bd9SDavid Brownell dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); 738ffa458c1SDavid Brownell 739ffa458c1SDavid Brownell /* take a first sample, leaving nPENIRQ active; avoid 740ffa458c1SDavid Brownell * the touchscreen, in case it's not connected. 741ffa458c1SDavid Brownell */ 7422e5a7bd9SDavid Brownell (void) ads7846_read12_ser(&spi->dev, 743ffa458c1SDavid Brownell READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); 744ffa458c1SDavid Brownell 745ffa458c1SDavid Brownell /* ads7843/7845 don't have temperature sensors, and 746ffa458c1SDavid Brownell * use the other sensors a bit differently too 747ffa458c1SDavid Brownell */ 748ffa458c1SDavid Brownell if (ts->model == 7846) { 7492e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_temp0); 7502e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_temp1); 751ffa458c1SDavid Brownell } 752ffa458c1SDavid Brownell if (ts->model != 7845) 7532e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_vbatt); 7542e5a7bd9SDavid Brownell device_create_file(&spi->dev, &dev_attr_vaux); 755ffa458c1SDavid Brownell 756438f2a74SImre Deak device_create_file(&spi->dev, &dev_attr_pen_down); 757438f2a74SImre Deak 7587de90a8cSImre Deak device_create_file(&spi->dev, &dev_attr_disable); 7597de90a8cSImre Deak 760a90f7e98SDmitry Torokhov err = input_register_device(input_dev); 761a90f7e98SDmitry Torokhov if (err) 7627de90a8cSImre Deak goto err_remove_attr; 763a90f7e98SDmitry Torokhov 764ffa458c1SDavid Brownell return 0; 765a90f7e98SDmitry Torokhov 7667de90a8cSImre Deak err_remove_attr: 7677de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_disable); 7687de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_pen_down); 7697de90a8cSImre Deak if (ts->model == 7846) { 7707de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_temp1); 7717de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_temp0); 7727de90a8cSImre Deak } 7737de90a8cSImre Deak if (ts->model != 7845) 7747de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_vbatt); 7757de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_vaux); 7767de90a8cSImre Deak 777a90f7e98SDmitry Torokhov free_irq(spi->irq, ts); 778a90f7e98SDmitry Torokhov err_free_mem: 779a90f7e98SDmitry Torokhov input_free_device(input_dev); 780a90f7e98SDmitry Torokhov kfree(ts); 781a90f7e98SDmitry Torokhov return err; 782ffa458c1SDavid Brownell } 783ffa458c1SDavid Brownell 7842e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi) 785ffa458c1SDavid Brownell { 7862e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 787ffa458c1SDavid Brownell 7887de90a8cSImre Deak input_unregister_device(ts->input); 7897de90a8cSImre Deak 7902e5a7bd9SDavid Brownell ads7846_suspend(spi, PMSG_SUSPEND); 791ffa458c1SDavid Brownell 7927de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_disable); 793438f2a74SImre Deak device_remove_file(&spi->dev, &dev_attr_pen_down); 794ffa458c1SDavid Brownell if (ts->model == 7846) { 7952e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_temp1); 7967de90a8cSImre Deak device_remove_file(&spi->dev, &dev_attr_temp0); 797ffa458c1SDavid Brownell } 798ffa458c1SDavid Brownell if (ts->model != 7845) 7992e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_vbatt); 8002e5a7bd9SDavid Brownell device_remove_file(&spi->dev, &dev_attr_vaux); 801ffa458c1SDavid Brownell 8027de90a8cSImre Deak free_irq(ts->spi->irq, ts); 803*c9e617a5SImre Deak /* suspend left the IRQ disabled */ 8047de90a8cSImre Deak enable_irq(ts->spi->irq); 8057de90a8cSImre Deak 806ffa458c1SDavid Brownell kfree(ts); 807ffa458c1SDavid Brownell 8082e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "unregistered touchscreen\n"); 809ffa458c1SDavid Brownell return 0; 810ffa458c1SDavid Brownell } 811ffa458c1SDavid Brownell 8122e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = { 8132e5a7bd9SDavid Brownell .driver = { 814ffa458c1SDavid Brownell .name = "ads7846", 815ffa458c1SDavid Brownell .bus = &spi_bus_type, 8162e5a7bd9SDavid Brownell .owner = THIS_MODULE, 8172e5a7bd9SDavid Brownell }, 818ffa458c1SDavid Brownell .probe = ads7846_probe, 8192e5a7bd9SDavid Brownell .remove = __devexit_p(ads7846_remove), 820ffa458c1SDavid Brownell .suspend = ads7846_suspend, 821ffa458c1SDavid Brownell .resume = ads7846_resume, 822ffa458c1SDavid Brownell }; 823ffa458c1SDavid Brownell 824ffa458c1SDavid Brownell static int __init ads7846_init(void) 825ffa458c1SDavid Brownell { 826ffa458c1SDavid Brownell /* grr, board-specific init should stay out of drivers!! */ 827ffa458c1SDavid Brownell 828ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 829ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 830ffa458c1SDavid Brownell /* GPIO4 = PENIRQ; GPIO6 = BUSY */ 831ffa458c1SDavid Brownell omap_request_gpio(4); 832ffa458c1SDavid Brownell omap_set_gpio_direction(4, 1); 833ffa458c1SDavid Brownell omap_request_gpio(6); 834ffa458c1SDavid Brownell omap_set_gpio_direction(6, 1); 835ffa458c1SDavid Brownell } 836ffa458c1SDavid Brownell // also TI 1510 Innovator, bitbanging through FPGA 837ffa458c1SDavid Brownell // also Nokia 770 838ffa458c1SDavid Brownell // also Palm Tungsten T2 839ffa458c1SDavid Brownell #endif 840ffa458c1SDavid Brownell 841ffa458c1SDavid Brownell // PXA: 842ffa458c1SDavid Brownell // also Dell Axim X50 843ffa458c1SDavid Brownell // also HP iPaq H191x/H192x/H415x/H435x 8442e5a7bd9SDavid Brownell // also Intel Lubbock (additional to UCB1400; as temperature sensor) 845ffa458c1SDavid Brownell // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) 846ffa458c1SDavid Brownell 8472e5a7bd9SDavid Brownell // Atmel at91sam9261-EK uses ads7843 8482e5a7bd9SDavid Brownell 849ffa458c1SDavid Brownell // also various AMD Au1x00 devel boards 850ffa458c1SDavid Brownell 8512e5a7bd9SDavid Brownell return spi_register_driver(&ads7846_driver); 852ffa458c1SDavid Brownell } 853ffa458c1SDavid Brownell module_init(ads7846_init); 854ffa458c1SDavid Brownell 855ffa458c1SDavid Brownell static void __exit ads7846_exit(void) 856ffa458c1SDavid Brownell { 8572e5a7bd9SDavid Brownell spi_unregister_driver(&ads7846_driver); 858ffa458c1SDavid Brownell 859ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 860ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 861ffa458c1SDavid Brownell omap_free_gpio(4); 862ffa458c1SDavid Brownell omap_free_gpio(6); 863ffa458c1SDavid Brownell } 864ffa458c1SDavid Brownell #endif 865ffa458c1SDavid Brownell 866ffa458c1SDavid Brownell } 867ffa458c1SDavid Brownell module_exit(ads7846_exit); 868ffa458c1SDavid Brownell 869ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); 870ffa458c1SDavid Brownell MODULE_LICENSE("GPL"); 871