180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2b4be468cSMichael Hennerich /*
34397c98aSMike Frysinger  * AD7879/AD7889 based touchscreen and GPIO driver
4b4be468cSMichael Hennerich  *
54397c98aSMike Frysinger  * Copyright (C) 2008-2010 Michael Hennerich, Analog Devices Inc.
6b4be468cSMichael Hennerich  *
7b4be468cSMichael Hennerich  * History:
8b4be468cSMichael Hennerich  * Copyright (c) 2005 David Brownell
9b4be468cSMichael Hennerich  * Copyright (c) 2006 Nokia Corporation
10b4be468cSMichael Hennerich  * Various changes: Imre Deak <imre.deak@nokia.com>
11b4be468cSMichael Hennerich  *
12b4be468cSMichael Hennerich  * Using code from:
13b4be468cSMichael Hennerich  *  - corgi_ts.c
14b4be468cSMichael Hennerich  *	Copyright (C) 2004-2005 Richard Purdie
15b4be468cSMichael Hennerich  *  - omap_ts.[hc], ads7846.h, ts_osk.c
16b4be468cSMichael Hennerich  *	Copyright (C) 2002 MontaVista Software
17b4be468cSMichael Hennerich  *	Copyright (C) 2004 Texas Instruments
18b4be468cSMichael Hennerich  *	Copyright (C) 2005 Dirk Behme
19b4be468cSMichael Hennerich  *  - ad7877.c
20b4be468cSMichael Hennerich  *	Copyright (C) 2006-2008 Analog Devices Inc.
21b4be468cSMichael Hennerich  */
22b4be468cSMichael Hennerich 
23b4be468cSMichael Hennerich #include <linux/device.h>
24b4be468cSMichael Hennerich #include <linux/delay.h>
25b4be468cSMichael Hennerich #include <linux/input.h>
26b4be468cSMichael Hennerich #include <linux/interrupt.h>
27b4be468cSMichael Hennerich #include <linux/irq.h>
28a4deb147SRandy Dunlap #include <linux/property.h>
29404a24c3SDmitry Torokhov #include <linux/regmap.h>
30b4be468cSMichael Hennerich #include <linux/slab.h>
311be7aa9bSLinus Walleij #include <linux/gpio/driver.h>
32b4be468cSMichael Hennerich 
33fa6e3ca2SStefan Agner #include <linux/input/touchscreen.h>
34d2d8442dSPaul Gortmaker #include <linux/module.h>
354397c98aSMike Frysinger #include "ad7879.h"
36b4be468cSMichael Hennerich 
37b4be468cSMichael Hennerich #define AD7879_REG_ZEROS		0
38b4be468cSMichael Hennerich #define AD7879_REG_CTRL1		1
39b4be468cSMichael Hennerich #define AD7879_REG_CTRL2		2
40b4be468cSMichael Hennerich #define AD7879_REG_CTRL3		3
41b4be468cSMichael Hennerich #define AD7879_REG_AUX1HIGH		4
42b4be468cSMichael Hennerich #define AD7879_REG_AUX1LOW		5
43b4be468cSMichael Hennerich #define AD7879_REG_TEMP1HIGH		6
44b4be468cSMichael Hennerich #define AD7879_REG_TEMP1LOW		7
45b4be468cSMichael Hennerich #define AD7879_REG_XPLUS		8
46b4be468cSMichael Hennerich #define AD7879_REG_YPLUS		9
47b4be468cSMichael Hennerich #define AD7879_REG_Z1			10
48b4be468cSMichael Hennerich #define AD7879_REG_Z2			11
49b4be468cSMichael Hennerich #define AD7879_REG_AUXVBAT		12
50b4be468cSMichael Hennerich #define AD7879_REG_TEMP			13
51b4be468cSMichael Hennerich #define AD7879_REG_REVID		14
52b4be468cSMichael Hennerich 
53b4be468cSMichael Hennerich /* Control REG 1 */
54b4be468cSMichael Hennerich #define AD7879_TMR(x)			((x & 0xFF) << 0)
55b4be468cSMichael Hennerich #define AD7879_ACQ(x)			((x & 0x3) << 8)
56b4be468cSMichael Hennerich #define AD7879_MODE_NOC			(0 << 10)	/* Do not convert */
57b4be468cSMichael Hennerich #define AD7879_MODE_SCC			(1 << 10)	/* Single channel conversion */
58b4be468cSMichael Hennerich #define AD7879_MODE_SEQ0		(2 << 10)	/* Sequence 0 in Slave Mode */
59b4be468cSMichael Hennerich #define AD7879_MODE_SEQ1		(3 << 10)	/* Sequence 1 in Master Mode */
60b4be468cSMichael Hennerich #define AD7879_MODE_INT			(1 << 15)	/* PENIRQ disabled INT enabled */
61b4be468cSMichael Hennerich 
62b4be468cSMichael Hennerich /* Control REG 2 */
63b4be468cSMichael Hennerich #define AD7879_FCD(x)			((x & 0x3) << 0)
64b4be468cSMichael Hennerich #define AD7879_RESET			(1 << 4)
65b4be468cSMichael Hennerich #define AD7879_MFS(x)			((x & 0x3) << 5)
66b4be468cSMichael Hennerich #define AD7879_AVG(x)			((x & 0x3) << 7)
67b4be468cSMichael Hennerich #define	AD7879_SER			(1 << 9)	/* non-differential */
68b4be468cSMichael Hennerich #define	AD7879_DFR			(0 << 9)	/* differential */
69b4be468cSMichael Hennerich #define AD7879_GPIOPOL			(1 << 10)
70b4be468cSMichael Hennerich #define AD7879_GPIODIR			(1 << 11)
71b4be468cSMichael Hennerich #define AD7879_GPIO_DATA		(1 << 12)
72b4be468cSMichael Hennerich #define AD7879_GPIO_EN			(1 << 13)
73b4be468cSMichael Hennerich #define AD7879_PM(x)			((x & 0x3) << 14)
74b4be468cSMichael Hennerich #define AD7879_PM_SHUTDOWN		(0)
75b4be468cSMichael Hennerich #define AD7879_PM_DYN			(1)
76b4be468cSMichael Hennerich #define AD7879_PM_FULLON		(2)
77b4be468cSMichael Hennerich 
78b4be468cSMichael Hennerich /* Control REG 3 */
79b4be468cSMichael Hennerich #define AD7879_TEMPMASK_BIT		(1<<15)
80b4be468cSMichael Hennerich #define AD7879_AUXVBATMASK_BIT		(1<<14)
81b4be468cSMichael Hennerich #define AD7879_INTMODE_BIT		(1<<13)
82b4be468cSMichael Hennerich #define AD7879_GPIOALERTMASK_BIT	(1<<12)
83b4be468cSMichael Hennerich #define AD7879_AUXLOW_BIT		(1<<11)
84b4be468cSMichael Hennerich #define AD7879_AUXHIGH_BIT		(1<<10)
85b4be468cSMichael Hennerich #define AD7879_TEMPLOW_BIT		(1<<9)
86b4be468cSMichael Hennerich #define AD7879_TEMPHIGH_BIT		(1<<8)
87b4be468cSMichael Hennerich #define AD7879_YPLUS_BIT		(1<<7)
88b4be468cSMichael Hennerich #define AD7879_XPLUS_BIT		(1<<6)
89b4be468cSMichael Hennerich #define AD7879_Z1_BIT			(1<<5)
90b4be468cSMichael Hennerich #define AD7879_Z2_BIT			(1<<4)
91b4be468cSMichael Hennerich #define AD7879_AUX_BIT			(1<<3)
92b4be468cSMichael Hennerich #define AD7879_VBAT_BIT			(1<<2)
93b4be468cSMichael Hennerich #define AD7879_TEMP_BIT			(1<<1)
94b4be468cSMichael Hennerich 
95b4be468cSMichael Hennerich enum {
965f2940c4SStefan Agner 	AD7879_SEQ_YPOS  = 0,
975f2940c4SStefan Agner 	AD7879_SEQ_XPOS  = 1,
98b4be468cSMichael Hennerich 	AD7879_SEQ_Z1    = 2,
99b4be468cSMichael Hennerich 	AD7879_SEQ_Z2    = 3,
100b4be468cSMichael Hennerich 	AD7879_NR_SENSE  = 4,
101b4be468cSMichael Hennerich };
102b4be468cSMichael Hennerich 
103b4be468cSMichael Hennerich #define	MAX_12BIT			((1<<12)-1)
104b4be468cSMichael Hennerich #define	TS_PEN_UP_TIMEOUT		msecs_to_jiffies(50)
105b4be468cSMichael Hennerich 
106b4be468cSMichael Hennerich struct ad7879 {
107404a24c3SDmitry Torokhov 	struct regmap		*regmap;
1084397c98aSMike Frysinger 	struct device		*dev;
109b4be468cSMichael Hennerich 	struct input_dev	*input;
110b4be468cSMichael Hennerich 	struct timer_list	timer;
111ec51b7f5SMichael Hennerich #ifdef CONFIG_GPIOLIB
112ec51b7f5SMichael Hennerich 	struct gpio_chip	gc;
11314fbbc36SDmitry Torokhov 	struct mutex		mutex;
114ec51b7f5SMichael Hennerich #endif
1154397c98aSMike Frysinger 	unsigned int		irq;
11614fbbc36SDmitry Torokhov 	bool			disabled;	/* P: input->mutex */
11714fbbc36SDmitry Torokhov 	bool			suspended;	/* P: input->mutex */
1186680884aSMichael Hennerich 	bool			swap_xy;
119b4be468cSMichael Hennerich 	u16			conversion_data[AD7879_NR_SENSE];
120b4be468cSMichael Hennerich 	char			phys[32];
121b4be468cSMichael Hennerich 	u8			first_conversion_delay;
122b4be468cSMichael Hennerich 	u8			acquisition_time;
123b4be468cSMichael Hennerich 	u8			averaging;
124b4be468cSMichael Hennerich 	u8			pen_down_acc_interval;
125b4be468cSMichael Hennerich 	u8			median;
126b4be468cSMichael Hennerich 	u16			x_plate_ohms;
127b4be468cSMichael Hennerich 	u16			cmd_crtl1;
128b4be468cSMichael Hennerich 	u16			cmd_crtl2;
129b4be468cSMichael Hennerich 	u16			cmd_crtl3;
130b584efc9SMichael Hennerich 	int			x;
131b584efc9SMichael Hennerich 	int			y;
132b584efc9SMichael Hennerich 	int			Rt;
133b4be468cSMichael Hennerich };
134b4be468cSMichael Hennerich 
ad7879_read(struct ad7879 * ts,u8 reg)1354397c98aSMike Frysinger static int ad7879_read(struct ad7879 *ts, u8 reg)
1364397c98aSMike Frysinger {
137404a24c3SDmitry Torokhov 	unsigned int val;
138404a24c3SDmitry Torokhov 	int error;
139404a24c3SDmitry Torokhov 
140404a24c3SDmitry Torokhov 	error = regmap_read(ts->regmap, reg, &val);
141404a24c3SDmitry Torokhov 	if (error) {
142404a24c3SDmitry Torokhov 		dev_err(ts->dev, "failed to read register %#02x: %d\n",
143404a24c3SDmitry Torokhov 			reg, error);
144404a24c3SDmitry Torokhov 		return error;
1454397c98aSMike Frysinger 	}
1464397c98aSMike Frysinger 
147404a24c3SDmitry Torokhov 	return val;
1484397c98aSMike Frysinger }
1494397c98aSMike Frysinger 
ad7879_write(struct ad7879 * ts,u8 reg,u16 val)1504397c98aSMike Frysinger static int ad7879_write(struct ad7879 *ts, u8 reg, u16 val)
1514397c98aSMike Frysinger {
152404a24c3SDmitry Torokhov 	int error;
153404a24c3SDmitry Torokhov 
154404a24c3SDmitry Torokhov 	error = regmap_write(ts->regmap, reg, val);
155404a24c3SDmitry Torokhov 	if (error) {
156404a24c3SDmitry Torokhov 		dev_err(ts->dev,
157404a24c3SDmitry Torokhov 			"failed to write %#04x to register %#02x: %d\n",
158404a24c3SDmitry Torokhov 			val, reg, error);
159404a24c3SDmitry Torokhov 		return error;
160404a24c3SDmitry Torokhov 	}
161404a24c3SDmitry Torokhov 
162404a24c3SDmitry Torokhov 	return 0;
1634397c98aSMike Frysinger }
164b4be468cSMichael Hennerich 
ad7879_report(struct ad7879 * ts)165963ce8aeSMichael Hennerich static int ad7879_report(struct ad7879 *ts)
166b4be468cSMichael Hennerich {
167b4be468cSMichael Hennerich 	struct input_dev *input_dev = ts->input;
168b4be468cSMichael Hennerich 	unsigned Rt;
169b4be468cSMichael Hennerich 	u16 x, y, z1, z2;
170b4be468cSMichael Hennerich 
171b4be468cSMichael Hennerich 	x = ts->conversion_data[AD7879_SEQ_XPOS] & MAX_12BIT;
172b4be468cSMichael Hennerich 	y = ts->conversion_data[AD7879_SEQ_YPOS] & MAX_12BIT;
173b4be468cSMichael Hennerich 	z1 = ts->conversion_data[AD7879_SEQ_Z1] & MAX_12BIT;
174b4be468cSMichael Hennerich 	z2 = ts->conversion_data[AD7879_SEQ_Z2] & MAX_12BIT;
175b4be468cSMichael Hennerich 
1766680884aSMichael Hennerich 	if (ts->swap_xy)
1776680884aSMichael Hennerich 		swap(x, y);
1786680884aSMichael Hennerich 
179b4be468cSMichael Hennerich 	/*
180b4be468cSMichael Hennerich 	 * The samples processed here are already preprocessed by the AD7879.
1814397c98aSMike Frysinger 	 * The preprocessing function consists of a median and an averaging
1824397c98aSMike Frysinger 	 * filter.  The combination of these two techniques provides a robust
1834397c98aSMike Frysinger 	 * solution, discarding the spurious noise in the signal and keeping
1844397c98aSMike Frysinger 	 * only the data of interest.  The size of both filters is
1854774f400SStefan Agner 	 * programmable. (dev.platform_data, see linux/platform_data/ad7879.h)
1864774f400SStefan Agner 	 * Other user-programmable conversion controls include variable
1874774f400SStefan Agner 	 * acquisition time, and first conversion delay. Up to 16 averages can
1884774f400SStefan Agner 	 * be taken per conversion.
189b4be468cSMichael Hennerich 	 */
190b4be468cSMichael Hennerich 
191b4be468cSMichael Hennerich 	if (likely(x && z1)) {
192b4be468cSMichael Hennerich 		/* compute touch pressure resistance using equation #1 */
193b4be468cSMichael Hennerich 		Rt = (z2 - z1) * x * ts->x_plate_ohms;
194b4be468cSMichael Hennerich 		Rt /= z1;
195b4be468cSMichael Hennerich 		Rt = (Rt + 2047) >> 12;
196b4be468cSMichael Hennerich 
197b584efc9SMichael Hennerich 		/*
198b584efc9SMichael Hennerich 		 * Sample found inconsistent, pressure is beyond
199b584efc9SMichael Hennerich 		 * the maximum. Don't report it to user space.
200b584efc9SMichael Hennerich 		 */
201fa6e3ca2SStefan Agner 		if (Rt > input_abs_get_max(input_dev, ABS_PRESSURE))
202b584efc9SMichael Hennerich 			return -EINVAL;
203963ce8aeSMichael Hennerich 
204b584efc9SMichael Hennerich 		/*
205b584efc9SMichael Hennerich 		 * Note that we delay reporting events by one sample.
206b584efc9SMichael Hennerich 		 * This is done to avoid reporting last sample of the
207b584efc9SMichael Hennerich 		 * touch sequence, which may be incomplete if finger
208b584efc9SMichael Hennerich 		 * leaves the surface before last reading is taken.
209b584efc9SMichael Hennerich 		 */
210b584efc9SMichael Hennerich 		if (timer_pending(&ts->timer)) {
211b584efc9SMichael Hennerich 			/* Touch continues */
212b584efc9SMichael Hennerich 			input_report_key(input_dev, BTN_TOUCH, 1);
213b584efc9SMichael Hennerich 			input_report_abs(input_dev, ABS_X, ts->x);
214b584efc9SMichael Hennerich 			input_report_abs(input_dev, ABS_Y, ts->y);
215b584efc9SMichael Hennerich 			input_report_abs(input_dev, ABS_PRESSURE, ts->Rt);
216b4be468cSMichael Hennerich 			input_sync(input_dev);
217b584efc9SMichael Hennerich 		}
218b584efc9SMichael Hennerich 
219b584efc9SMichael Hennerich 		ts->x = x;
220b584efc9SMichael Hennerich 		ts->y = y;
221b584efc9SMichael Hennerich 		ts->Rt = Rt;
222b584efc9SMichael Hennerich 
223963ce8aeSMichael Hennerich 		return 0;
224b4be468cSMichael Hennerich 	}
225963ce8aeSMichael Hennerich 
226963ce8aeSMichael Hennerich 	return -EINVAL;
227b4be468cSMichael Hennerich }
228b4be468cSMichael Hennerich 
ad7879_ts_event_release(struct ad7879 * ts)229b4be468cSMichael Hennerich static void ad7879_ts_event_release(struct ad7879 *ts)
230b4be468cSMichael Hennerich {
231b4be468cSMichael Hennerich 	struct input_dev *input_dev = ts->input;
232b4be468cSMichael Hennerich 
233b4be468cSMichael Hennerich 	input_report_abs(input_dev, ABS_PRESSURE, 0);
234963ce8aeSMichael Hennerich 	input_report_key(input_dev, BTN_TOUCH, 0);
235b4be468cSMichael Hennerich 	input_sync(input_dev);
236b4be468cSMichael Hennerich }
237b4be468cSMichael Hennerich 
ad7879_timer(struct timer_list * t)238ee03e3f0SKees Cook static void ad7879_timer(struct timer_list *t)
239b4be468cSMichael Hennerich {
240ee03e3f0SKees Cook 	struct ad7879 *ts = from_timer(ts, t, timer);
241b4be468cSMichael Hennerich 
242b4be468cSMichael Hennerich 	ad7879_ts_event_release(ts);
243b4be468cSMichael Hennerich }
244b4be468cSMichael Hennerich 
ad7879_irq(int irq,void * handle)245b4be468cSMichael Hennerich static irqreturn_t ad7879_irq(int irq, void *handle)
246b4be468cSMichael Hennerich {
247b4be468cSMichael Hennerich 	struct ad7879 *ts = handle;
248e85bb0beSAditya Pakki 	int error;
249b4be468cSMichael Hennerich 
250e85bb0beSAditya Pakki 	error = regmap_bulk_read(ts->regmap, AD7879_REG_XPLUS,
251404a24c3SDmitry Torokhov 				 ts->conversion_data, AD7879_NR_SENSE);
252e85bb0beSAditya Pakki 	if (error)
253e85bb0beSAditya Pakki 		dev_err_ratelimited(ts->dev, "failed to read %#02x: %d\n",
254e85bb0beSAditya Pakki 				    AD7879_REG_XPLUS, error);
255e85bb0beSAditya Pakki 	else if (!ad7879_report(ts))
2567cd7a82dSDmitry Torokhov 		mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
257b4be468cSMichael Hennerich 
258b4be468cSMichael Hennerich 	return IRQ_HANDLED;
259b4be468cSMichael Hennerich }
260b4be468cSMichael Hennerich 
__ad7879_enable(struct ad7879 * ts)26114fbbc36SDmitry Torokhov static void __ad7879_enable(struct ad7879 *ts)
262b4be468cSMichael Hennerich {
2634397c98aSMike Frysinger 	ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
2644397c98aSMike Frysinger 	ad7879_write(ts, AD7879_REG_CTRL3, ts->cmd_crtl3);
2654397c98aSMike Frysinger 	ad7879_write(ts, AD7879_REG_CTRL1, ts->cmd_crtl1);
26614fbbc36SDmitry Torokhov 
26714fbbc36SDmitry Torokhov 	enable_irq(ts->irq);
268b4be468cSMichael Hennerich }
269b4be468cSMichael Hennerich 
__ad7879_disable(struct ad7879 * ts)27014fbbc36SDmitry Torokhov static void __ad7879_disable(struct ad7879 *ts)
271b4be468cSMichael Hennerich {
2724fecc208SMichael Hennerich 	u16 reg = (ts->cmd_crtl2 & ~AD7879_PM(-1)) |
2734fecc208SMichael Hennerich 		AD7879_PM(AD7879_PM_SHUTDOWN);
2744397c98aSMike Frysinger 	disable_irq(ts->irq);
275b4be468cSMichael Hennerich 
276b4be468cSMichael Hennerich 	if (del_timer_sync(&ts->timer))
277b4be468cSMichael Hennerich 		ad7879_ts_event_release(ts);
278b4be468cSMichael Hennerich 
2794fecc208SMichael Hennerich 	ad7879_write(ts, AD7879_REG_CTRL2, reg);
280b4be468cSMichael Hennerich }
281b4be468cSMichael Hennerich 
282b4be468cSMichael Hennerich 
ad7879_open(struct input_dev * input)28314fbbc36SDmitry Torokhov static int ad7879_open(struct input_dev *input)
284b4be468cSMichael Hennerich {
28514fbbc36SDmitry Torokhov 	struct ad7879 *ts = input_get_drvdata(input);
286b4be468cSMichael Hennerich 
28714fbbc36SDmitry Torokhov 	/* protected by input->mutex */
28814fbbc36SDmitry Torokhov 	if (!ts->disabled && !ts->suspended)
28914fbbc36SDmitry Torokhov 		__ad7879_enable(ts);
29014fbbc36SDmitry Torokhov 
29114fbbc36SDmitry Torokhov 	return 0;
292b4be468cSMichael Hennerich }
293b4be468cSMichael Hennerich 
ad7879_close(struct input_dev * input)29414fbbc36SDmitry Torokhov static void ad7879_close(struct input_dev *input)
29514fbbc36SDmitry Torokhov {
29614fbbc36SDmitry Torokhov 	struct ad7879 *ts = input_get_drvdata(input);
29714fbbc36SDmitry Torokhov 
29814fbbc36SDmitry Torokhov 	/* protected by input->mutex */
29914fbbc36SDmitry Torokhov 	if (!ts->disabled && !ts->suspended)
30014fbbc36SDmitry Torokhov 		__ad7879_disable(ts);
301b4be468cSMichael Hennerich }
30214fbbc36SDmitry Torokhov 
ad7879_suspend(struct device * dev)30302b6a58bSJingoo Han static int __maybe_unused ad7879_suspend(struct device *dev)
30414fbbc36SDmitry Torokhov {
3058672bd93SDmitry Torokhov 	struct ad7879 *ts = dev_get_drvdata(dev);
3068672bd93SDmitry Torokhov 
30714fbbc36SDmitry Torokhov 	mutex_lock(&ts->input->mutex);
30814fbbc36SDmitry Torokhov 
309*d69f0a43SAndrzej Pietrasiewicz 	if (!ts->suspended && !ts->disabled && input_device_enabled(ts->input))
31014fbbc36SDmitry Torokhov 		__ad7879_disable(ts);
31114fbbc36SDmitry Torokhov 
31214fbbc36SDmitry Torokhov 	ts->suspended = true;
31314fbbc36SDmitry Torokhov 
31414fbbc36SDmitry Torokhov 	mutex_unlock(&ts->input->mutex);
31514fbbc36SDmitry Torokhov 
3168672bd93SDmitry Torokhov 	return 0;
3178672bd93SDmitry Torokhov }
3188672bd93SDmitry Torokhov 
ad7879_resume(struct device * dev)31902b6a58bSJingoo Han static int __maybe_unused ad7879_resume(struct device *dev)
32014fbbc36SDmitry Torokhov {
3218672bd93SDmitry Torokhov 	struct ad7879 *ts = dev_get_drvdata(dev);
3228672bd93SDmitry Torokhov 
32314fbbc36SDmitry Torokhov 	mutex_lock(&ts->input->mutex);
32414fbbc36SDmitry Torokhov 
325*d69f0a43SAndrzej Pietrasiewicz 	if (ts->suspended && !ts->disabled && input_device_enabled(ts->input))
32614fbbc36SDmitry Torokhov 		__ad7879_enable(ts);
32714fbbc36SDmitry Torokhov 
32814fbbc36SDmitry Torokhov 	ts->suspended = false;
32914fbbc36SDmitry Torokhov 
33014fbbc36SDmitry Torokhov 	mutex_unlock(&ts->input->mutex);
3318672bd93SDmitry Torokhov 
3328672bd93SDmitry Torokhov 	return 0;
33314fbbc36SDmitry Torokhov }
3348672bd93SDmitry Torokhov 
3358672bd93SDmitry Torokhov SIMPLE_DEV_PM_OPS(ad7879_pm_ops, ad7879_suspend, ad7879_resume);
3368672bd93SDmitry Torokhov EXPORT_SYMBOL(ad7879_pm_ops);
33714fbbc36SDmitry Torokhov 
ad7879_toggle(struct ad7879 * ts,bool disable)33814fbbc36SDmitry Torokhov static void ad7879_toggle(struct ad7879 *ts, bool disable)
33914fbbc36SDmitry Torokhov {
34014fbbc36SDmitry Torokhov 	mutex_lock(&ts->input->mutex);
34114fbbc36SDmitry Torokhov 
342*d69f0a43SAndrzej Pietrasiewicz 	if (!ts->suspended && input_device_enabled(ts->input)) {
34314fbbc36SDmitry Torokhov 
34414fbbc36SDmitry Torokhov 		if (disable) {
34514fbbc36SDmitry Torokhov 			if (ts->disabled)
34614fbbc36SDmitry Torokhov 				__ad7879_enable(ts);
34714fbbc36SDmitry Torokhov 		} else {
34814fbbc36SDmitry Torokhov 			if (!ts->disabled)
34914fbbc36SDmitry Torokhov 				__ad7879_disable(ts);
35014fbbc36SDmitry Torokhov 		}
35114fbbc36SDmitry Torokhov 	}
35214fbbc36SDmitry Torokhov 
35314fbbc36SDmitry Torokhov 	ts->disabled = disable;
35414fbbc36SDmitry Torokhov 
35514fbbc36SDmitry Torokhov 	mutex_unlock(&ts->input->mutex);
35614fbbc36SDmitry Torokhov }
357b4be468cSMichael Hennerich 
ad7879_disable_show(struct device * dev,struct device_attribute * attr,char * buf)358b4be468cSMichael Hennerich static ssize_t ad7879_disable_show(struct device *dev,
359b4be468cSMichael Hennerich 				     struct device_attribute *attr, char *buf)
360b4be468cSMichael Hennerich {
361b4be468cSMichael Hennerich 	struct ad7879 *ts = dev_get_drvdata(dev);
362b4be468cSMichael Hennerich 
363b4be468cSMichael Hennerich 	return sprintf(buf, "%u\n", ts->disabled);
364b4be468cSMichael Hennerich }
365b4be468cSMichael Hennerich 
ad7879_disable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)366b4be468cSMichael Hennerich static ssize_t ad7879_disable_store(struct device *dev,
367b4be468cSMichael Hennerich 				     struct device_attribute *attr,
368b4be468cSMichael Hennerich 				     const char *buf, size_t count)
369b4be468cSMichael Hennerich {
370b4be468cSMichael Hennerich 	struct ad7879 *ts = dev_get_drvdata(dev);
37176496e7aSJJ Ding 	unsigned int val;
372b4be468cSMichael Hennerich 	int error;
373b4be468cSMichael Hennerich 
37476496e7aSJJ Ding 	error = kstrtouint(buf, 10, &val);
375b4be468cSMichael Hennerich 	if (error)
376b4be468cSMichael Hennerich 		return error;
377b4be468cSMichael Hennerich 
37814fbbc36SDmitry Torokhov 	ad7879_toggle(ts, val);
379b4be468cSMichael Hennerich 
380b4be468cSMichael Hennerich 	return count;
381b4be468cSMichael Hennerich }
382b4be468cSMichael Hennerich 
383b4be468cSMichael Hennerich static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store);
384b4be468cSMichael Hennerich 
385b4be468cSMichael Hennerich static struct attribute *ad7879_attributes[] = {
386b4be468cSMichael Hennerich 	&dev_attr_disable.attr,
387b4be468cSMichael Hennerich 	NULL
388b4be468cSMichael Hennerich };
389b4be468cSMichael Hennerich 
390b4be468cSMichael Hennerich static const struct attribute_group ad7879_attr_group = {
391b4be468cSMichael Hennerich 	.attrs = ad7879_attributes,
392b4be468cSMichael Hennerich };
393b4be468cSMichael Hennerich 
394ec51b7f5SMichael Hennerich #ifdef CONFIG_GPIOLIB
ad7879_gpio_direction_input(struct gpio_chip * chip,unsigned gpio)395ec51b7f5SMichael Hennerich static int ad7879_gpio_direction_input(struct gpio_chip *chip,
396ec51b7f5SMichael Hennerich 					unsigned gpio)
397ec51b7f5SMichael Hennerich {
398d9478044SLinus Walleij 	struct ad7879 *ts = gpiochip_get_data(chip);
399ec51b7f5SMichael Hennerich 	int err;
400ec51b7f5SMichael Hennerich 
401ec51b7f5SMichael Hennerich 	mutex_lock(&ts->mutex);
402ec51b7f5SMichael Hennerich 	ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL;
4034397c98aSMike Frysinger 	err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
404ec51b7f5SMichael Hennerich 	mutex_unlock(&ts->mutex);
405ec51b7f5SMichael Hennerich 
406ec51b7f5SMichael Hennerich 	return err;
407ec51b7f5SMichael Hennerich }
408ec51b7f5SMichael Hennerich 
ad7879_gpio_direction_output(struct gpio_chip * chip,unsigned gpio,int level)409ec51b7f5SMichael Hennerich static int ad7879_gpio_direction_output(struct gpio_chip *chip,
410ec51b7f5SMichael Hennerich 					unsigned gpio, int level)
411ec51b7f5SMichael Hennerich {
412d9478044SLinus Walleij 	struct ad7879 *ts = gpiochip_get_data(chip);
413ec51b7f5SMichael Hennerich 	int err;
414ec51b7f5SMichael Hennerich 
415ec51b7f5SMichael Hennerich 	mutex_lock(&ts->mutex);
416ec51b7f5SMichael Hennerich 	ts->cmd_crtl2 &= ~AD7879_GPIODIR;
417ec51b7f5SMichael Hennerich 	ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIOPOL;
418ec51b7f5SMichael Hennerich 	if (level)
419ec51b7f5SMichael Hennerich 		ts->cmd_crtl2 |= AD7879_GPIO_DATA;
420ec51b7f5SMichael Hennerich 	else
421ec51b7f5SMichael Hennerich 		ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
422ec51b7f5SMichael Hennerich 
4234397c98aSMike Frysinger 	err = ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
424ec51b7f5SMichael Hennerich 	mutex_unlock(&ts->mutex);
425ec51b7f5SMichael Hennerich 
426ec51b7f5SMichael Hennerich 	return err;
427ec51b7f5SMichael Hennerich }
428ec51b7f5SMichael Hennerich 
ad7879_gpio_get_value(struct gpio_chip * chip,unsigned gpio)429ec51b7f5SMichael Hennerich static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
430ec51b7f5SMichael Hennerich {
431d9478044SLinus Walleij 	struct ad7879 *ts = gpiochip_get_data(chip);
432ec51b7f5SMichael Hennerich 	u16 val;
433ec51b7f5SMichael Hennerich 
434ec51b7f5SMichael Hennerich 	mutex_lock(&ts->mutex);
4354397c98aSMike Frysinger 	val = ad7879_read(ts, AD7879_REG_CTRL2);
436ec51b7f5SMichael Hennerich 	mutex_unlock(&ts->mutex);
437ec51b7f5SMichael Hennerich 
438ec51b7f5SMichael Hennerich 	return !!(val & AD7879_GPIO_DATA);
439ec51b7f5SMichael Hennerich }
440ec51b7f5SMichael Hennerich 
ad7879_gpio_set_value(struct gpio_chip * chip,unsigned gpio,int value)441ec51b7f5SMichael Hennerich static void ad7879_gpio_set_value(struct gpio_chip *chip,
442ec51b7f5SMichael Hennerich 				  unsigned gpio, int value)
443ec51b7f5SMichael Hennerich {
444d9478044SLinus Walleij 	struct ad7879 *ts = gpiochip_get_data(chip);
445ec51b7f5SMichael Hennerich 
446ec51b7f5SMichael Hennerich 	mutex_lock(&ts->mutex);
447ec51b7f5SMichael Hennerich 	if (value)
448ec51b7f5SMichael Hennerich 		ts->cmd_crtl2 |= AD7879_GPIO_DATA;
449ec51b7f5SMichael Hennerich 	else
450ec51b7f5SMichael Hennerich 		ts->cmd_crtl2 &= ~AD7879_GPIO_DATA;
451ec51b7f5SMichael Hennerich 
4524397c98aSMike Frysinger 	ad7879_write(ts, AD7879_REG_CTRL2, ts->cmd_crtl2);
453ec51b7f5SMichael Hennerich 	mutex_unlock(&ts->mutex);
454ec51b7f5SMichael Hennerich }
455ec51b7f5SMichael Hennerich 
ad7879_gpio_add(struct ad7879 * ts)4561be7aa9bSLinus Walleij static int ad7879_gpio_add(struct ad7879 *ts)
457ec51b7f5SMichael Hennerich {
458ec51b7f5SMichael Hennerich 	int ret = 0;
459ec51b7f5SMichael Hennerich 
46014fbbc36SDmitry Torokhov 	mutex_init(&ts->mutex);
46114fbbc36SDmitry Torokhov 
4621be7aa9bSLinus Walleij 	/* Do not create a chip unless flagged for it */
4631be7aa9bSLinus Walleij 	if (!device_property_read_bool(ts->dev, "gpio-controller"))
4641be7aa9bSLinus Walleij 		return 0;
4651be7aa9bSLinus Walleij 
466ec51b7f5SMichael Hennerich 	ts->gc.direction_input = ad7879_gpio_direction_input;
467ec51b7f5SMichael Hennerich 	ts->gc.direction_output = ad7879_gpio_direction_output;
468ec51b7f5SMichael Hennerich 	ts->gc.get = ad7879_gpio_get_value;
469ec51b7f5SMichael Hennerich 	ts->gc.set = ad7879_gpio_set_value;
470ec51b7f5SMichael Hennerich 	ts->gc.can_sleep = 1;
4711be7aa9bSLinus Walleij 	ts->gc.base = -1;
472ec51b7f5SMichael Hennerich 	ts->gc.ngpio = 1;
473ec51b7f5SMichael Hennerich 	ts->gc.label = "AD7879-GPIO";
474ec51b7f5SMichael Hennerich 	ts->gc.owner = THIS_MODULE;
47558383c78SLinus Walleij 	ts->gc.parent = ts->dev;
476ec51b7f5SMichael Hennerich 
477069b2e2cSDmitry Torokhov 	ret = devm_gpiochip_add_data(ts->dev, &ts->gc, ts);
478ec51b7f5SMichael Hennerich 	if (ret)
4794397c98aSMike Frysinger 		dev_err(ts->dev, "failed to register gpio %d\n",
480ec51b7f5SMichael Hennerich 			ts->gc.base);
481ec51b7f5SMichael Hennerich 
482ec51b7f5SMichael Hennerich 	return ret;
483ec51b7f5SMichael Hennerich }
484ec51b7f5SMichael Hennerich #else
ad7879_gpio_add(struct ad7879 * ts)4851be7aa9bSLinus Walleij static int ad7879_gpio_add(struct ad7879 *ts)
486ec51b7f5SMichael Hennerich {
487ec51b7f5SMichael Hennerich 	return 0;
488ec51b7f5SMichael Hennerich }
489ec51b7f5SMichael Hennerich #endif
490ec51b7f5SMichael Hennerich 
ad7879_parse_dt(struct device * dev,struct ad7879 * ts)491fa6e3ca2SStefan Agner static int ad7879_parse_dt(struct device *dev, struct ad7879 *ts)
492fa6e3ca2SStefan Agner {
493fa6e3ca2SStefan Agner 	int err;
494fa6e3ca2SStefan Agner 	u32 tmp;
495fa6e3ca2SStefan Agner 
496fa6e3ca2SStefan Agner 	err = device_property_read_u32(dev, "adi,resistance-plate-x", &tmp);
497fa6e3ca2SStefan Agner 	if (err) {
498fa6e3ca2SStefan Agner 		dev_err(dev, "failed to get resistance-plate-x property\n");
499fa6e3ca2SStefan Agner 		return err;
500fa6e3ca2SStefan Agner 	}
501fa6e3ca2SStefan Agner 	ts->x_plate_ohms = (u16)tmp;
502fa6e3ca2SStefan Agner 
503fa6e3ca2SStefan Agner 	device_property_read_u8(dev, "adi,first-conversion-delay",
504fa6e3ca2SStefan Agner 				&ts->first_conversion_delay);
505fa6e3ca2SStefan Agner 	device_property_read_u8(dev, "adi,acquisition-time",
506fa6e3ca2SStefan Agner 				&ts->acquisition_time);
507fa6e3ca2SStefan Agner 	device_property_read_u8(dev, "adi,median-filter-size", &ts->median);
508fa6e3ca2SStefan Agner 	device_property_read_u8(dev, "adi,averaging", &ts->averaging);
509fa6e3ca2SStefan Agner 	device_property_read_u8(dev, "adi,conversion-interval",
510fa6e3ca2SStefan Agner 				&ts->pen_down_acc_interval);
511fa6e3ca2SStefan Agner 
512fa6e3ca2SStefan Agner 	ts->swap_xy = device_property_read_bool(dev, "touchscreen-swapped-x-y");
513fa6e3ca2SStefan Agner 
514fa6e3ca2SStefan Agner 	return 0;
515fa6e3ca2SStefan Agner }
516fa6e3ca2SStefan Agner 
ad7879_probe(struct device * dev,struct regmap * regmap,int irq,u16 bustype,u8 devid)5174e34025bSDmitry Torokhov int ad7879_probe(struct device *dev, struct regmap *regmap,
518404a24c3SDmitry Torokhov 		 int irq, u16 bustype, u8 devid)
519b4be468cSMichael Hennerich {
5204397c98aSMike Frysinger 	struct ad7879 *ts;
521b4be468cSMichael Hennerich 	struct input_dev *input_dev;
522b4be468cSMichael Hennerich 	int err;
523b4be468cSMichael Hennerich 	u16 revid;
524b4be468cSMichael Hennerich 
525404a24c3SDmitry Torokhov 	if (irq <= 0) {
526fa6e3ca2SStefan Agner 		dev_err(dev, "No IRQ specified\n");
5274e34025bSDmitry Torokhov 		return -EINVAL;
528b4be468cSMichael Hennerich 	}
529b4be468cSMichael Hennerich 
530fa6e3ca2SStefan Agner 	ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL);
531fa6e3ca2SStefan Agner 	if (!ts)
5324e34025bSDmitry Torokhov 		return -ENOMEM;
533fa6e3ca2SStefan Agner 
5343a97c3d1SDmitry Torokhov 	err = ad7879_parse_dt(dev, ts);
5353a97c3d1SDmitry Torokhov 	if (err)
5363a97c3d1SDmitry Torokhov 		return err;
537b4be468cSMichael Hennerich 
538fa6e3ca2SStefan Agner 	input_dev = devm_input_allocate_device(dev);
539fa6e3ca2SStefan Agner 	if (!input_dev) {
540fa6e3ca2SStefan Agner 		dev_err(dev, "Failed to allocate input device\n");
5414e34025bSDmitry Torokhov 		return -ENOMEM;
5424397c98aSMike Frysinger 	}
543b4be468cSMichael Hennerich 
5444397c98aSMike Frysinger 	ts->dev = dev;
545b4be468cSMichael Hennerich 	ts->input = input_dev;
54614fbbc36SDmitry Torokhov 	ts->irq = irq;
547404a24c3SDmitry Torokhov 	ts->regmap = regmap;
5485f2940c4SStefan Agner 
549ee03e3f0SKees Cook 	timer_setup(&ts->timer, ad7879_timer, 0);
5504397c98aSMike Frysinger 	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
551b4be468cSMichael Hennerich 
552b4be468cSMichael Hennerich 	input_dev->name = "AD7879 Touchscreen";
553b4be468cSMichael Hennerich 	input_dev->phys = ts->phys;
5544397c98aSMike Frysinger 	input_dev->dev.parent = dev;
555404a24c3SDmitry Torokhov 	input_dev->id.bustype = bustype;
556b4be468cSMichael Hennerich 
55714fbbc36SDmitry Torokhov 	input_dev->open = ad7879_open;
55814fbbc36SDmitry Torokhov 	input_dev->close = ad7879_close;
55914fbbc36SDmitry Torokhov 
56014fbbc36SDmitry Torokhov 	input_set_drvdata(input_dev, ts);
56114fbbc36SDmitry Torokhov 
5624f959635SDmitry Torokhov 	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
563963ce8aeSMichael Hennerich 
564fa6e3ca2SStefan Agner 	input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
565fa6e3ca2SStefan Agner 	input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
5664f959635SDmitry Torokhov 	input_set_capability(input_dev, EV_ABS, ABS_PRESSURE);
567ed7c9870SHans de Goede 	touchscreen_parse_properties(input_dev, false, NULL);
568fa6e3ca2SStefan Agner 	if (!input_abs_get_max(input_dev, ABS_PRESSURE)) {
569fa6e3ca2SStefan Agner 		dev_err(dev, "Touchscreen pressure is not specified\n");
5704e34025bSDmitry Torokhov 		return -EINVAL;
571fa6e3ca2SStefan Agner 	}
572b4be468cSMichael Hennerich 
5734397c98aSMike Frysinger 	err = ad7879_write(ts, AD7879_REG_CTRL2, AD7879_RESET);
574b4be468cSMichael Hennerich 	if (err < 0) {
5754397c98aSMike Frysinger 		dev_err(dev, "Failed to write %s\n", input_dev->name);
5764e34025bSDmitry Torokhov 		return err;
577b4be468cSMichael Hennerich 	}
578b4be468cSMichael Hennerich 
5794397c98aSMike Frysinger 	revid = ad7879_read(ts, AD7879_REG_REVID);
5804397c98aSMike Frysinger 	input_dev->id.product = (revid & 0xff);
5814397c98aSMike Frysinger 	input_dev->id.version = revid >> 8;
5824397c98aSMike Frysinger 	if (input_dev->id.product != devid) {
5834397c98aSMike Frysinger 		dev_err(dev, "Failed to probe %s (%x vs %x)\n",
5844397c98aSMike Frysinger 			input_dev->name, devid, revid);
5854e34025bSDmitry Torokhov 		return -ENODEV;
586b4be468cSMichael Hennerich 	}
587b4be468cSMichael Hennerich 
588ec51b7f5SMichael Hennerich 	ts->cmd_crtl3 = AD7879_YPLUS_BIT |
589ec51b7f5SMichael Hennerich 			AD7879_XPLUS_BIT |
590ec51b7f5SMichael Hennerich 			AD7879_Z2_BIT |
591ec51b7f5SMichael Hennerich 			AD7879_Z1_BIT |
592ec51b7f5SMichael Hennerich 			AD7879_TEMPMASK_BIT |
593ec51b7f5SMichael Hennerich 			AD7879_AUXVBATMASK_BIT |
594ec51b7f5SMichael Hennerich 			AD7879_GPIOALERTMASK_BIT;
595ec51b7f5SMichael Hennerich 
596ec51b7f5SMichael Hennerich 	ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR |
597ec51b7f5SMichael Hennerich 			AD7879_AVG(ts->averaging) |
598ec51b7f5SMichael Hennerich 			AD7879_MFS(ts->median) |
599ec51b7f5SMichael Hennerich 			AD7879_FCD(ts->first_conversion_delay);
600ec51b7f5SMichael Hennerich 
601ec51b7f5SMichael Hennerich 	ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 |
602ec51b7f5SMichael Hennerich 			AD7879_ACQ(ts->acquisition_time) |
603ec51b7f5SMichael Hennerich 			AD7879_TMR(ts->pen_down_acc_interval);
604ec51b7f5SMichael Hennerich 
605fa6e3ca2SStefan Agner 	err = devm_request_threaded_irq(dev, ts->irq, NULL, ad7879_irq,
6069b7e31bbSLars-Peter Clausen 					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
6074397c98aSMike Frysinger 					dev_name(dev), ts);
608b4be468cSMichael Hennerich 	if (err) {
609fa6e3ca2SStefan Agner 		dev_err(dev, "Failed to request IRQ: %d\n", err);
6104e34025bSDmitry Torokhov 		return err;
611b4be468cSMichael Hennerich 	}
612b4be468cSMichael Hennerich 
61314fbbc36SDmitry Torokhov 	__ad7879_disable(ts);
61414fbbc36SDmitry Torokhov 
615a8b4aa0cSAndi Shyti 	err = devm_device_add_group(dev, &ad7879_attr_group);
616069b2e2cSDmitry Torokhov 	if (err)
6174e34025bSDmitry Torokhov 		return err;
618069b2e2cSDmitry Torokhov 
6191be7aa9bSLinus Walleij 	err = ad7879_gpio_add(ts);
620b4be468cSMichael Hennerich 	if (err)
6214e34025bSDmitry Torokhov 		return err;
622b4be468cSMichael Hennerich 
623ec51b7f5SMichael Hennerich 	err = input_register_device(input_dev);
624ec51b7f5SMichael Hennerich 	if (err)
6254e34025bSDmitry Torokhov 		return err;
626069b2e2cSDmitry Torokhov 
627af160c54SDmitry Torokhov 	dev_set_drvdata(dev, ts);
628af160c54SDmitry Torokhov 
629069b2e2cSDmitry Torokhov 	return 0;
630b4be468cSMichael Hennerich }
6314397c98aSMike Frysinger EXPORT_SYMBOL(ad7879_probe);
632b4be468cSMichael Hennerich 
6332581e5d1SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
634b4be468cSMichael Hennerich MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver");
635b4be468cSMichael Hennerich MODULE_LICENSE("GPL");
636