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