xref: /linux/drivers/input/touchscreen/ads7846.c (revision 7d12e780e003f93433d49ce78cfedf4b4c52adc5)
1ffa458c1SDavid Brownell /*
2ffa458c1SDavid Brownell  * ADS7846 based touchscreen and sensor driver
3ffa458c1SDavid Brownell  *
4ffa458c1SDavid Brownell  * Copyright (c) 2005 David Brownell
57de90a8cSImre Deak  * Copyright (c) 2006 Nokia Corporation
67de90a8cSImre Deak  * Various changes: Imre Deak <imre.deak@nokia.com>
7ffa458c1SDavid Brownell  *
8ffa458c1SDavid Brownell  * Using code from:
9ffa458c1SDavid Brownell  *  - corgi_ts.c
10ffa458c1SDavid Brownell  *	Copyright (C) 2004-2005 Richard Purdie
11ffa458c1SDavid Brownell  *  - omap_ts.[hc], ads7846.h, ts_osk.c
12ffa458c1SDavid Brownell  *	Copyright (C) 2002 MontaVista Software
13ffa458c1SDavid Brownell  *	Copyright (C) 2004 Texas Instruments
14ffa458c1SDavid Brownell  *	Copyright (C) 2005 Dirk Behme
15ffa458c1SDavid Brownell  *
16ffa458c1SDavid Brownell  *  This program is free software; you can redistribute it and/or modify
17ffa458c1SDavid Brownell  *  it under the terms of the GNU General Public License version 2 as
18ffa458c1SDavid Brownell  *  published by the Free Software Foundation.
19ffa458c1SDavid Brownell  */
20ffa458c1SDavid Brownell #include <linux/device.h>
21ffa458c1SDavid Brownell #include <linux/init.h>
22ffa458c1SDavid Brownell #include <linux/delay.h>
23ffa458c1SDavid Brownell #include <linux/input.h>
24ffa458c1SDavid Brownell #include <linux/interrupt.h>
25ffa458c1SDavid Brownell #include <linux/slab.h>
26ffa458c1SDavid Brownell #include <linux/spi/spi.h>
27ffa458c1SDavid Brownell #include <linux/spi/ads7846.h>
283ac8bf07SAndrew Morton #include <asm/irq.h>
29ffa458c1SDavid Brownell 
30ffa458c1SDavid Brownell #ifdef	CONFIG_ARM
31ffa458c1SDavid Brownell #include <asm/mach-types.h>
32ffa458c1SDavid Brownell #ifdef	CONFIG_ARCH_OMAP
33ffa458c1SDavid Brownell #include <asm/arch/gpio.h>
34ffa458c1SDavid Brownell #endif
35ffa458c1SDavid Brownell #endif
36ffa458c1SDavid Brownell 
37ffa458c1SDavid Brownell 
38ffa458c1SDavid Brownell /*
399084533eSDavid Brownell  * This code has been heavily tested on a Nokia 770, and lightly
409084533eSDavid Brownell  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
41ffa458c1SDavid Brownell  * Support for ads7843 and ads7845 has only been stubbed in.
42ffa458c1SDavid Brownell  *
437de90a8cSImre Deak  * IRQ handling needs a workaround because of a shortcoming in handling
447de90a8cSImre Deak  * edge triggered IRQs on some platforms like the OMAP1/2. These
457de90a8cSImre Deak  * platforms don't handle the ARM lazy IRQ disabling properly, thus we
467de90a8cSImre Deak  * have to maintain our own SW IRQ disabled status. This should be
477de90a8cSImre Deak  * removed as soon as the affected platform's IRQ handling is fixed.
487de90a8cSImre Deak  *
49ffa458c1SDavid Brownell  * app note sbaa036 talks in more detail about accurate sampling...
50ffa458c1SDavid Brownell  * that ought to help in situations like LCDs inducing noise (which
51ffa458c1SDavid Brownell  * can also be helped by using synch signals) and more generally.
527de90a8cSImre Deak  * This driver tries to utilize the measures described in the app
537de90a8cSImre Deak  * note. The strength of filtering can be set in the board-* specific
547de90a8cSImre Deak  * files.
55ffa458c1SDavid Brownell  */
56ffa458c1SDavid Brownell 
57ffa458c1SDavid Brownell #define	TS_POLL_PERIOD	msecs_to_jiffies(10)
58ffa458c1SDavid Brownell 
59d93f70b2SDavid Brownell /* this driver doesn't aim at the peak continuous sample rate */
60d93f70b2SDavid Brownell #define	SAMPLE_BITS	(8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
61d93f70b2SDavid Brownell 
62ffa458c1SDavid Brownell struct ts_event {
63ffa458c1SDavid Brownell 	/* For portability, we can't read 12 bit values using SPI (which
64ffa458c1SDavid Brownell 	 * would make the controller deliver them as native byteorder u16
65d93f70b2SDavid Brownell 	 * with msbs zeroed).  Instead, we read them as two 8-bit values,
66ffa458c1SDavid Brownell 	 * which need byteswapping then range adjustment.
67ffa458c1SDavid Brownell 	 */
68ffa458c1SDavid Brownell 	__be16 x;
69ffa458c1SDavid Brownell 	__be16 y;
70ffa458c1SDavid Brownell 	__be16 z1, z2;
71d5b415c9SImre Deak 	int    ignore;
72ffa458c1SDavid Brownell };
73ffa458c1SDavid Brownell 
74ffa458c1SDavid Brownell struct ads7846 {
75a90f7e98SDmitry Torokhov 	struct input_dev	*input;
76ffa458c1SDavid Brownell 	char			phys[32];
77ffa458c1SDavid Brownell 
78ffa458c1SDavid Brownell 	struct spi_device	*spi;
79ffa458c1SDavid Brownell 	u16			model;
80ffa458c1SDavid Brownell 	u16			vref_delay_usecs;
81ffa458c1SDavid Brownell 	u16			x_plate_ohms;
82d5b415c9SImre Deak 	u16			pressure_max;
83ffa458c1SDavid Brownell 
8453a0ef89SImre Deak 	u8			read_x, read_y, read_z1, read_z2, pwrdown;
8553a0ef89SImre Deak 	u16			dummy;		/* for the pwrdown read */
86ffa458c1SDavid Brownell 	struct ts_event		tc;
87ffa458c1SDavid Brownell 
8853a0ef89SImre Deak 	struct spi_transfer	xfer[10];
890b7018aaSImre Deak 	struct spi_message	msg[5];
90d5b415c9SImre Deak 	struct spi_message	*last_msg;
910b7018aaSImre Deak 	int			msg_idx;
920b7018aaSImre Deak 	int			read_cnt;
93d5b415c9SImre Deak 	int			read_rep;
940b7018aaSImre Deak 	int			last_read;
950b7018aaSImre Deak 
960b7018aaSImre Deak 	u16			debounce_max;
970b7018aaSImre Deak 	u16			debounce_tol;
98d5b415c9SImre Deak 	u16			debounce_rep;
99ffa458c1SDavid Brownell 
100ffa458c1SDavid Brownell 	spinlock_t		lock;
101ffa458c1SDavid Brownell 	struct timer_list	timer;		/* P: lock */
102ffa458c1SDavid Brownell 	unsigned		pendown:1;	/* P: lock */
103ffa458c1SDavid Brownell 	unsigned		pending:1;	/* P: lock */
104ffa458c1SDavid Brownell // FIXME remove "irq_disabled"
105ffa458c1SDavid Brownell 	unsigned		irq_disabled:1;	/* P: lock */
1067de90a8cSImre Deak 	unsigned		disabled:1;
107c9e617a5SImre Deak 
108c9e617a5SImre Deak 	int			(*get_pendown_state)(void);
109ffa458c1SDavid Brownell };
110ffa458c1SDavid Brownell 
111ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */
112ffa458c1SDavid Brownell #if	0
113ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 1)
114ffa458c1SDavid Brownell #else
115ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 0)
116ffa458c1SDavid Brownell #endif
117ffa458c1SDavid Brownell 
118ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
119ffa458c1SDavid Brownell 
120ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors.
121ffa458c1SDavid Brownell  * Earlier ads784x chips are somewhat compatible.
122ffa458c1SDavid Brownell  */
123ffa458c1SDavid Brownell #define	ADS_START		(1 << 7)
124ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_y		(1 << 4)	/* differential */
125ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z1		(3 << 4)	/* differential */
126ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z2		(4 << 4)	/* differential */
127ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_x		(5 << 4)	/* differential */
128ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp0	(0 << 4)	/* non-differential */
129ffa458c1SDavid Brownell #define	ADS_A2A1A0_vbatt	(2 << 4)	/* non-differential */
130ffa458c1SDavid Brownell #define	ADS_A2A1A0_vaux		(6 << 4)	/* non-differential */
131ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp1	(7 << 4)	/* non-differential */
132ffa458c1SDavid Brownell #define	ADS_8_BIT		(1 << 3)
133ffa458c1SDavid Brownell #define	ADS_12_BIT		(0 << 3)
134ffa458c1SDavid Brownell #define	ADS_SER			(1 << 2)	/* non-differential */
135ffa458c1SDavid Brownell #define	ADS_DFR			(0 << 2)	/* differential */
136ffa458c1SDavid Brownell #define	ADS_PD10_PDOWN		(0 << 0)	/* lowpower mode + penirq */
137ffa458c1SDavid Brownell #define	ADS_PD10_ADC_ON		(1 << 0)	/* ADC on */
138ffa458c1SDavid Brownell #define	ADS_PD10_REF_ON		(2 << 0)	/* vREF on + penirq */
139ffa458c1SDavid Brownell #define	ADS_PD10_ALL_ON		(3 << 0)	/* ADC + vREF on */
140ffa458c1SDavid Brownell 
141ffa458c1SDavid Brownell #define	MAX_12BIT	((1<<12)-1)
142ffa458c1SDavid Brownell 
143ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */
144ffa458c1SDavid Brownell #define	READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \
145ffa458c1SDavid Brownell 	| ADS_12_BIT | ADS_DFR)
146ffa458c1SDavid Brownell 
147d93f70b2SDavid Brownell #define	READ_Y	(READ_12BIT_DFR(y)  | ADS_PD10_ADC_ON)
148d93f70b2SDavid Brownell #define	READ_Z1	(READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON)
149d93f70b2SDavid Brownell #define	READ_Z2	(READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON)
15053a0ef89SImre Deak 
15153a0ef89SImre Deak #define	READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_ADC_ON)
15253a0ef89SImre Deak #define	PWRDOWN	(READ_12BIT_DFR(y)  | ADS_PD10_PDOWN)	/* LAST */
153ffa458c1SDavid Brownell 
154ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage;
155ffa458c1SDavid Brownell  * we leave both ADC and VREF powered
156ffa458c1SDavid Brownell  */
157ffa458c1SDavid Brownell #define	READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
158ffa458c1SDavid Brownell 	| ADS_12_BIT | ADS_SER)
159ffa458c1SDavid Brownell 
160d93f70b2SDavid Brownell #define	REF_ON	(READ_12BIT_DFR(x) | ADS_PD10_ALL_ON)
161d93f70b2SDavid Brownell #define	REF_OFF	(READ_12BIT_DFR(y) | ADS_PD10_PDOWN)
162ffa458c1SDavid Brownell 
163ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
164ffa458c1SDavid Brownell 
165ffa458c1SDavid Brownell /*
166ffa458c1SDavid Brownell  * Non-touchscreen sensors only use single-ended conversions.
167ffa458c1SDavid Brownell  */
168ffa458c1SDavid Brownell 
169ffa458c1SDavid Brownell struct ser_req {
170d93f70b2SDavid Brownell 	u8			ref_on;
171ffa458c1SDavid Brownell 	u8			command;
172d93f70b2SDavid Brownell 	u8			ref_off;
173ffa458c1SDavid Brownell 	u16			scratch;
174ffa458c1SDavid Brownell 	__be16			sample;
175ffa458c1SDavid Brownell 	struct spi_message	msg;
176ffa458c1SDavid Brownell 	struct spi_transfer	xfer[6];
177ffa458c1SDavid Brownell };
178ffa458c1SDavid Brownell 
1797de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts);
1807de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts);
1817de90a8cSImre Deak 
182c9e617a5SImre Deak static int device_suspended(struct device *dev)
183c9e617a5SImre Deak {
184c9e617a5SImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
185c9e617a5SImre Deak 	return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
186c9e617a5SImre Deak }
187c9e617a5SImre Deak 
188ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command)
189ffa458c1SDavid Brownell {
190ffa458c1SDavid Brownell 	struct spi_device	*spi = to_spi_device(dev);
191ffa458c1SDavid Brownell 	struct ads7846		*ts = dev_get_drvdata(dev);
192ffa458c1SDavid Brownell 	struct ser_req		*req = kzalloc(sizeof *req, SLAB_KERNEL);
193ffa458c1SDavid Brownell 	int			status;
194ffa458c1SDavid Brownell 	int			sample;
1958275c642SVitaly Wool 	int			i;
196ffa458c1SDavid Brownell 
197ffa458c1SDavid Brownell 	if (!req)
198ffa458c1SDavid Brownell 		return -ENOMEM;
199ffa458c1SDavid Brownell 
2000b7018aaSImre Deak 	spi_message_init(&req->msg);
2018275c642SVitaly Wool 
202ffa458c1SDavid Brownell 	/* activate reference, so it has time to settle; */
203d93f70b2SDavid Brownell 	req->ref_on = REF_ON;
204d93f70b2SDavid Brownell 	req->xfer[0].tx_buf = &req->ref_on;
205ffa458c1SDavid Brownell 	req->xfer[0].len = 1;
206ffa458c1SDavid Brownell 	req->xfer[1].rx_buf = &req->scratch;
207ffa458c1SDavid Brownell 	req->xfer[1].len = 2;
208ffa458c1SDavid Brownell 
209ffa458c1SDavid Brownell 	/*
210ffa458c1SDavid Brownell 	 * for external VREF, 0 usec (and assume it's always on);
211ffa458c1SDavid Brownell 	 * for 1uF, use 800 usec;
212ffa458c1SDavid Brownell 	 * no cap, 100 usec.
213ffa458c1SDavid Brownell 	 */
214ffa458c1SDavid Brownell 	req->xfer[1].delay_usecs = ts->vref_delay_usecs;
215ffa458c1SDavid Brownell 
216ffa458c1SDavid Brownell 	/* take sample */
217ffa458c1SDavid Brownell 	req->command = (u8) command;
218ffa458c1SDavid Brownell 	req->xfer[2].tx_buf = &req->command;
219ffa458c1SDavid Brownell 	req->xfer[2].len = 1;
220ffa458c1SDavid Brownell 	req->xfer[3].rx_buf = &req->sample;
221ffa458c1SDavid Brownell 	req->xfer[3].len = 2;
222ffa458c1SDavid Brownell 
223ffa458c1SDavid Brownell 	/* REVISIT:  take a few more samples, and compare ... */
224ffa458c1SDavid Brownell 
225ffa458c1SDavid Brownell 	/* turn off reference */
226d93f70b2SDavid Brownell 	req->ref_off = REF_OFF;
227d93f70b2SDavid Brownell 	req->xfer[4].tx_buf = &req->ref_off;
228ffa458c1SDavid Brownell 	req->xfer[4].len = 1;
229ffa458c1SDavid Brownell 	req->xfer[5].rx_buf = &req->scratch;
230ffa458c1SDavid Brownell 	req->xfer[5].len = 2;
231ffa458c1SDavid Brownell 
232ffa458c1SDavid Brownell 	CS_CHANGE(req->xfer[5]);
233ffa458c1SDavid Brownell 
234ffa458c1SDavid Brownell 	/* group all the transfers together, so we can't interfere with
235ffa458c1SDavid Brownell 	 * reading touchscreen state; disable penirq while sampling
236ffa458c1SDavid Brownell 	 */
2378275c642SVitaly Wool 	for (i = 0; i < 6; i++)
2388275c642SVitaly Wool 		spi_message_add_tail(&req->xfer[i], &req->msg);
239ffa458c1SDavid Brownell 
240c9e617a5SImre Deak 	ts->irq_disabled = 1;
241ffa458c1SDavid Brownell 	disable_irq(spi->irq);
242ffa458c1SDavid Brownell 	status = spi_sync(spi, &req->msg);
243c9e617a5SImre Deak 	ts->irq_disabled = 0;
244ffa458c1SDavid Brownell 	enable_irq(spi->irq);
245ffa458c1SDavid Brownell 
246ffa458c1SDavid Brownell 	if (req->msg.status)
247ffa458c1SDavid Brownell 		status = req->msg.status;
248ffa458c1SDavid Brownell 
2499084533eSDavid Brownell 	/* on-wire is a must-ignore bit, a BE12 value, then padding */
2509084533eSDavid Brownell 	sample = be16_to_cpu(req->sample);
2519084533eSDavid Brownell 	sample = sample >> 3;
2529084533eSDavid Brownell 	sample &= 0x0fff;
2539084533eSDavid Brownell 
2549084533eSDavid Brownell 	kfree(req);
255ffa458c1SDavid Brownell 	return status ? status : sample;
256ffa458c1SDavid Brownell }
257ffa458c1SDavid Brownell 
258ffa458c1SDavid Brownell #define SHOW(name) static ssize_t \
259ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
260ffa458c1SDavid Brownell { \
261ffa458c1SDavid Brownell 	ssize_t v = ads7846_read12_ser(dev, \
262ffa458c1SDavid Brownell 			READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
263ffa458c1SDavid Brownell 	if (v < 0) \
264ffa458c1SDavid Brownell 		return v; \
265ffa458c1SDavid Brownell 	return sprintf(buf, "%u\n", (unsigned) v); \
266ffa458c1SDavid Brownell } \
267ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
268ffa458c1SDavid Brownell 
269ffa458c1SDavid Brownell SHOW(temp0)
270ffa458c1SDavid Brownell SHOW(temp1)
271ffa458c1SDavid Brownell SHOW(vaux)
272ffa458c1SDavid Brownell SHOW(vbatt)
273ffa458c1SDavid Brownell 
274438f2a74SImre Deak static int is_pen_down(struct device *dev)
275438f2a74SImre Deak {
276438f2a74SImre Deak 	struct ads7846		*ts = dev_get_drvdata(dev);
277438f2a74SImre Deak 
278438f2a74SImre Deak 	return ts->pendown;
279438f2a74SImre Deak }
280438f2a74SImre Deak 
281438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev,
282438f2a74SImre Deak 				     struct device_attribute *attr, char *buf)
283438f2a74SImre Deak {
284438f2a74SImre Deak 	return sprintf(buf, "%u\n", is_pen_down(dev));
285438f2a74SImre Deak }
286438f2a74SImre Deak 
287438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
288438f2a74SImre Deak 
2897de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev,
2907de90a8cSImre Deak 				     struct device_attribute *attr, char *buf)
2917de90a8cSImre Deak {
2927de90a8cSImre Deak 	struct ads7846	*ts = dev_get_drvdata(dev);
2937de90a8cSImre Deak 
2947de90a8cSImre Deak 	return sprintf(buf, "%u\n", ts->disabled);
2957de90a8cSImre Deak }
2967de90a8cSImre Deak 
2977de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev,
2987de90a8cSImre Deak 				     struct device_attribute *attr,
2997de90a8cSImre Deak 				     const char *buf, size_t count)
3007de90a8cSImre Deak {
3017de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
3027de90a8cSImre Deak 	char *endp;
3037de90a8cSImre Deak 	int i;
3047de90a8cSImre Deak 
3057de90a8cSImre Deak 	i = simple_strtoul(buf, &endp, 10);
3067de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
3077de90a8cSImre Deak 
3087de90a8cSImre Deak 	if (i)
3097de90a8cSImre Deak 		ads7846_disable(ts);
3107de90a8cSImre Deak 	else
3117de90a8cSImre Deak 		ads7846_enable(ts);
3127de90a8cSImre Deak 
3137de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
3147de90a8cSImre Deak 
3157de90a8cSImre Deak 	return count;
3167de90a8cSImre Deak }
3177de90a8cSImre Deak 
3187de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
3197de90a8cSImre Deak 
320ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
321ffa458c1SDavid Brownell 
322ffa458c1SDavid Brownell /*
323ffa458c1SDavid Brownell  * PENIRQ only kicks the timer.  The timer only reissues the SPI transfer,
324ffa458c1SDavid Brownell  * to retrieve touchscreen status.
325ffa458c1SDavid Brownell  *
326ffa458c1SDavid Brownell  * The SPI transfer completion callback does the real work.  It reports
327ffa458c1SDavid Brownell  * touchscreen events and reactivates the timer (or IRQ) as appropriate.
328ffa458c1SDavid Brownell  */
329ffa458c1SDavid Brownell 
330ffa458c1SDavid Brownell static void ads7846_rx(void *ads)
331ffa458c1SDavid Brownell {
332ffa458c1SDavid Brownell 	struct ads7846		*ts = ads;
333a90f7e98SDmitry Torokhov 	struct input_dev	*input_dev = ts->input;
334ffa458c1SDavid Brownell 	unsigned		Rt;
335ffa458c1SDavid Brownell 	unsigned		sync = 0;
336ffa458c1SDavid Brownell 	u16			x, y, z1, z2;
337ffa458c1SDavid Brownell 	unsigned long		flags;
338ffa458c1SDavid Brownell 
3399084533eSDavid Brownell 	/* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
3409084533eSDavid Brownell 	 * built from two 8 bit values written msb-first.
341ffa458c1SDavid Brownell 	 */
3429084533eSDavid Brownell 	x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
3439084533eSDavid Brownell 	y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
3449084533eSDavid Brownell 	z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff;
3459084533eSDavid Brownell 	z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff;
346ffa458c1SDavid Brownell 
347ffa458c1SDavid Brownell 	/* range filtering */
348ffa458c1SDavid Brownell 	if (x == MAX_12BIT)
349ffa458c1SDavid Brownell 		x = 0;
350ffa458c1SDavid Brownell 
351c9e617a5SImre Deak 	if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
352ffa458c1SDavid Brownell 		/* compute touch pressure resistance using equation #2 */
353ffa458c1SDavid Brownell 		Rt = z2;
354ffa458c1SDavid Brownell 		Rt -= z1;
355ffa458c1SDavid Brownell 		Rt *= x;
356ffa458c1SDavid Brownell 		Rt *= ts->x_plate_ohms;
357ffa458c1SDavid Brownell 		Rt /= z1;
358ffa458c1SDavid Brownell 		Rt = (Rt + 2047) >> 12;
359ffa458c1SDavid Brownell 	} else
360ffa458c1SDavid Brownell 		Rt = 0;
361ffa458c1SDavid Brownell 
362d5b415c9SImre Deak 	/* Sample found inconsistent by debouncing or pressure is beyond
363d5b415c9SImre Deak 	* the maximum. Don't report it to user space, repeat at least
364d5b415c9SImre Deak 	* once more the measurement */
365d5b415c9SImre Deak 	if (ts->tc.ignore || Rt > ts->pressure_max) {
366d5b415c9SImre Deak 		mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
367d5b415c9SImre Deak 		return;
368d5b415c9SImre Deak 	}
369d5b415c9SImre Deak 
370ffa458c1SDavid Brownell 	/* NOTE:  "pendown" is inferred from pressure; we don't rely on
371ffa458c1SDavid Brownell 	 * being able to check nPENIRQ status, or "friendly" trigger modes
372ffa458c1SDavid Brownell 	 * (both-edges is much better than just-falling or low-level).
373ffa458c1SDavid Brownell 	 *
374ffa458c1SDavid Brownell 	 * REVISIT:  some boards may require reading nPENIRQ; it's
375ffa458c1SDavid Brownell 	 * needed on 7843.  and 7845 reads pressure differently...
376ffa458c1SDavid Brownell 	 *
377ffa458c1SDavid Brownell 	 * REVISIT:  the touchscreen might not be connected; this code
378ffa458c1SDavid Brownell 	 * won't notice that, even if nPENIRQ never fires ...
379ffa458c1SDavid Brownell 	 */
380ffa458c1SDavid Brownell 	if (!ts->pendown && Rt != 0) {
381a90f7e98SDmitry Torokhov 		input_report_key(input_dev, BTN_TOUCH, 1);
382ffa458c1SDavid Brownell 		sync = 1;
383ffa458c1SDavid Brownell 	} else if (ts->pendown && Rt == 0) {
384a90f7e98SDmitry Torokhov 		input_report_key(input_dev, BTN_TOUCH, 0);
385ffa458c1SDavid Brownell 		sync = 1;
386ffa458c1SDavid Brownell 	}
387ffa458c1SDavid Brownell 
388ffa458c1SDavid Brownell 	if (Rt) {
389a90f7e98SDmitry Torokhov 		input_report_abs(input_dev, ABS_X, x);
390a90f7e98SDmitry Torokhov 		input_report_abs(input_dev, ABS_Y, y);
391ffa458c1SDavid Brownell 		sync = 1;
392ffa458c1SDavid Brownell 	}
393ae82d5abSImre Deak 
394ae82d5abSImre Deak 	if (sync) {
395ae82d5abSImre Deak 		input_report_abs(input_dev, ABS_PRESSURE, Rt);
396a90f7e98SDmitry Torokhov 		input_sync(input_dev);
397ae82d5abSImre Deak 	}
398ffa458c1SDavid Brownell 
399ffa458c1SDavid Brownell #ifdef	VERBOSE
400ffa458c1SDavid Brownell 	if (Rt || ts->pendown)
401ffa458c1SDavid Brownell 		pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
402ffa458c1SDavid Brownell 			x, y, Rt, Rt ? "" : " UP");
403ffa458c1SDavid Brownell #endif
404ffa458c1SDavid Brownell 
405ffa458c1SDavid Brownell 	spin_lock_irqsave(&ts->lock, flags);
406ffa458c1SDavid Brownell 
407ffa458c1SDavid Brownell 	ts->pendown = (Rt != 0);
408ffa458c1SDavid Brownell 	mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
409ffa458c1SDavid Brownell 
410ffa458c1SDavid Brownell 	spin_unlock_irqrestore(&ts->lock, flags);
411ffa458c1SDavid Brownell }
412ffa458c1SDavid Brownell 
4130b7018aaSImre Deak static void ads7846_debounce(void *ads)
414ffa458c1SDavid Brownell {
4150b7018aaSImre Deak 	struct ads7846		*ts = ads;
4160b7018aaSImre Deak 	struct spi_message	*m;
4170b7018aaSImre Deak 	struct spi_transfer	*t;
418d5b415c9SImre Deak 	int			val;
4190b7018aaSImre Deak 	int			status;
420ffa458c1SDavid Brownell 
4210b7018aaSImre Deak 	m = &ts->msg[ts->msg_idx];
4220b7018aaSImre Deak 	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
4239084533eSDavid Brownell 	val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff;
424d5b415c9SImre Deak 	if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) {
425d5b415c9SImre Deak 		/* Repeat it, if this was the first read or the read
426d5b415c9SImre Deak 		 * wasn't consistent enough. */
427d5b415c9SImre Deak 		if (ts->read_cnt < ts->debounce_max) {
4280b7018aaSImre Deak 			ts->last_read = val;
429d5b415c9SImre Deak 			ts->read_cnt++;
4300b7018aaSImre Deak 		} else {
431d5b415c9SImre Deak 			/* Maximum number of debouncing reached and still
432d5b415c9SImre Deak 			 * not enough number of consistent readings. Abort
433d5b415c9SImre Deak 			 * the whole sample, repeat it in the next sampling
434d5b415c9SImre Deak 			 * period.
435d5b415c9SImre Deak 			 */
436d5b415c9SImre Deak 			ts->tc.ignore = 1;
437d5b415c9SImre Deak 			ts->read_cnt = 0;
438d5b415c9SImre Deak 			/* Last message will contain ads7846_rx() as the
439d5b415c9SImre Deak 			 * completion function.
440d5b415c9SImre Deak 			 */
441d5b415c9SImre Deak 			m = ts->last_msg;
442d5b415c9SImre Deak 		}
443d5b415c9SImre Deak 		/* Start over collecting consistent readings. */
444d5b415c9SImre Deak 		ts->read_rep = 0;
445d5b415c9SImre Deak 	} else {
446d5b415c9SImre Deak 		if (++ts->read_rep > ts->debounce_rep) {
447d5b415c9SImre Deak 			/* Got a good reading for this coordinate,
448d5b415c9SImre Deak 			 * go for the next one. */
449d5b415c9SImre Deak 			ts->tc.ignore = 0;
4500b7018aaSImre Deak 			ts->msg_idx++;
4510b7018aaSImre Deak 			ts->read_cnt = 0;
452d5b415c9SImre Deak 			ts->read_rep = 0;
4530b7018aaSImre Deak 			m++;
454d5b415c9SImre Deak 		} else
455d5b415c9SImre Deak 			/* Read more values that are consistent. */
456d5b415c9SImre Deak 			ts->read_cnt++;
457ffa458c1SDavid Brownell 	}
4580b7018aaSImre Deak 	status = spi_async(ts->spi, m);
459ffa458c1SDavid Brownell 	if (status)
460ffa458c1SDavid Brownell 		dev_err(&ts->spi->dev, "spi_async --> %d\n",
461ffa458c1SDavid Brownell 				status);
462ffa458c1SDavid Brownell }
4630b7018aaSImre Deak 
4640b7018aaSImre Deak static void ads7846_timer(unsigned long handle)
4650b7018aaSImre Deak {
4660b7018aaSImre Deak 	struct ads7846	*ts = (void *)handle;
4670b7018aaSImre Deak 	int		status = 0;
4680b7018aaSImre Deak 
469c9e617a5SImre Deak 	spin_lock_irq(&ts->lock);
470c9e617a5SImre Deak 
471c9e617a5SImre Deak 	if (unlikely(ts->msg_idx && !ts->pendown)) {
4729084533eSDavid Brownell 		/* measurement cycle ended */
473c9e617a5SImre Deak 		if (!device_suspended(&ts->spi->dev)) {
474c9e617a5SImre Deak 			ts->irq_disabled = 0;
475c9e617a5SImre Deak 			enable_irq(ts->spi->irq);
476c9e617a5SImre Deak 		}
477c9e617a5SImre Deak 		ts->pending = 0;
478c9e617a5SImre Deak 		ts->msg_idx = 0;
479c9e617a5SImre Deak 	} else {
480c9e617a5SImre Deak 		/* pen is still down, continue with the measurement */
4810b7018aaSImre Deak 		ts->msg_idx = 0;
4820b7018aaSImre Deak 		status = spi_async(ts->spi, &ts->msg[0]);
4830b7018aaSImre Deak 		if (status)
4840b7018aaSImre Deak 			dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
485ffa458c1SDavid Brownell 	}
486ffa458c1SDavid Brownell 
487c9e617a5SImre Deak 	spin_unlock_irq(&ts->lock);
488c9e617a5SImre Deak }
489c9e617a5SImre Deak 
490*7d12e780SDavid Howells static irqreturn_t ads7846_irq(int irq, void *handle)
491ffa458c1SDavid Brownell {
4920b7018aaSImre Deak 	struct ads7846 *ts = handle;
4930b7018aaSImre Deak 	unsigned long flags;
4940b7018aaSImre Deak 
4950b7018aaSImre Deak 	spin_lock_irqsave(&ts->lock, flags);
496c9e617a5SImre Deak 	if (likely(ts->get_pendown_state())) {
4970b7018aaSImre Deak 		if (!ts->irq_disabled) {
4989084533eSDavid Brownell 			/* The ARM do_simple_IRQ() dispatcher doesn't act
4999084533eSDavid Brownell 			 * like the other dispatchers:  it will report IRQs
5009084533eSDavid Brownell 			 * even after they've been disabled.  We work around
5019084533eSDavid Brownell 			 * that here.  (The "generic irq" framework may help...)
5020b7018aaSImre Deak 			 */
5030b7018aaSImre Deak 			ts->irq_disabled = 1;
5040b7018aaSImre Deak 			disable_irq(ts->spi->irq);
5050b7018aaSImre Deak 			ts->pending = 1;
5060b7018aaSImre Deak 			mod_timer(&ts->timer, jiffies);
5070b7018aaSImre Deak 		}
5080b7018aaSImre Deak 	}
5090b7018aaSImre Deak 	spin_unlock_irqrestore(&ts->lock, flags);
5107de90a8cSImre Deak 
5117de90a8cSImre Deak 	return IRQ_HANDLED;
512ffa458c1SDavid Brownell }
513ffa458c1SDavid Brownell 
514ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
515ffa458c1SDavid Brownell 
5167de90a8cSImre Deak /* Must be called with ts->lock held */
5177de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts)
518ffa458c1SDavid Brownell {
5197de90a8cSImre Deak 	if (ts->disabled)
5207de90a8cSImre Deak 		return;
521ffa458c1SDavid Brownell 
522c9e617a5SImre Deak 	ts->disabled = 1;
523c9e617a5SImre Deak 
524ffa458c1SDavid Brownell 	/* are we waiting for IRQ, or polling? */
525c9e617a5SImre Deak 	if (!ts->pending) {
526ffa458c1SDavid Brownell 		ts->irq_disabled = 1;
527ffa458c1SDavid Brownell 		disable_irq(ts->spi->irq);
528ffa458c1SDavid Brownell 	} else {
529c9e617a5SImre Deak 		/* the timer will run at least once more, and
530c9e617a5SImre Deak 		 * leave everything in a clean state, IRQ disabled
531ffa458c1SDavid Brownell 		 */
532c9e617a5SImre Deak 		while (ts->pending) {
5337de90a8cSImre Deak 			spin_unlock_irq(&ts->lock);
534c4febb94SJuha Yrjola 			msleep(1);
5357de90a8cSImre Deak 			spin_lock_irq(&ts->lock);
536ffa458c1SDavid Brownell 		}
537ffa458c1SDavid Brownell 	}
538ffa458c1SDavid Brownell 
539ffa458c1SDavid Brownell 	/* we know the chip's in lowpower mode since we always
540ffa458c1SDavid Brownell 	 * leave it that way after every request
541ffa458c1SDavid Brownell 	 */
542ffa458c1SDavid Brownell 
5437de90a8cSImre Deak }
5447de90a8cSImre Deak 
5457de90a8cSImre Deak /* Must be called with ts->lock held */
5467de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts)
5477de90a8cSImre Deak {
5487de90a8cSImre Deak 	if (!ts->disabled)
5497de90a8cSImre Deak 		return;
5507de90a8cSImre Deak 
5517de90a8cSImre Deak 	ts->disabled = 0;
5527de90a8cSImre Deak 	ts->irq_disabled = 0;
5537de90a8cSImre Deak 	enable_irq(ts->spi->irq);
5547de90a8cSImre Deak }
5557de90a8cSImre Deak 
5567de90a8cSImre Deak static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
5577de90a8cSImre Deak {
5587de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
5597de90a8cSImre Deak 
5607de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
5617de90a8cSImre Deak 
5627de90a8cSImre Deak 	spi->dev.power.power_state = message;
5637de90a8cSImre Deak 	ads7846_disable(ts);
5647de90a8cSImre Deak 
5657de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
5667de90a8cSImre Deak 
567ffa458c1SDavid Brownell 	return 0;
5687de90a8cSImre Deak 
569ffa458c1SDavid Brownell }
570ffa458c1SDavid Brownell 
5712e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi)
572ffa458c1SDavid Brownell {
5732e5a7bd9SDavid Brownell 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
574ffa458c1SDavid Brownell 
5757de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
5767de90a8cSImre Deak 
5772e5a7bd9SDavid Brownell 	spi->dev.power.power_state = PMSG_ON;
5787de90a8cSImre Deak 	ads7846_enable(ts);
5797de90a8cSImre Deak 
5807de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
5817de90a8cSImre Deak 
582ffa458c1SDavid Brownell 	return 0;
583ffa458c1SDavid Brownell }
584ffa458c1SDavid Brownell 
5852e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi)
586ffa458c1SDavid Brownell {
587ffa458c1SDavid Brownell 	struct ads7846			*ts;
588a90f7e98SDmitry Torokhov 	struct input_dev		*input_dev;
5892e5a7bd9SDavid Brownell 	struct ads7846_platform_data	*pdata = spi->dev.platform_data;
5900b7018aaSImre Deak 	struct spi_message		*m;
591ffa458c1SDavid Brownell 	struct spi_transfer		*x;
592a90f7e98SDmitry Torokhov 	int				err;
593ffa458c1SDavid Brownell 
594ffa458c1SDavid Brownell 	if (!spi->irq) {
5952e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "no IRQ?\n");
596ffa458c1SDavid Brownell 		return -ENODEV;
597ffa458c1SDavid Brownell 	}
598ffa458c1SDavid Brownell 
599ffa458c1SDavid Brownell 	if (!pdata) {
6002e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "no platform data?\n");
601ffa458c1SDavid Brownell 		return -ENODEV;
602ffa458c1SDavid Brownell 	}
603ffa458c1SDavid Brownell 
604ffa458c1SDavid Brownell 	/* don't exceed max specified sample rate */
605d93f70b2SDavid Brownell 	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
6062e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
607d93f70b2SDavid Brownell 				(spi->max_speed_hz/SAMPLE_BITS)/1000);
608ffa458c1SDavid Brownell 		return -EINVAL;
609ffa458c1SDavid Brownell 	}
610ffa458c1SDavid Brownell 
6119084533eSDavid Brownell 	/* REVISIT when the irq can be triggered active-low, or if for some
6129084533eSDavid Brownell 	 * reason the touchscreen isn't hooked up, we don't need to access
6139084533eSDavid Brownell 	 * the pendown state.
6149084533eSDavid Brownell 	 */
615c9e617a5SImre Deak 	if (pdata->get_pendown_state == NULL) {
616c9e617a5SImre Deak 		dev_dbg(&spi->dev, "no get_pendown_state function?\n");
617c9e617a5SImre Deak 		return -EINVAL;
618c9e617a5SImre Deak 	}
619c9e617a5SImre Deak 
6209084533eSDavid Brownell 	/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
6219084533eSDavid Brownell 	 * that even if the hardware can do that, the SPI controller driver
6229084533eSDavid Brownell 	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
623ffa458c1SDavid Brownell 	 */
6249084533eSDavid Brownell 	spi->bits_per_word = 8;
625ffa458c1SDavid Brownell 
626a90f7e98SDmitry Torokhov 	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
627a90f7e98SDmitry Torokhov 	input_dev = input_allocate_device();
628a90f7e98SDmitry Torokhov 	if (!ts || !input_dev) {
629a90f7e98SDmitry Torokhov 		err = -ENOMEM;
630a90f7e98SDmitry Torokhov 		goto err_free_mem;
631a90f7e98SDmitry Torokhov 	}
632ffa458c1SDavid Brownell 
6332e5a7bd9SDavid Brownell 	dev_set_drvdata(&spi->dev, ts);
634a90f7e98SDmitry Torokhov 	spi->dev.power.power_state = PMSG_ON;
635ffa458c1SDavid Brownell 
636ffa458c1SDavid Brownell 	ts->spi = spi;
637a90f7e98SDmitry Torokhov 	ts->input = input_dev;
638ffa458c1SDavid Brownell 
639ffa458c1SDavid Brownell 	init_timer(&ts->timer);
640ffa458c1SDavid Brownell 	ts->timer.data = (unsigned long) ts;
641ffa458c1SDavid Brownell 	ts->timer.function = ads7846_timer;
642ffa458c1SDavid Brownell 
6437de90a8cSImre Deak 	spin_lock_init(&ts->lock);
6447de90a8cSImre Deak 
645ffa458c1SDavid Brownell 	ts->model = pdata->model ? : 7846;
646ffa458c1SDavid Brownell 	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
647ffa458c1SDavid Brownell 	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
648d5b415c9SImre Deak 	ts->pressure_max = pdata->pressure_max ? : ~0;
649d5b415c9SImre Deak 	if (pdata->debounce_max) {
650d5b415c9SImre Deak 		ts->debounce_max = pdata->debounce_max;
651d5b415c9SImre Deak 		ts->debounce_tol = pdata->debounce_tol;
652d5b415c9SImre Deak 		ts->debounce_rep = pdata->debounce_rep;
653d5b415c9SImre Deak 		if (ts->debounce_rep > ts->debounce_max + 1)
654d5b415c9SImre Deak 			ts->debounce_rep = ts->debounce_max - 1;
655d5b415c9SImre Deak 	} else
656d5b415c9SImre Deak 		ts->debounce_tol = ~0;
657c9e617a5SImre Deak 	ts->get_pendown_state = pdata->get_pendown_state;
658ffa458c1SDavid Brownell 
659a90f7e98SDmitry Torokhov 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
660ffa458c1SDavid Brownell 
661a90f7e98SDmitry Torokhov 	input_dev->name = "ADS784x Touchscreen";
662a90f7e98SDmitry Torokhov 	input_dev->phys = ts->phys;
663a90f7e98SDmitry Torokhov 	input_dev->cdev.dev = &spi->dev;
664ffa458c1SDavid Brownell 
665a90f7e98SDmitry Torokhov 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
666a90f7e98SDmitry Torokhov 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
667a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_X,
668ffa458c1SDavid Brownell 			pdata->x_min ? : 0,
669ffa458c1SDavid Brownell 			pdata->x_max ? : MAX_12BIT,
670ffa458c1SDavid Brownell 			0, 0);
671a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_Y,
672ffa458c1SDavid Brownell 			pdata->y_min ? : 0,
673ffa458c1SDavid Brownell 			pdata->y_max ? : MAX_12BIT,
674ffa458c1SDavid Brownell 			0, 0);
675a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_PRESSURE,
676ffa458c1SDavid Brownell 			pdata->pressure_min, pdata->pressure_max, 0, 0);
677ffa458c1SDavid Brownell 
678ffa458c1SDavid Brownell 	/* set up the transfers to read touchscreen state; this assumes we
679ffa458c1SDavid Brownell 	 * use formula #2 for pressure, not #3.
680ffa458c1SDavid Brownell 	 */
6810b7018aaSImre Deak 	m = &ts->msg[0];
682ffa458c1SDavid Brownell 	x = ts->xfer;
683ffa458c1SDavid Brownell 
6840b7018aaSImre Deak 	spi_message_init(m);
6850b7018aaSImre Deak 
686ffa458c1SDavid Brownell 	/* y- still on; turn on only y+ (and ADC) */
687d93f70b2SDavid Brownell 	ts->read_y = READ_Y;
688d93f70b2SDavid Brownell 	x->tx_buf = &ts->read_y;
689ffa458c1SDavid Brownell 	x->len = 1;
6900b7018aaSImre Deak 	spi_message_add_tail(x, m);
691d93f70b2SDavid Brownell 
692ffa458c1SDavid Brownell 	x++;
693ffa458c1SDavid Brownell 	x->rx_buf = &ts->tc.y;
694ffa458c1SDavid Brownell 	x->len = 2;
6950b7018aaSImre Deak 	spi_message_add_tail(x, m);
696ffa458c1SDavid Brownell 
6970b7018aaSImre Deak 	m->complete = ads7846_debounce;
6980b7018aaSImre Deak 	m->context = ts;
699d93f70b2SDavid Brownell 
7000b7018aaSImre Deak 	m++;
7010b7018aaSImre Deak 	spi_message_init(m);
702ffa458c1SDavid Brownell 
703ffa458c1SDavid Brownell 	/* turn y- off, x+ on, then leave in lowpower */
704d93f70b2SDavid Brownell 	x++;
705d93f70b2SDavid Brownell 	ts->read_x = READ_X;
706d93f70b2SDavid Brownell 	x->tx_buf = &ts->read_x;
707ffa458c1SDavid Brownell 	x->len = 1;
7080b7018aaSImre Deak 	spi_message_add_tail(x, m);
709d93f70b2SDavid Brownell 
710ffa458c1SDavid Brownell 	x++;
711ffa458c1SDavid Brownell 	x->rx_buf = &ts->tc.x;
712ffa458c1SDavid Brownell 	x->len = 2;
7130b7018aaSImre Deak 	spi_message_add_tail(x, m);
7140b7018aaSImre Deak 
7150b7018aaSImre Deak 	m->complete = ads7846_debounce;
7160b7018aaSImre Deak 	m->context = ts;
7170b7018aaSImre Deak 
7180b7018aaSImre Deak 	/* turn y+ off, x- on; we'll use formula #2 */
7190b7018aaSImre Deak 	if (ts->model == 7846) {
7200b7018aaSImre Deak 		m++;
7210b7018aaSImre Deak 		spi_message_init(m);
7220b7018aaSImre Deak 
7230b7018aaSImre Deak 		x++;
7240b7018aaSImre Deak 		ts->read_z1 = READ_Z1;
7250b7018aaSImre Deak 		x->tx_buf = &ts->read_z1;
7260b7018aaSImre Deak 		x->len = 1;
7270b7018aaSImre Deak 		spi_message_add_tail(x, m);
7280b7018aaSImre Deak 
7290b7018aaSImre Deak 		x++;
7300b7018aaSImre Deak 		x->rx_buf = &ts->tc.z1;
7310b7018aaSImre Deak 		x->len = 2;
7320b7018aaSImre Deak 		spi_message_add_tail(x, m);
7330b7018aaSImre Deak 
7340b7018aaSImre Deak 		m->complete = ads7846_debounce;
7350b7018aaSImre Deak 		m->context = ts;
7360b7018aaSImre Deak 
7370b7018aaSImre Deak 		m++;
7380b7018aaSImre Deak 		spi_message_init(m);
7390b7018aaSImre Deak 
7400b7018aaSImre Deak 		x++;
7410b7018aaSImre Deak 		ts->read_z2 = READ_Z2;
7420b7018aaSImre Deak 		x->tx_buf = &ts->read_z2;
7430b7018aaSImre Deak 		x->len = 1;
7440b7018aaSImre Deak 		spi_message_add_tail(x, m);
7450b7018aaSImre Deak 
7460b7018aaSImre Deak 		x++;
7470b7018aaSImre Deak 		x->rx_buf = &ts->tc.z2;
7480b7018aaSImre Deak 		x->len = 2;
7490b7018aaSImre Deak 		spi_message_add_tail(x, m);
7500b7018aaSImre Deak 
7510b7018aaSImre Deak 		m->complete = ads7846_debounce;
7520b7018aaSImre Deak 		m->context = ts;
7530b7018aaSImre Deak 	}
75453a0ef89SImre Deak 
75553a0ef89SImre Deak 	/* power down */
7560b7018aaSImre Deak 	m++;
7570b7018aaSImre Deak 	spi_message_init(m);
7580b7018aaSImre Deak 
75953a0ef89SImre Deak 	x++;
76053a0ef89SImre Deak 	ts->pwrdown = PWRDOWN;
76153a0ef89SImre Deak 	x->tx_buf = &ts->pwrdown;
76253a0ef89SImre Deak 	x->len = 1;
7630b7018aaSImre Deak 	spi_message_add_tail(x, m);
76453a0ef89SImre Deak 
76553a0ef89SImre Deak 	x++;
76653a0ef89SImre Deak 	x->rx_buf = &ts->dummy;
76753a0ef89SImre Deak 	x->len = 2;
768d93f70b2SDavid Brownell 	CS_CHANGE(*x);
7690b7018aaSImre Deak 	spi_message_add_tail(x, m);
770ffa458c1SDavid Brownell 
7710b7018aaSImre Deak 	m->complete = ads7846_rx;
7720b7018aaSImre Deak 	m->context = ts;
773ffa458c1SDavid Brownell 
774d5b415c9SImre Deak 	ts->last_msg = m;
775d5b415c9SImre Deak 
776dace1453SThomas Gleixner 	if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
7779084533eSDavid Brownell 			spi->dev.driver->name, ts)) {
7782e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
779a90f7e98SDmitry Torokhov 		err = -EBUSY;
780a90f7e98SDmitry Torokhov 		goto err_free_mem;
781ffa458c1SDavid Brownell 	}
782ffa458c1SDavid Brownell 
7832e5a7bd9SDavid Brownell 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
784ffa458c1SDavid Brownell 
785ffa458c1SDavid Brownell 	/* take a first sample, leaving nPENIRQ active; avoid
786ffa458c1SDavid Brownell 	 * the touchscreen, in case it's not connected.
787ffa458c1SDavid Brownell 	 */
7882e5a7bd9SDavid Brownell 	(void) ads7846_read12_ser(&spi->dev,
789ffa458c1SDavid Brownell 			  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
790ffa458c1SDavid Brownell 
791ffa458c1SDavid Brownell 	/* ads7843/7845 don't have temperature sensors, and
792ffa458c1SDavid Brownell 	 * use the other sensors a bit differently too
793ffa458c1SDavid Brownell 	 */
794ffa458c1SDavid Brownell 	if (ts->model == 7846) {
7952e5a7bd9SDavid Brownell 		device_create_file(&spi->dev, &dev_attr_temp0);
7962e5a7bd9SDavid Brownell 		device_create_file(&spi->dev, &dev_attr_temp1);
797ffa458c1SDavid Brownell 	}
798ffa458c1SDavid Brownell 	if (ts->model != 7845)
7992e5a7bd9SDavid Brownell 		device_create_file(&spi->dev, &dev_attr_vbatt);
8002e5a7bd9SDavid Brownell 	device_create_file(&spi->dev, &dev_attr_vaux);
801ffa458c1SDavid Brownell 
802438f2a74SImre Deak 	device_create_file(&spi->dev, &dev_attr_pen_down);
803438f2a74SImre Deak 
8047de90a8cSImre Deak 	device_create_file(&spi->dev, &dev_attr_disable);
8057de90a8cSImre Deak 
806a90f7e98SDmitry Torokhov 	err = input_register_device(input_dev);
807a90f7e98SDmitry Torokhov 	if (err)
8087de90a8cSImre Deak 		goto err_remove_attr;
809a90f7e98SDmitry Torokhov 
810ffa458c1SDavid Brownell 	return 0;
811a90f7e98SDmitry Torokhov 
8127de90a8cSImre Deak  err_remove_attr:
8137de90a8cSImre Deak 	device_remove_file(&spi->dev, &dev_attr_disable);
8147de90a8cSImre Deak 	device_remove_file(&spi->dev, &dev_attr_pen_down);
8157de90a8cSImre Deak 	if (ts->model == 7846) {
8167de90a8cSImre Deak 		device_remove_file(&spi->dev, &dev_attr_temp1);
8177de90a8cSImre Deak 		device_remove_file(&spi->dev, &dev_attr_temp0);
8187de90a8cSImre Deak 	}
8197de90a8cSImre Deak 	if (ts->model != 7845)
8207de90a8cSImre Deak 		device_remove_file(&spi->dev, &dev_attr_vbatt);
8217de90a8cSImre Deak 	device_remove_file(&spi->dev, &dev_attr_vaux);
8227de90a8cSImre Deak 
823a90f7e98SDmitry Torokhov 	free_irq(spi->irq, ts);
824a90f7e98SDmitry Torokhov  err_free_mem:
825a90f7e98SDmitry Torokhov 	input_free_device(input_dev);
826a90f7e98SDmitry Torokhov 	kfree(ts);
827a90f7e98SDmitry Torokhov 	return err;
828ffa458c1SDavid Brownell }
829ffa458c1SDavid Brownell 
8302e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi)
831ffa458c1SDavid Brownell {
8322e5a7bd9SDavid Brownell 	struct ads7846		*ts = dev_get_drvdata(&spi->dev);
833ffa458c1SDavid Brownell 
8347de90a8cSImre Deak 	input_unregister_device(ts->input);
8357de90a8cSImre Deak 
8362e5a7bd9SDavid Brownell 	ads7846_suspend(spi, PMSG_SUSPEND);
837ffa458c1SDavid Brownell 
8387de90a8cSImre Deak 	device_remove_file(&spi->dev, &dev_attr_disable);
839438f2a74SImre Deak 	device_remove_file(&spi->dev, &dev_attr_pen_down);
840ffa458c1SDavid Brownell 	if (ts->model == 7846) {
8412e5a7bd9SDavid Brownell 		device_remove_file(&spi->dev, &dev_attr_temp1);
8427de90a8cSImre Deak 		device_remove_file(&spi->dev, &dev_attr_temp0);
843ffa458c1SDavid Brownell 	}
844ffa458c1SDavid Brownell 	if (ts->model != 7845)
8452e5a7bd9SDavid Brownell 		device_remove_file(&spi->dev, &dev_attr_vbatt);
8462e5a7bd9SDavid Brownell 	device_remove_file(&spi->dev, &dev_attr_vaux);
847ffa458c1SDavid Brownell 
8487de90a8cSImre Deak 	free_irq(ts->spi->irq, ts);
849c9e617a5SImre Deak 	/* suspend left the IRQ disabled */
8507de90a8cSImre Deak 	enable_irq(ts->spi->irq);
8517de90a8cSImre Deak 
852ffa458c1SDavid Brownell 	kfree(ts);
853ffa458c1SDavid Brownell 
8542e5a7bd9SDavid Brownell 	dev_dbg(&spi->dev, "unregistered touchscreen\n");
855ffa458c1SDavid Brownell 	return 0;
856ffa458c1SDavid Brownell }
857ffa458c1SDavid Brownell 
8582e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = {
8592e5a7bd9SDavid Brownell 	.driver = {
860ffa458c1SDavid Brownell 		.name	= "ads7846",
861ffa458c1SDavid Brownell 		.bus	= &spi_bus_type,
8622e5a7bd9SDavid Brownell 		.owner	= THIS_MODULE,
8632e5a7bd9SDavid Brownell 	},
864ffa458c1SDavid Brownell 	.probe		= ads7846_probe,
8652e5a7bd9SDavid Brownell 	.remove		= __devexit_p(ads7846_remove),
866ffa458c1SDavid Brownell 	.suspend	= ads7846_suspend,
867ffa458c1SDavid Brownell 	.resume		= ads7846_resume,
868ffa458c1SDavid Brownell };
869ffa458c1SDavid Brownell 
870ffa458c1SDavid Brownell static int __init ads7846_init(void)
871ffa458c1SDavid Brownell {
872ffa458c1SDavid Brownell 	/* grr, board-specific init should stay out of drivers!! */
873ffa458c1SDavid Brownell 
874ffa458c1SDavid Brownell #ifdef	CONFIG_ARCH_OMAP
875ffa458c1SDavid Brownell 	if (machine_is_omap_osk()) {
876ffa458c1SDavid Brownell 		/* GPIO4 = PENIRQ; GPIO6 = BUSY */
877ffa458c1SDavid Brownell 		omap_request_gpio(4);
878ffa458c1SDavid Brownell 		omap_set_gpio_direction(4, 1);
879ffa458c1SDavid Brownell 		omap_request_gpio(6);
880ffa458c1SDavid Brownell 		omap_set_gpio_direction(6, 1);
881ffa458c1SDavid Brownell 	}
882ffa458c1SDavid Brownell 	// also TI 1510 Innovator, bitbanging through FPGA
883ffa458c1SDavid Brownell 	// also Nokia 770
884ffa458c1SDavid Brownell 	// also Palm Tungsten T2
885ffa458c1SDavid Brownell #endif
886ffa458c1SDavid Brownell 
887ffa458c1SDavid Brownell 	// PXA:
888ffa458c1SDavid Brownell 	// also Dell Axim X50
889ffa458c1SDavid Brownell 	// also HP iPaq H191x/H192x/H415x/H435x
8902e5a7bd9SDavid Brownell 	// also Intel Lubbock (additional to UCB1400; as temperature sensor)
891ffa458c1SDavid Brownell 	// also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
892ffa458c1SDavid Brownell 
8932e5a7bd9SDavid Brownell 	// Atmel at91sam9261-EK uses ads7843
8942e5a7bd9SDavid Brownell 
895ffa458c1SDavid Brownell 	// also various AMD Au1x00 devel boards
896ffa458c1SDavid Brownell 
8972e5a7bd9SDavid Brownell 	return spi_register_driver(&ads7846_driver);
898ffa458c1SDavid Brownell }
899ffa458c1SDavid Brownell module_init(ads7846_init);
900ffa458c1SDavid Brownell 
901ffa458c1SDavid Brownell static void __exit ads7846_exit(void)
902ffa458c1SDavid Brownell {
9032e5a7bd9SDavid Brownell 	spi_unregister_driver(&ads7846_driver);
904ffa458c1SDavid Brownell 
905ffa458c1SDavid Brownell #ifdef	CONFIG_ARCH_OMAP
906ffa458c1SDavid Brownell 	if (machine_is_omap_osk()) {
907ffa458c1SDavid Brownell 		omap_free_gpio(4);
908ffa458c1SDavid Brownell 		omap_free_gpio(6);
909ffa458c1SDavid Brownell 	}
910ffa458c1SDavid Brownell #endif
911ffa458c1SDavid Brownell 
912ffa458c1SDavid Brownell }
913ffa458c1SDavid Brownell module_exit(ads7846_exit);
914ffa458c1SDavid Brownell 
915ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
916ffa458c1SDavid Brownell MODULE_LICENSE("GPL");
917