1b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich/*
24397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * AD7879/AD7889 based touchscreen and GPIO driver
3b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *
44397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * Copyright (C) 2008-2010 Michael Hennerich, Analog Devices Inc.
5b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *
64397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger * Licensed under the GPL-2 or later.
7b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *
8b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich * History:
9b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich * Copyright (c) 2005 David Brownell
10b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich * Copyright (c) 2006 Nokia Corporation
11b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich * Various changes: Imre Deak <imre.deak@nokia.com>
12b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *
13b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich * Using code from:
14b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *  - corgi_ts.c
15b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *	Copyright (C) 2004-2005 Richard Purdie
16b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *  - omap_ts.[hc], ads7846.h, ts_osk.c
17b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *	Copyright (C) 2002 MontaVista Software
18b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *	Copyright (C) 2004 Texas Instruments
19b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *	Copyright (C) 2005 Dirk Behme
20b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *  - ad7877.c
21b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich *	Copyright (C) 2006-2008 Analog Devices Inc.
22b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich */
23b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
24b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/device.h>
25b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/init.h>
26b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/delay.h>
27b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/input.h>
28b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/interrupt.h>
29b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/irq.h>
30b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/slab.h>
31b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/spi/spi.h>
32b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/i2c.h>
33ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#include <linux/gpio.h>
34b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
35b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#include <linux/spi/ad7879.h>
36d2d8442d0094a7d4b585e2bbde31e3775dba7eb1Paul Gortmaker#include <linux/module.h>
374397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger#include "ad7879.h"
38b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
39b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_ZEROS		0
40b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_CTRL1		1
41b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_CTRL2		2
42b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_CTRL3		3
43b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_AUX1HIGH		4
44b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_AUX1LOW		5
45b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_TEMP1HIGH		6
46b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_TEMP1LOW		7
47b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_XPLUS		8
48b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_YPLUS		9
49b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_Z1			10
50b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_Z2			11
51b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_AUXVBAT		12
52b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_TEMP			13
53b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_REG_REVID		14
54b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
55b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich/* Control REG 1 */
56b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_TMR(x)			((x & 0xFF) << 0)
57b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_ACQ(x)			((x & 0x3) << 8)
58b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MODE_NOC			(0 << 10)	/* Do not convert */
59b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MODE_SCC			(1 << 10)	/* Single channel conversion */
60b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MODE_SEQ0		(2 << 10)	/* Sequence 0 in Slave Mode */
61b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MODE_SEQ1		(3 << 10)	/* Sequence 1 in Master Mode */
62b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MODE_INT			(1 << 15)	/* PENIRQ disabled INT enabled */
63b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
64b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich/* Control REG 2 */
65b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_FCD(x)			((x & 0x3) << 0)
66b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_RESET			(1 << 4)
67b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_MFS(x)			((x & 0x3) << 5)
68b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_AVG(x)			((x & 0x3) << 7)
69b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define	AD7879_SER			(1 << 9)	/* non-differential */
70b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define	AD7879_DFR			(0 << 9)	/* differential */
71b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_GPIOPOL			(1 << 10)
72b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_GPIODIR			(1 << 11)
73b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_GPIO_DATA		(1 << 12)
74b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_GPIO_EN			(1 << 13)
75b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_PM(x)			((x & 0x3) << 14)
76b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_PM_SHUTDOWN		(0)
77b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_PM_DYN			(1)
78b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_PM_FULLON		(2)
79b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
80b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich/* Control REG 3 */
81b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_TEMPMASK_BIT		(1<<15)
82b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_AUXVBATMASK_BIT		(1<<14)
83b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_INTMODE_BIT		(1<<13)
84b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_GPIOALERTMASK_BIT	(1<<12)
85b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_AUXLOW_BIT		(1<<11)
86b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_AUXHIGH_BIT		(1<<10)
87b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_TEMPLOW_BIT		(1<<9)
88b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_TEMPHIGH_BIT		(1<<8)
89b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_YPLUS_BIT		(1<<7)
90b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_XPLUS_BIT		(1<<6)
91b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_Z1_BIT			(1<<5)
92b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_Z2_BIT			(1<<4)
93b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_AUX_BIT			(1<<3)
94b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_VBAT_BIT			(1<<2)
95b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define AD7879_TEMP_BIT			(1<<1)
96b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
97b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichenum {
98b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	AD7879_SEQ_XPOS  = 0,
99b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	AD7879_SEQ_YPOS  = 1,
100b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	AD7879_SEQ_Z1    = 2,
101b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	AD7879_SEQ_Z2    = 3,
102b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	AD7879_NR_SENSE  = 4,
103b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich};
104b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
105b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define	MAX_12BIT			((1<<12)-1)
106b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich#define	TS_PEN_UP_TIMEOUT		msecs_to_jiffies(50)
107b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
108b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstruct ad7879 {
1094397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	const struct ad7879_bus_ops *bops;
1104397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
1114397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct device		*dev;
112b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct input_dev	*input;
113b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct timer_list	timer;
114ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#ifdef CONFIG_GPIOLIB
115ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	struct gpio_chip	gc;
11614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	struct mutex		mutex;
117ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#endif
1184397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	unsigned int		irq;
11914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	bool			disabled;	/* P: input->mutex */
12014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	bool			suspended;	/* P: input->mutex */
121b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			conversion_data[AD7879_NR_SENSE];
122b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	char			phys[32];
123b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u8			first_conversion_delay;
124b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u8			acquisition_time;
125b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u8			averaging;
126b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u8			pen_down_acc_interval;
127b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u8			median;
128b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			x_plate_ohms;
129b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			pressure_max;
130b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			cmd_crtl1;
131b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			cmd_crtl2;
132b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16			cmd_crtl3;
133b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich	int			x;
134b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich	int			y;
135b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich	int			Rt;
136b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich};
137b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
1384397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_read(struct ad7879 *ts, u8 reg)
1394397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
1404397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return ts->bops->read(ts->dev, reg);
1414397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
1424397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
1434397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_multi_read(struct ad7879 *ts, u8 first_reg, u8 count, u16 *buf)
1444397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
1454397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return ts->bops->multi_read(ts->dev, first_reg, count, buf);
1464397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
1474397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
1484397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_write(struct ad7879 *ts, u8 reg, u16 val)
1494397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger{
1504397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return ts->bops->write(ts->dev, reg, val);
1514397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger}
152b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
153963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerichstatic int ad7879_report(struct ad7879 *ts)
154b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
155b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct input_dev *input_dev = ts->input;
156b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	unsigned Rt;
157b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16 x, y, z1, z2;
158b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
159b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	x = ts->conversion_data[AD7879_SEQ_XPOS] & MAX_12BIT;
160b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	y = ts->conversion_data[AD7879_SEQ_YPOS] & MAX_12BIT;
161b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT;
162b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT;
163b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
164b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	/*
165b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	 * The samples processed here are already preprocessed by the AD7879.
1664397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * The preprocessing function consists of a median and an averaging
1674397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * filter.  The combination of these two techniques provides a robust
1684397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * solution, discarding the spurious noise in the signal and keeping
1694397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * only the data of interest.  The size of both filters is
1704397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * programmable. (dev.platform_data, see linux/spi/ad7879.h) Other
1714397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * user-programmable conversion controls include variable acquisition
1724397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * time, and first conversion delay. Up to 16 averages can be taken
1734397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	 * per conversion.
174b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	 */
175b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
176b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (likely(x && z1)) {
177b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		/* compute touch pressure resistance using equation #1 */
178b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		Rt = (z2 - z1) * x * ts->x_plate_ohms;
179b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		Rt /= z1;
180b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		Rt = (Rt + 2047) >> 12;
181b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
182b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		/*
183b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * Sample found inconsistent, pressure is beyond
184b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * the maximum. Don't report it to user space.
185b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 */
186b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		if (Rt > ts->pressure_max)
187b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			return -EINVAL;
188b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich
189b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		/*
190b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * Note that we delay reporting events by one sample.
191b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * This is done to avoid reporting last sample of the
192b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * touch sequence, which may be incomplete if finger
193b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 * leaves the surface before last reading is taken.
194b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		 */
195b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		if (timer_pending(&ts->timer)) {
196b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			/* Touch continues */
197963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich			input_report_key(input_dev, BTN_TOUCH, 1);
198b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			input_report_abs(input_dev, ABS_X, ts->x);
199b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			input_report_abs(input_dev, ABS_Y, ts->y);
200b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			input_report_abs(input_dev, ABS_PRESSURE, ts->Rt);
201b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich			input_sync(input_dev);
202b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		}
203b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich
204b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		ts->x = x;
205b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		ts->y = y;
206b584efc9ea7575d3235cfd745e8a28201d2c37f6Michael Hennerich		ts->Rt = Rt;
207963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich
208963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich		return 0;
209b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
210963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich
211963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich	return -EINVAL;
212b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
213b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
214b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic void ad7879_ts_event_release(struct ad7879 *ts)
215b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
216b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct input_dev *input_dev = ts->input;
217b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
218b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_report_abs(input_dev, ABS_PRESSURE, 0);
219963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich	input_report_key(input_dev, BTN_TOUCH, 0);
220b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_sync(input_dev);
221b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
222b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
223b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic void ad7879_timer(unsigned long handle)
224b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
225b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct ad7879 *ts = (void *)handle;
226b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
227b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ad7879_ts_event_release(ts);
228b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
229b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
230b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic irqreturn_t ad7879_irq(int irq, void *handle)
231b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
232b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct ad7879 *ts = handle;
233b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
2344397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_multi_read(ts, AD7879_REG_XPLUS, AD7879_NR_SENSE, ts->conversion_data);
235b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
236963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich	if (!ad7879_report(ts))
237963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich		mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
238b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
239b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	return IRQ_HANDLED;
240b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
241b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
24214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhovstatic void __ad7879_enable(struct ad7879 *ts)
243b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
2444397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
2454397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3);
2464397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1);
24714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
24814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	enable_irq(ts->irq);
249b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
250b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
25114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhovstatic void __ad7879_disable(struct ad7879 *ts)
252b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
2534fecc2088fd02ce8a6580c12822987d3c6bab9b8Michael Hennerich	u16 reg = (ts->cmd_crtl2 & ~AD7879_PM(-1)) |
2544fecc2088fd02ce8a6580c12822987d3c6bab9b8Michael Hennerich		AD7879_PM(AD7879_PM_SHUTDOWN);
25514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	disable_irq(ts->irq);
256b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
25714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (del_timer_sync(&ts->timer))
25814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		ad7879_ts_event_release(ts);
259b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
2604fecc2088fd02ce8a6580c12822987d3c6bab9b8Michael Hennerich	ad7879_write(ts, AD7879_REG_CTRL2, reg);
26114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov}
262b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
263b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
26414fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhovstatic int ad7879_open(struct input_dev *input)
26514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov{
26614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	struct ad7879 *ts = input_get_drvdata(input);
267b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
26814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	/* protected by input->mutex */
26914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (!ts->disabled && !ts->suspended)
27014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		__ad7879_enable(ts);
27114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
27214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	return 0;
273b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
274b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
27514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhovstatic void ad7879_close(struct input_dev* input)
276b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
27714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	struct ad7879 *ts = input_get_drvdata(input);
27814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
27914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	/* protected by input->mutex */
28014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (!ts->disabled && !ts->suspended)
28114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		__ad7879_disable(ts);
28214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov}
28314fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
2848672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov#ifdef CONFIG_PM_SLEEP
2858672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhovstatic int ad7879_suspend(struct device *dev)
28614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov{
2878672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov	struct ad7879 *ts = dev_get_drvdata(dev);
2888672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov
28914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_lock(&ts->input->mutex);
29014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
29114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (!ts->suspended && !ts->disabled && ts->input->users)
29214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		__ad7879_disable(ts);
29314fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
29414fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	ts->suspended = true;
29514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
29614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_unlock(&ts->input->mutex);
2978672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov
2988672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov	return 0;
29914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov}
30014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
3018672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhovstatic int ad7879_resume(struct device *dev)
30214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov{
3038672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov	struct ad7879 *ts = dev_get_drvdata(dev);
3048672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov
30514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_lock(&ts->input->mutex);
306b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
30714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (ts->suspended && !ts->disabled && ts->input->users)
30814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		__ad7879_enable(ts);
30914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
31014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	ts->suspended = false;
31114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
31214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_unlock(&ts->input->mutex);
3138672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov
3148672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov	return 0;
31514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov}
3168672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov#endif
3178672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry Torokhov
3188672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry TorokhovSIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume);
3198672bd93d3d67b18a2b067ece30dabcda11f8cdeDmitry TorokhovEXPORT_SYMBOL(ad7879_pm_ops);
32014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
32114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhovstatic void ad7879_toggle(struct ad7879 *ts, bool disable)
32214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov{
32314fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_lock(&ts->input->mutex);
32414fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
32514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	if (!ts->suspended && ts->input->users != 0) {
32614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
32714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		if (disable) {
32814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov			if (ts->disabled)
32914fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov				__ad7879_enable(ts);
33014fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		} else {
33114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov			if (!ts->disabled)
33214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov				__ad7879_disable(ts);
33314fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov		}
334b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
335b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
33614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	ts->disabled = disable;
33714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
33814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_unlock(&ts->input->mutex);
339b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
340b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
341b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic ssize_t ad7879_disable_show(struct device *dev,
342b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich				     struct device_attribute *attr, char *buf)
343b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
344b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct ad7879 *ts = dev_get_drvdata(dev);
345b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
346b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	return sprintf(buf, "%u\n", ts->disabled);
347b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
348b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
349b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic ssize_t ad7879_disable_store(struct device *dev,
350b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich				     struct device_attribute *attr,
351b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich				     const char *buf, size_t count)
352b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
353b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct ad7879 *ts = dev_get_drvdata(dev);
35476496e7a02e99d42844f4fffa145b81e513e7acdJJ Ding	unsigned int val;
355b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	int error;
356b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
35776496e7a02e99d42844f4fffa145b81e513e7acdJJ Ding	error = kstrtouint(buf, 10, &val);
358b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (error)
359b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		return error;
360b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
36114fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	ad7879_toggle(ts, val);
362b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
363b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	return count;
364b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
365b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
366b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerichstatic DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store);
367b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
368ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic struct attribute *ad7879_attributes[] = {
369ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	&dev_attr_disable.attr,
370ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	NULL
371ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich};
372ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
373ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic const struct attribute_group ad7879_attr_group = {
374ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	.attrs = ad7879_attributes,
375ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich};
376ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
377ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#ifdef CONFIG_GPIOLIB
378ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic int ad7879_gpio_direction_input(struct gpio_chip *chip,
379ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich					unsigned gpio)
380b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
381ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	struct ad7879 *ts = container_of(chip, struct ad7879, gc);
382ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	int err;
383b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
384ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_lock(&ts->mutex);
385ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL;
3864397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
387ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_unlock(&ts->mutex);
388ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
389ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	return err;
390b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
391b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
392ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic int ad7879_gpio_direction_output(struct gpio_chip *chip,
393ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich					unsigned gpio, int level)
394b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
395ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	struct ad7879 *ts = container_of(chip, struct ad7879, gc);
396ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	int err;
397b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
398ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_lock(&ts->mutex);
399ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl2 &= ~AD7879_GPIODIR;
400ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIOPOL;
401ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	if (level)
402ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->cmd_crtl2 |= AD7879_GPIO_DATA;
403ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	else
404ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
405ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
4064397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
407ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_unlock(&ts->mutex);
408ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
409ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	return err;
410ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
411ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
412ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
413ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
414ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	struct ad7879 *ts = container_of(chip, struct ad7879, gc);
415ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	u16 val;
416b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
417b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	mutex_lock(&ts->mutex);
4184397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	val = ad7879_read(ts, AD7879_REG_CTRL2);
419b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	mutex_unlock(&ts->mutex);
420b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
421ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	return !!(val & AD7879_GPIO_DATA);
422b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
423b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
424ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerichstatic void ad7879_gpio_set_value(struct gpio_chip *chip,
425ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich				  unsigned gpio, int value)
426ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
427ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	struct ad7879 *ts = container_of(chip, struct ad7879, gc);
428b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
429ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_lock(&ts->mutex);
430ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	if (value)
431ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->cmd_crtl2 |= AD7879_GPIO_DATA;
432ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	else
433ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
434b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
4354397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
436ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	mutex_unlock(&ts->mutex);
437ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
438ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
4394397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic int ad7879_gpio_add(struct ad7879 *ts,
4404397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			   const struct ad7879_platform_data *pdata)
441ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
442ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	int ret = 0;
443ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
44414fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	mutex_init(&ts->mutex);
44514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
446ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	if (pdata->gpio_export) {
447ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.direction_input = ad7879_gpio_direction_input;
448ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.direction_output = ad7879_gpio_direction_output;
449ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.get = ad7879_gpio_get_value;
450ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.set = ad7879_gpio_set_value;
451ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.can_sleep = 1;
452ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.base = pdata->gpio_base;
453ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.ngpio = 1;
454ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.label = "AD7879-GPIO";
455ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ts->gc.owner = THIS_MODULE;
4564397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		ts->gc.dev = ts->dev;
457ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
458ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ret = gpiochip_add(&ts->gc);
459ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		if (ret)
4604397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			dev_err(ts->dev, "failed to register gpio %d\n",
461ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich				ts->gc.base);
462ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	}
463ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
464ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	return ret;
465ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
466ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
4674397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic void ad7879_gpio_remove(struct ad7879 *ts)
468ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
4694397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	const struct ad7879_platform_data *pdata = ts->dev->platform_data;
470ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	int ret;
471ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
472ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	if (pdata->gpio_export) {
473ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		ret = gpiochip_remove(&ts->gc);
474ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		if (ret)
4754397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			dev_err(ts->dev, "failed to remove gpio %d\n",
476ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich				ts->gc.base);
477ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	}
478ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
479ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#else
4804397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic inline int ad7879_gpio_add(struct ad7879 *ts,
4814397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger				  const struct ad7879_platform_data *pdata)
482ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
483ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	return 0;
484ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
485ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
4864397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstatic inline void ad7879_gpio_remove(struct ad7879 *ts)
487ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich{
488ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich}
489ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich#endif
490b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
4914397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingerstruct ad7879 *ad7879_probe(struct device *dev, u8 devid, unsigned int irq,
4924397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			    const struct ad7879_bus_ops *bops)
493b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
4944397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct ad7879_platform_data *pdata = dev->platform_data;
4954397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	struct ad7879 *ts;
496b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	struct input_dev *input_dev;
497b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	int err;
498b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	u16 revid;
499b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5004397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	if (!irq) {
5014397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(dev, "no IRQ?\n");
5024397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		err = -EINVAL;
5034397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		goto err_out;
504b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
505b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
506b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (!pdata) {
5074397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(dev, "no platform data?\n");
5084397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		err = -EINVAL;
5094397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		goto err_out;
510b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
511b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5124397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
513b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_dev = input_allocate_device();
5144397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	if (!ts || !input_dev) {
5154397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		err = -ENOMEM;
5164397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		goto err_free_mem;
5174397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	}
518b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5194397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ts->bops = bops;
5204397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ts->dev = dev;
521b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->input = input_dev;
52214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	ts->irq = irq;
523b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
524b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	setup_timer(&ts->timer, ad7879_timer, (unsigned long) ts);
5254397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger
526b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
527b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->pressure_max = pdata->pressure_max ? : ~0;
528b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
529b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->first_conversion_delay = pdata->first_conversion_delay;
530b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->acquisition_time = pdata->acquisition_time;
531b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->averaging = pdata->averaging;
532b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->pen_down_acc_interval = pdata->pen_down_acc_interval;
533b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	ts->median = pdata->median;
534b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5354397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
536b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
537b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_dev->name = "AD7879 Touchscreen";
538b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_dev->phys = ts->phys;
5394397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	input_dev->dev.parent = dev;
5404397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	input_dev->id.bustype = bops->bustype;
541b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
54214fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	input_dev->open = ad7879_open;
54314fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	input_dev->close = ad7879_close;
54414fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
54514fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	input_set_drvdata(input_dev, ts);
54614fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
547b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	__set_bit(EV_ABS, input_dev->evbit);
548b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	__set_bit(ABS_X, input_dev->absbit);
549b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	__set_bit(ABS_Y, input_dev->absbit);
550b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	__set_bit(ABS_PRESSURE, input_dev->absbit);
551b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
552963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich	__set_bit(EV_KEY, input_dev->evbit);
553963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich	__set_bit(BTN_TOUCH, input_dev->keybit);
554963ce8ae6dbc7c8dffb1b117ba14673d40b22ddaMichael Hennerich
555b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_set_abs_params(input_dev, ABS_X,
556b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			pdata->x_min ? : 0,
557b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			pdata->x_max ? : MAX_12BIT,
558b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			0, 0);
559b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_set_abs_params(input_dev, ABS_Y,
560b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			pdata->y_min ? : 0,
561b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			pdata->y_max ? : MAX_12BIT,
562b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			0, 0);
563b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_set_abs_params(input_dev, ABS_PRESSURE,
564b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich			pdata->pressure_min, pdata->pressure_max, 0, 0);
565b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5664397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET);
567b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (err < 0) {
5684397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(dev, "Failed to write %s\n", input_dev->name);
569b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		goto err_free_mem;
570b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
571b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
5724397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	revid = ad7879_read(ts, AD7879_REG_REVID);
5734397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	input_dev->id.product = (revid & 0xff);
5744397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	input_dev->id.version = revid >> 8;
5754397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	if (input_dev->id.product != devid) {
5764397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(dev, "Failed to probe %s (%x vs %x)\n",
5774397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger			input_dev->name, devid, revid);
578b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		err = -ENODEV;
579b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		goto err_free_mem;
580b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
581b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
582ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl3 = AD7879_YPLUS_BIT |
583ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_XPLUS_BIT |
584ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_Z2_BIT |
585ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_Z1_BIT |
586ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_TEMPMASK_BIT |
587ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_AUXVBATMASK_BIT |
588ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_GPIOALERTMASK_BIT;
589ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
590ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR |
591ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_AVG(ts->averaging) |
592ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_MFS(ts->median) |
593ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_FCD(ts->first_conversion_delay);
594ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
595ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 |
596ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_ACQ(ts->acquisition_time) |
597ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich			AD7879_TMR(ts->pen_down_acc_interval);
598ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
5994397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = request_threaded_irq(ts->irq, NULL, ad7879_irq,
6007cd7a82d16ad5a711338c1baf2316f24121d93aaDmitry Torokhov				   IRQF_TRIGGER_FALLING,
6014397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger				   dev_name(dev), ts);
602b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (err) {
6034397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger		dev_err(dev, "irq %d busy?\n", ts->irq);
604b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		goto err_free_mem;
605b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	}
606b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
60714fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov	__ad7879_disable(ts);
60814fbbc36d126d7ec7717144def386b9fc4c7fba2Dmitry Torokhov
6094397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = sysfs_create_group(&dev->kobj, &ad7879_attr_group);
610b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (err)
611b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		goto err_free_irq;
612b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
6134397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	err = ad7879_gpio_add(ts, pdata);
614b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	if (err)
615b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich		goto err_remove_attr;
616b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
617ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	err = input_register_device(input_dev);
618ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich	if (err)
619ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich		goto err_remove_gpio;
620ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennerich
6214397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return ts;
622b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
623ec51b7f538c440bfa5a4d538133c659071c02155Michael Hennericherr_remove_gpio:
6244397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_gpio_remove(ts);
625b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennericherr_remove_attr:
6264397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	sysfs_remove_group(&dev->kobj, &ad7879_attr_group);
627b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennericherr_free_irq:
6284397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	free_irq(ts->irq, ts);
629b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennericherr_free_mem:
630b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_free_device(input_dev);
6314397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	kfree(ts);
6324397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingererr_out:
6334397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	return ERR_PTR(err);
634b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
6354397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerEXPORT_SYMBOL(ad7879_probe);
636b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
6374397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysingervoid ad7879_remove(struct ad7879 *ts)
638b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich{
6394397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	ad7879_gpio_remove(ts);
6404397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	sysfs_remove_group(&ts->dev->kobj, &ad7879_attr_group);
6414397c98a8a60ba029f2d0051d0cbafe600f05d8cMike Frysinger	free_irq(ts->irq, ts);
642b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	input_unregister_device(ts->input);
643b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich	kfree(ts);
644b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich}
6454397c98a8a60ba029f2d0051d0cbafe600f05d8cMike FrysingerEXPORT_SYMBOL(ad7879_remove);
646b4be468cc1e65110d9144751bf7079dad6f142b7Michael Hennerich
647b4be468cc1e65110d9144751bf7079dad6f142b7Michael HennerichMODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
648b4be468cc1e65110d9144751bf7079dad6f142b7Michael HennerichMODULE_DESCRIPTION("AD7879(-1) touchscreen Driver");
649b4be468cc1e65110d9144751bf7079dad6f142b7Michael HennerichMODULE_LICENSE("GPL");
650