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 */ 202c8dc071SDavid Brownell #include <linux/hwmon.h> 21ffa458c1SDavid Brownell #include <linux/init.h> 222c8dc071SDavid Brownell #include <linux/err.h> 23ffa458c1SDavid Brownell #include <linux/delay.h> 24ffa458c1SDavid Brownell #include <linux/input.h> 25ffa458c1SDavid Brownell #include <linux/interrupt.h> 26ffa458c1SDavid Brownell #include <linux/slab.h> 27ffa458c1SDavid Brownell #include <linux/spi/spi.h> 28ffa458c1SDavid Brownell #include <linux/spi/ads7846.h> 293ac8bf07SAndrew Morton #include <asm/irq.h> 30ffa458c1SDavid Brownell 31ffa458c1SDavid Brownell #ifdef CONFIG_ARM 32ffa458c1SDavid Brownell #include <asm/mach-types.h> 33ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 34ffa458c1SDavid Brownell #include <asm/arch/gpio.h> 35ffa458c1SDavid Brownell #endif 36ffa458c1SDavid Brownell #endif 37ffa458c1SDavid Brownell 38ffa458c1SDavid Brownell 39ffa458c1SDavid Brownell /* 409084533eSDavid Brownell * This code has been heavily tested on a Nokia 770, and lightly 419084533eSDavid Brownell * tested on other ads7846 devices (OSK/Mistral, Lubbock). 42bff0de5fSDavid Brownell * TSC2046 is just newer ads7846 silicon. 43969111e9SNicolas Ferre * Support for ads7843 tested on Atmel at91sam926x-EK. 44969111e9SNicolas Ferre * Support for ads7845 has only been stubbed in. 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 601936d590SImre Deak #define TS_POLL_DELAY (1 * 1000000) /* ns delay before the first sample */ 611936d590SImre Deak #define TS_POLL_PERIOD (5 * 1000000) /* ns delay between samples */ 62ffa458c1SDavid Brownell 63d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */ 64d93f70b2SDavid Brownell #define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */) 65d93f70b2SDavid Brownell 66ffa458c1SDavid Brownell struct ts_event { 67ffa458c1SDavid Brownell /* For portability, we can't read 12 bit values using SPI (which 68ffa458c1SDavid Brownell * would make the controller deliver them as native byteorder u16 69d93f70b2SDavid Brownell * with msbs zeroed). Instead, we read them as two 8-bit values, 70da970e69SImre Deak * *** WHICH NEED BYTESWAPPING *** and range adjustment. 71ffa458c1SDavid Brownell */ 72da970e69SImre Deak u16 x; 73da970e69SImre Deak u16 y; 74da970e69SImre Deak u16 z1, z2; 75d5b415c9SImre Deak int ignore; 76ffa458c1SDavid Brownell }; 77ffa458c1SDavid Brownell 78ffa458c1SDavid Brownell struct ads7846 { 79a90f7e98SDmitry Torokhov struct input_dev *input; 80ffa458c1SDavid Brownell char phys[32]; 81ffa458c1SDavid Brownell 82ffa458c1SDavid Brownell struct spi_device *spi; 832c8dc071SDavid Brownell 842c8dc071SDavid Brownell #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) 858dd51650SDmitry Torokhov struct attribute_group *attr_group; 861beeffe4STony Jones struct device *hwmon; 872c8dc071SDavid Brownell #endif 882c8dc071SDavid Brownell 89ffa458c1SDavid Brownell u16 model; 90ffa458c1SDavid Brownell u16 vref_delay_usecs; 91ffa458c1SDavid Brownell u16 x_plate_ohms; 92d5b415c9SImre Deak u16 pressure_max; 93ffa458c1SDavid Brownell 9453a0ef89SImre Deak u8 read_x, read_y, read_z1, read_z2, pwrdown; 9553a0ef89SImre Deak u16 dummy; /* for the pwrdown read */ 96ffa458c1SDavid Brownell struct ts_event tc; 97ffa458c1SDavid Brownell 98e4f48861SSemih Hazar struct spi_transfer xfer[18]; 990b7018aaSImre Deak struct spi_message msg[5]; 100d5b415c9SImre Deak struct spi_message *last_msg; 1010b7018aaSImre Deak int msg_idx; 1020b7018aaSImre Deak int read_cnt; 103d5b415c9SImre Deak int read_rep; 1040b7018aaSImre Deak int last_read; 1050b7018aaSImre Deak 1060b7018aaSImre Deak u16 debounce_max; 1070b7018aaSImre Deak u16 debounce_tol; 108d5b415c9SImre Deak u16 debounce_rep; 109ffa458c1SDavid Brownell 1101d25891fSSemih Hazar u16 penirq_recheck_delay_usecs; 1111d25891fSSemih Hazar 112ffa458c1SDavid Brownell spinlock_t lock; 1131936d590SImre Deak struct hrtimer timer; 114ffa458c1SDavid Brownell unsigned pendown:1; /* P: lock */ 115ffa458c1SDavid Brownell unsigned pending:1; /* P: lock */ 116ffa458c1SDavid Brownell // FIXME remove "irq_disabled" 117ffa458c1SDavid Brownell unsigned irq_disabled:1; /* P: lock */ 1187de90a8cSImre Deak unsigned disabled:1; 119*fbb38e30SDavid Brownell unsigned is_suspended:1; 120c9e617a5SImre Deak 121da970e69SImre Deak int (*filter)(void *data, int data_idx, int *val); 122da970e69SImre Deak void *filter_data; 123da970e69SImre Deak void (*filter_cleanup)(void *data); 124c9e617a5SImre Deak int (*get_pendown_state)(void); 125ffa458c1SDavid Brownell }; 126ffa458c1SDavid Brownell 127ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */ 128ffa458c1SDavid Brownell #if 0 129ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 1) 130ffa458c1SDavid Brownell #else 131ffa458c1SDavid Brownell #define CS_CHANGE(xfer) ((xfer).cs_change = 0) 132ffa458c1SDavid Brownell #endif 133ffa458c1SDavid Brownell 134ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 135ffa458c1SDavid Brownell 136ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors. 137ffa458c1SDavid Brownell * Earlier ads784x chips are somewhat compatible. 138ffa458c1SDavid Brownell */ 139ffa458c1SDavid Brownell #define ADS_START (1 << 7) 140ffa458c1SDavid Brownell #define ADS_A2A1A0_d_y (1 << 4) /* differential */ 141ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ 142ffa458c1SDavid Brownell #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ 143ffa458c1SDavid Brownell #define ADS_A2A1A0_d_x (5 << 4) /* differential */ 144ffa458c1SDavid Brownell #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ 145ffa458c1SDavid Brownell #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ 146ffa458c1SDavid Brownell #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ 147ffa458c1SDavid Brownell #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ 148ffa458c1SDavid Brownell #define ADS_8_BIT (1 << 3) 149ffa458c1SDavid Brownell #define ADS_12_BIT (0 << 3) 150ffa458c1SDavid Brownell #define ADS_SER (1 << 2) /* non-differential */ 151ffa458c1SDavid Brownell #define ADS_DFR (0 << 2) /* differential */ 152ffa458c1SDavid Brownell #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ 153ffa458c1SDavid Brownell #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ 154ffa458c1SDavid Brownell #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ 155ffa458c1SDavid Brownell #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ 156ffa458c1SDavid Brownell 157ffa458c1SDavid Brownell #define MAX_12BIT ((1<<12)-1) 158ffa458c1SDavid Brownell 159ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */ 160de2defd9SImre Deak #define READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \ 161de2defd9SImre Deak | ADS_12_BIT | ADS_DFR | \ 162de2defd9SImre Deak (adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0)) 163ffa458c1SDavid Brownell 164de2defd9SImre Deak #define READ_Y(vref) (READ_12BIT_DFR(y, 1, vref)) 165de2defd9SImre Deak #define READ_Z1(vref) (READ_12BIT_DFR(z1, 1, vref)) 166de2defd9SImre Deak #define READ_Z2(vref) (READ_12BIT_DFR(z2, 1, vref)) 16753a0ef89SImre Deak 168de2defd9SImre Deak #define READ_X(vref) (READ_12BIT_DFR(x, 1, vref)) 169de2defd9SImre Deak #define PWRDOWN (READ_12BIT_DFR(y, 0, 0)) /* LAST */ 170ffa458c1SDavid Brownell 171ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage; 172ffa458c1SDavid Brownell * we leave both ADC and VREF powered 173ffa458c1SDavid Brownell */ 174ffa458c1SDavid Brownell #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ 175ffa458c1SDavid Brownell | ADS_12_BIT | ADS_SER) 176ffa458c1SDavid Brownell 177de2defd9SImre Deak #define REF_ON (READ_12BIT_DFR(x, 1, 1)) 178de2defd9SImre Deak #define REF_OFF (READ_12BIT_DFR(y, 0, 0)) 179ffa458c1SDavid Brownell 180ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 181ffa458c1SDavid Brownell 182ffa458c1SDavid Brownell /* 183ffa458c1SDavid Brownell * Non-touchscreen sensors only use single-ended conversions. 1842c8dc071SDavid Brownell * The range is GND..vREF. The ads7843 and ads7835 must use external vREF; 1852c8dc071SDavid Brownell * ads7846 lets that pin be unconnected, to use internal vREF. 186ffa458c1SDavid Brownell */ 1872c8dc071SDavid Brownell static unsigned vREF_mV; 1882c8dc071SDavid Brownell module_param(vREF_mV, uint, 0); 1892c8dc071SDavid Brownell MODULE_PARM_DESC(vREF_mV, "external vREF voltage, in milliVolts"); 190ffa458c1SDavid Brownell 191ffa458c1SDavid Brownell struct ser_req { 192d93f70b2SDavid Brownell u8 ref_on; 193ffa458c1SDavid Brownell u8 command; 194d93f70b2SDavid Brownell u8 ref_off; 195ffa458c1SDavid Brownell u16 scratch; 196ffa458c1SDavid Brownell __be16 sample; 197ffa458c1SDavid Brownell struct spi_message msg; 198ffa458c1SDavid Brownell struct spi_transfer xfer[6]; 199ffa458c1SDavid Brownell }; 200ffa458c1SDavid Brownell 2017de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts); 2027de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts); 2037de90a8cSImre Deak 204c9e617a5SImre Deak static int device_suspended(struct device *dev) 205c9e617a5SImre Deak { 206c9e617a5SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 207*fbb38e30SDavid Brownell return ts->is_suspended || ts->disabled; 208c9e617a5SImre Deak } 209c9e617a5SImre Deak 210ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command) 211ffa458c1SDavid Brownell { 212ffa458c1SDavid Brownell struct spi_device *spi = to_spi_device(dev); 213ffa458c1SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); 214e94b1766SChristoph Lameter struct ser_req *req = kzalloc(sizeof *req, GFP_KERNEL); 215ffa458c1SDavid Brownell int status; 216ffa458c1SDavid Brownell int sample; 2172c8dc071SDavid Brownell int use_internal; 218ffa458c1SDavid Brownell 219ffa458c1SDavid Brownell if (!req) 220ffa458c1SDavid Brownell return -ENOMEM; 221ffa458c1SDavid Brownell 2220b7018aaSImre Deak spi_message_init(&req->msg); 2238275c642SVitaly Wool 2242c8dc071SDavid Brownell /* FIXME boards with ads7846 might use external vref instead ... */ 2252c8dc071SDavid Brownell use_internal = (ts->model == 7846); 2262c8dc071SDavid Brownell 2272c8dc071SDavid Brownell /* maybe turn on internal vREF, and let it settle */ 2282c8dc071SDavid Brownell if (use_internal) { 229d93f70b2SDavid Brownell req->ref_on = REF_ON; 230d93f70b2SDavid Brownell req->xfer[0].tx_buf = &req->ref_on; 231ffa458c1SDavid Brownell req->xfer[0].len = 1; 2322c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[0], &req->msg); 2332c8dc071SDavid Brownell 234ffa458c1SDavid Brownell req->xfer[1].rx_buf = &req->scratch; 235ffa458c1SDavid Brownell req->xfer[1].len = 2; 236ffa458c1SDavid Brownell 2372c8dc071SDavid Brownell /* for 1uF, settle for 800 usec; no cap, 100 usec. */ 238ffa458c1SDavid Brownell req->xfer[1].delay_usecs = ts->vref_delay_usecs; 2392c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[1], &req->msg); 2402c8dc071SDavid Brownell } 241ffa458c1SDavid Brownell 242ffa458c1SDavid Brownell /* take sample */ 243ffa458c1SDavid Brownell req->command = (u8) command; 244ffa458c1SDavid Brownell req->xfer[2].tx_buf = &req->command; 245ffa458c1SDavid Brownell req->xfer[2].len = 1; 2462c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[2], &req->msg); 2472c8dc071SDavid Brownell 248ffa458c1SDavid Brownell req->xfer[3].rx_buf = &req->sample; 249ffa458c1SDavid Brownell req->xfer[3].len = 2; 2502c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[3], &req->msg); 251ffa458c1SDavid Brownell 252ffa458c1SDavid Brownell /* REVISIT: take a few more samples, and compare ... */ 253ffa458c1SDavid Brownell 254969111e9SNicolas Ferre /* converter in low power mode & enable PENIRQ */ 255969111e9SNicolas Ferre req->ref_off = PWRDOWN; 256d93f70b2SDavid Brownell req->xfer[4].tx_buf = &req->ref_off; 257ffa458c1SDavid Brownell req->xfer[4].len = 1; 2582c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[4], &req->msg); 2592c8dc071SDavid Brownell 260ffa458c1SDavid Brownell req->xfer[5].rx_buf = &req->scratch; 261ffa458c1SDavid Brownell req->xfer[5].len = 2; 262ffa458c1SDavid Brownell CS_CHANGE(req->xfer[5]); 2632c8dc071SDavid Brownell spi_message_add_tail(&req->xfer[5], &req->msg); 264ffa458c1SDavid Brownell 265c9e617a5SImre Deak ts->irq_disabled = 1; 266ffa458c1SDavid Brownell disable_irq(spi->irq); 267ffa458c1SDavid Brownell status = spi_sync(spi, &req->msg); 268c9e617a5SImre Deak ts->irq_disabled = 0; 269ffa458c1SDavid Brownell enable_irq(spi->irq); 270ffa458c1SDavid Brownell 271ffa458c1SDavid Brownell if (req->msg.status) 272ffa458c1SDavid Brownell status = req->msg.status; 273ffa458c1SDavid Brownell 2749084533eSDavid Brownell /* on-wire is a must-ignore bit, a BE12 value, then padding */ 2759084533eSDavid Brownell sample = be16_to_cpu(req->sample); 2769084533eSDavid Brownell sample = sample >> 3; 2779084533eSDavid Brownell sample &= 0x0fff; 2789084533eSDavid Brownell 2799084533eSDavid Brownell kfree(req); 280ffa458c1SDavid Brownell return status ? status : sample; 281ffa458c1SDavid Brownell } 282ffa458c1SDavid Brownell 2832c8dc071SDavid Brownell #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) 2842c8dc071SDavid Brownell 2852c8dc071SDavid Brownell #define SHOW(name, var, adjust) static ssize_t \ 286ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ 287ffa458c1SDavid Brownell { \ 2882c8dc071SDavid Brownell struct ads7846 *ts = dev_get_drvdata(dev); \ 289ffa458c1SDavid Brownell ssize_t v = ads7846_read12_ser(dev, \ 2902c8dc071SDavid Brownell READ_12BIT_SER(var) | ADS_PD10_ALL_ON); \ 291ffa458c1SDavid Brownell if (v < 0) \ 292ffa458c1SDavid Brownell return v; \ 2932c8dc071SDavid Brownell return sprintf(buf, "%u\n", adjust(ts, v)); \ 294ffa458c1SDavid Brownell } \ 295ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); 296ffa458c1SDavid Brownell 2972c8dc071SDavid Brownell 2982c8dc071SDavid Brownell /* Sysfs conventions report temperatures in millidegrees Celcius. 2992c8dc071SDavid Brownell * ADS7846 could use the low-accuracy two-sample scheme, but can't do the high 3002c8dc071SDavid Brownell * accuracy scheme without calibration data. For now we won't try either; 3012c8dc071SDavid Brownell * userspace sees raw sensor values, and must scale/calibrate appropriately. 3022c8dc071SDavid Brownell */ 3032c8dc071SDavid Brownell static inline unsigned null_adjust(struct ads7846 *ts, ssize_t v) 3042c8dc071SDavid Brownell { 3052c8dc071SDavid Brownell return v; 3062c8dc071SDavid Brownell } 3072c8dc071SDavid Brownell 3082c8dc071SDavid Brownell SHOW(temp0, temp0, null_adjust) /* temp1_input */ 3092c8dc071SDavid Brownell SHOW(temp1, temp1, null_adjust) /* temp2_input */ 3102c8dc071SDavid Brownell 3112c8dc071SDavid Brownell 3122c8dc071SDavid Brownell /* sysfs conventions report voltages in millivolts. We can convert voltages 3132c8dc071SDavid Brownell * if we know vREF. userspace may need to scale vAUX to match the board's 3142c8dc071SDavid Brownell * external resistors; we assume that vBATT only uses the internal ones. 3152c8dc071SDavid Brownell */ 3162c8dc071SDavid Brownell static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v) 3172c8dc071SDavid Brownell { 3182c8dc071SDavid Brownell unsigned retval = v; 3192c8dc071SDavid Brownell 3202c8dc071SDavid Brownell /* external resistors may scale vAUX into 0..vREF */ 3212c8dc071SDavid Brownell retval *= vREF_mV; 3222c8dc071SDavid Brownell retval = retval >> 12; 3232c8dc071SDavid Brownell return retval; 3242c8dc071SDavid Brownell } 3252c8dc071SDavid Brownell 3262c8dc071SDavid Brownell static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v) 3272c8dc071SDavid Brownell { 3282c8dc071SDavid Brownell unsigned retval = vaux_adjust(ts, v); 3292c8dc071SDavid Brownell 3302c8dc071SDavid Brownell /* ads7846 has a resistor ladder to scale this signal down */ 3312c8dc071SDavid Brownell if (ts->model == 7846) 3322c8dc071SDavid Brownell retval *= 4; 3332c8dc071SDavid Brownell return retval; 3342c8dc071SDavid Brownell } 3352c8dc071SDavid Brownell 3362c8dc071SDavid Brownell SHOW(in0_input, vaux, vaux_adjust) 3372c8dc071SDavid Brownell SHOW(in1_input, vbatt, vbatt_adjust) 3382c8dc071SDavid Brownell 3392c8dc071SDavid Brownell 3402c8dc071SDavid Brownell static struct attribute *ads7846_attributes[] = { 3412c8dc071SDavid Brownell &dev_attr_temp0.attr, 3422c8dc071SDavid Brownell &dev_attr_temp1.attr, 3432c8dc071SDavid Brownell &dev_attr_in0_input.attr, 3442c8dc071SDavid Brownell &dev_attr_in1_input.attr, 3452c8dc071SDavid Brownell NULL, 3462c8dc071SDavid Brownell }; 3472c8dc071SDavid Brownell 3482c8dc071SDavid Brownell static struct attribute_group ads7846_attr_group = { 3492c8dc071SDavid Brownell .attrs = ads7846_attributes, 3502c8dc071SDavid Brownell }; 3512c8dc071SDavid Brownell 3522c8dc071SDavid Brownell static struct attribute *ads7843_attributes[] = { 3532c8dc071SDavid Brownell &dev_attr_in0_input.attr, 3542c8dc071SDavid Brownell &dev_attr_in1_input.attr, 3552c8dc071SDavid Brownell NULL, 3562c8dc071SDavid Brownell }; 3572c8dc071SDavid Brownell 3582c8dc071SDavid Brownell static struct attribute_group ads7843_attr_group = { 3592c8dc071SDavid Brownell .attrs = ads7843_attributes, 3602c8dc071SDavid Brownell }; 3612c8dc071SDavid Brownell 3622c8dc071SDavid Brownell static struct attribute *ads7845_attributes[] = { 3632c8dc071SDavid Brownell &dev_attr_in0_input.attr, 3642c8dc071SDavid Brownell NULL, 3652c8dc071SDavid Brownell }; 3662c8dc071SDavid Brownell 3672c8dc071SDavid Brownell static struct attribute_group ads7845_attr_group = { 3682c8dc071SDavid Brownell .attrs = ads7845_attributes, 3692c8dc071SDavid Brownell }; 3702c8dc071SDavid Brownell 3712c8dc071SDavid Brownell static int ads784x_hwmon_register(struct spi_device *spi, struct ads7846 *ts) 3722c8dc071SDavid Brownell { 3731beeffe4STony Jones struct device *hwmon; 3742c8dc071SDavid Brownell int err; 3752c8dc071SDavid Brownell 3762c8dc071SDavid Brownell /* hwmon sensors need a reference voltage */ 3772c8dc071SDavid Brownell switch (ts->model) { 3782c8dc071SDavid Brownell case 7846: 3792c8dc071SDavid Brownell if (!vREF_mV) { 3802c8dc071SDavid Brownell dev_dbg(&spi->dev, "assuming 2.5V internal vREF\n"); 3812c8dc071SDavid Brownell vREF_mV = 2500; 3822c8dc071SDavid Brownell } 3832c8dc071SDavid Brownell break; 3842c8dc071SDavid Brownell case 7845: 3852c8dc071SDavid Brownell case 7843: 3862c8dc071SDavid Brownell if (!vREF_mV) { 3872c8dc071SDavid Brownell dev_warn(&spi->dev, 3882c8dc071SDavid Brownell "external vREF for ADS%d not specified\n", 3892c8dc071SDavid Brownell ts->model); 3902c8dc071SDavid Brownell return 0; 3912c8dc071SDavid Brownell } 3922c8dc071SDavid Brownell break; 3932c8dc071SDavid Brownell } 3942c8dc071SDavid Brownell 3952c8dc071SDavid Brownell /* different chips have different sensor groups */ 3962c8dc071SDavid Brownell switch (ts->model) { 3972c8dc071SDavid Brownell case 7846: 3982c8dc071SDavid Brownell ts->attr_group = &ads7846_attr_group; 3992c8dc071SDavid Brownell break; 4002c8dc071SDavid Brownell case 7845: 4012c8dc071SDavid Brownell ts->attr_group = &ads7845_attr_group; 4022c8dc071SDavid Brownell break; 4032c8dc071SDavid Brownell case 7843: 4042c8dc071SDavid Brownell ts->attr_group = &ads7843_attr_group; 4052c8dc071SDavid Brownell break; 4062c8dc071SDavid Brownell default: 4072c8dc071SDavid Brownell dev_dbg(&spi->dev, "ADS%d not recognized\n", ts->model); 4082c8dc071SDavid Brownell return 0; 4092c8dc071SDavid Brownell } 4102c8dc071SDavid Brownell 4112c8dc071SDavid Brownell err = sysfs_create_group(&spi->dev.kobj, ts->attr_group); 4122c8dc071SDavid Brownell if (err) 4132c8dc071SDavid Brownell return err; 4142c8dc071SDavid Brownell 4152c8dc071SDavid Brownell hwmon = hwmon_device_register(&spi->dev); 4162c8dc071SDavid Brownell if (IS_ERR(hwmon)) { 4172c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, ts->attr_group); 4182c8dc071SDavid Brownell return PTR_ERR(hwmon); 4192c8dc071SDavid Brownell } 4202c8dc071SDavid Brownell 4212c8dc071SDavid Brownell ts->hwmon = hwmon; 4222c8dc071SDavid Brownell return 0; 4232c8dc071SDavid Brownell } 4242c8dc071SDavid Brownell 4252c8dc071SDavid Brownell static void ads784x_hwmon_unregister(struct spi_device *spi, 4262c8dc071SDavid Brownell struct ads7846 *ts) 4272c8dc071SDavid Brownell { 4282c8dc071SDavid Brownell if (ts->hwmon) { 4292c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, ts->attr_group); 4302c8dc071SDavid Brownell hwmon_device_unregister(ts->hwmon); 4312c8dc071SDavid Brownell } 4322c8dc071SDavid Brownell } 4332c8dc071SDavid Brownell 4342c8dc071SDavid Brownell #else 4352c8dc071SDavid Brownell static inline int ads784x_hwmon_register(struct spi_device *spi, 4362c8dc071SDavid Brownell struct ads7846 *ts) 4372c8dc071SDavid Brownell { 4382c8dc071SDavid Brownell return 0; 4392c8dc071SDavid Brownell } 4402c8dc071SDavid Brownell 4412c8dc071SDavid Brownell static inline void ads784x_hwmon_unregister(struct spi_device *spi, 4422c8dc071SDavid Brownell struct ads7846 *ts) 4432c8dc071SDavid Brownell { 4442c8dc071SDavid Brownell } 4452c8dc071SDavid Brownell #endif 446ffa458c1SDavid Brownell 447438f2a74SImre Deak static int is_pen_down(struct device *dev) 448438f2a74SImre Deak { 449438f2a74SImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 450438f2a74SImre Deak 451438f2a74SImre Deak return ts->pendown; 452438f2a74SImre Deak } 453438f2a74SImre Deak 454438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev, 455438f2a74SImre Deak struct device_attribute *attr, char *buf) 456438f2a74SImre Deak { 457438f2a74SImre Deak return sprintf(buf, "%u\n", is_pen_down(dev)); 458438f2a74SImre Deak } 459438f2a74SImre Deak 460438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL); 461438f2a74SImre Deak 4627de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev, 4637de90a8cSImre Deak struct device_attribute *attr, char *buf) 4647de90a8cSImre Deak { 4657de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 4667de90a8cSImre Deak 4677de90a8cSImre Deak return sprintf(buf, "%u\n", ts->disabled); 4687de90a8cSImre Deak } 4697de90a8cSImre Deak 4707de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev, 4717de90a8cSImre Deak struct device_attribute *attr, 4727de90a8cSImre Deak const char *buf, size_t count) 4737de90a8cSImre Deak { 4747de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(dev); 4757de90a8cSImre Deak char *endp; 4767de90a8cSImre Deak int i; 4777de90a8cSImre Deak 4787de90a8cSImre Deak i = simple_strtoul(buf, &endp, 10); 4797de90a8cSImre Deak spin_lock_irq(&ts->lock); 4807de90a8cSImre Deak 4817de90a8cSImre Deak if (i) 4827de90a8cSImre Deak ads7846_disable(ts); 4837de90a8cSImre Deak else 4847de90a8cSImre Deak ads7846_enable(ts); 4857de90a8cSImre Deak 4867de90a8cSImre Deak spin_unlock_irq(&ts->lock); 4877de90a8cSImre Deak 4887de90a8cSImre Deak return count; 4897de90a8cSImre Deak } 4907de90a8cSImre Deak 4917de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store); 4927de90a8cSImre Deak 4932c8dc071SDavid Brownell static struct attribute *ads784x_attributes[] = { 4948dd51650SDmitry Torokhov &dev_attr_pen_down.attr, 4958dd51650SDmitry Torokhov &dev_attr_disable.attr, 4968dd51650SDmitry Torokhov NULL, 4978dd51650SDmitry Torokhov }; 4988dd51650SDmitry Torokhov 4992c8dc071SDavid Brownell static struct attribute_group ads784x_attr_group = { 5002c8dc071SDavid Brownell .attrs = ads784x_attributes, 5018dd51650SDmitry Torokhov }; 5028dd51650SDmitry Torokhov 503ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 504ffa458c1SDavid Brownell 505ffa458c1SDavid Brownell /* 506ffa458c1SDavid Brownell * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, 507ffa458c1SDavid Brownell * to retrieve touchscreen status. 508ffa458c1SDavid Brownell * 509ffa458c1SDavid Brownell * The SPI transfer completion callback does the real work. It reports 510ffa458c1SDavid Brownell * touchscreen events and reactivates the timer (or IRQ) as appropriate. 511ffa458c1SDavid Brownell */ 512ffa458c1SDavid Brownell 513ffa458c1SDavid Brownell static void ads7846_rx(void *ads) 514ffa458c1SDavid Brownell { 515ffa458c1SDavid Brownell struct ads7846 *ts = ads; 516ffa458c1SDavid Brownell unsigned Rt; 517ffa458c1SDavid Brownell u16 x, y, z1, z2; 518ffa458c1SDavid Brownell 519da970e69SImre Deak /* ads7846_rx_val() did in-place conversion (including byteswap) from 520da970e69SImre Deak * on-the-wire format as part of debouncing to get stable readings. 521ffa458c1SDavid Brownell */ 522da970e69SImre Deak x = ts->tc.x; 523da970e69SImre Deak y = ts->tc.y; 524da970e69SImre Deak z1 = ts->tc.z1; 525da970e69SImre Deak z2 = ts->tc.z2; 526ffa458c1SDavid Brownell 527ffa458c1SDavid Brownell /* range filtering */ 528ffa458c1SDavid Brownell if (x == MAX_12BIT) 529ffa458c1SDavid Brownell x = 0; 530ffa458c1SDavid Brownell 53115e3589eSImre Deak if (likely(x && z1)) { 532ffa458c1SDavid Brownell /* compute touch pressure resistance using equation #2 */ 533ffa458c1SDavid Brownell Rt = z2; 534ffa458c1SDavid Brownell Rt -= z1; 535ffa458c1SDavid Brownell Rt *= x; 536ffa458c1SDavid Brownell Rt *= ts->x_plate_ohms; 537ffa458c1SDavid Brownell Rt /= z1; 538ffa458c1SDavid Brownell Rt = (Rt + 2047) >> 12; 539ffa458c1SDavid Brownell } else 540ffa458c1SDavid Brownell Rt = 0; 541ffa458c1SDavid Brownell 542969111e9SNicolas Ferre if (ts->model == 7843) 543969111e9SNicolas Ferre Rt = ts->pressure_max / 2; 544969111e9SNicolas Ferre 545d5b415c9SImre Deak /* Sample found inconsistent by debouncing or pressure is beyond 546d5b415c9SImre Deak * the maximum. Don't report it to user space, repeat at least 5471936d590SImre Deak * once more the measurement 5481936d590SImre Deak */ 549d5b415c9SImre Deak if (ts->tc.ignore || Rt > ts->pressure_max) { 55015e3589eSImre Deak #ifdef VERBOSE 55115e3589eSImre Deak pr_debug("%s: ignored %d pressure %d\n", 55215e3589eSImre Deak ts->spi->dev.bus_id, ts->tc.ignore, Rt); 55315e3589eSImre Deak #endif 5541936d590SImre Deak hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 555c9cb2e3dSThomas Gleixner HRTIMER_MODE_REL); 556d5b415c9SImre Deak return; 557d5b415c9SImre Deak } 558d5b415c9SImre Deak 5591d25891fSSemih Hazar /* Maybe check the pendown state before reporting. This discards 5601d25891fSSemih Hazar * false readings when the pen is lifted. 5611d25891fSSemih Hazar */ 5621d25891fSSemih Hazar if (ts->penirq_recheck_delay_usecs) { 5631d25891fSSemih Hazar udelay(ts->penirq_recheck_delay_usecs); 5641d25891fSSemih Hazar if (!ts->get_pendown_state()) 5651d25891fSSemih Hazar Rt = 0; 5661d25891fSSemih Hazar } 5671d25891fSSemih Hazar 56815e3589eSImre Deak /* NOTE: We can't rely on the pressure to determine the pen down 56915e3589eSImre Deak * state, even this controller has a pressure sensor. The pressure 57015e3589eSImre Deak * value can fluctuate for quite a while after lifting the pen and 57115e3589eSImre Deak * in some cases may not even settle at the expected value. 572ffa458c1SDavid Brownell * 57315e3589eSImre Deak * The only safe way to check for the pen up condition is in the 57415e3589eSImre Deak * timer by reading the pen signal state (it's a GPIO _and_ IRQ). 575ffa458c1SDavid Brownell */ 576ffa458c1SDavid Brownell if (Rt) { 57715e3589eSImre Deak struct input_dev *input = ts->input; 578ae82d5abSImre Deak 57915e3589eSImre Deak if (!ts->pendown) { 58015e3589eSImre Deak input_report_key(input, BTN_TOUCH, 1); 58115e3589eSImre Deak ts->pendown = 1; 582ffa458c1SDavid Brownell #ifdef VERBOSE 58315e3589eSImre Deak dev_dbg(&ts->spi->dev, "DOWN\n"); 584ffa458c1SDavid Brownell #endif 58515e3589eSImre Deak } 58615e3589eSImre Deak input_report_abs(input, ABS_X, x); 58715e3589eSImre Deak input_report_abs(input, ABS_Y, y); 58815e3589eSImre Deak input_report_abs(input, ABS_PRESSURE, Rt); 589ffa458c1SDavid Brownell 59015e3589eSImre Deak input_sync(input); 59115e3589eSImre Deak #ifdef VERBOSE 59215e3589eSImre Deak dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); 59315e3589eSImre Deak #endif 59415e3589eSImre Deak } 595ffa458c1SDavid Brownell 596c9cb2e3dSThomas Gleixner hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), 597c9cb2e3dSThomas Gleixner HRTIMER_MODE_REL); 598ffa458c1SDavid Brownell } 599ffa458c1SDavid Brownell 600da970e69SImre Deak static int ads7846_debounce(void *ads, int data_idx, int *val) 601ffa458c1SDavid Brownell { 6020b7018aaSImre Deak struct ads7846 *ts = ads; 603ffa458c1SDavid Brownell 604da970e69SImre Deak if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) { 605da970e69SImre Deak /* Start over collecting consistent readings. */ 606da970e69SImre Deak ts->read_rep = 0; 607d5b415c9SImre Deak /* Repeat it, if this was the first read or the read 608d5b415c9SImre Deak * wasn't consistent enough. */ 609d5b415c9SImre Deak if (ts->read_cnt < ts->debounce_max) { 610da970e69SImre Deak ts->last_read = *val; 611d5b415c9SImre Deak ts->read_cnt++; 612da970e69SImre Deak return ADS7846_FILTER_REPEAT; 6130b7018aaSImre Deak } else { 614d5b415c9SImre Deak /* Maximum number of debouncing reached and still 615d5b415c9SImre Deak * not enough number of consistent readings. Abort 616d5b415c9SImre Deak * the whole sample, repeat it in the next sampling 617d5b415c9SImre Deak * period. 618d5b415c9SImre Deak */ 619d5b415c9SImre Deak ts->read_cnt = 0; 620da970e69SImre Deak return ADS7846_FILTER_IGNORE; 621d5b415c9SImre Deak } 622d5b415c9SImre Deak } else { 623d5b415c9SImre Deak if (++ts->read_rep > ts->debounce_rep) { 624d5b415c9SImre Deak /* Got a good reading for this coordinate, 625d5b415c9SImre Deak * go for the next one. */ 6260b7018aaSImre Deak ts->read_cnt = 0; 627d5b415c9SImre Deak ts->read_rep = 0; 628da970e69SImre Deak return ADS7846_FILTER_OK; 629da970e69SImre Deak } else { 630d5b415c9SImre Deak /* Read more values that are consistent. */ 631d5b415c9SImre Deak ts->read_cnt++; 632da970e69SImre Deak return ADS7846_FILTER_REPEAT; 633da970e69SImre Deak } 634da970e69SImre Deak } 635da970e69SImre Deak } 636da970e69SImre Deak 637da970e69SImre Deak static int ads7846_no_filter(void *ads, int data_idx, int *val) 638da970e69SImre Deak { 639da970e69SImre Deak return ADS7846_FILTER_OK; 640da970e69SImre Deak } 641da970e69SImre Deak 642da970e69SImre Deak static void ads7846_rx_val(void *ads) 643da970e69SImre Deak { 644da970e69SImre Deak struct ads7846 *ts = ads; 645da970e69SImre Deak struct spi_message *m; 646da970e69SImre Deak struct spi_transfer *t; 647da970e69SImre Deak u16 *rx_val; 648da970e69SImre Deak int val; 649da970e69SImre Deak int action; 650da970e69SImre Deak int status; 651da970e69SImre Deak 652da970e69SImre Deak m = &ts->msg[ts->msg_idx]; 653da970e69SImre Deak t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); 654da970e69SImre Deak rx_val = t->rx_buf; 655da970e69SImre Deak 656da970e69SImre Deak /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; 657da970e69SImre Deak * built from two 8 bit values written msb-first. 658da970e69SImre Deak */ 659da970e69SImre Deak val = be16_to_cpu(*rx_val) >> 3; 660da970e69SImre Deak 661da970e69SImre Deak action = ts->filter(ts->filter_data, ts->msg_idx, &val); 662da970e69SImre Deak switch (action) { 663da970e69SImre Deak case ADS7846_FILTER_REPEAT: 664da970e69SImre Deak break; 665da970e69SImre Deak case ADS7846_FILTER_IGNORE: 666da970e69SImre Deak ts->tc.ignore = 1; 667da970e69SImre Deak /* Last message will contain ads7846_rx() as the 668da970e69SImre Deak * completion function. 669da970e69SImre Deak */ 670da970e69SImre Deak m = ts->last_msg; 671da970e69SImre Deak break; 672da970e69SImre Deak case ADS7846_FILTER_OK: 673da970e69SImre Deak *rx_val = val; 674da970e69SImre Deak ts->tc.ignore = 0; 675da970e69SImre Deak m = &ts->msg[++ts->msg_idx]; 676da970e69SImre Deak break; 677da970e69SImre Deak default: 678da970e69SImre Deak BUG(); 679ffa458c1SDavid Brownell } 6800b7018aaSImre Deak status = spi_async(ts->spi, m); 681ffa458c1SDavid Brownell if (status) 682ffa458c1SDavid Brownell dev_err(&ts->spi->dev, "spi_async --> %d\n", 683ffa458c1SDavid Brownell status); 684ffa458c1SDavid Brownell } 6850b7018aaSImre Deak 686c9cb2e3dSThomas Gleixner static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) 6870b7018aaSImre Deak { 6881936d590SImre Deak struct ads7846 *ts = container_of(handle, struct ads7846, timer); 6890b7018aaSImre Deak int status = 0; 6900b7018aaSImre Deak 691c9e617a5SImre Deak spin_lock_irq(&ts->lock); 692c9e617a5SImre Deak 69315e3589eSImre Deak if (unlikely(!ts->get_pendown_state() || 69415e3589eSImre Deak device_suspended(&ts->spi->dev))) { 69515e3589eSImre Deak if (ts->pendown) { 69615e3589eSImre Deak struct input_dev *input = ts->input; 69715e3589eSImre Deak 69815e3589eSImre Deak input_report_key(input, BTN_TOUCH, 0); 69915e3589eSImre Deak input_report_abs(input, ABS_PRESSURE, 0); 70015e3589eSImre Deak input_sync(input); 70115e3589eSImre Deak 70215e3589eSImre Deak ts->pendown = 0; 70315e3589eSImre Deak #ifdef VERBOSE 70415e3589eSImre Deak dev_dbg(&ts->spi->dev, "UP\n"); 70515e3589eSImre Deak #endif 70615e3589eSImre Deak } 70715e3589eSImre Deak 7089084533eSDavid Brownell /* measurement cycle ended */ 709c9e617a5SImre Deak if (!device_suspended(&ts->spi->dev)) { 710c9e617a5SImre Deak ts->irq_disabled = 0; 711c9e617a5SImre Deak enable_irq(ts->spi->irq); 712c9e617a5SImre Deak } 713c9e617a5SImre Deak ts->pending = 0; 714c9e617a5SImre Deak } else { 715c9e617a5SImre Deak /* pen is still down, continue with the measurement */ 7160b7018aaSImre Deak ts->msg_idx = 0; 7170b7018aaSImre Deak status = spi_async(ts->spi, &ts->msg[0]); 7180b7018aaSImre Deak if (status) 7190b7018aaSImre Deak dev_err(&ts->spi->dev, "spi_async --> %d\n", status); 720ffa458c1SDavid Brownell } 721ffa458c1SDavid Brownell 722c9e617a5SImre Deak spin_unlock_irq(&ts->lock); 7231936d590SImre Deak return HRTIMER_NORESTART; 724c9e617a5SImre Deak } 725c9e617a5SImre Deak 7267d12e780SDavid Howells static irqreturn_t ads7846_irq(int irq, void *handle) 727ffa458c1SDavid Brownell { 7280b7018aaSImre Deak struct ads7846 *ts = handle; 7290b7018aaSImre Deak unsigned long flags; 7300b7018aaSImre Deak 7310b7018aaSImre Deak spin_lock_irqsave(&ts->lock, flags); 732c9e617a5SImre Deak if (likely(ts->get_pendown_state())) { 7330b7018aaSImre Deak if (!ts->irq_disabled) { 7349084533eSDavid Brownell /* The ARM do_simple_IRQ() dispatcher doesn't act 7359084533eSDavid Brownell * like the other dispatchers: it will report IRQs 7369084533eSDavid Brownell * even after they've been disabled. We work around 7379084533eSDavid Brownell * that here. (The "generic irq" framework may help...) 7380b7018aaSImre Deak */ 7390b7018aaSImre Deak ts->irq_disabled = 1; 7400b7018aaSImre Deak disable_irq(ts->spi->irq); 7410b7018aaSImre Deak ts->pending = 1; 7421936d590SImre Deak hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), 743c9cb2e3dSThomas Gleixner HRTIMER_MODE_REL); 7440b7018aaSImre Deak } 7450b7018aaSImre Deak } 7460b7018aaSImre Deak spin_unlock_irqrestore(&ts->lock, flags); 7477de90a8cSImre Deak 7487de90a8cSImre Deak return IRQ_HANDLED; 749ffa458c1SDavid Brownell } 750ffa458c1SDavid Brownell 751ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/ 752ffa458c1SDavid Brownell 7537de90a8cSImre Deak /* Must be called with ts->lock held */ 7547de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts) 755ffa458c1SDavid Brownell { 7567de90a8cSImre Deak if (ts->disabled) 7577de90a8cSImre Deak return; 758ffa458c1SDavid Brownell 759c9e617a5SImre Deak ts->disabled = 1; 760c9e617a5SImre Deak 761ffa458c1SDavid Brownell /* are we waiting for IRQ, or polling? */ 762c9e617a5SImre Deak if (!ts->pending) { 763ffa458c1SDavid Brownell ts->irq_disabled = 1; 764ffa458c1SDavid Brownell disable_irq(ts->spi->irq); 765ffa458c1SDavid Brownell } else { 766c9e617a5SImre Deak /* the timer will run at least once more, and 767c9e617a5SImre Deak * leave everything in a clean state, IRQ disabled 768ffa458c1SDavid Brownell */ 769c9e617a5SImre Deak while (ts->pending) { 7707de90a8cSImre Deak spin_unlock_irq(&ts->lock); 771c4febb94SJuha Yrjola msleep(1); 7727de90a8cSImre Deak spin_lock_irq(&ts->lock); 773ffa458c1SDavid Brownell } 774ffa458c1SDavid Brownell } 775ffa458c1SDavid Brownell 776ffa458c1SDavid Brownell /* we know the chip's in lowpower mode since we always 777ffa458c1SDavid Brownell * leave it that way after every request 778ffa458c1SDavid Brownell */ 779ffa458c1SDavid Brownell 7807de90a8cSImre Deak } 7817de90a8cSImre Deak 7827de90a8cSImre Deak /* Must be called with ts->lock held */ 7837de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts) 7847de90a8cSImre Deak { 7857de90a8cSImre Deak if (!ts->disabled) 7867de90a8cSImre Deak return; 7877de90a8cSImre Deak 7887de90a8cSImre Deak ts->disabled = 0; 7897de90a8cSImre Deak ts->irq_disabled = 0; 7907de90a8cSImre Deak enable_irq(ts->spi->irq); 7917de90a8cSImre Deak } 7927de90a8cSImre Deak 7937de90a8cSImre Deak static int ads7846_suspend(struct spi_device *spi, pm_message_t message) 7947de90a8cSImre Deak { 7957de90a8cSImre Deak struct ads7846 *ts = dev_get_drvdata(&spi->dev); 7967de90a8cSImre Deak 7977de90a8cSImre Deak spin_lock_irq(&ts->lock); 7987de90a8cSImre Deak 799*fbb38e30SDavid Brownell ts->is_suspended = 1; 8007de90a8cSImre Deak ads7846_disable(ts); 8017de90a8cSImre Deak 8027de90a8cSImre Deak spin_unlock_irq(&ts->lock); 8037de90a8cSImre Deak 804ffa458c1SDavid Brownell return 0; 8057de90a8cSImre Deak 806ffa458c1SDavid Brownell } 807ffa458c1SDavid Brownell 8082e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi) 809ffa458c1SDavid Brownell { 8102e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 811ffa458c1SDavid Brownell 8127de90a8cSImre Deak spin_lock_irq(&ts->lock); 8137de90a8cSImre Deak 814*fbb38e30SDavid Brownell ts->is_suspended = 0; 8157de90a8cSImre Deak ads7846_enable(ts); 8167de90a8cSImre Deak 8177de90a8cSImre Deak spin_unlock_irq(&ts->lock); 8187de90a8cSImre Deak 819ffa458c1SDavid Brownell return 0; 820ffa458c1SDavid Brownell } 821ffa458c1SDavid Brownell 8222e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi) 823ffa458c1SDavid Brownell { 824ffa458c1SDavid Brownell struct ads7846 *ts; 825a90f7e98SDmitry Torokhov struct input_dev *input_dev; 8262e5a7bd9SDavid Brownell struct ads7846_platform_data *pdata = spi->dev.platform_data; 8270b7018aaSImre Deak struct spi_message *m; 828ffa458c1SDavid Brownell struct spi_transfer *x; 829de2defd9SImre Deak int vref; 830a90f7e98SDmitry Torokhov int err; 831ffa458c1SDavid Brownell 832ffa458c1SDavid Brownell if (!spi->irq) { 8332e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no IRQ?\n"); 834ffa458c1SDavid Brownell return -ENODEV; 835ffa458c1SDavid Brownell } 836ffa458c1SDavid Brownell 837ffa458c1SDavid Brownell if (!pdata) { 8382e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "no platform data?\n"); 839ffa458c1SDavid Brownell return -ENODEV; 840ffa458c1SDavid Brownell } 841ffa458c1SDavid Brownell 842ffa458c1SDavid Brownell /* don't exceed max specified sample rate */ 843d93f70b2SDavid Brownell if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) { 8442e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "f(sample) %d KHz?\n", 845d93f70b2SDavid Brownell (spi->max_speed_hz/SAMPLE_BITS)/1000); 846ffa458c1SDavid Brownell return -EINVAL; 847ffa458c1SDavid Brownell } 848ffa458c1SDavid Brownell 8499084533eSDavid Brownell /* REVISIT when the irq can be triggered active-low, or if for some 8509084533eSDavid Brownell * reason the touchscreen isn't hooked up, we don't need to access 8519084533eSDavid Brownell * the pendown state. 8529084533eSDavid Brownell */ 853c9e617a5SImre Deak if (pdata->get_pendown_state == NULL) { 854c9e617a5SImre Deak dev_dbg(&spi->dev, "no get_pendown_state function?\n"); 855c9e617a5SImre Deak return -EINVAL; 856c9e617a5SImre Deak } 857c9e617a5SImre Deak 8589084533eSDavid Brownell /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except 8599084533eSDavid Brownell * that even if the hardware can do that, the SPI controller driver 8609084533eSDavid Brownell * may not. So we stick to very-portable 8 bit words, both RX and TX. 861ffa458c1SDavid Brownell */ 8629084533eSDavid Brownell spi->bits_per_word = 8; 863230ffc8eSSemih Hazar spi->mode = SPI_MODE_0; 8647937e86aSImre Deak err = spi_setup(spi); 8657937e86aSImre Deak if (err < 0) 8667937e86aSImre Deak return err; 867ffa458c1SDavid Brownell 868a90f7e98SDmitry Torokhov ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); 869a90f7e98SDmitry Torokhov input_dev = input_allocate_device(); 870a90f7e98SDmitry Torokhov if (!ts || !input_dev) { 871a90f7e98SDmitry Torokhov err = -ENOMEM; 872a90f7e98SDmitry Torokhov goto err_free_mem; 873a90f7e98SDmitry Torokhov } 874ffa458c1SDavid Brownell 8752e5a7bd9SDavid Brownell dev_set_drvdata(&spi->dev, ts); 876ffa458c1SDavid Brownell 877ffa458c1SDavid Brownell ts->spi = spi; 878a90f7e98SDmitry Torokhov ts->input = input_dev; 879ffa458c1SDavid Brownell 880c9cb2e3dSThomas Gleixner hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 881ffa458c1SDavid Brownell ts->timer.function = ads7846_timer; 882ffa458c1SDavid Brownell 8837de90a8cSImre Deak spin_lock_init(&ts->lock); 8847de90a8cSImre Deak 885ffa458c1SDavid Brownell ts->model = pdata->model ? : 7846; 886ffa458c1SDavid Brownell ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; 887ffa458c1SDavid Brownell ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; 888d5b415c9SImre Deak ts->pressure_max = pdata->pressure_max ? : ~0; 889da970e69SImre Deak 890da970e69SImre Deak if (pdata->filter != NULL) { 891da970e69SImre Deak if (pdata->filter_init != NULL) { 892da970e69SImre Deak err = pdata->filter_init(pdata, &ts->filter_data); 893da970e69SImre Deak if (err < 0) 894da970e69SImre Deak goto err_free_mem; 895da970e69SImre Deak } 896da970e69SImre Deak ts->filter = pdata->filter; 897da970e69SImre Deak ts->filter_cleanup = pdata->filter_cleanup; 898da970e69SImre Deak } else if (pdata->debounce_max) { 899d5b415c9SImre Deak ts->debounce_max = pdata->debounce_max; 900da970e69SImre Deak if (ts->debounce_max < 2) 901da970e69SImre Deak ts->debounce_max = 2; 902d5b415c9SImre Deak ts->debounce_tol = pdata->debounce_tol; 903d5b415c9SImre Deak ts->debounce_rep = pdata->debounce_rep; 904da970e69SImre Deak ts->filter = ads7846_debounce; 905da970e69SImre Deak ts->filter_data = ts; 906d5b415c9SImre Deak } else 907da970e69SImre Deak ts->filter = ads7846_no_filter; 908c9e617a5SImre Deak ts->get_pendown_state = pdata->get_pendown_state; 909ffa458c1SDavid Brownell 9101d25891fSSemih Hazar if (pdata->penirq_recheck_delay_usecs) 9111d25891fSSemih Hazar ts->penirq_recheck_delay_usecs = 9121d25891fSSemih Hazar pdata->penirq_recheck_delay_usecs; 9131d25891fSSemih Hazar 914a90f7e98SDmitry Torokhov snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id); 915ffa458c1SDavid Brownell 916a90f7e98SDmitry Torokhov input_dev->name = "ADS784x Touchscreen"; 917a90f7e98SDmitry Torokhov input_dev->phys = ts->phys; 918a5394fb0SDmitry Torokhov input_dev->dev.parent = &spi->dev; 919ffa458c1SDavid Brownell 9207b19ada2SJiri Slaby input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); 9217b19ada2SJiri Slaby input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); 922a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_X, 923ffa458c1SDavid Brownell pdata->x_min ? : 0, 924ffa458c1SDavid Brownell pdata->x_max ? : MAX_12BIT, 925ffa458c1SDavid Brownell 0, 0); 926a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_Y, 927ffa458c1SDavid Brownell pdata->y_min ? : 0, 928ffa458c1SDavid Brownell pdata->y_max ? : MAX_12BIT, 929ffa458c1SDavid Brownell 0, 0); 930a90f7e98SDmitry Torokhov input_set_abs_params(input_dev, ABS_PRESSURE, 931ffa458c1SDavid Brownell pdata->pressure_min, pdata->pressure_max, 0, 0); 932ffa458c1SDavid Brownell 933de2defd9SImre Deak vref = pdata->keep_vref_on; 934de2defd9SImre Deak 935ffa458c1SDavid Brownell /* set up the transfers to read touchscreen state; this assumes we 936ffa458c1SDavid Brownell * use formula #2 for pressure, not #3. 937ffa458c1SDavid Brownell */ 9380b7018aaSImre Deak m = &ts->msg[0]; 939ffa458c1SDavid Brownell x = ts->xfer; 940ffa458c1SDavid Brownell 9410b7018aaSImre Deak spi_message_init(m); 9420b7018aaSImre Deak 943ffa458c1SDavid Brownell /* y- still on; turn on only y+ (and ADC) */ 944de2defd9SImre Deak ts->read_y = READ_Y(vref); 945d93f70b2SDavid Brownell x->tx_buf = &ts->read_y; 946ffa458c1SDavid Brownell x->len = 1; 9470b7018aaSImre Deak spi_message_add_tail(x, m); 948d93f70b2SDavid Brownell 949ffa458c1SDavid Brownell x++; 950ffa458c1SDavid Brownell x->rx_buf = &ts->tc.y; 951ffa458c1SDavid Brownell x->len = 2; 9520b7018aaSImre Deak spi_message_add_tail(x, m); 953ffa458c1SDavid Brownell 954e4f48861SSemih Hazar /* the first sample after switching drivers can be low quality; 955e4f48861SSemih Hazar * optionally discard it, using a second one after the signals 956e4f48861SSemih Hazar * have had enough time to stabilize. 957e4f48861SSemih Hazar */ 958e4f48861SSemih Hazar if (pdata->settle_delay_usecs) { 959e4f48861SSemih Hazar x->delay_usecs = pdata->settle_delay_usecs; 960e4f48861SSemih Hazar 961e4f48861SSemih Hazar x++; 962e4f48861SSemih Hazar x->tx_buf = &ts->read_y; 963e4f48861SSemih Hazar x->len = 1; 964e4f48861SSemih Hazar spi_message_add_tail(x, m); 965e4f48861SSemih Hazar 966e4f48861SSemih Hazar x++; 967e4f48861SSemih Hazar x->rx_buf = &ts->tc.y; 968e4f48861SSemih Hazar x->len = 2; 969e4f48861SSemih Hazar spi_message_add_tail(x, m); 970e4f48861SSemih Hazar } 971e4f48861SSemih Hazar 972da970e69SImre Deak m->complete = ads7846_rx_val; 9730b7018aaSImre Deak m->context = ts; 974d93f70b2SDavid Brownell 9750b7018aaSImre Deak m++; 9760b7018aaSImre Deak spi_message_init(m); 977ffa458c1SDavid Brownell 978ffa458c1SDavid Brownell /* turn y- off, x+ on, then leave in lowpower */ 979d93f70b2SDavid Brownell x++; 980de2defd9SImre Deak ts->read_x = READ_X(vref); 981d93f70b2SDavid Brownell x->tx_buf = &ts->read_x; 982ffa458c1SDavid Brownell x->len = 1; 9830b7018aaSImre Deak spi_message_add_tail(x, m); 984d93f70b2SDavid Brownell 985ffa458c1SDavid Brownell x++; 986ffa458c1SDavid Brownell x->rx_buf = &ts->tc.x; 987ffa458c1SDavid Brownell x->len = 2; 9880b7018aaSImre Deak spi_message_add_tail(x, m); 9890b7018aaSImre Deak 990e4f48861SSemih Hazar /* ... maybe discard first sample ... */ 991e4f48861SSemih Hazar if (pdata->settle_delay_usecs) { 992e4f48861SSemih Hazar x->delay_usecs = pdata->settle_delay_usecs; 993e4f48861SSemih Hazar 994e4f48861SSemih Hazar x++; 995e4f48861SSemih Hazar x->tx_buf = &ts->read_x; 996e4f48861SSemih Hazar x->len = 1; 997e4f48861SSemih Hazar spi_message_add_tail(x, m); 998e4f48861SSemih Hazar 999e4f48861SSemih Hazar x++; 1000e4f48861SSemih Hazar x->rx_buf = &ts->tc.x; 1001e4f48861SSemih Hazar x->len = 2; 1002e4f48861SSemih Hazar spi_message_add_tail(x, m); 1003e4f48861SSemih Hazar } 1004e4f48861SSemih Hazar 1005da970e69SImre Deak m->complete = ads7846_rx_val; 10060b7018aaSImre Deak m->context = ts; 10070b7018aaSImre Deak 10080b7018aaSImre Deak /* turn y+ off, x- on; we'll use formula #2 */ 10090b7018aaSImre Deak if (ts->model == 7846) { 10100b7018aaSImre Deak m++; 10110b7018aaSImre Deak spi_message_init(m); 10120b7018aaSImre Deak 10130b7018aaSImre Deak x++; 1014de2defd9SImre Deak ts->read_z1 = READ_Z1(vref); 10150b7018aaSImre Deak x->tx_buf = &ts->read_z1; 10160b7018aaSImre Deak x->len = 1; 10170b7018aaSImre Deak spi_message_add_tail(x, m); 10180b7018aaSImre Deak 10190b7018aaSImre Deak x++; 10200b7018aaSImre Deak x->rx_buf = &ts->tc.z1; 10210b7018aaSImre Deak x->len = 2; 10220b7018aaSImre Deak spi_message_add_tail(x, m); 10230b7018aaSImre Deak 1024e4f48861SSemih Hazar /* ... maybe discard first sample ... */ 1025e4f48861SSemih Hazar if (pdata->settle_delay_usecs) { 1026e4f48861SSemih Hazar x->delay_usecs = pdata->settle_delay_usecs; 1027e4f48861SSemih Hazar 1028e4f48861SSemih Hazar x++; 1029e4f48861SSemih Hazar x->tx_buf = &ts->read_z1; 1030e4f48861SSemih Hazar x->len = 1; 1031e4f48861SSemih Hazar spi_message_add_tail(x, m); 1032e4f48861SSemih Hazar 1033e4f48861SSemih Hazar x++; 1034e4f48861SSemih Hazar x->rx_buf = &ts->tc.z1; 1035e4f48861SSemih Hazar x->len = 2; 1036e4f48861SSemih Hazar spi_message_add_tail(x, m); 1037e4f48861SSemih Hazar } 1038e4f48861SSemih Hazar 1039da970e69SImre Deak m->complete = ads7846_rx_val; 10400b7018aaSImre Deak m->context = ts; 10410b7018aaSImre Deak 10420b7018aaSImre Deak m++; 10430b7018aaSImre Deak spi_message_init(m); 10440b7018aaSImre Deak 10450b7018aaSImre Deak x++; 1046de2defd9SImre Deak ts->read_z2 = READ_Z2(vref); 10470b7018aaSImre Deak x->tx_buf = &ts->read_z2; 10480b7018aaSImre Deak x->len = 1; 10490b7018aaSImre Deak spi_message_add_tail(x, m); 10500b7018aaSImre Deak 10510b7018aaSImre Deak x++; 10520b7018aaSImre Deak x->rx_buf = &ts->tc.z2; 10530b7018aaSImre Deak x->len = 2; 10540b7018aaSImre Deak spi_message_add_tail(x, m); 10550b7018aaSImre Deak 1056e4f48861SSemih Hazar /* ... maybe discard first sample ... */ 1057e4f48861SSemih Hazar if (pdata->settle_delay_usecs) { 1058e4f48861SSemih Hazar x->delay_usecs = pdata->settle_delay_usecs; 1059e4f48861SSemih Hazar 1060e4f48861SSemih Hazar x++; 1061e4f48861SSemih Hazar x->tx_buf = &ts->read_z2; 1062e4f48861SSemih Hazar x->len = 1; 1063e4f48861SSemih Hazar spi_message_add_tail(x, m); 1064e4f48861SSemih Hazar 1065e4f48861SSemih Hazar x++; 1066e4f48861SSemih Hazar x->rx_buf = &ts->tc.z2; 1067e4f48861SSemih Hazar x->len = 2; 1068e4f48861SSemih Hazar spi_message_add_tail(x, m); 1069e4f48861SSemih Hazar } 1070e4f48861SSemih Hazar 1071da970e69SImre Deak m->complete = ads7846_rx_val; 10720b7018aaSImre Deak m->context = ts; 10730b7018aaSImre Deak } 107453a0ef89SImre Deak 107553a0ef89SImre Deak /* power down */ 10760b7018aaSImre Deak m++; 10770b7018aaSImre Deak spi_message_init(m); 10780b7018aaSImre Deak 107953a0ef89SImre Deak x++; 108053a0ef89SImre Deak ts->pwrdown = PWRDOWN; 108153a0ef89SImre Deak x->tx_buf = &ts->pwrdown; 108253a0ef89SImre Deak x->len = 1; 10830b7018aaSImre Deak spi_message_add_tail(x, m); 108453a0ef89SImre Deak 108553a0ef89SImre Deak x++; 108653a0ef89SImre Deak x->rx_buf = &ts->dummy; 108753a0ef89SImre Deak x->len = 2; 1088d93f70b2SDavid Brownell CS_CHANGE(*x); 10890b7018aaSImre Deak spi_message_add_tail(x, m); 1090ffa458c1SDavid Brownell 10910b7018aaSImre Deak m->complete = ads7846_rx; 10920b7018aaSImre Deak m->context = ts; 1093ffa458c1SDavid Brownell 1094d5b415c9SImre Deak ts->last_msg = m; 1095d5b415c9SImre Deak 1096dace1453SThomas Gleixner if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, 10979084533eSDavid Brownell spi->dev.driver->name, ts)) { 10982e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); 1099a90f7e98SDmitry Torokhov err = -EBUSY; 1100da970e69SImre Deak goto err_cleanup_filter; 1101ffa458c1SDavid Brownell } 1102ffa458c1SDavid Brownell 11032c8dc071SDavid Brownell err = ads784x_hwmon_register(spi, ts); 11042c8dc071SDavid Brownell if (err) 11052c8dc071SDavid Brownell goto err_free_irq; 11062c8dc071SDavid Brownell 11072e5a7bd9SDavid Brownell dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); 1108ffa458c1SDavid Brownell 11092c8dc071SDavid Brownell /* take a first sample, leaving nPENIRQ active and vREF off; avoid 1110ffa458c1SDavid Brownell * the touchscreen, in case it's not connected. 1111ffa458c1SDavid Brownell */ 11122e5a7bd9SDavid Brownell (void) ads7846_read12_ser(&spi->dev, 1113ffa458c1SDavid Brownell READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); 1114ffa458c1SDavid Brownell 11152c8dc071SDavid Brownell err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group); 11168dd51650SDmitry Torokhov if (err) 11172c8dc071SDavid Brownell goto err_remove_hwmon; 11187de90a8cSImre Deak 1119a90f7e98SDmitry Torokhov err = input_register_device(input_dev); 1120a90f7e98SDmitry Torokhov if (err) 11218dd51650SDmitry Torokhov goto err_remove_attr_group; 1122a90f7e98SDmitry Torokhov 1123ffa458c1SDavid Brownell return 0; 1124a90f7e98SDmitry Torokhov 11258dd51650SDmitry Torokhov err_remove_attr_group: 11262c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); 11272c8dc071SDavid Brownell err_remove_hwmon: 11282c8dc071SDavid Brownell ads784x_hwmon_unregister(spi, ts); 11298dd51650SDmitry Torokhov err_free_irq: 1130a90f7e98SDmitry Torokhov free_irq(spi->irq, ts); 1131da970e69SImre Deak err_cleanup_filter: 1132da970e69SImre Deak if (ts->filter_cleanup) 1133da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 1134a90f7e98SDmitry Torokhov err_free_mem: 1135a90f7e98SDmitry Torokhov input_free_device(input_dev); 1136a90f7e98SDmitry Torokhov kfree(ts); 1137a90f7e98SDmitry Torokhov return err; 1138ffa458c1SDavid Brownell } 1139ffa458c1SDavid Brownell 11402e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi) 1141ffa458c1SDavid Brownell { 11422e5a7bd9SDavid Brownell struct ads7846 *ts = dev_get_drvdata(&spi->dev); 1143ffa458c1SDavid Brownell 11442c8dc071SDavid Brownell ads784x_hwmon_unregister(spi, ts); 11457de90a8cSImre Deak input_unregister_device(ts->input); 11467de90a8cSImre Deak 11472e5a7bd9SDavid Brownell ads7846_suspend(spi, PMSG_SUSPEND); 1148ffa458c1SDavid Brownell 11492c8dc071SDavid Brownell sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group); 1150ffa458c1SDavid Brownell 11517de90a8cSImre Deak free_irq(ts->spi->irq, ts); 1152c9e617a5SImre Deak /* suspend left the IRQ disabled */ 11537de90a8cSImre Deak enable_irq(ts->spi->irq); 11547de90a8cSImre Deak 1155da970e69SImre Deak if (ts->filter_cleanup) 1156da970e69SImre Deak ts->filter_cleanup(ts->filter_data); 1157da970e69SImre Deak 1158ffa458c1SDavid Brownell kfree(ts); 1159ffa458c1SDavid Brownell 11602e5a7bd9SDavid Brownell dev_dbg(&spi->dev, "unregistered touchscreen\n"); 1161ffa458c1SDavid Brownell return 0; 1162ffa458c1SDavid Brownell } 1163ffa458c1SDavid Brownell 11642e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = { 11652e5a7bd9SDavid Brownell .driver = { 1166ffa458c1SDavid Brownell .name = "ads7846", 1167ffa458c1SDavid Brownell .bus = &spi_bus_type, 11682e5a7bd9SDavid Brownell .owner = THIS_MODULE, 11692e5a7bd9SDavid Brownell }, 1170ffa458c1SDavid Brownell .probe = ads7846_probe, 11712e5a7bd9SDavid Brownell .remove = __devexit_p(ads7846_remove), 1172ffa458c1SDavid Brownell .suspend = ads7846_suspend, 1173ffa458c1SDavid Brownell .resume = ads7846_resume, 1174ffa458c1SDavid Brownell }; 1175ffa458c1SDavid Brownell 1176ffa458c1SDavid Brownell static int __init ads7846_init(void) 1177ffa458c1SDavid Brownell { 1178ffa458c1SDavid Brownell /* grr, board-specific init should stay out of drivers!! */ 1179ffa458c1SDavid Brownell 1180ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 1181ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 1182ffa458c1SDavid Brownell /* GPIO4 = PENIRQ; GPIO6 = BUSY */ 1183ffa458c1SDavid Brownell omap_request_gpio(4); 1184ffa458c1SDavid Brownell omap_set_gpio_direction(4, 1); 1185ffa458c1SDavid Brownell omap_request_gpio(6); 1186ffa458c1SDavid Brownell omap_set_gpio_direction(6, 1); 1187ffa458c1SDavid Brownell } 1188ffa458c1SDavid Brownell // also TI 1510 Innovator, bitbanging through FPGA 1189ffa458c1SDavid Brownell // also Nokia 770 1190ffa458c1SDavid Brownell // also Palm Tungsten T2 1191ffa458c1SDavid Brownell #endif 1192ffa458c1SDavid Brownell 1193ffa458c1SDavid Brownell // PXA: 1194ffa458c1SDavid Brownell // also Dell Axim X50 1195ffa458c1SDavid Brownell // also HP iPaq H191x/H192x/H415x/H435x 11962e5a7bd9SDavid Brownell // also Intel Lubbock (additional to UCB1400; as temperature sensor) 1197ffa458c1SDavid Brownell // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) 1198ffa458c1SDavid Brownell 11992e5a7bd9SDavid Brownell // Atmel at91sam9261-EK uses ads7843 12002e5a7bd9SDavid Brownell 1201ffa458c1SDavid Brownell // also various AMD Au1x00 devel boards 1202ffa458c1SDavid Brownell 12032e5a7bd9SDavid Brownell return spi_register_driver(&ads7846_driver); 1204ffa458c1SDavid Brownell } 1205ffa458c1SDavid Brownell module_init(ads7846_init); 1206ffa458c1SDavid Brownell 1207ffa458c1SDavid Brownell static void __exit ads7846_exit(void) 1208ffa458c1SDavid Brownell { 12092e5a7bd9SDavid Brownell spi_unregister_driver(&ads7846_driver); 1210ffa458c1SDavid Brownell 1211ffa458c1SDavid Brownell #ifdef CONFIG_ARCH_OMAP 1212ffa458c1SDavid Brownell if (machine_is_omap_osk()) { 1213ffa458c1SDavid Brownell omap_free_gpio(4); 1214ffa458c1SDavid Brownell omap_free_gpio(6); 1215ffa458c1SDavid Brownell } 1216ffa458c1SDavid Brownell #endif 1217ffa458c1SDavid Brownell 1218ffa458c1SDavid Brownell } 1219ffa458c1SDavid Brownell module_exit(ads7846_exit); 1220ffa458c1SDavid Brownell 1221ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); 1222ffa458c1SDavid Brownell MODULE_LICENSE("GPL"); 1223