xref: /OK3568_Linux_fs/kernel/drivers/input/touchscreen/edt-ft5x06.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
4*4882a593Smuzhiyun  * Daniel Wagener <daniel.wagener@kernelconcepts.de> (M09 firmware support)
5*4882a593Smuzhiyun  * Lothar Waßmann <LW@KARO-electronics.de> (DT support)
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * This is a driver for the EDT "Polytouch" family of touch controllers
10*4882a593Smuzhiyun  * based on the FocalTech FT5x06 line of chips.
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * Development of this driver has been sponsored by Glyn:
13*4882a593Smuzhiyun  *    http://www.glyn.com/Products/Displays
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <linux/debugfs.h>
17*4882a593Smuzhiyun #include <linux/delay.h>
18*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
19*4882a593Smuzhiyun #include <linux/i2c.h>
20*4882a593Smuzhiyun #include <linux/interrupt.h>
21*4882a593Smuzhiyun #include <linux/input.h>
22*4882a593Smuzhiyun #include <linux/input/mt.h>
23*4882a593Smuzhiyun #include <linux/input/touchscreen.h>
24*4882a593Smuzhiyun #include <linux/irq.h>
25*4882a593Smuzhiyun #include <linux/kernel.h>
26*4882a593Smuzhiyun #include <linux/module.h>
27*4882a593Smuzhiyun #include <linux/ratelimit.h>
28*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
29*4882a593Smuzhiyun #include <linux/slab.h>
30*4882a593Smuzhiyun #include <linux/uaccess.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #include <asm/unaligned.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define WORK_REGISTER_THRESHOLD		0x00
35*4882a593Smuzhiyun #define WORK_REGISTER_REPORT_RATE	0x08
36*4882a593Smuzhiyun #define WORK_REGISTER_GAIN		0x30
37*4882a593Smuzhiyun #define WORK_REGISTER_OFFSET		0x31
38*4882a593Smuzhiyun #define WORK_REGISTER_NUM_X		0x33
39*4882a593Smuzhiyun #define WORK_REGISTER_NUM_Y		0x34
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define PMOD_REGISTER_ACTIVE		0x00
42*4882a593Smuzhiyun #define PMOD_REGISTER_HIBERNATE		0x03
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define M09_REGISTER_THRESHOLD		0x80
45*4882a593Smuzhiyun #define M09_REGISTER_GAIN		0x92
46*4882a593Smuzhiyun #define M09_REGISTER_OFFSET		0x93
47*4882a593Smuzhiyun #define M09_REGISTER_NUM_X		0x94
48*4882a593Smuzhiyun #define M09_REGISTER_NUM_Y		0x95
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define EV_REGISTER_THRESHOLD		0x40
51*4882a593Smuzhiyun #define EV_REGISTER_GAIN		0x41
52*4882a593Smuzhiyun #define EV_REGISTER_OFFSET_Y		0x45
53*4882a593Smuzhiyun #define EV_REGISTER_OFFSET_X		0x46
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define NO_REGISTER			0xff
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #define WORK_REGISTER_OPMODE		0x3c
58*4882a593Smuzhiyun #define FACTORY_REGISTER_OPMODE		0x01
59*4882a593Smuzhiyun #define PMOD_REGISTER_OPMODE		0xa5
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define TOUCH_EVENT_DOWN		0x00
62*4882a593Smuzhiyun #define TOUCH_EVENT_UP			0x01
63*4882a593Smuzhiyun #define TOUCH_EVENT_ON			0x02
64*4882a593Smuzhiyun #define TOUCH_EVENT_RESERVED		0x03
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #define EDT_NAME_LEN			23
67*4882a593Smuzhiyun #define EDT_SWITCH_MODE_RETRIES		10
68*4882a593Smuzhiyun #define EDT_SWITCH_MODE_DELAY		5 /* msec */
69*4882a593Smuzhiyun #define EDT_RAW_DATA_RETRIES		100
70*4882a593Smuzhiyun #define EDT_RAW_DATA_DELAY		1000 /* usec */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun enum edt_pmode {
73*4882a593Smuzhiyun 	EDT_PMODE_NOT_SUPPORTED,
74*4882a593Smuzhiyun 	EDT_PMODE_HIBERNATE,
75*4882a593Smuzhiyun 	EDT_PMODE_POWEROFF,
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun enum edt_ver {
79*4882a593Smuzhiyun 	EDT_M06,
80*4882a593Smuzhiyun 	EDT_M09,
81*4882a593Smuzhiyun 	EDT_M12,
82*4882a593Smuzhiyun 	EV_FT,
83*4882a593Smuzhiyun 	GENERIC_FT,
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun struct edt_reg_addr {
87*4882a593Smuzhiyun 	int reg_threshold;
88*4882a593Smuzhiyun 	int reg_report_rate;
89*4882a593Smuzhiyun 	int reg_gain;
90*4882a593Smuzhiyun 	int reg_offset;
91*4882a593Smuzhiyun 	int reg_offset_x;
92*4882a593Smuzhiyun 	int reg_offset_y;
93*4882a593Smuzhiyun 	int reg_num_x;
94*4882a593Smuzhiyun 	int reg_num_y;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun struct edt_ft5x06_ts_data {
98*4882a593Smuzhiyun 	struct i2c_client *client;
99*4882a593Smuzhiyun 	struct input_dev *input;
100*4882a593Smuzhiyun 	struct touchscreen_properties prop;
101*4882a593Smuzhiyun 	u16 num_x;
102*4882a593Smuzhiyun 	u16 num_y;
103*4882a593Smuzhiyun 	struct regulator *vcc;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	struct gpio_desc *reset_gpio;
106*4882a593Smuzhiyun 	struct gpio_desc *wake_gpio;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun #if defined(CONFIG_DEBUG_FS)
109*4882a593Smuzhiyun 	struct dentry *debug_dir;
110*4882a593Smuzhiyun 	u8 *raw_buffer;
111*4882a593Smuzhiyun 	size_t raw_bufsize;
112*4882a593Smuzhiyun #endif
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	struct mutex mutex;
115*4882a593Smuzhiyun 	bool factory_mode;
116*4882a593Smuzhiyun 	enum edt_pmode suspend_mode;
117*4882a593Smuzhiyun 	int threshold;
118*4882a593Smuzhiyun 	int gain;
119*4882a593Smuzhiyun 	int offset;
120*4882a593Smuzhiyun 	int offset_x;
121*4882a593Smuzhiyun 	int offset_y;
122*4882a593Smuzhiyun 	int report_rate;
123*4882a593Smuzhiyun 	int max_support_points;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	char name[EDT_NAME_LEN];
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	struct edt_reg_addr reg_addr;
128*4882a593Smuzhiyun 	enum edt_ver version;
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun struct edt_i2c_chip_data {
132*4882a593Smuzhiyun 	int  max_support_points;
133*4882a593Smuzhiyun };
134*4882a593Smuzhiyun 
edt_ft5x06_ts_readwrite(struct i2c_client * client,u16 wr_len,u8 * wr_buf,u16 rd_len,u8 * rd_buf)135*4882a593Smuzhiyun static int edt_ft5x06_ts_readwrite(struct i2c_client *client,
136*4882a593Smuzhiyun 				   u16 wr_len, u8 *wr_buf,
137*4882a593Smuzhiyun 				   u16 rd_len, u8 *rd_buf)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun 	struct i2c_msg wrmsg[2];
140*4882a593Smuzhiyun 	int i = 0;
141*4882a593Smuzhiyun 	int ret;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	if (wr_len) {
144*4882a593Smuzhiyun 		wrmsg[i].addr  = client->addr;
145*4882a593Smuzhiyun 		wrmsg[i].flags = 0;
146*4882a593Smuzhiyun 		wrmsg[i].len = wr_len;
147*4882a593Smuzhiyun 		wrmsg[i].buf = wr_buf;
148*4882a593Smuzhiyun 		i++;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 	if (rd_len) {
151*4882a593Smuzhiyun 		wrmsg[i].addr  = client->addr;
152*4882a593Smuzhiyun 		wrmsg[i].flags = I2C_M_RD;
153*4882a593Smuzhiyun 		wrmsg[i].len = rd_len;
154*4882a593Smuzhiyun 		wrmsg[i].buf = rd_buf;
155*4882a593Smuzhiyun 		i++;
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	ret = i2c_transfer(client->adapter, wrmsg, i);
159*4882a593Smuzhiyun 	if (ret < 0)
160*4882a593Smuzhiyun 		return ret;
161*4882a593Smuzhiyun 	if (ret != i)
162*4882a593Smuzhiyun 		return -EIO;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return 0;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data * tsdata,u8 * buf,int buflen)167*4882a593Smuzhiyun static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
168*4882a593Smuzhiyun 				    u8 *buf, int buflen)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	int i;
171*4882a593Smuzhiyun 	u8 crc = 0;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	for (i = 0; i < buflen - 1; i++)
174*4882a593Smuzhiyun 		crc ^= buf[i];
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	if (crc != buf[buflen-1]) {
177*4882a593Smuzhiyun 		dev_err_ratelimited(&tsdata->client->dev,
178*4882a593Smuzhiyun 				    "crc error: 0x%02x expected, got 0x%02x\n",
179*4882a593Smuzhiyun 				    crc, buf[buflen-1]);
180*4882a593Smuzhiyun 		return false;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	return true;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
edt_ft5x06_ts_isr(int irq,void * dev_id)186*4882a593Smuzhiyun static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = dev_id;
189*4882a593Smuzhiyun 	struct device *dev = &tsdata->client->dev;
190*4882a593Smuzhiyun 	u8 cmd;
191*4882a593Smuzhiyun 	u8 rdbuf[63];
192*4882a593Smuzhiyun 	int i, type, x, y, id;
193*4882a593Smuzhiyun 	int offset, tplen, datalen, crclen;
194*4882a593Smuzhiyun 	int error;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	switch (tsdata->version) {
197*4882a593Smuzhiyun 	case EDT_M06:
198*4882a593Smuzhiyun 		cmd = 0xf9; /* tell the controller to send touch data */
199*4882a593Smuzhiyun 		offset = 5; /* where the actual touch data starts */
200*4882a593Smuzhiyun 		tplen = 4;  /* data comes in so called frames */
201*4882a593Smuzhiyun 		crclen = 1; /* length of the crc data */
202*4882a593Smuzhiyun 		break;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 	case EDT_M09:
205*4882a593Smuzhiyun 	case EDT_M12:
206*4882a593Smuzhiyun 	case EV_FT:
207*4882a593Smuzhiyun 	case GENERIC_FT:
208*4882a593Smuzhiyun 		cmd = 0x0;
209*4882a593Smuzhiyun 		offset = 3;
210*4882a593Smuzhiyun 		tplen = 6;
211*4882a593Smuzhiyun 		crclen = 0;
212*4882a593Smuzhiyun 		break;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	default:
215*4882a593Smuzhiyun 		goto out;
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	memset(rdbuf, 0, sizeof(rdbuf));
219*4882a593Smuzhiyun 	datalen = tplen * tsdata->max_support_points + offset + crclen;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	error = edt_ft5x06_ts_readwrite(tsdata->client,
222*4882a593Smuzhiyun 					sizeof(cmd), &cmd,
223*4882a593Smuzhiyun 					datalen, rdbuf);
224*4882a593Smuzhiyun 	if (error) {
225*4882a593Smuzhiyun 		dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
226*4882a593Smuzhiyun 				    error);
227*4882a593Smuzhiyun 		goto out;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	/* M09/M12 does not send header or CRC */
231*4882a593Smuzhiyun 	if (tsdata->version == EDT_M06) {
232*4882a593Smuzhiyun 		if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa ||
233*4882a593Smuzhiyun 			rdbuf[2] != datalen) {
234*4882a593Smuzhiyun 			dev_err_ratelimited(dev,
235*4882a593Smuzhiyun 					"Unexpected header: %02x%02x%02x!\n",
236*4882a593Smuzhiyun 					rdbuf[0], rdbuf[1], rdbuf[2]);
237*4882a593Smuzhiyun 			goto out;
238*4882a593Smuzhiyun 		}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen))
241*4882a593Smuzhiyun 			goto out;
242*4882a593Smuzhiyun 	}
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	for (i = 0; i < tsdata->max_support_points; i++) {
245*4882a593Smuzhiyun 		u8 *buf = &rdbuf[i * tplen + offset];
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 		type = buf[0] >> 6;
248*4882a593Smuzhiyun 		/* ignore Reserved events */
249*4882a593Smuzhiyun 		if (type == TOUCH_EVENT_RESERVED)
250*4882a593Smuzhiyun 			continue;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 		/* M06 sometimes sends bogus coordinates in TOUCH_DOWN */
253*4882a593Smuzhiyun 		if (tsdata->version == EDT_M06 && type == TOUCH_EVENT_DOWN)
254*4882a593Smuzhiyun 			continue;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 		x = get_unaligned_be16(buf) & 0x0fff;
257*4882a593Smuzhiyun 		y = get_unaligned_be16(buf + 2) & 0x0fff;
258*4882a593Smuzhiyun 		/* The FT5x26 send the y coordinate first */
259*4882a593Smuzhiyun 		if (tsdata->version == EV_FT)
260*4882a593Smuzhiyun 			swap(x, y);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		id = (buf[2] >> 4) & 0x0f;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 		input_mt_slot(tsdata->input, id);
265*4882a593Smuzhiyun 		if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,
266*4882a593Smuzhiyun 					       type != TOUCH_EVENT_UP))
267*4882a593Smuzhiyun 			touchscreen_report_pos(tsdata->input, &tsdata->prop,
268*4882a593Smuzhiyun 					       x, y, true);
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	input_mt_report_pointer_emulation(tsdata->input, true);
272*4882a593Smuzhiyun 	input_sync(tsdata->input);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun out:
275*4882a593Smuzhiyun 	return IRQ_HANDLED;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
edt_ft5x06_register_write(struct edt_ft5x06_ts_data * tsdata,u8 addr,u8 value)278*4882a593Smuzhiyun static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
279*4882a593Smuzhiyun 				     u8 addr, u8 value)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	u8 wrbuf[4];
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	switch (tsdata->version) {
284*4882a593Smuzhiyun 	case EDT_M06:
285*4882a593Smuzhiyun 		wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
286*4882a593Smuzhiyun 		wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
287*4882a593Smuzhiyun 		wrbuf[2] = value;
288*4882a593Smuzhiyun 		wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
289*4882a593Smuzhiyun 		return edt_ft5x06_ts_readwrite(tsdata->client, 4,
290*4882a593Smuzhiyun 					wrbuf, 0, NULL);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	case EDT_M09:
293*4882a593Smuzhiyun 	case EDT_M12:
294*4882a593Smuzhiyun 	case EV_FT:
295*4882a593Smuzhiyun 	case GENERIC_FT:
296*4882a593Smuzhiyun 		wrbuf[0] = addr;
297*4882a593Smuzhiyun 		wrbuf[1] = value;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 		return edt_ft5x06_ts_readwrite(tsdata->client, 2,
300*4882a593Smuzhiyun 					wrbuf, 0, NULL);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	default:
303*4882a593Smuzhiyun 		return -EINVAL;
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
edt_ft5x06_register_read(struct edt_ft5x06_ts_data * tsdata,u8 addr)307*4882a593Smuzhiyun static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
308*4882a593Smuzhiyun 				    u8 addr)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	u8 wrbuf[2], rdbuf[2];
311*4882a593Smuzhiyun 	int error;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	switch (tsdata->version) {
314*4882a593Smuzhiyun 	case EDT_M06:
315*4882a593Smuzhiyun 		wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
316*4882a593Smuzhiyun 		wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
317*4882a593Smuzhiyun 		wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 		error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2,
320*4882a593Smuzhiyun 						rdbuf);
321*4882a593Smuzhiyun 		if (error)
322*4882a593Smuzhiyun 			return error;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 		if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) {
325*4882a593Smuzhiyun 			dev_err(&tsdata->client->dev,
326*4882a593Smuzhiyun 				"crc error: 0x%02x expected, got 0x%02x\n",
327*4882a593Smuzhiyun 				wrbuf[0] ^ wrbuf[1] ^ rdbuf[0],
328*4882a593Smuzhiyun 				rdbuf[1]);
329*4882a593Smuzhiyun 			return -EIO;
330*4882a593Smuzhiyun 		}
331*4882a593Smuzhiyun 		break;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	case EDT_M09:
334*4882a593Smuzhiyun 	case EDT_M12:
335*4882a593Smuzhiyun 	case EV_FT:
336*4882a593Smuzhiyun 	case GENERIC_FT:
337*4882a593Smuzhiyun 		wrbuf[0] = addr;
338*4882a593Smuzhiyun 		error = edt_ft5x06_ts_readwrite(tsdata->client, 1,
339*4882a593Smuzhiyun 						wrbuf, 1, rdbuf);
340*4882a593Smuzhiyun 		if (error)
341*4882a593Smuzhiyun 			return error;
342*4882a593Smuzhiyun 		break;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	default:
345*4882a593Smuzhiyun 		return -EINVAL;
346*4882a593Smuzhiyun 	}
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	return rdbuf[0];
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun struct edt_ft5x06_attribute {
352*4882a593Smuzhiyun 	struct device_attribute dattr;
353*4882a593Smuzhiyun 	size_t field_offset;
354*4882a593Smuzhiyun 	u8 limit_low;
355*4882a593Smuzhiyun 	u8 limit_high;
356*4882a593Smuzhiyun 	u8 addr_m06;
357*4882a593Smuzhiyun 	u8 addr_m09;
358*4882a593Smuzhiyun 	u8 addr_ev;
359*4882a593Smuzhiyun };
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun #define EDT_ATTR(_field, _mode, _addr_m06, _addr_m09, _addr_ev,		\
362*4882a593Smuzhiyun 		_limit_low, _limit_high)				\
363*4882a593Smuzhiyun 	struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = {	\
364*4882a593Smuzhiyun 		.dattr = __ATTR(_field, _mode,				\
365*4882a593Smuzhiyun 				edt_ft5x06_setting_show,		\
366*4882a593Smuzhiyun 				edt_ft5x06_setting_store),		\
367*4882a593Smuzhiyun 		.field_offset = offsetof(struct edt_ft5x06_ts_data, _field), \
368*4882a593Smuzhiyun 		.addr_m06 = _addr_m06,					\
369*4882a593Smuzhiyun 		.addr_m09 = _addr_m09,					\
370*4882a593Smuzhiyun 		.addr_ev  = _addr_ev,					\
371*4882a593Smuzhiyun 		.limit_low = _limit_low,				\
372*4882a593Smuzhiyun 		.limit_high = _limit_high,				\
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
edt_ft5x06_setting_show(struct device * dev,struct device_attribute * dattr,char * buf)375*4882a593Smuzhiyun static ssize_t edt_ft5x06_setting_show(struct device *dev,
376*4882a593Smuzhiyun 				       struct device_attribute *dattr,
377*4882a593Smuzhiyun 				       char *buf)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
380*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
381*4882a593Smuzhiyun 	struct edt_ft5x06_attribute *attr =
382*4882a593Smuzhiyun 			container_of(dattr, struct edt_ft5x06_attribute, dattr);
383*4882a593Smuzhiyun 	u8 *field = (u8 *)tsdata + attr->field_offset;
384*4882a593Smuzhiyun 	int val;
385*4882a593Smuzhiyun 	size_t count = 0;
386*4882a593Smuzhiyun 	int error = 0;
387*4882a593Smuzhiyun 	u8 addr;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	mutex_lock(&tsdata->mutex);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun 	if (tsdata->factory_mode) {
392*4882a593Smuzhiyun 		error = -EIO;
393*4882a593Smuzhiyun 		goto out;
394*4882a593Smuzhiyun 	}
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	switch (tsdata->version) {
397*4882a593Smuzhiyun 	case EDT_M06:
398*4882a593Smuzhiyun 		addr = attr->addr_m06;
399*4882a593Smuzhiyun 		break;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	case EDT_M09:
402*4882a593Smuzhiyun 	case EDT_M12:
403*4882a593Smuzhiyun 	case GENERIC_FT:
404*4882a593Smuzhiyun 		addr = attr->addr_m09;
405*4882a593Smuzhiyun 		break;
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	case EV_FT:
408*4882a593Smuzhiyun 		addr = attr->addr_ev;
409*4882a593Smuzhiyun 		break;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	default:
412*4882a593Smuzhiyun 		error = -ENODEV;
413*4882a593Smuzhiyun 		goto out;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	if (addr != NO_REGISTER) {
417*4882a593Smuzhiyun 		val = edt_ft5x06_register_read(tsdata, addr);
418*4882a593Smuzhiyun 		if (val < 0) {
419*4882a593Smuzhiyun 			error = val;
420*4882a593Smuzhiyun 			dev_err(&tsdata->client->dev,
421*4882a593Smuzhiyun 				"Failed to fetch attribute %s, error %d\n",
422*4882a593Smuzhiyun 				dattr->attr.name, error);
423*4882a593Smuzhiyun 			goto out;
424*4882a593Smuzhiyun 		}
425*4882a593Smuzhiyun 	} else {
426*4882a593Smuzhiyun 		val = *field;
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	if (val != *field) {
430*4882a593Smuzhiyun 		dev_warn(&tsdata->client->dev,
431*4882a593Smuzhiyun 			 "%s: read (%d) and stored value (%d) differ\n",
432*4882a593Smuzhiyun 			 dattr->attr.name, val, *field);
433*4882a593Smuzhiyun 		*field = val;
434*4882a593Smuzhiyun 	}
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	count = scnprintf(buf, PAGE_SIZE, "%d\n", val);
437*4882a593Smuzhiyun out:
438*4882a593Smuzhiyun 	mutex_unlock(&tsdata->mutex);
439*4882a593Smuzhiyun 	return error ?: count;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun 
edt_ft5x06_setting_store(struct device * dev,struct device_attribute * dattr,const char * buf,size_t count)442*4882a593Smuzhiyun static ssize_t edt_ft5x06_setting_store(struct device *dev,
443*4882a593Smuzhiyun 					struct device_attribute *dattr,
444*4882a593Smuzhiyun 					const char *buf, size_t count)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
447*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
448*4882a593Smuzhiyun 	struct edt_ft5x06_attribute *attr =
449*4882a593Smuzhiyun 			container_of(dattr, struct edt_ft5x06_attribute, dattr);
450*4882a593Smuzhiyun 	u8 *field = (u8 *)tsdata + attr->field_offset;
451*4882a593Smuzhiyun 	unsigned int val;
452*4882a593Smuzhiyun 	int error;
453*4882a593Smuzhiyun 	u8 addr;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	mutex_lock(&tsdata->mutex);
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	if (tsdata->factory_mode) {
458*4882a593Smuzhiyun 		error = -EIO;
459*4882a593Smuzhiyun 		goto out;
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	error = kstrtouint(buf, 0, &val);
463*4882a593Smuzhiyun 	if (error)
464*4882a593Smuzhiyun 		goto out;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	if (val < attr->limit_low || val > attr->limit_high) {
467*4882a593Smuzhiyun 		error = -ERANGE;
468*4882a593Smuzhiyun 		goto out;
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	switch (tsdata->version) {
472*4882a593Smuzhiyun 	case EDT_M06:
473*4882a593Smuzhiyun 		addr = attr->addr_m06;
474*4882a593Smuzhiyun 		break;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun 	case EDT_M09:
477*4882a593Smuzhiyun 	case EDT_M12:
478*4882a593Smuzhiyun 	case GENERIC_FT:
479*4882a593Smuzhiyun 		addr = attr->addr_m09;
480*4882a593Smuzhiyun 		break;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	case EV_FT:
483*4882a593Smuzhiyun 		addr = attr->addr_ev;
484*4882a593Smuzhiyun 		break;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	default:
487*4882a593Smuzhiyun 		error = -ENODEV;
488*4882a593Smuzhiyun 		goto out;
489*4882a593Smuzhiyun 	}
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	if (addr != NO_REGISTER) {
492*4882a593Smuzhiyun 		error = edt_ft5x06_register_write(tsdata, addr, val);
493*4882a593Smuzhiyun 		if (error) {
494*4882a593Smuzhiyun 			dev_err(&tsdata->client->dev,
495*4882a593Smuzhiyun 				"Failed to update attribute %s, error: %d\n",
496*4882a593Smuzhiyun 				dattr->attr.name, error);
497*4882a593Smuzhiyun 			goto out;
498*4882a593Smuzhiyun 		}
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 	*field = val;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun out:
503*4882a593Smuzhiyun 	mutex_unlock(&tsdata->mutex);
504*4882a593Smuzhiyun 	return error ?: count;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun /* m06, m09: range 0-31, m12: range 0-5 */
508*4882a593Smuzhiyun static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN,
509*4882a593Smuzhiyun 		M09_REGISTER_GAIN, EV_REGISTER_GAIN, 0, 31);
510*4882a593Smuzhiyun /* m06, m09: range 0-31, m12: range 0-16 */
511*4882a593Smuzhiyun static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET,
512*4882a593Smuzhiyun 		M09_REGISTER_OFFSET, NO_REGISTER, 0, 31);
513*4882a593Smuzhiyun /* m06, m09, m12: no supported, ev_ft: range 0-80 */
514*4882a593Smuzhiyun static EDT_ATTR(offset_x, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
515*4882a593Smuzhiyun 		EV_REGISTER_OFFSET_X, 0, 80);
516*4882a593Smuzhiyun /* m06, m09, m12: no supported, ev_ft: range 0-80 */
517*4882a593Smuzhiyun static EDT_ATTR(offset_y, S_IWUSR | S_IRUGO, NO_REGISTER, NO_REGISTER,
518*4882a593Smuzhiyun 		EV_REGISTER_OFFSET_Y, 0, 80);
519*4882a593Smuzhiyun /* m06: range 20 to 80, m09: range 0 to 30, m12: range 1 to 255... */
520*4882a593Smuzhiyun static EDT_ATTR(threshold, S_IWUSR | S_IRUGO, WORK_REGISTER_THRESHOLD,
521*4882a593Smuzhiyun 		M09_REGISTER_THRESHOLD, EV_REGISTER_THRESHOLD, 0, 255);
522*4882a593Smuzhiyun /* m06: range 3 to 14, m12: (0x64: 100Hz) */
523*4882a593Smuzhiyun static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO, WORK_REGISTER_REPORT_RATE,
524*4882a593Smuzhiyun 		NO_REGISTER, NO_REGISTER, 0, 255);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun static struct attribute *edt_ft5x06_attrs[] = {
527*4882a593Smuzhiyun 	&edt_ft5x06_attr_gain.dattr.attr,
528*4882a593Smuzhiyun 	&edt_ft5x06_attr_offset.dattr.attr,
529*4882a593Smuzhiyun 	&edt_ft5x06_attr_offset_x.dattr.attr,
530*4882a593Smuzhiyun 	&edt_ft5x06_attr_offset_y.dattr.attr,
531*4882a593Smuzhiyun 	&edt_ft5x06_attr_threshold.dattr.attr,
532*4882a593Smuzhiyun 	&edt_ft5x06_attr_report_rate.dattr.attr,
533*4882a593Smuzhiyun 	NULL
534*4882a593Smuzhiyun };
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun static const struct attribute_group edt_ft5x06_attr_group = {
537*4882a593Smuzhiyun 	.attrs = edt_ft5x06_attrs,
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun 
edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data * tsdata)540*4882a593Smuzhiyun static void edt_ft5x06_restore_reg_parameters(struct edt_ft5x06_ts_data *tsdata)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun 	struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun 	edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold,
545*4882a593Smuzhiyun 				  tsdata->threshold);
546*4882a593Smuzhiyun 	edt_ft5x06_register_write(tsdata, reg_addr->reg_gain,
547*4882a593Smuzhiyun 				  tsdata->gain);
548*4882a593Smuzhiyun 	if (reg_addr->reg_offset != NO_REGISTER)
549*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset,
550*4882a593Smuzhiyun 					  tsdata->offset);
551*4882a593Smuzhiyun 	if (reg_addr->reg_offset_x != NO_REGISTER)
552*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x,
553*4882a593Smuzhiyun 					  tsdata->offset_x);
554*4882a593Smuzhiyun 	if (reg_addr->reg_offset_y != NO_REGISTER)
555*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y,
556*4882a593Smuzhiyun 					  tsdata->offset_y);
557*4882a593Smuzhiyun 	if (reg_addr->reg_report_rate != NO_REGISTER)
558*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_report_rate,
559*4882a593Smuzhiyun 				  tsdata->report_rate);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun }
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_FS
edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data * tsdata)564*4882a593Smuzhiyun static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun 	struct i2c_client *client = tsdata->client;
567*4882a593Smuzhiyun 	int retries = EDT_SWITCH_MODE_RETRIES;
568*4882a593Smuzhiyun 	int ret;
569*4882a593Smuzhiyun 	int error;
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	if (tsdata->version != EDT_M06) {
572*4882a593Smuzhiyun 		dev_err(&client->dev,
573*4882a593Smuzhiyun 			"No factory mode support for non-M06 devices\n");
574*4882a593Smuzhiyun 		return -EINVAL;
575*4882a593Smuzhiyun 	}
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	disable_irq(client->irq);
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	if (!tsdata->raw_buffer) {
580*4882a593Smuzhiyun 		tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y *
581*4882a593Smuzhiyun 				      sizeof(u16);
582*4882a593Smuzhiyun 		tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL);
583*4882a593Smuzhiyun 		if (!tsdata->raw_buffer) {
584*4882a593Smuzhiyun 			error = -ENOMEM;
585*4882a593Smuzhiyun 			goto err_out;
586*4882a593Smuzhiyun 		}
587*4882a593Smuzhiyun 	}
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 	/* mode register is 0x3c when in the work mode */
590*4882a593Smuzhiyun 	error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
591*4882a593Smuzhiyun 	if (error) {
592*4882a593Smuzhiyun 		dev_err(&client->dev,
593*4882a593Smuzhiyun 			"failed to switch to factory mode, error %d\n", error);
594*4882a593Smuzhiyun 		goto err_out;
595*4882a593Smuzhiyun 	}
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	tsdata->factory_mode = true;
598*4882a593Smuzhiyun 	do {
599*4882a593Smuzhiyun 		mdelay(EDT_SWITCH_MODE_DELAY);
600*4882a593Smuzhiyun 		/* mode register is 0x01 when in factory mode */
601*4882a593Smuzhiyun 		ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE);
602*4882a593Smuzhiyun 		if (ret == 0x03)
603*4882a593Smuzhiyun 			break;
604*4882a593Smuzhiyun 	} while (--retries > 0);
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	if (retries == 0) {
607*4882a593Smuzhiyun 		dev_err(&client->dev, "not in factory mode after %dms.\n",
608*4882a593Smuzhiyun 			EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY);
609*4882a593Smuzhiyun 		error = -EIO;
610*4882a593Smuzhiyun 		goto err_out;
611*4882a593Smuzhiyun 	}
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	return 0;
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun err_out:
616*4882a593Smuzhiyun 	kfree(tsdata->raw_buffer);
617*4882a593Smuzhiyun 	tsdata->raw_buffer = NULL;
618*4882a593Smuzhiyun 	tsdata->factory_mode = false;
619*4882a593Smuzhiyun 	enable_irq(client->irq);
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	return error;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun 
edt_ft5x06_work_mode(struct edt_ft5x06_ts_data * tsdata)624*4882a593Smuzhiyun static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
625*4882a593Smuzhiyun {
626*4882a593Smuzhiyun 	struct i2c_client *client = tsdata->client;
627*4882a593Smuzhiyun 	int retries = EDT_SWITCH_MODE_RETRIES;
628*4882a593Smuzhiyun 	int ret;
629*4882a593Smuzhiyun 	int error;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	/* mode register is 0x01 when in the factory mode */
632*4882a593Smuzhiyun 	error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1);
633*4882a593Smuzhiyun 	if (error) {
634*4882a593Smuzhiyun 		dev_err(&client->dev,
635*4882a593Smuzhiyun 			"failed to switch to work mode, error: %d\n", error);
636*4882a593Smuzhiyun 		return error;
637*4882a593Smuzhiyun 	}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	tsdata->factory_mode = false;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	do {
642*4882a593Smuzhiyun 		mdelay(EDT_SWITCH_MODE_DELAY);
643*4882a593Smuzhiyun 		/* mode register is 0x01 when in factory mode */
644*4882a593Smuzhiyun 		ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE);
645*4882a593Smuzhiyun 		if (ret == 0x01)
646*4882a593Smuzhiyun 			break;
647*4882a593Smuzhiyun 	} while (--retries > 0);
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	if (retries == 0) {
650*4882a593Smuzhiyun 		dev_err(&client->dev, "not in work mode after %dms.\n",
651*4882a593Smuzhiyun 			EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY);
652*4882a593Smuzhiyun 		tsdata->factory_mode = true;
653*4882a593Smuzhiyun 		return -EIO;
654*4882a593Smuzhiyun 	}
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun 	kfree(tsdata->raw_buffer);
657*4882a593Smuzhiyun 	tsdata->raw_buffer = NULL;
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	edt_ft5x06_restore_reg_parameters(tsdata);
660*4882a593Smuzhiyun 	enable_irq(client->irq);
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	return 0;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun 
edt_ft5x06_debugfs_mode_get(void * data,u64 * mode)665*4882a593Smuzhiyun static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = data;
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun 	*mode = tsdata->factory_mode;
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	return 0;
672*4882a593Smuzhiyun };
673*4882a593Smuzhiyun 
edt_ft5x06_debugfs_mode_set(void * data,u64 mode)674*4882a593Smuzhiyun static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
675*4882a593Smuzhiyun {
676*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = data;
677*4882a593Smuzhiyun 	int retval = 0;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 	if (mode > 1)
680*4882a593Smuzhiyun 		return -ERANGE;
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 	mutex_lock(&tsdata->mutex);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	if (mode != tsdata->factory_mode) {
685*4882a593Smuzhiyun 		retval = mode ? edt_ft5x06_factory_mode(tsdata) :
686*4882a593Smuzhiyun 				edt_ft5x06_work_mode(tsdata);
687*4882a593Smuzhiyun 	}
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	mutex_unlock(&tsdata->mutex);
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	return retval;
692*4882a593Smuzhiyun };
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
695*4882a593Smuzhiyun 			edt_ft5x06_debugfs_mode_set, "%llu\n");
696*4882a593Smuzhiyun 
edt_ft5x06_debugfs_raw_data_read(struct file * file,char __user * buf,size_t count,loff_t * off)697*4882a593Smuzhiyun static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
698*4882a593Smuzhiyun 				char __user *buf, size_t count, loff_t *off)
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = file->private_data;
701*4882a593Smuzhiyun 	struct i2c_client *client = tsdata->client;
702*4882a593Smuzhiyun 	int retries  = EDT_RAW_DATA_RETRIES;
703*4882a593Smuzhiyun 	int val, i, error;
704*4882a593Smuzhiyun 	size_t read = 0;
705*4882a593Smuzhiyun 	int colbytes;
706*4882a593Smuzhiyun 	char wrbuf[3];
707*4882a593Smuzhiyun 	u8 *rdbuf;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (*off < 0 || *off >= tsdata->raw_bufsize)
710*4882a593Smuzhiyun 		return 0;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	mutex_lock(&tsdata->mutex);
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun 	if (!tsdata->factory_mode || !tsdata->raw_buffer) {
715*4882a593Smuzhiyun 		error = -EIO;
716*4882a593Smuzhiyun 		goto out;
717*4882a593Smuzhiyun 	}
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	error = edt_ft5x06_register_write(tsdata, 0x08, 0x01);
720*4882a593Smuzhiyun 	if (error) {
721*4882a593Smuzhiyun 		dev_dbg(&client->dev,
722*4882a593Smuzhiyun 			"failed to write 0x08 register, error %d\n", error);
723*4882a593Smuzhiyun 		goto out;
724*4882a593Smuzhiyun 	}
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	do {
727*4882a593Smuzhiyun 		usleep_range(EDT_RAW_DATA_DELAY, EDT_RAW_DATA_DELAY + 100);
728*4882a593Smuzhiyun 		val = edt_ft5x06_register_read(tsdata, 0x08);
729*4882a593Smuzhiyun 		if (val < 1)
730*4882a593Smuzhiyun 			break;
731*4882a593Smuzhiyun 	} while (--retries > 0);
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun 	if (val < 0) {
734*4882a593Smuzhiyun 		error = val;
735*4882a593Smuzhiyun 		dev_dbg(&client->dev,
736*4882a593Smuzhiyun 			"failed to read 0x08 register, error %d\n", error);
737*4882a593Smuzhiyun 		goto out;
738*4882a593Smuzhiyun 	}
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun 	if (retries == 0) {
741*4882a593Smuzhiyun 		dev_dbg(&client->dev,
742*4882a593Smuzhiyun 			"timed out waiting for register to settle\n");
743*4882a593Smuzhiyun 		error = -ETIMEDOUT;
744*4882a593Smuzhiyun 		goto out;
745*4882a593Smuzhiyun 	}
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	rdbuf = tsdata->raw_buffer;
748*4882a593Smuzhiyun 	colbytes = tsdata->num_y * sizeof(u16);
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun 	wrbuf[0] = 0xf5;
751*4882a593Smuzhiyun 	wrbuf[1] = 0x0e;
752*4882a593Smuzhiyun 	for (i = 0; i < tsdata->num_x; i++) {
753*4882a593Smuzhiyun 		wrbuf[2] = i;  /* column index */
754*4882a593Smuzhiyun 		error = edt_ft5x06_ts_readwrite(tsdata->client,
755*4882a593Smuzhiyun 						sizeof(wrbuf), wrbuf,
756*4882a593Smuzhiyun 						colbytes, rdbuf);
757*4882a593Smuzhiyun 		if (error)
758*4882a593Smuzhiyun 			goto out;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 		rdbuf += colbytes;
761*4882a593Smuzhiyun 	}
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	read = min_t(size_t, count, tsdata->raw_bufsize - *off);
764*4882a593Smuzhiyun 	if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
765*4882a593Smuzhiyun 		error = -EFAULT;
766*4882a593Smuzhiyun 		goto out;
767*4882a593Smuzhiyun 	}
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun 	*off += read;
770*4882a593Smuzhiyun out:
771*4882a593Smuzhiyun 	mutex_unlock(&tsdata->mutex);
772*4882a593Smuzhiyun 	return error ?: read;
773*4882a593Smuzhiyun };
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun static const struct file_operations debugfs_raw_data_fops = {
776*4882a593Smuzhiyun 	.open = simple_open,
777*4882a593Smuzhiyun 	.read = edt_ft5x06_debugfs_raw_data_read,
778*4882a593Smuzhiyun };
779*4882a593Smuzhiyun 
edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data * tsdata,const char * debugfs_name)780*4882a593Smuzhiyun static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
781*4882a593Smuzhiyun 					  const char *debugfs_name)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun 	tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL);
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x);
786*4882a593Smuzhiyun 	debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y);
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	debugfs_create_file("mode", S_IRUSR | S_IWUSR,
789*4882a593Smuzhiyun 			    tsdata->debug_dir, tsdata, &debugfs_mode_fops);
790*4882a593Smuzhiyun 	debugfs_create_file("raw_data", S_IRUSR,
791*4882a593Smuzhiyun 			    tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
792*4882a593Smuzhiyun }
793*4882a593Smuzhiyun 
edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data * tsdata)794*4882a593Smuzhiyun static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun 	debugfs_remove_recursive(tsdata->debug_dir);
797*4882a593Smuzhiyun 	kfree(tsdata->raw_buffer);
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun #else
801*4882a593Smuzhiyun 
edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data * tsdata)802*4882a593Smuzhiyun static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
803*4882a593Smuzhiyun {
804*4882a593Smuzhiyun 	return -ENOSYS;
805*4882a593Smuzhiyun }
806*4882a593Smuzhiyun 
edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data * tsdata,const char * debugfs_name)807*4882a593Smuzhiyun static void edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
808*4882a593Smuzhiyun 					  const char *debugfs_name)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun 
edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data * tsdata)812*4882a593Smuzhiyun static void edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun }
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun #endif /* CONFIG_DEBUGFS */
817*4882a593Smuzhiyun 
edt_ft5x06_ts_identify(struct i2c_client * client,struct edt_ft5x06_ts_data * tsdata,char * fw_version)818*4882a593Smuzhiyun static int edt_ft5x06_ts_identify(struct i2c_client *client,
819*4882a593Smuzhiyun 					struct edt_ft5x06_ts_data *tsdata,
820*4882a593Smuzhiyun 					char *fw_version)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun 	u8 rdbuf[EDT_NAME_LEN];
823*4882a593Smuzhiyun 	char *p;
824*4882a593Smuzhiyun 	int error;
825*4882a593Smuzhiyun 	char *model_name = tsdata->name;
826*4882a593Smuzhiyun 
827*4882a593Smuzhiyun 	/* see what we find if we assume it is a M06 *
828*4882a593Smuzhiyun 	 * if we get less than EDT_NAME_LEN, we don't want
829*4882a593Smuzhiyun 	 * to have garbage in there
830*4882a593Smuzhiyun 	 */
831*4882a593Smuzhiyun 	memset(rdbuf, 0, sizeof(rdbuf));
832*4882a593Smuzhiyun 	error = edt_ft5x06_ts_readwrite(client, 1, "\xBB",
833*4882a593Smuzhiyun 					EDT_NAME_LEN - 1, rdbuf);
834*4882a593Smuzhiyun 	if (error)
835*4882a593Smuzhiyun 		return error;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	/* Probe content for something consistent.
838*4882a593Smuzhiyun 	 * M06 starts with a response byte, M12 gives the data directly.
839*4882a593Smuzhiyun 	 * M09/Generic does not provide model number information.
840*4882a593Smuzhiyun 	 */
841*4882a593Smuzhiyun 	if (!strncasecmp(rdbuf + 1, "EP0", 3)) {
842*4882a593Smuzhiyun 		tsdata->version = EDT_M06;
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 		/* remove last '$' end marker */
845*4882a593Smuzhiyun 		rdbuf[EDT_NAME_LEN - 1] = '\0';
846*4882a593Smuzhiyun 		if (rdbuf[EDT_NAME_LEN - 2] == '$')
847*4882a593Smuzhiyun 			rdbuf[EDT_NAME_LEN - 2] = '\0';
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun 		/* look for Model/Version separator */
850*4882a593Smuzhiyun 		p = strchr(rdbuf, '*');
851*4882a593Smuzhiyun 		if (p)
852*4882a593Smuzhiyun 			*p++ = '\0';
853*4882a593Smuzhiyun 		strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
854*4882a593Smuzhiyun 		strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
855*4882a593Smuzhiyun 	} else if (!strncasecmp(rdbuf, "EP0", 3)) {
856*4882a593Smuzhiyun 		tsdata->version = EDT_M12;
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 		/* remove last '$' end marker */
859*4882a593Smuzhiyun 		rdbuf[EDT_NAME_LEN - 2] = '\0';
860*4882a593Smuzhiyun 		if (rdbuf[EDT_NAME_LEN - 3] == '$')
861*4882a593Smuzhiyun 			rdbuf[EDT_NAME_LEN - 3] = '\0';
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 		/* look for Model/Version separator */
864*4882a593Smuzhiyun 		p = strchr(rdbuf, '*');
865*4882a593Smuzhiyun 		if (p)
866*4882a593Smuzhiyun 			*p++ = '\0';
867*4882a593Smuzhiyun 		strlcpy(model_name, rdbuf, EDT_NAME_LEN);
868*4882a593Smuzhiyun 		strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
869*4882a593Smuzhiyun 	} else {
870*4882a593Smuzhiyun 		/* If it is not an EDT M06/M12 touchscreen, then the model
871*4882a593Smuzhiyun 		 * detection is a bit hairy. The different ft5x06
872*4882a593Smuzhiyun 		 * firmares around don't reliably implement the
873*4882a593Smuzhiyun 		 * identification registers. Well, we'll take a shot.
874*4882a593Smuzhiyun 		 *
875*4882a593Smuzhiyun 		 * The main difference between generic focaltec based
876*4882a593Smuzhiyun 		 * touches and EDT M09 is that we know how to retrieve
877*4882a593Smuzhiyun 		 * the max coordinates for the latter.
878*4882a593Smuzhiyun 		 */
879*4882a593Smuzhiyun 		tsdata->version = GENERIC_FT;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun 		error = edt_ft5x06_ts_readwrite(client, 1, "\xA6",
882*4882a593Smuzhiyun 						2, rdbuf);
883*4882a593Smuzhiyun 		if (error)
884*4882a593Smuzhiyun 			return error;
885*4882a593Smuzhiyun 
886*4882a593Smuzhiyun 		strlcpy(fw_version, rdbuf, 2);
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 		error = edt_ft5x06_ts_readwrite(client, 1, "\xA8",
889*4882a593Smuzhiyun 						1, rdbuf);
890*4882a593Smuzhiyun 		if (error)
891*4882a593Smuzhiyun 			return error;
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun 		/* This "model identification" is not exact. Unfortunately
894*4882a593Smuzhiyun 		 * not all firmwares for the ft5x06 put useful values in
895*4882a593Smuzhiyun 		 * the identification registers.
896*4882a593Smuzhiyun 		 */
897*4882a593Smuzhiyun 		switch (rdbuf[0]) {
898*4882a593Smuzhiyun 		case 0x35:   /* EDT EP0350M09 */
899*4882a593Smuzhiyun 		case 0x43:   /* EDT EP0430M09 */
900*4882a593Smuzhiyun 		case 0x50:   /* EDT EP0500M09 */
901*4882a593Smuzhiyun 		case 0x57:   /* EDT EP0570M09 */
902*4882a593Smuzhiyun 		case 0x70:   /* EDT EP0700M09 */
903*4882a593Smuzhiyun 			tsdata->version = EDT_M09;
904*4882a593Smuzhiyun 			snprintf(model_name, EDT_NAME_LEN, "EP0%i%i0M09",
905*4882a593Smuzhiyun 				rdbuf[0] >> 4, rdbuf[0] & 0x0F);
906*4882a593Smuzhiyun 			break;
907*4882a593Smuzhiyun 		case 0xa1:   /* EDT EP1010ML00 */
908*4882a593Smuzhiyun 			tsdata->version = EDT_M09;
909*4882a593Smuzhiyun 			snprintf(model_name, EDT_NAME_LEN, "EP%i%i0ML00",
910*4882a593Smuzhiyun 				rdbuf[0] >> 4, rdbuf[0] & 0x0F);
911*4882a593Smuzhiyun 			break;
912*4882a593Smuzhiyun 		case 0x5a:   /* Solomon Goldentek Display */
913*4882a593Smuzhiyun 			snprintf(model_name, EDT_NAME_LEN, "GKTW50SCED1R0");
914*4882a593Smuzhiyun 			break;
915*4882a593Smuzhiyun 		case 0x59:  /* Evervision Display with FT5xx6 TS */
916*4882a593Smuzhiyun 			tsdata->version = EV_FT;
917*4882a593Smuzhiyun 			error = edt_ft5x06_ts_readwrite(client, 1, "\x53",
918*4882a593Smuzhiyun 							1, rdbuf);
919*4882a593Smuzhiyun 			if (error)
920*4882a593Smuzhiyun 				return error;
921*4882a593Smuzhiyun 			strlcpy(fw_version, rdbuf, 1);
922*4882a593Smuzhiyun 			snprintf(model_name, EDT_NAME_LEN,
923*4882a593Smuzhiyun 				 "EVERVISION-FT5726NEi");
924*4882a593Smuzhiyun 			break;
925*4882a593Smuzhiyun 		default:
926*4882a593Smuzhiyun 			snprintf(model_name, EDT_NAME_LEN,
927*4882a593Smuzhiyun 				 "generic ft5x06 (%02x)",
928*4882a593Smuzhiyun 				 rdbuf[0]);
929*4882a593Smuzhiyun 			break;
930*4882a593Smuzhiyun 		}
931*4882a593Smuzhiyun 	}
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 	return 0;
934*4882a593Smuzhiyun }
935*4882a593Smuzhiyun 
edt_ft5x06_ts_get_defaults(struct device * dev,struct edt_ft5x06_ts_data * tsdata)936*4882a593Smuzhiyun static void edt_ft5x06_ts_get_defaults(struct device *dev,
937*4882a593Smuzhiyun 				       struct edt_ft5x06_ts_data *tsdata)
938*4882a593Smuzhiyun {
939*4882a593Smuzhiyun 	struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
940*4882a593Smuzhiyun 	u32 val;
941*4882a593Smuzhiyun 	int error;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	error = device_property_read_u32(dev, "threshold", &val);
944*4882a593Smuzhiyun 	if (!error) {
945*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_threshold, val);
946*4882a593Smuzhiyun 		tsdata->threshold = val;
947*4882a593Smuzhiyun 	}
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	error = device_property_read_u32(dev, "gain", &val);
950*4882a593Smuzhiyun 	if (!error) {
951*4882a593Smuzhiyun 		edt_ft5x06_register_write(tsdata, reg_addr->reg_gain, val);
952*4882a593Smuzhiyun 		tsdata->gain = val;
953*4882a593Smuzhiyun 	}
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 	error = device_property_read_u32(dev, "offset", &val);
956*4882a593Smuzhiyun 	if (!error) {
957*4882a593Smuzhiyun 		if (reg_addr->reg_offset != NO_REGISTER)
958*4882a593Smuzhiyun 			edt_ft5x06_register_write(tsdata,
959*4882a593Smuzhiyun 						  reg_addr->reg_offset, val);
960*4882a593Smuzhiyun 		tsdata->offset = val;
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	error = device_property_read_u32(dev, "offset-x", &val);
964*4882a593Smuzhiyun 	if (!error) {
965*4882a593Smuzhiyun 		if (reg_addr->reg_offset_x != NO_REGISTER)
966*4882a593Smuzhiyun 			edt_ft5x06_register_write(tsdata,
967*4882a593Smuzhiyun 						  reg_addr->reg_offset_x, val);
968*4882a593Smuzhiyun 		tsdata->offset_x = val;
969*4882a593Smuzhiyun 	}
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	error = device_property_read_u32(dev, "offset-y", &val);
972*4882a593Smuzhiyun 	if (!error) {
973*4882a593Smuzhiyun 		if (reg_addr->reg_offset_y != NO_REGISTER)
974*4882a593Smuzhiyun 			edt_ft5x06_register_write(tsdata,
975*4882a593Smuzhiyun 						  reg_addr->reg_offset_y, val);
976*4882a593Smuzhiyun 		tsdata->offset_y = val;
977*4882a593Smuzhiyun 	}
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun static void
edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data * tsdata)981*4882a593Smuzhiyun edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun 	struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	tsdata->threshold = edt_ft5x06_register_read(tsdata,
986*4882a593Smuzhiyun 						     reg_addr->reg_threshold);
987*4882a593Smuzhiyun 	tsdata->gain = edt_ft5x06_register_read(tsdata, reg_addr->reg_gain);
988*4882a593Smuzhiyun 	if (reg_addr->reg_offset != NO_REGISTER)
989*4882a593Smuzhiyun 		tsdata->offset =
990*4882a593Smuzhiyun 			edt_ft5x06_register_read(tsdata, reg_addr->reg_offset);
991*4882a593Smuzhiyun 	if (reg_addr->reg_offset_x != NO_REGISTER)
992*4882a593Smuzhiyun 		tsdata->offset_x = edt_ft5x06_register_read(tsdata,
993*4882a593Smuzhiyun 						reg_addr->reg_offset_x);
994*4882a593Smuzhiyun 	if (reg_addr->reg_offset_y != NO_REGISTER)
995*4882a593Smuzhiyun 		tsdata->offset_y = edt_ft5x06_register_read(tsdata,
996*4882a593Smuzhiyun 						reg_addr->reg_offset_y);
997*4882a593Smuzhiyun 	if (reg_addr->reg_report_rate != NO_REGISTER)
998*4882a593Smuzhiyun 		tsdata->report_rate = edt_ft5x06_register_read(tsdata,
999*4882a593Smuzhiyun 						reg_addr->reg_report_rate);
1000*4882a593Smuzhiyun 	if (tsdata->version == EDT_M06 ||
1001*4882a593Smuzhiyun 	    tsdata->version == EDT_M09 ||
1002*4882a593Smuzhiyun 	    tsdata->version == EDT_M12) {
1003*4882a593Smuzhiyun 		tsdata->num_x = edt_ft5x06_register_read(tsdata,
1004*4882a593Smuzhiyun 							 reg_addr->reg_num_x);
1005*4882a593Smuzhiyun 		tsdata->num_y = edt_ft5x06_register_read(tsdata,
1006*4882a593Smuzhiyun 							 reg_addr->reg_num_y);
1007*4882a593Smuzhiyun 	} else {
1008*4882a593Smuzhiyun 		tsdata->num_x = -1;
1009*4882a593Smuzhiyun 		tsdata->num_y = -1;
1010*4882a593Smuzhiyun 	}
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun 
1013*4882a593Smuzhiyun static void
edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data * tsdata)1014*4882a593Smuzhiyun edt_ft5x06_ts_set_regs(struct edt_ft5x06_ts_data *tsdata)
1015*4882a593Smuzhiyun {
1016*4882a593Smuzhiyun 	struct edt_reg_addr *reg_addr = &tsdata->reg_addr;
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	switch (tsdata->version) {
1019*4882a593Smuzhiyun 	case EDT_M06:
1020*4882a593Smuzhiyun 		reg_addr->reg_threshold = WORK_REGISTER_THRESHOLD;
1021*4882a593Smuzhiyun 		reg_addr->reg_report_rate = WORK_REGISTER_REPORT_RATE;
1022*4882a593Smuzhiyun 		reg_addr->reg_gain = WORK_REGISTER_GAIN;
1023*4882a593Smuzhiyun 		reg_addr->reg_offset = WORK_REGISTER_OFFSET;
1024*4882a593Smuzhiyun 		reg_addr->reg_offset_x = NO_REGISTER;
1025*4882a593Smuzhiyun 		reg_addr->reg_offset_y = NO_REGISTER;
1026*4882a593Smuzhiyun 		reg_addr->reg_num_x = WORK_REGISTER_NUM_X;
1027*4882a593Smuzhiyun 		reg_addr->reg_num_y = WORK_REGISTER_NUM_Y;
1028*4882a593Smuzhiyun 		break;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 	case EDT_M09:
1031*4882a593Smuzhiyun 	case EDT_M12:
1032*4882a593Smuzhiyun 		reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
1033*4882a593Smuzhiyun 		reg_addr->reg_report_rate = NO_REGISTER;
1034*4882a593Smuzhiyun 		reg_addr->reg_gain = M09_REGISTER_GAIN;
1035*4882a593Smuzhiyun 		reg_addr->reg_offset = M09_REGISTER_OFFSET;
1036*4882a593Smuzhiyun 		reg_addr->reg_offset_x = NO_REGISTER;
1037*4882a593Smuzhiyun 		reg_addr->reg_offset_y = NO_REGISTER;
1038*4882a593Smuzhiyun 		reg_addr->reg_num_x = M09_REGISTER_NUM_X;
1039*4882a593Smuzhiyun 		reg_addr->reg_num_y = M09_REGISTER_NUM_Y;
1040*4882a593Smuzhiyun 		break;
1041*4882a593Smuzhiyun 
1042*4882a593Smuzhiyun 	case EV_FT:
1043*4882a593Smuzhiyun 		reg_addr->reg_threshold = EV_REGISTER_THRESHOLD;
1044*4882a593Smuzhiyun 		reg_addr->reg_gain = EV_REGISTER_GAIN;
1045*4882a593Smuzhiyun 		reg_addr->reg_offset = NO_REGISTER;
1046*4882a593Smuzhiyun 		reg_addr->reg_offset_x = EV_REGISTER_OFFSET_X;
1047*4882a593Smuzhiyun 		reg_addr->reg_offset_y = EV_REGISTER_OFFSET_Y;
1048*4882a593Smuzhiyun 		reg_addr->reg_num_x = NO_REGISTER;
1049*4882a593Smuzhiyun 		reg_addr->reg_num_y = NO_REGISTER;
1050*4882a593Smuzhiyun 		reg_addr->reg_report_rate = NO_REGISTER;
1051*4882a593Smuzhiyun 		break;
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	case GENERIC_FT:
1054*4882a593Smuzhiyun 		/* this is a guesswork */
1055*4882a593Smuzhiyun 		reg_addr->reg_threshold = M09_REGISTER_THRESHOLD;
1056*4882a593Smuzhiyun 		reg_addr->reg_gain = M09_REGISTER_GAIN;
1057*4882a593Smuzhiyun 		reg_addr->reg_offset = M09_REGISTER_OFFSET;
1058*4882a593Smuzhiyun 		reg_addr->reg_offset_x = NO_REGISTER;
1059*4882a593Smuzhiyun 		reg_addr->reg_offset_y = NO_REGISTER;
1060*4882a593Smuzhiyun 		break;
1061*4882a593Smuzhiyun 	}
1062*4882a593Smuzhiyun }
1063*4882a593Smuzhiyun 
edt_ft5x06_disable_regulator(void * arg)1064*4882a593Smuzhiyun static void edt_ft5x06_disable_regulator(void *arg)
1065*4882a593Smuzhiyun {
1066*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *data = arg;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun 	regulator_disable(data->vcc);
1069*4882a593Smuzhiyun }
1070*4882a593Smuzhiyun 
edt_ft5x06_ts_probe(struct i2c_client * client,const struct i2c_device_id * id)1071*4882a593Smuzhiyun static int edt_ft5x06_ts_probe(struct i2c_client *client,
1072*4882a593Smuzhiyun 					 const struct i2c_device_id *id)
1073*4882a593Smuzhiyun {
1074*4882a593Smuzhiyun 	const struct edt_i2c_chip_data *chip_data;
1075*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata;
1076*4882a593Smuzhiyun 	u8 buf[2] = { 0xfc, 0x00 };
1077*4882a593Smuzhiyun 	struct input_dev *input;
1078*4882a593Smuzhiyun 	unsigned long irq_flags;
1079*4882a593Smuzhiyun 	int error;
1080*4882a593Smuzhiyun 	char fw_version[EDT_NAME_LEN];
1081*4882a593Smuzhiyun 
1082*4882a593Smuzhiyun 	dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n");
1083*4882a593Smuzhiyun 
1084*4882a593Smuzhiyun 	tsdata = devm_kzalloc(&client->dev, sizeof(*tsdata), GFP_KERNEL);
1085*4882a593Smuzhiyun 	if (!tsdata) {
1086*4882a593Smuzhiyun 		dev_err(&client->dev, "failed to allocate driver data.\n");
1087*4882a593Smuzhiyun 		return -ENOMEM;
1088*4882a593Smuzhiyun 	}
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	chip_data = device_get_match_data(&client->dev);
1091*4882a593Smuzhiyun 	if (!chip_data)
1092*4882a593Smuzhiyun 		chip_data = (const struct edt_i2c_chip_data *)id->driver_data;
1093*4882a593Smuzhiyun 	if (!chip_data || !chip_data->max_support_points) {
1094*4882a593Smuzhiyun 		dev_err(&client->dev, "invalid or missing chip data\n");
1095*4882a593Smuzhiyun 		return -EINVAL;
1096*4882a593Smuzhiyun 	}
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun 	tsdata->max_support_points = chip_data->max_support_points;
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun 	tsdata->vcc = devm_regulator_get(&client->dev, "vcc");
1101*4882a593Smuzhiyun 	if (IS_ERR(tsdata->vcc)) {
1102*4882a593Smuzhiyun 		error = PTR_ERR(tsdata->vcc);
1103*4882a593Smuzhiyun 		if (error != -EPROBE_DEFER)
1104*4882a593Smuzhiyun 			dev_err(&client->dev,
1105*4882a593Smuzhiyun 				"failed to request regulator: %d\n", error);
1106*4882a593Smuzhiyun 		return error;
1107*4882a593Smuzhiyun 	}
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	error = regulator_enable(tsdata->vcc);
1110*4882a593Smuzhiyun 	if (error < 0) {
1111*4882a593Smuzhiyun 		dev_err(&client->dev, "failed to enable vcc: %d\n", error);
1112*4882a593Smuzhiyun 		return error;
1113*4882a593Smuzhiyun 	}
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	error = devm_add_action_or_reset(&client->dev,
1116*4882a593Smuzhiyun 					 edt_ft5x06_disable_regulator,
1117*4882a593Smuzhiyun 					 tsdata);
1118*4882a593Smuzhiyun 	if (error)
1119*4882a593Smuzhiyun 		return error;
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun 	tsdata->reset_gpio = devm_gpiod_get_optional(&client->dev,
1122*4882a593Smuzhiyun 						     "reset", GPIOD_OUT_HIGH);
1123*4882a593Smuzhiyun 	if (IS_ERR(tsdata->reset_gpio)) {
1124*4882a593Smuzhiyun 		error = PTR_ERR(tsdata->reset_gpio);
1125*4882a593Smuzhiyun 		dev_err(&client->dev,
1126*4882a593Smuzhiyun 			"Failed to request GPIO reset pin, error %d\n", error);
1127*4882a593Smuzhiyun 		return error;
1128*4882a593Smuzhiyun 	}
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun 	tsdata->wake_gpio = devm_gpiod_get_optional(&client->dev,
1131*4882a593Smuzhiyun 						    "wake", GPIOD_OUT_LOW);
1132*4882a593Smuzhiyun 	if (IS_ERR(tsdata->wake_gpio)) {
1133*4882a593Smuzhiyun 		error = PTR_ERR(tsdata->wake_gpio);
1134*4882a593Smuzhiyun 		dev_err(&client->dev,
1135*4882a593Smuzhiyun 			"Failed to request GPIO wake pin, error %d\n", error);
1136*4882a593Smuzhiyun 		return error;
1137*4882a593Smuzhiyun 	}
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun 	/*
1140*4882a593Smuzhiyun 	 * Check which sleep modes we can support. Power-off requieres the
1141*4882a593Smuzhiyun 	 * reset-pin to ensure correct power-down/power-up behaviour. Start with
1142*4882a593Smuzhiyun 	 * the EDT_PMODE_POWEROFF test since this is the deepest possible sleep
1143*4882a593Smuzhiyun 	 * mode.
1144*4882a593Smuzhiyun 	 */
1145*4882a593Smuzhiyun 	if (tsdata->reset_gpio)
1146*4882a593Smuzhiyun 		tsdata->suspend_mode = EDT_PMODE_POWEROFF;
1147*4882a593Smuzhiyun 	else if (tsdata->wake_gpio)
1148*4882a593Smuzhiyun 		tsdata->suspend_mode = EDT_PMODE_HIBERNATE;
1149*4882a593Smuzhiyun 	else
1150*4882a593Smuzhiyun 		tsdata->suspend_mode = EDT_PMODE_NOT_SUPPORTED;
1151*4882a593Smuzhiyun 
1152*4882a593Smuzhiyun 	if (tsdata->wake_gpio) {
1153*4882a593Smuzhiyun 		usleep_range(5000, 6000);
1154*4882a593Smuzhiyun 		gpiod_set_value_cansleep(tsdata->wake_gpio, 1);
1155*4882a593Smuzhiyun 	}
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	if (tsdata->reset_gpio) {
1158*4882a593Smuzhiyun 		usleep_range(5000, 6000);
1159*4882a593Smuzhiyun 		gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
1160*4882a593Smuzhiyun 		msleep(300);
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 
1163*4882a593Smuzhiyun 	input = devm_input_allocate_device(&client->dev);
1164*4882a593Smuzhiyun 	if (!input) {
1165*4882a593Smuzhiyun 		dev_err(&client->dev, "failed to allocate input device.\n");
1166*4882a593Smuzhiyun 		return -ENOMEM;
1167*4882a593Smuzhiyun 	}
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun 	mutex_init(&tsdata->mutex);
1170*4882a593Smuzhiyun 	tsdata->client = client;
1171*4882a593Smuzhiyun 	tsdata->input = input;
1172*4882a593Smuzhiyun 	tsdata->factory_mode = false;
1173*4882a593Smuzhiyun 
1174*4882a593Smuzhiyun 	error = edt_ft5x06_ts_identify(client, tsdata, fw_version);
1175*4882a593Smuzhiyun 	if (error) {
1176*4882a593Smuzhiyun 		dev_err(&client->dev, "touchscreen probe failed\n");
1177*4882a593Smuzhiyun 		return error;
1178*4882a593Smuzhiyun 	}
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun 	/*
1181*4882a593Smuzhiyun 	 * Dummy read access. EP0700MLP1 returns bogus data on the first
1182*4882a593Smuzhiyun 	 * register read access and ignores writes.
1183*4882a593Smuzhiyun 	 */
1184*4882a593Smuzhiyun 	edt_ft5x06_ts_readwrite(tsdata->client, 2, buf, 2, buf);
1185*4882a593Smuzhiyun 
1186*4882a593Smuzhiyun 	edt_ft5x06_ts_set_regs(tsdata);
1187*4882a593Smuzhiyun 	edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
1188*4882a593Smuzhiyun 	edt_ft5x06_ts_get_parameters(tsdata);
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun 	dev_dbg(&client->dev,
1191*4882a593Smuzhiyun 		"Model \"%s\", Rev. \"%s\", %dx%d sensors\n",
1192*4882a593Smuzhiyun 		tsdata->name, fw_version, tsdata->num_x, tsdata->num_y);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	input->name = tsdata->name;
1195*4882a593Smuzhiyun 	input->id.bustype = BUS_I2C;
1196*4882a593Smuzhiyun 	input->dev.parent = &client->dev;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun 	if (tsdata->version == EDT_M06 ||
1199*4882a593Smuzhiyun 	    tsdata->version == EDT_M09 ||
1200*4882a593Smuzhiyun 	    tsdata->version == EDT_M12) {
1201*4882a593Smuzhiyun 		input_set_abs_params(input, ABS_MT_POSITION_X,
1202*4882a593Smuzhiyun 				     0, tsdata->num_x * 64 - 1, 0, 0);
1203*4882a593Smuzhiyun 		input_set_abs_params(input, ABS_MT_POSITION_Y,
1204*4882a593Smuzhiyun 				     0, tsdata->num_y * 64 - 1, 0, 0);
1205*4882a593Smuzhiyun 	} else {
1206*4882a593Smuzhiyun 		/* Unknown maximum values. Specify via devicetree */
1207*4882a593Smuzhiyun 		input_set_abs_params(input, ABS_MT_POSITION_X,
1208*4882a593Smuzhiyun 				     0, 65535, 0, 0);
1209*4882a593Smuzhiyun 		input_set_abs_params(input, ABS_MT_POSITION_Y,
1210*4882a593Smuzhiyun 				     0, 65535, 0, 0);
1211*4882a593Smuzhiyun 	}
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun 	touchscreen_parse_properties(input, true, &tsdata->prop);
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun 	error = input_mt_init_slots(input, tsdata->max_support_points,
1216*4882a593Smuzhiyun 				INPUT_MT_DIRECT);
1217*4882a593Smuzhiyun 	if (error) {
1218*4882a593Smuzhiyun 		dev_err(&client->dev, "Unable to init MT slots.\n");
1219*4882a593Smuzhiyun 		return error;
1220*4882a593Smuzhiyun 	}
1221*4882a593Smuzhiyun 
1222*4882a593Smuzhiyun 	i2c_set_clientdata(client, tsdata);
1223*4882a593Smuzhiyun 
1224*4882a593Smuzhiyun 	irq_flags = irq_get_trigger_type(client->irq);
1225*4882a593Smuzhiyun 	if (irq_flags == IRQF_TRIGGER_NONE)
1226*4882a593Smuzhiyun 		irq_flags = IRQF_TRIGGER_FALLING;
1227*4882a593Smuzhiyun 	irq_flags |= IRQF_ONESHOT;
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	error = devm_request_threaded_irq(&client->dev, client->irq,
1230*4882a593Smuzhiyun 					NULL, edt_ft5x06_ts_isr, irq_flags,
1231*4882a593Smuzhiyun 					client->name, tsdata);
1232*4882a593Smuzhiyun 	if (error) {
1233*4882a593Smuzhiyun 		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
1234*4882a593Smuzhiyun 		return error;
1235*4882a593Smuzhiyun 	}
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
1238*4882a593Smuzhiyun 	if (error)
1239*4882a593Smuzhiyun 		return error;
1240*4882a593Smuzhiyun 
1241*4882a593Smuzhiyun 	error = input_register_device(input);
1242*4882a593Smuzhiyun 	if (error)
1243*4882a593Smuzhiyun 		return error;
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun 	edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 	dev_dbg(&client->dev,
1248*4882a593Smuzhiyun 		"EDT FT5x06 initialized: IRQ %d, WAKE pin %d, Reset pin %d.\n",
1249*4882a593Smuzhiyun 		client->irq,
1250*4882a593Smuzhiyun 		tsdata->wake_gpio ? desc_to_gpio(tsdata->wake_gpio) : -1,
1251*4882a593Smuzhiyun 		tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1);
1252*4882a593Smuzhiyun 
1253*4882a593Smuzhiyun 	return 0;
1254*4882a593Smuzhiyun }
1255*4882a593Smuzhiyun 
edt_ft5x06_ts_remove(struct i2c_client * client)1256*4882a593Smuzhiyun static int edt_ft5x06_ts_remove(struct i2c_client *client)
1257*4882a593Smuzhiyun {
1258*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	edt_ft5x06_ts_teardown_debugfs(tsdata);
1261*4882a593Smuzhiyun 
1262*4882a593Smuzhiyun 	return 0;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun 
edt_ft5x06_ts_suspend(struct device * dev)1265*4882a593Smuzhiyun static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
1266*4882a593Smuzhiyun {
1267*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1268*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
1269*4882a593Smuzhiyun 	struct gpio_desc *reset_gpio = tsdata->reset_gpio;
1270*4882a593Smuzhiyun 	int ret;
1271*4882a593Smuzhiyun 
1272*4882a593Smuzhiyun 	if (device_may_wakeup(dev))
1273*4882a593Smuzhiyun 		return 0;
1274*4882a593Smuzhiyun 
1275*4882a593Smuzhiyun 	if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED)
1276*4882a593Smuzhiyun 		return 0;
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	/* Enter hibernate mode. */
1279*4882a593Smuzhiyun 	ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE,
1280*4882a593Smuzhiyun 					PMOD_REGISTER_HIBERNATE);
1281*4882a593Smuzhiyun 	if (ret)
1282*4882a593Smuzhiyun 		dev_warn(dev, "Failed to set hibernate mode\n");
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	if (tsdata->suspend_mode == EDT_PMODE_HIBERNATE)
1285*4882a593Smuzhiyun 		return 0;
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun 	/*
1288*4882a593Smuzhiyun 	 * Power-off according the datasheet. Cut the power may leaf the irq
1289*4882a593Smuzhiyun 	 * line in an undefined state depending on the host pull resistor
1290*4882a593Smuzhiyun 	 * settings. Disable the irq to avoid adjusting each host till the
1291*4882a593Smuzhiyun 	 * device is back in a full functional state.
1292*4882a593Smuzhiyun 	 */
1293*4882a593Smuzhiyun 	disable_irq(tsdata->client->irq);
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	gpiod_set_value_cansleep(reset_gpio, 1);
1296*4882a593Smuzhiyun 	usleep_range(1000, 2000);
1297*4882a593Smuzhiyun 
1298*4882a593Smuzhiyun 	ret = regulator_disable(tsdata->vcc);
1299*4882a593Smuzhiyun 	if (ret)
1300*4882a593Smuzhiyun 		dev_warn(dev, "Failed to disable vcc\n");
1301*4882a593Smuzhiyun 
1302*4882a593Smuzhiyun 	return 0;
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun 
edt_ft5x06_ts_resume(struct device * dev)1305*4882a593Smuzhiyun static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
1306*4882a593Smuzhiyun {
1307*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
1308*4882a593Smuzhiyun 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
1309*4882a593Smuzhiyun 	int ret = 0;
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun 	if (device_may_wakeup(dev))
1312*4882a593Smuzhiyun 		return 0;
1313*4882a593Smuzhiyun 
1314*4882a593Smuzhiyun 	if (tsdata->suspend_mode == EDT_PMODE_NOT_SUPPORTED)
1315*4882a593Smuzhiyun 		return 0;
1316*4882a593Smuzhiyun 
1317*4882a593Smuzhiyun 	if (tsdata->suspend_mode == EDT_PMODE_POWEROFF) {
1318*4882a593Smuzhiyun 		struct gpio_desc *reset_gpio = tsdata->reset_gpio;
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 		/*
1321*4882a593Smuzhiyun 		 * We can't check if the regulator is a dummy or a real
1322*4882a593Smuzhiyun 		 * regulator. So we need to specify the 5ms reset time (T_rst)
1323*4882a593Smuzhiyun 		 * here instead of the 100us T_rtp time. We also need to wait
1324*4882a593Smuzhiyun 		 * 300ms in case it was a real supply and the power was cutted
1325*4882a593Smuzhiyun 		 * of. Toggle the reset pin is also a way to exit the hibernate
1326*4882a593Smuzhiyun 		 * mode.
1327*4882a593Smuzhiyun 		 */
1328*4882a593Smuzhiyun 		gpiod_set_value_cansleep(reset_gpio, 1);
1329*4882a593Smuzhiyun 		usleep_range(5000, 6000);
1330*4882a593Smuzhiyun 
1331*4882a593Smuzhiyun 		ret = regulator_enable(tsdata->vcc);
1332*4882a593Smuzhiyun 		if (ret) {
1333*4882a593Smuzhiyun 			dev_err(dev, "Failed to enable vcc\n");
1334*4882a593Smuzhiyun 			return ret;
1335*4882a593Smuzhiyun 		}
1336*4882a593Smuzhiyun 
1337*4882a593Smuzhiyun 		usleep_range(1000, 2000);
1338*4882a593Smuzhiyun 		gpiod_set_value_cansleep(reset_gpio, 0);
1339*4882a593Smuzhiyun 		msleep(300);
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 		edt_ft5x06_restore_reg_parameters(tsdata);
1342*4882a593Smuzhiyun 		enable_irq(tsdata->client->irq);
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun 		if (tsdata->factory_mode)
1345*4882a593Smuzhiyun 			ret = edt_ft5x06_factory_mode(tsdata);
1346*4882a593Smuzhiyun 	} else {
1347*4882a593Smuzhiyun 		struct gpio_desc *wake_gpio = tsdata->wake_gpio;
1348*4882a593Smuzhiyun 
1349*4882a593Smuzhiyun 		gpiod_set_value_cansleep(wake_gpio, 0);
1350*4882a593Smuzhiyun 		usleep_range(5000, 6000);
1351*4882a593Smuzhiyun 		gpiod_set_value_cansleep(wake_gpio, 1);
1352*4882a593Smuzhiyun 	}
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun 
1355*4882a593Smuzhiyun 	return ret;
1356*4882a593Smuzhiyun }
1357*4882a593Smuzhiyun 
1358*4882a593Smuzhiyun static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
1359*4882a593Smuzhiyun 			 edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun static const struct edt_i2c_chip_data edt_ft5x06_data = {
1362*4882a593Smuzhiyun 	.max_support_points = 5,
1363*4882a593Smuzhiyun };
1364*4882a593Smuzhiyun 
1365*4882a593Smuzhiyun static const struct edt_i2c_chip_data edt_ft5506_data = {
1366*4882a593Smuzhiyun 	.max_support_points = 10,
1367*4882a593Smuzhiyun };
1368*4882a593Smuzhiyun 
1369*4882a593Smuzhiyun static const struct edt_i2c_chip_data edt_ft6236_data = {
1370*4882a593Smuzhiyun 	.max_support_points = 2,
1371*4882a593Smuzhiyun };
1372*4882a593Smuzhiyun 
1373*4882a593Smuzhiyun static const struct i2c_device_id edt_ft5x06_ts_id[] = {
1374*4882a593Smuzhiyun 	{ .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
1375*4882a593Smuzhiyun 	{ .name = "edt-ft5506", .driver_data = (long)&edt_ft5506_data },
1376*4882a593Smuzhiyun 	{ .name = "ev-ft5726", .driver_data = (long)&edt_ft5506_data },
1377*4882a593Smuzhiyun 	/* Note no edt- prefix for compatibility with the ft6236.c driver */
1378*4882a593Smuzhiyun 	{ .name = "ft6236", .driver_data = (long)&edt_ft6236_data },
1379*4882a593Smuzhiyun 	{ /* sentinel */ }
1380*4882a593Smuzhiyun };
1381*4882a593Smuzhiyun MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun static const struct of_device_id edt_ft5x06_of_match[] = {
1384*4882a593Smuzhiyun 	{ .compatible = "edt,edt-ft5206", .data = &edt_ft5x06_data },
1385*4882a593Smuzhiyun 	{ .compatible = "edt,edt-ft5306", .data = &edt_ft5x06_data },
1386*4882a593Smuzhiyun 	{ .compatible = "edt,edt-ft5406", .data = &edt_ft5x06_data },
1387*4882a593Smuzhiyun 	{ .compatible = "edt,edt-ft5506", .data = &edt_ft5506_data },
1388*4882a593Smuzhiyun 	{ .compatible = "evervision,ev-ft5726", .data = &edt_ft5506_data },
1389*4882a593Smuzhiyun 	/* Note focaltech vendor prefix for compatibility with ft6236.c */
1390*4882a593Smuzhiyun 	{ .compatible = "focaltech,ft6236", .data = &edt_ft6236_data },
1391*4882a593Smuzhiyun 	{ /* sentinel */ }
1392*4882a593Smuzhiyun };
1393*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, edt_ft5x06_of_match);
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun static struct i2c_driver edt_ft5x06_ts_driver = {
1396*4882a593Smuzhiyun 	.driver = {
1397*4882a593Smuzhiyun 		.name = "edt_ft5x06",
1398*4882a593Smuzhiyun 		.of_match_table = edt_ft5x06_of_match,
1399*4882a593Smuzhiyun 		.pm = &edt_ft5x06_ts_pm_ops,
1400*4882a593Smuzhiyun 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
1401*4882a593Smuzhiyun 	},
1402*4882a593Smuzhiyun 	.id_table = edt_ft5x06_ts_id,
1403*4882a593Smuzhiyun 	.probe    = edt_ft5x06_ts_probe,
1404*4882a593Smuzhiyun 	.remove   = edt_ft5x06_ts_remove,
1405*4882a593Smuzhiyun };
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun module_i2c_driver(edt_ft5x06_ts_driver);
1408*4882a593Smuzhiyun 
1409*4882a593Smuzhiyun MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>");
1410*4882a593Smuzhiyun MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");
1411*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1412