xref: /linux/drivers/input/touchscreen/ads7846.c (revision de2defd96d7d92fe8b5f9cf2bfd385d8d4819923)
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,
66da970e69SImre Deak 	 * *** WHICH NEED BYTESWAPPING *** and range adjustment.
67ffa458c1SDavid Brownell 	 */
68da970e69SImre Deak 	u16	x;
69da970e69SImre Deak 	u16	y;
70da970e69SImre Deak 	u16	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;
798dd51650SDmitry Torokhov 	struct attribute_group	*attr_group;
80ffa458c1SDavid Brownell 	u16			model;
81ffa458c1SDavid Brownell 	u16			vref_delay_usecs;
82ffa458c1SDavid Brownell 	u16			x_plate_ohms;
83d5b415c9SImre Deak 	u16			pressure_max;
84ffa458c1SDavid Brownell 
8553a0ef89SImre Deak 	u8			read_x, read_y, read_z1, read_z2, pwrdown;
8653a0ef89SImre Deak 	u16			dummy;		/* for the pwrdown read */
87ffa458c1SDavid Brownell 	struct ts_event		tc;
88ffa458c1SDavid Brownell 
8953a0ef89SImre Deak 	struct spi_transfer	xfer[10];
900b7018aaSImre Deak 	struct spi_message	msg[5];
91d5b415c9SImre Deak 	struct spi_message	*last_msg;
920b7018aaSImre Deak 	int			msg_idx;
930b7018aaSImre Deak 	int			read_cnt;
94d5b415c9SImre Deak 	int			read_rep;
950b7018aaSImre Deak 	int			last_read;
960b7018aaSImre Deak 
970b7018aaSImre Deak 	u16			debounce_max;
980b7018aaSImre Deak 	u16			debounce_tol;
99d5b415c9SImre Deak 	u16			debounce_rep;
100ffa458c1SDavid Brownell 
101ffa458c1SDavid Brownell 	spinlock_t		lock;
102ffa458c1SDavid Brownell 	struct timer_list	timer;		/* P: lock */
103ffa458c1SDavid Brownell 	unsigned		pendown:1;	/* P: lock */
104ffa458c1SDavid Brownell 	unsigned		pending:1;	/* P: lock */
105ffa458c1SDavid Brownell // FIXME remove "irq_disabled"
106ffa458c1SDavid Brownell 	unsigned		irq_disabled:1;	/* P: lock */
1077de90a8cSImre Deak 	unsigned		disabled:1;
108c9e617a5SImre Deak 
109da970e69SImre Deak 	int			(*filter)(void *data, int data_idx, int *val);
110da970e69SImre Deak 	void			*filter_data;
111da970e69SImre Deak 	void			(*filter_cleanup)(void *data);
112c9e617a5SImre Deak 	int			(*get_pendown_state)(void);
113ffa458c1SDavid Brownell };
114ffa458c1SDavid Brownell 
115ffa458c1SDavid Brownell /* leave chip selected when we're done, for quicker re-select? */
116ffa458c1SDavid Brownell #if	0
117ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 1)
118ffa458c1SDavid Brownell #else
119ffa458c1SDavid Brownell #define	CS_CHANGE(xfer)	((xfer).cs_change = 0)
120ffa458c1SDavid Brownell #endif
121ffa458c1SDavid Brownell 
122ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
123ffa458c1SDavid Brownell 
124ffa458c1SDavid Brownell /* The ADS7846 has touchscreen and other sensors.
125ffa458c1SDavid Brownell  * Earlier ads784x chips are somewhat compatible.
126ffa458c1SDavid Brownell  */
127ffa458c1SDavid Brownell #define	ADS_START		(1 << 7)
128ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_y		(1 << 4)	/* differential */
129ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z1		(3 << 4)	/* differential */
130ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_z2		(4 << 4)	/* differential */
131ffa458c1SDavid Brownell #define	ADS_A2A1A0_d_x		(5 << 4)	/* differential */
132ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp0	(0 << 4)	/* non-differential */
133ffa458c1SDavid Brownell #define	ADS_A2A1A0_vbatt	(2 << 4)	/* non-differential */
134ffa458c1SDavid Brownell #define	ADS_A2A1A0_vaux		(6 << 4)	/* non-differential */
135ffa458c1SDavid Brownell #define	ADS_A2A1A0_temp1	(7 << 4)	/* non-differential */
136ffa458c1SDavid Brownell #define	ADS_8_BIT		(1 << 3)
137ffa458c1SDavid Brownell #define	ADS_12_BIT		(0 << 3)
138ffa458c1SDavid Brownell #define	ADS_SER			(1 << 2)	/* non-differential */
139ffa458c1SDavid Brownell #define	ADS_DFR			(0 << 2)	/* differential */
140ffa458c1SDavid Brownell #define	ADS_PD10_PDOWN		(0 << 0)	/* lowpower mode + penirq */
141ffa458c1SDavid Brownell #define	ADS_PD10_ADC_ON		(1 << 0)	/* ADC on */
142ffa458c1SDavid Brownell #define	ADS_PD10_REF_ON		(2 << 0)	/* vREF on + penirq */
143ffa458c1SDavid Brownell #define	ADS_PD10_ALL_ON		(3 << 0)	/* ADC + vREF on */
144ffa458c1SDavid Brownell 
145ffa458c1SDavid Brownell #define	MAX_12BIT	((1<<12)-1)
146ffa458c1SDavid Brownell 
147ffa458c1SDavid Brownell /* leave ADC powered up (disables penirq) between differential samples */
148*de2defd9SImre Deak #define	READ_12BIT_DFR(x, adc, vref) (ADS_START | ADS_A2A1A0_d_ ## x \
149*de2defd9SImre Deak 	| ADS_12_BIT | ADS_DFR | \
150*de2defd9SImre Deak 	(adc ? ADS_PD10_ADC_ON : 0) | (vref ? ADS_PD10_REF_ON : 0))
151ffa458c1SDavid Brownell 
152*de2defd9SImre Deak #define	READ_Y(vref)	(READ_12BIT_DFR(y,  1, vref))
153*de2defd9SImre Deak #define	READ_Z1(vref)	(READ_12BIT_DFR(z1, 1, vref))
154*de2defd9SImre Deak #define	READ_Z2(vref)	(READ_12BIT_DFR(z2, 1, vref))
15553a0ef89SImre Deak 
156*de2defd9SImre Deak #define	READ_X(vref)	(READ_12BIT_DFR(x,  1, vref))
157*de2defd9SImre Deak #define	PWRDOWN		(READ_12BIT_DFR(y,  0, 0))	/* LAST */
158ffa458c1SDavid Brownell 
159ffa458c1SDavid Brownell /* single-ended samples need to first power up reference voltage;
160ffa458c1SDavid Brownell  * we leave both ADC and VREF powered
161ffa458c1SDavid Brownell  */
162ffa458c1SDavid Brownell #define	READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \
163ffa458c1SDavid Brownell 	| ADS_12_BIT | ADS_SER)
164ffa458c1SDavid Brownell 
165*de2defd9SImre Deak #define	REF_ON	(READ_12BIT_DFR(x, 1, 1))
166*de2defd9SImre Deak #define	REF_OFF	(READ_12BIT_DFR(y, 0, 0))
167ffa458c1SDavid Brownell 
168ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
169ffa458c1SDavid Brownell 
170ffa458c1SDavid Brownell /*
171ffa458c1SDavid Brownell  * Non-touchscreen sensors only use single-ended conversions.
172ffa458c1SDavid Brownell  */
173ffa458c1SDavid Brownell 
174ffa458c1SDavid Brownell struct ser_req {
175d93f70b2SDavid Brownell 	u8			ref_on;
176ffa458c1SDavid Brownell 	u8			command;
177d93f70b2SDavid Brownell 	u8			ref_off;
178ffa458c1SDavid Brownell 	u16			scratch;
179ffa458c1SDavid Brownell 	__be16			sample;
180ffa458c1SDavid Brownell 	struct spi_message	msg;
181ffa458c1SDavid Brownell 	struct spi_transfer	xfer[6];
182ffa458c1SDavid Brownell };
183ffa458c1SDavid Brownell 
1847de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts);
1857de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts);
1867de90a8cSImre Deak 
187c9e617a5SImre Deak static int device_suspended(struct device *dev)
188c9e617a5SImre Deak {
189c9e617a5SImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
190c9e617a5SImre Deak 	return dev->power.power_state.event != PM_EVENT_ON || ts->disabled;
191c9e617a5SImre Deak }
192c9e617a5SImre Deak 
193ffa458c1SDavid Brownell static int ads7846_read12_ser(struct device *dev, unsigned command)
194ffa458c1SDavid Brownell {
195ffa458c1SDavid Brownell 	struct spi_device	*spi = to_spi_device(dev);
196ffa458c1SDavid Brownell 	struct ads7846		*ts = dev_get_drvdata(dev);
197e94b1766SChristoph Lameter 	struct ser_req		*req = kzalloc(sizeof *req, GFP_KERNEL);
198ffa458c1SDavid Brownell 	int			status;
199ffa458c1SDavid Brownell 	int			sample;
2008275c642SVitaly Wool 	int			i;
201ffa458c1SDavid Brownell 
202ffa458c1SDavid Brownell 	if (!req)
203ffa458c1SDavid Brownell 		return -ENOMEM;
204ffa458c1SDavid Brownell 
2050b7018aaSImre Deak 	spi_message_init(&req->msg);
2068275c642SVitaly Wool 
207ffa458c1SDavid Brownell 	/* activate reference, so it has time to settle; */
208d93f70b2SDavid Brownell 	req->ref_on = REF_ON;
209d93f70b2SDavid Brownell 	req->xfer[0].tx_buf = &req->ref_on;
210ffa458c1SDavid Brownell 	req->xfer[0].len = 1;
211ffa458c1SDavid Brownell 	req->xfer[1].rx_buf = &req->scratch;
212ffa458c1SDavid Brownell 	req->xfer[1].len = 2;
213ffa458c1SDavid Brownell 
214ffa458c1SDavid Brownell 	/*
215ffa458c1SDavid Brownell 	 * for external VREF, 0 usec (and assume it's always on);
216ffa458c1SDavid Brownell 	 * for 1uF, use 800 usec;
217ffa458c1SDavid Brownell 	 * no cap, 100 usec.
218ffa458c1SDavid Brownell 	 */
219ffa458c1SDavid Brownell 	req->xfer[1].delay_usecs = ts->vref_delay_usecs;
220ffa458c1SDavid Brownell 
221ffa458c1SDavid Brownell 	/* take sample */
222ffa458c1SDavid Brownell 	req->command = (u8) command;
223ffa458c1SDavid Brownell 	req->xfer[2].tx_buf = &req->command;
224ffa458c1SDavid Brownell 	req->xfer[2].len = 1;
225ffa458c1SDavid Brownell 	req->xfer[3].rx_buf = &req->sample;
226ffa458c1SDavid Brownell 	req->xfer[3].len = 2;
227ffa458c1SDavid Brownell 
228ffa458c1SDavid Brownell 	/* REVISIT:  take a few more samples, and compare ... */
229ffa458c1SDavid Brownell 
230ffa458c1SDavid Brownell 	/* turn off reference */
231d93f70b2SDavid Brownell 	req->ref_off = REF_OFF;
232d93f70b2SDavid Brownell 	req->xfer[4].tx_buf = &req->ref_off;
233ffa458c1SDavid Brownell 	req->xfer[4].len = 1;
234ffa458c1SDavid Brownell 	req->xfer[5].rx_buf = &req->scratch;
235ffa458c1SDavid Brownell 	req->xfer[5].len = 2;
236ffa458c1SDavid Brownell 
237ffa458c1SDavid Brownell 	CS_CHANGE(req->xfer[5]);
238ffa458c1SDavid Brownell 
239ffa458c1SDavid Brownell 	/* group all the transfers together, so we can't interfere with
240ffa458c1SDavid Brownell 	 * reading touchscreen state; disable penirq while sampling
241ffa458c1SDavid Brownell 	 */
2428275c642SVitaly Wool 	for (i = 0; i < 6; i++)
2438275c642SVitaly Wool 		spi_message_add_tail(&req->xfer[i], &req->msg);
244ffa458c1SDavid Brownell 
245c9e617a5SImre Deak 	ts->irq_disabled = 1;
246ffa458c1SDavid Brownell 	disable_irq(spi->irq);
247ffa458c1SDavid Brownell 	status = spi_sync(spi, &req->msg);
248c9e617a5SImre Deak 	ts->irq_disabled = 0;
249ffa458c1SDavid Brownell 	enable_irq(spi->irq);
250ffa458c1SDavid Brownell 
251ffa458c1SDavid Brownell 	if (req->msg.status)
252ffa458c1SDavid Brownell 		status = req->msg.status;
253ffa458c1SDavid Brownell 
2549084533eSDavid Brownell 	/* on-wire is a must-ignore bit, a BE12 value, then padding */
2559084533eSDavid Brownell 	sample = be16_to_cpu(req->sample);
2569084533eSDavid Brownell 	sample = sample >> 3;
2579084533eSDavid Brownell 	sample &= 0x0fff;
2589084533eSDavid Brownell 
2599084533eSDavid Brownell 	kfree(req);
260ffa458c1SDavid Brownell 	return status ? status : sample;
261ffa458c1SDavid Brownell }
262ffa458c1SDavid Brownell 
263ffa458c1SDavid Brownell #define SHOW(name) static ssize_t \
264ffa458c1SDavid Brownell name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
265ffa458c1SDavid Brownell { \
266ffa458c1SDavid Brownell 	ssize_t v = ads7846_read12_ser(dev, \
267ffa458c1SDavid Brownell 			READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \
268ffa458c1SDavid Brownell 	if (v < 0) \
269ffa458c1SDavid Brownell 		return v; \
270ffa458c1SDavid Brownell 	return sprintf(buf, "%u\n", (unsigned) v); \
271ffa458c1SDavid Brownell } \
272ffa458c1SDavid Brownell static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL);
273ffa458c1SDavid Brownell 
274ffa458c1SDavid Brownell SHOW(temp0)
275ffa458c1SDavid Brownell SHOW(temp1)
276ffa458c1SDavid Brownell SHOW(vaux)
277ffa458c1SDavid Brownell SHOW(vbatt)
278ffa458c1SDavid Brownell 
279438f2a74SImre Deak static int is_pen_down(struct device *dev)
280438f2a74SImre Deak {
281438f2a74SImre Deak 	struct ads7846		*ts = dev_get_drvdata(dev);
282438f2a74SImre Deak 
283438f2a74SImre Deak 	return ts->pendown;
284438f2a74SImre Deak }
285438f2a74SImre Deak 
286438f2a74SImre Deak static ssize_t ads7846_pen_down_show(struct device *dev,
287438f2a74SImre Deak 				     struct device_attribute *attr, char *buf)
288438f2a74SImre Deak {
289438f2a74SImre Deak 	return sprintf(buf, "%u\n", is_pen_down(dev));
290438f2a74SImre Deak }
291438f2a74SImre Deak 
292438f2a74SImre Deak static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
293438f2a74SImre Deak 
2947de90a8cSImre Deak static ssize_t ads7846_disable_show(struct device *dev,
2957de90a8cSImre Deak 				     struct device_attribute *attr, char *buf)
2967de90a8cSImre Deak {
2977de90a8cSImre Deak 	struct ads7846	*ts = dev_get_drvdata(dev);
2987de90a8cSImre Deak 
2997de90a8cSImre Deak 	return sprintf(buf, "%u\n", ts->disabled);
3007de90a8cSImre Deak }
3017de90a8cSImre Deak 
3027de90a8cSImre Deak static ssize_t ads7846_disable_store(struct device *dev,
3037de90a8cSImre Deak 				     struct device_attribute *attr,
3047de90a8cSImre Deak 				     const char *buf, size_t count)
3057de90a8cSImre Deak {
3067de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(dev);
3077de90a8cSImre Deak 	char *endp;
3087de90a8cSImre Deak 	int i;
3097de90a8cSImre Deak 
3107de90a8cSImre Deak 	i = simple_strtoul(buf, &endp, 10);
3117de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
3127de90a8cSImre Deak 
3137de90a8cSImre Deak 	if (i)
3147de90a8cSImre Deak 		ads7846_disable(ts);
3157de90a8cSImre Deak 	else
3167de90a8cSImre Deak 		ads7846_enable(ts);
3177de90a8cSImre Deak 
3187de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
3197de90a8cSImre Deak 
3207de90a8cSImre Deak 	return count;
3217de90a8cSImre Deak }
3227de90a8cSImre Deak 
3237de90a8cSImre Deak static DEVICE_ATTR(disable, 0664, ads7846_disable_show, ads7846_disable_store);
3247de90a8cSImre Deak 
3258dd51650SDmitry Torokhov static struct attribute *ads7846_attributes[] = {
3268dd51650SDmitry Torokhov 	&dev_attr_temp0.attr,
3278dd51650SDmitry Torokhov 	&dev_attr_temp1.attr,
3288dd51650SDmitry Torokhov 	&dev_attr_vbatt.attr,
3298dd51650SDmitry Torokhov 	&dev_attr_vaux.attr,
3308dd51650SDmitry Torokhov 	&dev_attr_pen_down.attr,
3318dd51650SDmitry Torokhov 	&dev_attr_disable.attr,
3328dd51650SDmitry Torokhov 	NULL,
3338dd51650SDmitry Torokhov };
3348dd51650SDmitry Torokhov 
3358dd51650SDmitry Torokhov static struct attribute_group ads7846_attr_group = {
3368dd51650SDmitry Torokhov 	.attrs = ads7846_attributes,
3378dd51650SDmitry Torokhov };
3388dd51650SDmitry Torokhov 
3398dd51650SDmitry Torokhov /*
3408dd51650SDmitry Torokhov  * ads7843/7845 don't have temperature sensors, and
3418dd51650SDmitry Torokhov  * use the other sensors a bit differently too
3428dd51650SDmitry Torokhov  */
3438dd51650SDmitry Torokhov 
3448dd51650SDmitry Torokhov static struct attribute *ads7843_attributes[] = {
3458dd51650SDmitry Torokhov 	&dev_attr_vbatt.attr,
3468dd51650SDmitry Torokhov 	&dev_attr_vaux.attr,
3478dd51650SDmitry Torokhov 	&dev_attr_pen_down.attr,
3488dd51650SDmitry Torokhov 	&dev_attr_disable.attr,
3498dd51650SDmitry Torokhov 	NULL,
3508dd51650SDmitry Torokhov };
3518dd51650SDmitry Torokhov 
3528dd51650SDmitry Torokhov static struct attribute_group ads7843_attr_group = {
3538dd51650SDmitry Torokhov 	.attrs = ads7843_attributes,
3548dd51650SDmitry Torokhov };
3558dd51650SDmitry Torokhov 
3568dd51650SDmitry Torokhov static struct attribute *ads7845_attributes[] = {
3578dd51650SDmitry Torokhov 	&dev_attr_vaux.attr,
3588dd51650SDmitry Torokhov 	&dev_attr_pen_down.attr,
3598dd51650SDmitry Torokhov 	&dev_attr_disable.attr,
3608dd51650SDmitry Torokhov 	NULL,
3618dd51650SDmitry Torokhov };
3628dd51650SDmitry Torokhov 
3638dd51650SDmitry Torokhov static struct attribute_group ads7845_attr_group = {
3648dd51650SDmitry Torokhov 	.attrs = ads7845_attributes,
3658dd51650SDmitry Torokhov };
3668dd51650SDmitry Torokhov 
367ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
368ffa458c1SDavid Brownell 
369ffa458c1SDavid Brownell /*
370ffa458c1SDavid Brownell  * PENIRQ only kicks the timer.  The timer only reissues the SPI transfer,
371ffa458c1SDavid Brownell  * to retrieve touchscreen status.
372ffa458c1SDavid Brownell  *
373ffa458c1SDavid Brownell  * The SPI transfer completion callback does the real work.  It reports
374ffa458c1SDavid Brownell  * touchscreen events and reactivates the timer (or IRQ) as appropriate.
375ffa458c1SDavid Brownell  */
376ffa458c1SDavid Brownell 
377ffa458c1SDavid Brownell static void ads7846_rx(void *ads)
378ffa458c1SDavid Brownell {
379ffa458c1SDavid Brownell 	struct ads7846		*ts = ads;
380a90f7e98SDmitry Torokhov 	struct input_dev	*input_dev = ts->input;
381ffa458c1SDavid Brownell 	unsigned		Rt;
382ffa458c1SDavid Brownell 	unsigned		sync = 0;
383ffa458c1SDavid Brownell 	u16			x, y, z1, z2;
384ffa458c1SDavid Brownell 	unsigned long		flags;
385ffa458c1SDavid Brownell 
386da970e69SImre Deak 	/* ads7846_rx_val() did in-place conversion (including byteswap) from
387da970e69SImre Deak 	 * on-the-wire format as part of debouncing to get stable readings.
388ffa458c1SDavid Brownell 	 */
389da970e69SImre Deak 	x = ts->tc.x;
390da970e69SImre Deak 	y = ts->tc.y;
391da970e69SImre Deak 	z1 = ts->tc.z1;
392da970e69SImre Deak 	z2 = ts->tc.z2;
393ffa458c1SDavid Brownell 
394ffa458c1SDavid Brownell 	/* range filtering */
395ffa458c1SDavid Brownell 	if (x == MAX_12BIT)
396ffa458c1SDavid Brownell 		x = 0;
397ffa458c1SDavid Brownell 
398c9e617a5SImre Deak 	if (likely(x && z1 && !device_suspended(&ts->spi->dev))) {
399ffa458c1SDavid Brownell 		/* compute touch pressure resistance using equation #2 */
400ffa458c1SDavid Brownell 		Rt = z2;
401ffa458c1SDavid Brownell 		Rt -= z1;
402ffa458c1SDavid Brownell 		Rt *= x;
403ffa458c1SDavid Brownell 		Rt *= ts->x_plate_ohms;
404ffa458c1SDavid Brownell 		Rt /= z1;
405ffa458c1SDavid Brownell 		Rt = (Rt + 2047) >> 12;
406ffa458c1SDavid Brownell 	} else
407ffa458c1SDavid Brownell 		Rt = 0;
408ffa458c1SDavid Brownell 
409d5b415c9SImre Deak 	/* Sample found inconsistent by debouncing or pressure is beyond
410d5b415c9SImre Deak 	* the maximum. Don't report it to user space, repeat at least
411d5b415c9SImre Deak 	* once more the measurement */
412d5b415c9SImre Deak 	if (ts->tc.ignore || Rt > ts->pressure_max) {
413d5b415c9SImre Deak 		mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
414d5b415c9SImre Deak 		return;
415d5b415c9SImre Deak 	}
416d5b415c9SImre Deak 
417ffa458c1SDavid Brownell 	/* NOTE:  "pendown" is inferred from pressure; we don't rely on
418ffa458c1SDavid Brownell 	 * being able to check nPENIRQ status, or "friendly" trigger modes
419ffa458c1SDavid Brownell 	 * (both-edges is much better than just-falling or low-level).
420ffa458c1SDavid Brownell 	 *
421ffa458c1SDavid Brownell 	 * REVISIT:  some boards may require reading nPENIRQ; it's
422ffa458c1SDavid Brownell 	 * needed on 7843.  and 7845 reads pressure differently...
423ffa458c1SDavid Brownell 	 *
424ffa458c1SDavid Brownell 	 * REVISIT:  the touchscreen might not be connected; this code
425ffa458c1SDavid Brownell 	 * won't notice that, even if nPENIRQ never fires ...
426ffa458c1SDavid Brownell 	 */
427ffa458c1SDavid Brownell 	if (!ts->pendown && Rt != 0) {
428a90f7e98SDmitry Torokhov 		input_report_key(input_dev, BTN_TOUCH, 1);
429ffa458c1SDavid Brownell 		sync = 1;
430ffa458c1SDavid Brownell 	} else if (ts->pendown && Rt == 0) {
431a90f7e98SDmitry Torokhov 		input_report_key(input_dev, BTN_TOUCH, 0);
432ffa458c1SDavid Brownell 		sync = 1;
433ffa458c1SDavid Brownell 	}
434ffa458c1SDavid Brownell 
435ffa458c1SDavid Brownell 	if (Rt) {
436a90f7e98SDmitry Torokhov 		input_report_abs(input_dev, ABS_X, x);
437a90f7e98SDmitry Torokhov 		input_report_abs(input_dev, ABS_Y, y);
438ffa458c1SDavid Brownell 		sync = 1;
439ffa458c1SDavid Brownell 	}
440ae82d5abSImre Deak 
441ae82d5abSImre Deak 	if (sync) {
442ae82d5abSImre Deak 		input_report_abs(input_dev, ABS_PRESSURE, Rt);
443a90f7e98SDmitry Torokhov 		input_sync(input_dev);
444ae82d5abSImre Deak 	}
445ffa458c1SDavid Brownell 
446ffa458c1SDavid Brownell #ifdef	VERBOSE
447ffa458c1SDavid Brownell 	if (Rt || ts->pendown)
448ffa458c1SDavid Brownell 		pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id,
449ffa458c1SDavid Brownell 			x, y, Rt, Rt ? "" : " UP");
450ffa458c1SDavid Brownell #endif
451ffa458c1SDavid Brownell 
452ffa458c1SDavid Brownell 	spin_lock_irqsave(&ts->lock, flags);
453ffa458c1SDavid Brownell 
454ffa458c1SDavid Brownell 	ts->pendown = (Rt != 0);
455ffa458c1SDavid Brownell 	mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
456ffa458c1SDavid Brownell 
457ffa458c1SDavid Brownell 	spin_unlock_irqrestore(&ts->lock, flags);
458ffa458c1SDavid Brownell }
459ffa458c1SDavid Brownell 
460da970e69SImre Deak static int ads7846_debounce(void *ads, int data_idx, int *val)
461ffa458c1SDavid Brownell {
4620b7018aaSImre Deak 	struct ads7846		*ts = ads;
463ffa458c1SDavid Brownell 
464da970e69SImre Deak 	if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
465da970e69SImre Deak 		/* Start over collecting consistent readings. */
466da970e69SImre Deak 		ts->read_rep = 0;
467d5b415c9SImre Deak 		/* Repeat it, if this was the first read or the read
468d5b415c9SImre Deak 		 * wasn't consistent enough. */
469d5b415c9SImre Deak 		if (ts->read_cnt < ts->debounce_max) {
470da970e69SImre Deak 			ts->last_read = *val;
471d5b415c9SImre Deak 			ts->read_cnt++;
472da970e69SImre Deak 			return ADS7846_FILTER_REPEAT;
4730b7018aaSImre Deak 		} else {
474d5b415c9SImre Deak 			/* Maximum number of debouncing reached and still
475d5b415c9SImre Deak 			 * not enough number of consistent readings. Abort
476d5b415c9SImre Deak 			 * the whole sample, repeat it in the next sampling
477d5b415c9SImre Deak 			 * period.
478d5b415c9SImre Deak 			 */
479d5b415c9SImre Deak 			ts->read_cnt = 0;
480da970e69SImre Deak 			return ADS7846_FILTER_IGNORE;
481d5b415c9SImre Deak 		}
482d5b415c9SImre Deak 	} else {
483d5b415c9SImre Deak 		if (++ts->read_rep > ts->debounce_rep) {
484d5b415c9SImre Deak 			/* Got a good reading for this coordinate,
485d5b415c9SImre Deak 			 * go for the next one. */
4860b7018aaSImre Deak 			ts->read_cnt = 0;
487d5b415c9SImre Deak 			ts->read_rep = 0;
488da970e69SImre Deak 			return ADS7846_FILTER_OK;
489da970e69SImre Deak 		} else {
490d5b415c9SImre Deak 			/* Read more values that are consistent. */
491d5b415c9SImre Deak 			ts->read_cnt++;
492da970e69SImre Deak 			return ADS7846_FILTER_REPEAT;
493da970e69SImre Deak 		}
494da970e69SImre Deak 	}
495da970e69SImre Deak }
496da970e69SImre Deak 
497da970e69SImre Deak static int ads7846_no_filter(void *ads, int data_idx, int *val)
498da970e69SImre Deak {
499da970e69SImre Deak 	return ADS7846_FILTER_OK;
500da970e69SImre Deak }
501da970e69SImre Deak 
502da970e69SImre Deak static void ads7846_rx_val(void *ads)
503da970e69SImre Deak {
504da970e69SImre Deak 	struct ads7846 *ts = ads;
505da970e69SImre Deak 	struct spi_message *m;
506da970e69SImre Deak 	struct spi_transfer *t;
507da970e69SImre Deak 	u16 *rx_val;
508da970e69SImre Deak 	int val;
509da970e69SImre Deak 	int action;
510da970e69SImre Deak 	int status;
511da970e69SImre Deak 
512da970e69SImre Deak 	m = &ts->msg[ts->msg_idx];
513da970e69SImre Deak 	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
514da970e69SImre Deak 	rx_val = t->rx_buf;
515da970e69SImre Deak 
516da970e69SImre Deak 	/* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
517da970e69SImre Deak 	 * built from two 8 bit values written msb-first.
518da970e69SImre Deak 	 */
519da970e69SImre Deak 	val = be16_to_cpu(*rx_val) >> 3;
520da970e69SImre Deak 
521da970e69SImre Deak 	action = ts->filter(ts->filter_data, ts->msg_idx, &val);
522da970e69SImre Deak 	switch (action) {
523da970e69SImre Deak 	case ADS7846_FILTER_REPEAT:
524da970e69SImre Deak 		break;
525da970e69SImre Deak 	case ADS7846_FILTER_IGNORE:
526da970e69SImre Deak 		ts->tc.ignore = 1;
527da970e69SImre Deak 		/* Last message will contain ads7846_rx() as the
528da970e69SImre Deak 		 * completion function.
529da970e69SImre Deak 		 */
530da970e69SImre Deak 		m = ts->last_msg;
531da970e69SImre Deak 		break;
532da970e69SImre Deak 	case ADS7846_FILTER_OK:
533da970e69SImre Deak 		*rx_val = val;
534da970e69SImre Deak 		ts->tc.ignore = 0;
535da970e69SImre Deak 		m = &ts->msg[++ts->msg_idx];
536da970e69SImre Deak 		break;
537da970e69SImre Deak 	default:
538da970e69SImre Deak 		BUG();
539ffa458c1SDavid Brownell 	}
5400b7018aaSImre Deak 	status = spi_async(ts->spi, m);
541ffa458c1SDavid Brownell 	if (status)
542ffa458c1SDavid Brownell 		dev_err(&ts->spi->dev, "spi_async --> %d\n",
543ffa458c1SDavid Brownell 				status);
544ffa458c1SDavid Brownell }
5450b7018aaSImre Deak 
5460b7018aaSImre Deak static void ads7846_timer(unsigned long handle)
5470b7018aaSImre Deak {
5480b7018aaSImre Deak 	struct ads7846	*ts = (void *)handle;
5490b7018aaSImre Deak 	int		status = 0;
5500b7018aaSImre Deak 
551c9e617a5SImre Deak 	spin_lock_irq(&ts->lock);
552c9e617a5SImre Deak 
553c9e617a5SImre Deak 	if (unlikely(ts->msg_idx && !ts->pendown)) {
5549084533eSDavid Brownell 		/* measurement cycle ended */
555c9e617a5SImre Deak 		if (!device_suspended(&ts->spi->dev)) {
556c9e617a5SImre Deak 			ts->irq_disabled = 0;
557c9e617a5SImre Deak 			enable_irq(ts->spi->irq);
558c9e617a5SImre Deak 		}
559c9e617a5SImre Deak 		ts->pending = 0;
560c9e617a5SImre Deak 		ts->msg_idx = 0;
561c9e617a5SImre Deak 	} else {
562c9e617a5SImre Deak 		/* pen is still down, continue with the measurement */
5630b7018aaSImre Deak 		ts->msg_idx = 0;
5640b7018aaSImre Deak 		status = spi_async(ts->spi, &ts->msg[0]);
5650b7018aaSImre Deak 		if (status)
5660b7018aaSImre Deak 			dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
567ffa458c1SDavid Brownell 	}
568ffa458c1SDavid Brownell 
569c9e617a5SImre Deak 	spin_unlock_irq(&ts->lock);
570c9e617a5SImre Deak }
571c9e617a5SImre Deak 
5727d12e780SDavid Howells static irqreturn_t ads7846_irq(int irq, void *handle)
573ffa458c1SDavid Brownell {
5740b7018aaSImre Deak 	struct ads7846 *ts = handle;
5750b7018aaSImre Deak 	unsigned long flags;
5760b7018aaSImre Deak 
5770b7018aaSImre Deak 	spin_lock_irqsave(&ts->lock, flags);
578c9e617a5SImre Deak 	if (likely(ts->get_pendown_state())) {
5790b7018aaSImre Deak 		if (!ts->irq_disabled) {
5809084533eSDavid Brownell 			/* The ARM do_simple_IRQ() dispatcher doesn't act
5819084533eSDavid Brownell 			 * like the other dispatchers:  it will report IRQs
5829084533eSDavid Brownell 			 * even after they've been disabled.  We work around
5839084533eSDavid Brownell 			 * that here.  (The "generic irq" framework may help...)
5840b7018aaSImre Deak 			 */
5850b7018aaSImre Deak 			ts->irq_disabled = 1;
5860b7018aaSImre Deak 			disable_irq(ts->spi->irq);
5870b7018aaSImre Deak 			ts->pending = 1;
5880b7018aaSImre Deak 			mod_timer(&ts->timer, jiffies);
5890b7018aaSImre Deak 		}
5900b7018aaSImre Deak 	}
5910b7018aaSImre Deak 	spin_unlock_irqrestore(&ts->lock, flags);
5927de90a8cSImre Deak 
5937de90a8cSImre Deak 	return IRQ_HANDLED;
594ffa458c1SDavid Brownell }
595ffa458c1SDavid Brownell 
596ffa458c1SDavid Brownell /*--------------------------------------------------------------------------*/
597ffa458c1SDavid Brownell 
5987de90a8cSImre Deak /* Must be called with ts->lock held */
5997de90a8cSImre Deak static void ads7846_disable(struct ads7846 *ts)
600ffa458c1SDavid Brownell {
6017de90a8cSImre Deak 	if (ts->disabled)
6027de90a8cSImre Deak 		return;
603ffa458c1SDavid Brownell 
604c9e617a5SImre Deak 	ts->disabled = 1;
605c9e617a5SImre Deak 
606ffa458c1SDavid Brownell 	/* are we waiting for IRQ, or polling? */
607c9e617a5SImre Deak 	if (!ts->pending) {
608ffa458c1SDavid Brownell 		ts->irq_disabled = 1;
609ffa458c1SDavid Brownell 		disable_irq(ts->spi->irq);
610ffa458c1SDavid Brownell 	} else {
611c9e617a5SImre Deak 		/* the timer will run at least once more, and
612c9e617a5SImre Deak 		 * leave everything in a clean state, IRQ disabled
613ffa458c1SDavid Brownell 		 */
614c9e617a5SImre Deak 		while (ts->pending) {
6157de90a8cSImre Deak 			spin_unlock_irq(&ts->lock);
616c4febb94SJuha Yrjola 			msleep(1);
6177de90a8cSImre Deak 			spin_lock_irq(&ts->lock);
618ffa458c1SDavid Brownell 		}
619ffa458c1SDavid Brownell 	}
620ffa458c1SDavid Brownell 
621ffa458c1SDavid Brownell 	/* we know the chip's in lowpower mode since we always
622ffa458c1SDavid Brownell 	 * leave it that way after every request
623ffa458c1SDavid Brownell 	 */
624ffa458c1SDavid Brownell 
6257de90a8cSImre Deak }
6267de90a8cSImre Deak 
6277de90a8cSImre Deak /* Must be called with ts->lock held */
6287de90a8cSImre Deak static void ads7846_enable(struct ads7846 *ts)
6297de90a8cSImre Deak {
6307de90a8cSImre Deak 	if (!ts->disabled)
6317de90a8cSImre Deak 		return;
6327de90a8cSImre Deak 
6337de90a8cSImre Deak 	ts->disabled = 0;
6347de90a8cSImre Deak 	ts->irq_disabled = 0;
6357de90a8cSImre Deak 	enable_irq(ts->spi->irq);
6367de90a8cSImre Deak }
6377de90a8cSImre Deak 
6387de90a8cSImre Deak static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
6397de90a8cSImre Deak {
6407de90a8cSImre Deak 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
6417de90a8cSImre Deak 
6427de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
6437de90a8cSImre Deak 
6447de90a8cSImre Deak 	spi->dev.power.power_state = message;
6457de90a8cSImre Deak 	ads7846_disable(ts);
6467de90a8cSImre Deak 
6477de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
6487de90a8cSImre Deak 
649ffa458c1SDavid Brownell 	return 0;
6507de90a8cSImre Deak 
651ffa458c1SDavid Brownell }
652ffa458c1SDavid Brownell 
6532e5a7bd9SDavid Brownell static int ads7846_resume(struct spi_device *spi)
654ffa458c1SDavid Brownell {
6552e5a7bd9SDavid Brownell 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
656ffa458c1SDavid Brownell 
6577de90a8cSImre Deak 	spin_lock_irq(&ts->lock);
6587de90a8cSImre Deak 
6592e5a7bd9SDavid Brownell 	spi->dev.power.power_state = PMSG_ON;
6607de90a8cSImre Deak 	ads7846_enable(ts);
6617de90a8cSImre Deak 
6627de90a8cSImre Deak 	spin_unlock_irq(&ts->lock);
6637de90a8cSImre Deak 
664ffa458c1SDavid Brownell 	return 0;
665ffa458c1SDavid Brownell }
666ffa458c1SDavid Brownell 
6672e5a7bd9SDavid Brownell static int __devinit ads7846_probe(struct spi_device *spi)
668ffa458c1SDavid Brownell {
669ffa458c1SDavid Brownell 	struct ads7846			*ts;
670a90f7e98SDmitry Torokhov 	struct input_dev		*input_dev;
6712e5a7bd9SDavid Brownell 	struct ads7846_platform_data	*pdata = spi->dev.platform_data;
6720b7018aaSImre Deak 	struct spi_message		*m;
673ffa458c1SDavid Brownell 	struct spi_transfer		*x;
674*de2defd9SImre Deak 	int				vref;
675a90f7e98SDmitry Torokhov 	int				err;
676ffa458c1SDavid Brownell 
677ffa458c1SDavid Brownell 	if (!spi->irq) {
6782e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "no IRQ?\n");
679ffa458c1SDavid Brownell 		return -ENODEV;
680ffa458c1SDavid Brownell 	}
681ffa458c1SDavid Brownell 
682ffa458c1SDavid Brownell 	if (!pdata) {
6832e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "no platform data?\n");
684ffa458c1SDavid Brownell 		return -ENODEV;
685ffa458c1SDavid Brownell 	}
686ffa458c1SDavid Brownell 
687ffa458c1SDavid Brownell 	/* don't exceed max specified sample rate */
688d93f70b2SDavid Brownell 	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
6892e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
690d93f70b2SDavid Brownell 				(spi->max_speed_hz/SAMPLE_BITS)/1000);
691ffa458c1SDavid Brownell 		return -EINVAL;
692ffa458c1SDavid Brownell 	}
693ffa458c1SDavid Brownell 
6949084533eSDavid Brownell 	/* REVISIT when the irq can be triggered active-low, or if for some
6959084533eSDavid Brownell 	 * reason the touchscreen isn't hooked up, we don't need to access
6969084533eSDavid Brownell 	 * the pendown state.
6979084533eSDavid Brownell 	 */
698c9e617a5SImre Deak 	if (pdata->get_pendown_state == NULL) {
699c9e617a5SImre Deak 		dev_dbg(&spi->dev, "no get_pendown_state function?\n");
700c9e617a5SImre Deak 		return -EINVAL;
701c9e617a5SImre Deak 	}
702c9e617a5SImre Deak 
7039084533eSDavid Brownell 	/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
7049084533eSDavid Brownell 	 * that even if the hardware can do that, the SPI controller driver
7059084533eSDavid Brownell 	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
706ffa458c1SDavid Brownell 	 */
7079084533eSDavid Brownell 	spi->bits_per_word = 8;
708ffa458c1SDavid Brownell 
709a90f7e98SDmitry Torokhov 	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
710a90f7e98SDmitry Torokhov 	input_dev = input_allocate_device();
711a90f7e98SDmitry Torokhov 	if (!ts || !input_dev) {
712a90f7e98SDmitry Torokhov 		err = -ENOMEM;
713a90f7e98SDmitry Torokhov 		goto err_free_mem;
714a90f7e98SDmitry Torokhov 	}
715ffa458c1SDavid Brownell 
7162e5a7bd9SDavid Brownell 	dev_set_drvdata(&spi->dev, ts);
717a90f7e98SDmitry Torokhov 	spi->dev.power.power_state = PMSG_ON;
718ffa458c1SDavid Brownell 
719ffa458c1SDavid Brownell 	ts->spi = spi;
720a90f7e98SDmitry Torokhov 	ts->input = input_dev;
721ffa458c1SDavid Brownell 
722ffa458c1SDavid Brownell 	init_timer(&ts->timer);
723ffa458c1SDavid Brownell 	ts->timer.data = (unsigned long) ts;
724ffa458c1SDavid Brownell 	ts->timer.function = ads7846_timer;
725ffa458c1SDavid Brownell 
7267de90a8cSImre Deak 	spin_lock_init(&ts->lock);
7277de90a8cSImre Deak 
728ffa458c1SDavid Brownell 	ts->model = pdata->model ? : 7846;
729ffa458c1SDavid Brownell 	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
730ffa458c1SDavid Brownell 	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
731d5b415c9SImre Deak 	ts->pressure_max = pdata->pressure_max ? : ~0;
732da970e69SImre Deak 
733da970e69SImre Deak 	if (pdata->filter != NULL) {
734da970e69SImre Deak 		if (pdata->filter_init != NULL) {
735da970e69SImre Deak 			err = pdata->filter_init(pdata, &ts->filter_data);
736da970e69SImre Deak 			if (err < 0)
737da970e69SImre Deak 				goto err_free_mem;
738da970e69SImre Deak 		}
739da970e69SImre Deak 		ts->filter = pdata->filter;
740da970e69SImre Deak 		ts->filter_cleanup = pdata->filter_cleanup;
741da970e69SImre Deak 	} else if (pdata->debounce_max) {
742d5b415c9SImre Deak 		ts->debounce_max = pdata->debounce_max;
743da970e69SImre Deak 		if (ts->debounce_max < 2)
744da970e69SImre Deak 			ts->debounce_max = 2;
745d5b415c9SImre Deak 		ts->debounce_tol = pdata->debounce_tol;
746d5b415c9SImre Deak 		ts->debounce_rep = pdata->debounce_rep;
747da970e69SImre Deak 		ts->filter = ads7846_debounce;
748da970e69SImre Deak 		ts->filter_data = ts;
749d5b415c9SImre Deak 	} else
750da970e69SImre Deak 		ts->filter = ads7846_no_filter;
751c9e617a5SImre Deak 	ts->get_pendown_state = pdata->get_pendown_state;
752ffa458c1SDavid Brownell 
753a90f7e98SDmitry Torokhov 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", spi->dev.bus_id);
754ffa458c1SDavid Brownell 
755a90f7e98SDmitry Torokhov 	input_dev->name = "ADS784x Touchscreen";
756a90f7e98SDmitry Torokhov 	input_dev->phys = ts->phys;
757a90f7e98SDmitry Torokhov 	input_dev->cdev.dev = &spi->dev;
758ffa458c1SDavid Brownell 
759a90f7e98SDmitry Torokhov 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
760a90f7e98SDmitry Torokhov 	input_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
761a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_X,
762ffa458c1SDavid Brownell 			pdata->x_min ? : 0,
763ffa458c1SDavid Brownell 			pdata->x_max ? : MAX_12BIT,
764ffa458c1SDavid Brownell 			0, 0);
765a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_Y,
766ffa458c1SDavid Brownell 			pdata->y_min ? : 0,
767ffa458c1SDavid Brownell 			pdata->y_max ? : MAX_12BIT,
768ffa458c1SDavid Brownell 			0, 0);
769a90f7e98SDmitry Torokhov 	input_set_abs_params(input_dev, ABS_PRESSURE,
770ffa458c1SDavid Brownell 			pdata->pressure_min, pdata->pressure_max, 0, 0);
771ffa458c1SDavid Brownell 
772*de2defd9SImre Deak 	vref = pdata->keep_vref_on;
773*de2defd9SImre Deak 
774ffa458c1SDavid Brownell 	/* set up the transfers to read touchscreen state; this assumes we
775ffa458c1SDavid Brownell 	 * use formula #2 for pressure, not #3.
776ffa458c1SDavid Brownell 	 */
7770b7018aaSImre Deak 	m = &ts->msg[0];
778ffa458c1SDavid Brownell 	x = ts->xfer;
779ffa458c1SDavid Brownell 
7800b7018aaSImre Deak 	spi_message_init(m);
7810b7018aaSImre Deak 
782ffa458c1SDavid Brownell 	/* y- still on; turn on only y+ (and ADC) */
783*de2defd9SImre Deak 	ts->read_y = READ_Y(vref);
784d93f70b2SDavid Brownell 	x->tx_buf = &ts->read_y;
785ffa458c1SDavid Brownell 	x->len = 1;
7860b7018aaSImre Deak 	spi_message_add_tail(x, m);
787d93f70b2SDavid Brownell 
788ffa458c1SDavid Brownell 	x++;
789ffa458c1SDavid Brownell 	x->rx_buf = &ts->tc.y;
790ffa458c1SDavid Brownell 	x->len = 2;
7910b7018aaSImre Deak 	spi_message_add_tail(x, m);
792ffa458c1SDavid Brownell 
793da970e69SImre Deak 	m->complete = ads7846_rx_val;
7940b7018aaSImre Deak 	m->context = ts;
795d93f70b2SDavid Brownell 
7960b7018aaSImre Deak 	m++;
7970b7018aaSImre Deak 	spi_message_init(m);
798ffa458c1SDavid Brownell 
799ffa458c1SDavid Brownell 	/* turn y- off, x+ on, then leave in lowpower */
800d93f70b2SDavid Brownell 	x++;
801*de2defd9SImre Deak 	ts->read_x = READ_X(vref);
802d93f70b2SDavid Brownell 	x->tx_buf = &ts->read_x;
803ffa458c1SDavid Brownell 	x->len = 1;
8040b7018aaSImre Deak 	spi_message_add_tail(x, m);
805d93f70b2SDavid Brownell 
806ffa458c1SDavid Brownell 	x++;
807ffa458c1SDavid Brownell 	x->rx_buf = &ts->tc.x;
808ffa458c1SDavid Brownell 	x->len = 2;
8090b7018aaSImre Deak 	spi_message_add_tail(x, m);
8100b7018aaSImre Deak 
811da970e69SImre Deak 	m->complete = ads7846_rx_val;
8120b7018aaSImre Deak 	m->context = ts;
8130b7018aaSImre Deak 
8140b7018aaSImre Deak 	/* turn y+ off, x- on; we'll use formula #2 */
8150b7018aaSImre Deak 	if (ts->model == 7846) {
8160b7018aaSImre Deak 		m++;
8170b7018aaSImre Deak 		spi_message_init(m);
8180b7018aaSImre Deak 
8190b7018aaSImre Deak 		x++;
820*de2defd9SImre Deak 		ts->read_z1 = READ_Z1(vref);
8210b7018aaSImre Deak 		x->tx_buf = &ts->read_z1;
8220b7018aaSImre Deak 		x->len = 1;
8230b7018aaSImre Deak 		spi_message_add_tail(x, m);
8240b7018aaSImre Deak 
8250b7018aaSImre Deak 		x++;
8260b7018aaSImre Deak 		x->rx_buf = &ts->tc.z1;
8270b7018aaSImre Deak 		x->len = 2;
8280b7018aaSImre Deak 		spi_message_add_tail(x, m);
8290b7018aaSImre Deak 
830da970e69SImre Deak 		m->complete = ads7846_rx_val;
8310b7018aaSImre Deak 		m->context = ts;
8320b7018aaSImre Deak 
8330b7018aaSImre Deak 		m++;
8340b7018aaSImre Deak 		spi_message_init(m);
8350b7018aaSImre Deak 
8360b7018aaSImre Deak 		x++;
837*de2defd9SImre Deak 		ts->read_z2 = READ_Z2(vref);
8380b7018aaSImre Deak 		x->tx_buf = &ts->read_z2;
8390b7018aaSImre Deak 		x->len = 1;
8400b7018aaSImre Deak 		spi_message_add_tail(x, m);
8410b7018aaSImre Deak 
8420b7018aaSImre Deak 		x++;
8430b7018aaSImre Deak 		x->rx_buf = &ts->tc.z2;
8440b7018aaSImre Deak 		x->len = 2;
8450b7018aaSImre Deak 		spi_message_add_tail(x, m);
8460b7018aaSImre Deak 
847da970e69SImre Deak 		m->complete = ads7846_rx_val;
8480b7018aaSImre Deak 		m->context = ts;
8490b7018aaSImre Deak 	}
85053a0ef89SImre Deak 
85153a0ef89SImre Deak 	/* power down */
8520b7018aaSImre Deak 	m++;
8530b7018aaSImre Deak 	spi_message_init(m);
8540b7018aaSImre Deak 
85553a0ef89SImre Deak 	x++;
85653a0ef89SImre Deak 	ts->pwrdown = PWRDOWN;
85753a0ef89SImre Deak 	x->tx_buf = &ts->pwrdown;
85853a0ef89SImre Deak 	x->len = 1;
8590b7018aaSImre Deak 	spi_message_add_tail(x, m);
86053a0ef89SImre Deak 
86153a0ef89SImre Deak 	x++;
86253a0ef89SImre Deak 	x->rx_buf = &ts->dummy;
86353a0ef89SImre Deak 	x->len = 2;
864d93f70b2SDavid Brownell 	CS_CHANGE(*x);
8650b7018aaSImre Deak 	spi_message_add_tail(x, m);
866ffa458c1SDavid Brownell 
8670b7018aaSImre Deak 	m->complete = ads7846_rx;
8680b7018aaSImre Deak 	m->context = ts;
869ffa458c1SDavid Brownell 
870d5b415c9SImre Deak 	ts->last_msg = m;
871d5b415c9SImre Deak 
872dace1453SThomas Gleixner 	if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING,
8739084533eSDavid Brownell 			spi->dev.driver->name, ts)) {
8742e5a7bd9SDavid Brownell 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
875a90f7e98SDmitry Torokhov 		err = -EBUSY;
876da970e69SImre Deak 		goto err_cleanup_filter;
877ffa458c1SDavid Brownell 	}
878ffa458c1SDavid Brownell 
8792e5a7bd9SDavid Brownell 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
880ffa458c1SDavid Brownell 
881ffa458c1SDavid Brownell 	/* take a first sample, leaving nPENIRQ active; avoid
882ffa458c1SDavid Brownell 	 * the touchscreen, in case it's not connected.
883ffa458c1SDavid Brownell 	 */
8842e5a7bd9SDavid Brownell 	(void) ads7846_read12_ser(&spi->dev,
885ffa458c1SDavid Brownell 			  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
886ffa458c1SDavid Brownell 
8878dd51650SDmitry Torokhov 	switch (ts->model) {
8888dd51650SDmitry Torokhov 	case 7846:
8898dd51650SDmitry Torokhov 		ts->attr_group = &ads7846_attr_group;
8908dd51650SDmitry Torokhov 		break;
8918dd51650SDmitry Torokhov 	case 7845:
8928dd51650SDmitry Torokhov 		ts->attr_group = &ads7845_attr_group;
8938dd51650SDmitry Torokhov 		break;
8948dd51650SDmitry Torokhov 	default:
8958dd51650SDmitry Torokhov 		ts->attr_group = &ads7843_attr_group;
8968dd51650SDmitry Torokhov 		break;
897ffa458c1SDavid Brownell 	}
8988dd51650SDmitry Torokhov 	err = sysfs_create_group(&spi->dev.kobj, ts->attr_group);
8998dd51650SDmitry Torokhov 	if (err)
9008dd51650SDmitry Torokhov 		goto err_free_irq;
9017de90a8cSImre Deak 
902a90f7e98SDmitry Torokhov 	err = input_register_device(input_dev);
903a90f7e98SDmitry Torokhov 	if (err)
9048dd51650SDmitry Torokhov 		goto err_remove_attr_group;
905a90f7e98SDmitry Torokhov 
906ffa458c1SDavid Brownell 	return 0;
907a90f7e98SDmitry Torokhov 
9088dd51650SDmitry Torokhov  err_remove_attr_group:
9098dd51650SDmitry Torokhov 	sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
9108dd51650SDmitry Torokhov  err_free_irq:
911a90f7e98SDmitry Torokhov 	free_irq(spi->irq, ts);
912da970e69SImre Deak  err_cleanup_filter:
913da970e69SImre Deak 	if (ts->filter_cleanup)
914da970e69SImre Deak 		ts->filter_cleanup(ts->filter_data);
915a90f7e98SDmitry Torokhov  err_free_mem:
916a90f7e98SDmitry Torokhov 	input_free_device(input_dev);
917a90f7e98SDmitry Torokhov 	kfree(ts);
918a90f7e98SDmitry Torokhov 	return err;
919ffa458c1SDavid Brownell }
920ffa458c1SDavid Brownell 
9212e5a7bd9SDavid Brownell static int __devexit ads7846_remove(struct spi_device *spi)
922ffa458c1SDavid Brownell {
9232e5a7bd9SDavid Brownell 	struct ads7846		*ts = dev_get_drvdata(&spi->dev);
924ffa458c1SDavid Brownell 
9257de90a8cSImre Deak 	input_unregister_device(ts->input);
9267de90a8cSImre Deak 
9272e5a7bd9SDavid Brownell 	ads7846_suspend(spi, PMSG_SUSPEND);
928ffa458c1SDavid Brownell 
9298dd51650SDmitry Torokhov 	sysfs_remove_group(&spi->dev.kobj, ts->attr_group);
930ffa458c1SDavid Brownell 
9317de90a8cSImre Deak 	free_irq(ts->spi->irq, ts);
932c9e617a5SImre Deak 	/* suspend left the IRQ disabled */
9337de90a8cSImre Deak 	enable_irq(ts->spi->irq);
9347de90a8cSImre Deak 
935da970e69SImre Deak 	if (ts->filter_cleanup)
936da970e69SImre Deak 		ts->filter_cleanup(ts->filter_data);
937da970e69SImre Deak 
938ffa458c1SDavid Brownell 	kfree(ts);
939ffa458c1SDavid Brownell 
9402e5a7bd9SDavid Brownell 	dev_dbg(&spi->dev, "unregistered touchscreen\n");
941ffa458c1SDavid Brownell 	return 0;
942ffa458c1SDavid Brownell }
943ffa458c1SDavid Brownell 
9442e5a7bd9SDavid Brownell static struct spi_driver ads7846_driver = {
9452e5a7bd9SDavid Brownell 	.driver = {
946ffa458c1SDavid Brownell 		.name	= "ads7846",
947ffa458c1SDavid Brownell 		.bus	= &spi_bus_type,
9482e5a7bd9SDavid Brownell 		.owner	= THIS_MODULE,
9492e5a7bd9SDavid Brownell 	},
950ffa458c1SDavid Brownell 	.probe		= ads7846_probe,
9512e5a7bd9SDavid Brownell 	.remove		= __devexit_p(ads7846_remove),
952ffa458c1SDavid Brownell 	.suspend	= ads7846_suspend,
953ffa458c1SDavid Brownell 	.resume		= ads7846_resume,
954ffa458c1SDavid Brownell };
955ffa458c1SDavid Brownell 
956ffa458c1SDavid Brownell static int __init ads7846_init(void)
957ffa458c1SDavid Brownell {
958ffa458c1SDavid Brownell 	/* grr, board-specific init should stay out of drivers!! */
959ffa458c1SDavid Brownell 
960ffa458c1SDavid Brownell #ifdef	CONFIG_ARCH_OMAP
961ffa458c1SDavid Brownell 	if (machine_is_omap_osk()) {
962ffa458c1SDavid Brownell 		/* GPIO4 = PENIRQ; GPIO6 = BUSY */
963ffa458c1SDavid Brownell 		omap_request_gpio(4);
964ffa458c1SDavid Brownell 		omap_set_gpio_direction(4, 1);
965ffa458c1SDavid Brownell 		omap_request_gpio(6);
966ffa458c1SDavid Brownell 		omap_set_gpio_direction(6, 1);
967ffa458c1SDavid Brownell 	}
968ffa458c1SDavid Brownell 	// also TI 1510 Innovator, bitbanging through FPGA
969ffa458c1SDavid Brownell 	// also Nokia 770
970ffa458c1SDavid Brownell 	// also Palm Tungsten T2
971ffa458c1SDavid Brownell #endif
972ffa458c1SDavid Brownell 
973ffa458c1SDavid Brownell 	// PXA:
974ffa458c1SDavid Brownell 	// also Dell Axim X50
975ffa458c1SDavid Brownell 	// also HP iPaq H191x/H192x/H415x/H435x
9762e5a7bd9SDavid Brownell 	// also Intel Lubbock (additional to UCB1400; as temperature sensor)
977ffa458c1SDavid Brownell 	// also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky)
978ffa458c1SDavid Brownell 
9792e5a7bd9SDavid Brownell 	// Atmel at91sam9261-EK uses ads7843
9802e5a7bd9SDavid Brownell 
981ffa458c1SDavid Brownell 	// also various AMD Au1x00 devel boards
982ffa458c1SDavid Brownell 
9832e5a7bd9SDavid Brownell 	return spi_register_driver(&ads7846_driver);
984ffa458c1SDavid Brownell }
985ffa458c1SDavid Brownell module_init(ads7846_init);
986ffa458c1SDavid Brownell 
987ffa458c1SDavid Brownell static void __exit ads7846_exit(void)
988ffa458c1SDavid Brownell {
9892e5a7bd9SDavid Brownell 	spi_unregister_driver(&ads7846_driver);
990ffa458c1SDavid Brownell 
991ffa458c1SDavid Brownell #ifdef	CONFIG_ARCH_OMAP
992ffa458c1SDavid Brownell 	if (machine_is_omap_osk()) {
993ffa458c1SDavid Brownell 		omap_free_gpio(4);
994ffa458c1SDavid Brownell 		omap_free_gpio(6);
995ffa458c1SDavid Brownell 	}
996ffa458c1SDavid Brownell #endif
997ffa458c1SDavid Brownell 
998ffa458c1SDavid Brownell }
999ffa458c1SDavid Brownell module_exit(ads7846_exit);
1000ffa458c1SDavid Brownell 
1001ffa458c1SDavid Brownell MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
1002ffa458c1SDavid Brownell MODULE_LICENSE("GPL");
1003