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