1ca96ea86SBastien Nocera /*
2ca96ea86SBastien Nocera  *  Driver for Goodix Touchscreens
3ca96ea86SBastien Nocera  *
4ca96ea86SBastien Nocera  *  Copyright (c) 2014 Red Hat Inc.
5ca96ea86SBastien Nocera  *
6ca96ea86SBastien Nocera  *  This code is based on gt9xx.c authored by andrew@goodix.com:
7ca96ea86SBastien Nocera  *
8ca96ea86SBastien Nocera  *  2010 - 2012 Goodix Technology.
9ca96ea86SBastien Nocera  */
10ca96ea86SBastien Nocera 
11ca96ea86SBastien Nocera /*
12ca96ea86SBastien Nocera  * This program is free software; you can redistribute it and/or modify it
13ca96ea86SBastien Nocera  * under the terms of the GNU General Public License as published by the Free
14ca96ea86SBastien Nocera  * Software Foundation; version 2 of the License.
15ca96ea86SBastien Nocera  */
16ca96ea86SBastien Nocera 
17ca96ea86SBastien Nocera #include <linux/kernel.h>
188b5a359cSBastien Nocera #include <linux/dmi.h>
19ca96ea86SBastien Nocera #include <linux/i2c.h>
20ca96ea86SBastien Nocera #include <linux/input.h>
21ca96ea86SBastien Nocera #include <linux/input/mt.h>
22ca96ea86SBastien Nocera #include <linux/module.h>
23ca96ea86SBastien Nocera #include <linux/delay.h>
24ca96ea86SBastien Nocera #include <linux/irq.h>
25ca96ea86SBastien Nocera #include <linux/interrupt.h>
26ca96ea86SBastien Nocera #include <linux/slab.h>
27771d8f1bSAleksei Mamlin #include <linux/acpi.h>
28771d8f1bSAleksei Mamlin #include <linux/of.h>
29ca96ea86SBastien Nocera #include <asm/unaligned.h>
30ca96ea86SBastien Nocera 
31ca96ea86SBastien Nocera struct goodix_ts_data {
32ca96ea86SBastien Nocera 	struct i2c_client *client;
33ca96ea86SBastien Nocera 	struct input_dev *input_dev;
34ca96ea86SBastien Nocera 	int abs_x_max;
35ca96ea86SBastien Nocera 	int abs_y_max;
36ca96ea86SBastien Nocera 	unsigned int max_touch_num;
37ca96ea86SBastien Nocera 	unsigned int int_trigger_type;
388b5a359cSBastien Nocera 	bool rotated_screen;
39a779fbc6SIrina Tirdea 	int cfg_len;
40ca96ea86SBastien Nocera };
41ca96ea86SBastien Nocera 
42ca96ea86SBastien Nocera #define GOODIX_MAX_HEIGHT		4096
43ca96ea86SBastien Nocera #define GOODIX_MAX_WIDTH		4096
44ca96ea86SBastien Nocera #define GOODIX_INT_TRIGGER		1
45ca96ea86SBastien Nocera #define GOODIX_CONTACT_SIZE		8
46ca96ea86SBastien Nocera #define GOODIX_MAX_CONTACTS		10
47ca96ea86SBastien Nocera 
48ca96ea86SBastien Nocera #define GOODIX_CONFIG_MAX_LENGTH	240
49a779fbc6SIrina Tirdea #define GOODIX_CONFIG_911_LENGTH	186
50a779fbc6SIrina Tirdea #define GOODIX_CONFIG_967_LENGTH	228
51ca96ea86SBastien Nocera 
52ca96ea86SBastien Nocera /* Register defines */
53ca96ea86SBastien Nocera #define GOODIX_READ_COOR_ADDR		0x814E
54ca96ea86SBastien Nocera #define GOODIX_REG_CONFIG_DATA		0x8047
55e70b0307SIrina Tirdea #define GOODIX_REG_ID			0x8140
56ca96ea86SBastien Nocera 
57ca96ea86SBastien Nocera #define RESOLUTION_LOC		1
58a7ac7c95SAleksei Mamlin #define MAX_CONTACTS_LOC	5
59ca96ea86SBastien Nocera #define TRIGGER_LOC		6
60ca96ea86SBastien Nocera 
61ca96ea86SBastien Nocera static const unsigned long goodix_irq_flags[] = {
62ca96ea86SBastien Nocera 	IRQ_TYPE_EDGE_RISING,
63ca96ea86SBastien Nocera 	IRQ_TYPE_EDGE_FALLING,
64ca96ea86SBastien Nocera 	IRQ_TYPE_LEVEL_LOW,
65ca96ea86SBastien Nocera 	IRQ_TYPE_LEVEL_HIGH,
66ca96ea86SBastien Nocera };
67ca96ea86SBastien Nocera 
688b5a359cSBastien Nocera /*
698b5a359cSBastien Nocera  * Those tablets have their coordinates origin at the bottom right
708b5a359cSBastien Nocera  * of the tablet, as if rotated 180 degrees
718b5a359cSBastien Nocera  */
728b5a359cSBastien Nocera static const struct dmi_system_id rotated_screen[] = {
738b5a359cSBastien Nocera #if defined(CONFIG_DMI) && defined(CONFIG_X86)
748b5a359cSBastien Nocera 	{
758b5a359cSBastien Nocera 		.ident = "WinBook TW100",
768b5a359cSBastien Nocera 		.matches = {
778b5a359cSBastien Nocera 			DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
788b5a359cSBastien Nocera 			DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
798b5a359cSBastien Nocera 		}
808b5a359cSBastien Nocera 	},
818b5a359cSBastien Nocera 	{
828b5a359cSBastien Nocera 		.ident = "WinBook TW700",
838b5a359cSBastien Nocera 		.matches = {
848b5a359cSBastien Nocera 			DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
858b5a359cSBastien Nocera 			DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
868b5a359cSBastien Nocera 		},
878b5a359cSBastien Nocera 	},
888b5a359cSBastien Nocera #endif
898b5a359cSBastien Nocera 	{}
908b5a359cSBastien Nocera };
918b5a359cSBastien Nocera 
92ca96ea86SBastien Nocera /**
93ca96ea86SBastien Nocera  * goodix_i2c_read - read data from a register of the i2c slave device.
94ca96ea86SBastien Nocera  *
95ca96ea86SBastien Nocera  * @client: i2c device.
96ca96ea86SBastien Nocera  * @reg: the register to read from.
97ca96ea86SBastien Nocera  * @buf: raw write data buffer.
98ca96ea86SBastien Nocera  * @len: length of the buffer to write
99ca96ea86SBastien Nocera  */
100ca96ea86SBastien Nocera static int goodix_i2c_read(struct i2c_client *client,
101ca96ea86SBastien Nocera 			   u16 reg, u8 *buf, int len)
102ca96ea86SBastien Nocera {
103ca96ea86SBastien Nocera 	struct i2c_msg msgs[2];
104ca96ea86SBastien Nocera 	u16 wbuf = cpu_to_be16(reg);
105ca96ea86SBastien Nocera 	int ret;
106ca96ea86SBastien Nocera 
107ca96ea86SBastien Nocera 	msgs[0].flags = 0;
108ca96ea86SBastien Nocera 	msgs[0].addr  = client->addr;
109ca96ea86SBastien Nocera 	msgs[0].len   = 2;
110ca96ea86SBastien Nocera 	msgs[0].buf   = (u8 *)&wbuf;
111ca96ea86SBastien Nocera 
112ca96ea86SBastien Nocera 	msgs[1].flags = I2C_M_RD;
113ca96ea86SBastien Nocera 	msgs[1].addr  = client->addr;
114ca96ea86SBastien Nocera 	msgs[1].len   = len;
115ca96ea86SBastien Nocera 	msgs[1].buf   = buf;
116ca96ea86SBastien Nocera 
117ca96ea86SBastien Nocera 	ret = i2c_transfer(client->adapter, msgs, 2);
118ca96ea86SBastien Nocera 	return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
119ca96ea86SBastien Nocera }
120ca96ea86SBastien Nocera 
121a779fbc6SIrina Tirdea static int goodix_get_cfg_len(u16 id)
122a779fbc6SIrina Tirdea {
123a779fbc6SIrina Tirdea 	switch (id) {
124a779fbc6SIrina Tirdea 	case 911:
125a779fbc6SIrina Tirdea 	case 9271:
126a779fbc6SIrina Tirdea 	case 9110:
127a779fbc6SIrina Tirdea 	case 927:
128a779fbc6SIrina Tirdea 	case 928:
129a779fbc6SIrina Tirdea 		return GOODIX_CONFIG_911_LENGTH;
130a779fbc6SIrina Tirdea 
131a779fbc6SIrina Tirdea 	case 912:
132a779fbc6SIrina Tirdea 	case 967:
133a779fbc6SIrina Tirdea 		return GOODIX_CONFIG_967_LENGTH;
134a779fbc6SIrina Tirdea 
135a779fbc6SIrina Tirdea 	default:
136a779fbc6SIrina Tirdea 		return GOODIX_CONFIG_MAX_LENGTH;
137a779fbc6SIrina Tirdea 	}
138a779fbc6SIrina Tirdea }
139a779fbc6SIrina Tirdea 
140ca96ea86SBastien Nocera static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
141ca96ea86SBastien Nocera {
142ca96ea86SBastien Nocera 	int touch_num;
143ca96ea86SBastien Nocera 	int error;
144ca96ea86SBastien Nocera 
145ca96ea86SBastien Nocera 	error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
146ca96ea86SBastien Nocera 				GOODIX_CONTACT_SIZE + 1);
147ca96ea86SBastien Nocera 	if (error) {
148ca96ea86SBastien Nocera 		dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
149ca96ea86SBastien Nocera 		return error;
150ca96ea86SBastien Nocera 	}
151ca96ea86SBastien Nocera 
1525f6f117cSPaul Cercueil 	if (!(data[0] & 0x80))
1535f6f117cSPaul Cercueil 		return -EAGAIN;
1545f6f117cSPaul Cercueil 
155ca96ea86SBastien Nocera 	touch_num = data[0] & 0x0f;
156a7ac7c95SAleksei Mamlin 	if (touch_num > ts->max_touch_num)
157ca96ea86SBastien Nocera 		return -EPROTO;
158ca96ea86SBastien Nocera 
159ca96ea86SBastien Nocera 	if (touch_num > 1) {
160ca96ea86SBastien Nocera 		data += 1 + GOODIX_CONTACT_SIZE;
161ca96ea86SBastien Nocera 		error = goodix_i2c_read(ts->client,
162ca96ea86SBastien Nocera 					GOODIX_READ_COOR_ADDR +
163ca96ea86SBastien Nocera 						1 + GOODIX_CONTACT_SIZE,
164ca96ea86SBastien Nocera 					data,
165ca96ea86SBastien Nocera 					GOODIX_CONTACT_SIZE * (touch_num - 1));
166ca96ea86SBastien Nocera 		if (error)
167ca96ea86SBastien Nocera 			return error;
168ca96ea86SBastien Nocera 	}
169ca96ea86SBastien Nocera 
170ca96ea86SBastien Nocera 	return touch_num;
171ca96ea86SBastien Nocera }
172ca96ea86SBastien Nocera 
173ca96ea86SBastien Nocera static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
174ca96ea86SBastien Nocera {
175ca96ea86SBastien Nocera 	int id = coor_data[0] & 0x0F;
176ca96ea86SBastien Nocera 	int input_x = get_unaligned_le16(&coor_data[1]);
177ca96ea86SBastien Nocera 	int input_y = get_unaligned_le16(&coor_data[3]);
178ca96ea86SBastien Nocera 	int input_w = get_unaligned_le16(&coor_data[5]);
179ca96ea86SBastien Nocera 
1808b5a359cSBastien Nocera 	if (ts->rotated_screen) {
1818b5a359cSBastien Nocera 		input_x = ts->abs_x_max - input_x;
1828b5a359cSBastien Nocera 		input_y = ts->abs_y_max - input_y;
1838b5a359cSBastien Nocera 	}
1848b5a359cSBastien Nocera 
185ca96ea86SBastien Nocera 	input_mt_slot(ts->input_dev, id);
186ca96ea86SBastien Nocera 	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
187ca96ea86SBastien Nocera 	input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
188ca96ea86SBastien Nocera 	input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
189ca96ea86SBastien Nocera 	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
190ca96ea86SBastien Nocera 	input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
191ca96ea86SBastien Nocera }
192ca96ea86SBastien Nocera 
193ca96ea86SBastien Nocera /**
194ca96ea86SBastien Nocera  * goodix_process_events - Process incoming events
195ca96ea86SBastien Nocera  *
196ca96ea86SBastien Nocera  * @ts: our goodix_ts_data pointer
197ca96ea86SBastien Nocera  *
198ca96ea86SBastien Nocera  * Called when the IRQ is triggered. Read the current device state, and push
199ca96ea86SBastien Nocera  * the input events to the user space.
200ca96ea86SBastien Nocera  */
201ca96ea86SBastien Nocera static void goodix_process_events(struct goodix_ts_data *ts)
202ca96ea86SBastien Nocera {
2030e0432f0SIrina Tirdea 	u8  point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
204ca96ea86SBastien Nocera 	int touch_num;
205ca96ea86SBastien Nocera 	int i;
206ca96ea86SBastien Nocera 
207ca96ea86SBastien Nocera 	touch_num = goodix_ts_read_input_report(ts, point_data);
208ca96ea86SBastien Nocera 	if (touch_num < 0)
209ca96ea86SBastien Nocera 		return;
210ca96ea86SBastien Nocera 
211ca96ea86SBastien Nocera 	for (i = 0; i < touch_num; i++)
212ca96ea86SBastien Nocera 		goodix_ts_report_touch(ts,
213ca96ea86SBastien Nocera 				&point_data[1 + GOODIX_CONTACT_SIZE * i]);
214ca96ea86SBastien Nocera 
215ca96ea86SBastien Nocera 	input_mt_sync_frame(ts->input_dev);
216ca96ea86SBastien Nocera 	input_sync(ts->input_dev);
217ca96ea86SBastien Nocera }
218ca96ea86SBastien Nocera 
219ca96ea86SBastien Nocera /**
220ca96ea86SBastien Nocera  * goodix_ts_irq_handler - The IRQ handler
221ca96ea86SBastien Nocera  *
222ca96ea86SBastien Nocera  * @irq: interrupt number.
223ca96ea86SBastien Nocera  * @dev_id: private data pointer.
224ca96ea86SBastien Nocera  */
225ca96ea86SBastien Nocera static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
226ca96ea86SBastien Nocera {
227ca96ea86SBastien Nocera 	static const u8 end_cmd[] = {
228ca96ea86SBastien Nocera 		GOODIX_READ_COOR_ADDR >> 8,
229ca96ea86SBastien Nocera 		GOODIX_READ_COOR_ADDR & 0xff,
230ca96ea86SBastien Nocera 		0
231ca96ea86SBastien Nocera 	};
232ca96ea86SBastien Nocera 	struct goodix_ts_data *ts = dev_id;
233ca96ea86SBastien Nocera 
234ca96ea86SBastien Nocera 	goodix_process_events(ts);
235ca96ea86SBastien Nocera 
236ca96ea86SBastien Nocera 	if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0)
237ca96ea86SBastien Nocera 		dev_err(&ts->client->dev, "I2C write end_cmd error\n");
238ca96ea86SBastien Nocera 
239ca96ea86SBastien Nocera 	return IRQ_HANDLED;
240ca96ea86SBastien Nocera }
241ca96ea86SBastien Nocera 
242ca96ea86SBastien Nocera /**
243ca96ea86SBastien Nocera  * goodix_read_config - Read the embedded configuration of the panel
244ca96ea86SBastien Nocera  *
245ca96ea86SBastien Nocera  * @ts: our goodix_ts_data pointer
246ca96ea86SBastien Nocera  *
247ca96ea86SBastien Nocera  * Must be called during probe
248ca96ea86SBastien Nocera  */
249ca96ea86SBastien Nocera static void goodix_read_config(struct goodix_ts_data *ts)
250ca96ea86SBastien Nocera {
251ca96ea86SBastien Nocera 	u8 config[GOODIX_CONFIG_MAX_LENGTH];
252ca96ea86SBastien Nocera 	int error;
253ca96ea86SBastien Nocera 
254ca96ea86SBastien Nocera 	error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
255a779fbc6SIrina Tirdea 				config, ts->cfg_len);
256ca96ea86SBastien Nocera 	if (error) {
257ca96ea86SBastien Nocera 		dev_warn(&ts->client->dev,
258ca96ea86SBastien Nocera 			 "Error reading config (%d), using defaults\n",
259ca96ea86SBastien Nocera 			 error);
260ca96ea86SBastien Nocera 		ts->abs_x_max = GOODIX_MAX_WIDTH;
261ca96ea86SBastien Nocera 		ts->abs_y_max = GOODIX_MAX_HEIGHT;
262ca96ea86SBastien Nocera 		ts->int_trigger_type = GOODIX_INT_TRIGGER;
263a7ac7c95SAleksei Mamlin 		ts->max_touch_num = GOODIX_MAX_CONTACTS;
264ca96ea86SBastien Nocera 		return;
265ca96ea86SBastien Nocera 	}
266ca96ea86SBastien Nocera 
267ca96ea86SBastien Nocera 	ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
268ca96ea86SBastien Nocera 	ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
269a7ac7c95SAleksei Mamlin 	ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
270a7ac7c95SAleksei Mamlin 	ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
271a7ac7c95SAleksei Mamlin 	if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
272ca96ea86SBastien Nocera 		dev_err(&ts->client->dev,
273ca96ea86SBastien Nocera 			"Invalid config, using defaults\n");
274ca96ea86SBastien Nocera 		ts->abs_x_max = GOODIX_MAX_WIDTH;
275ca96ea86SBastien Nocera 		ts->abs_y_max = GOODIX_MAX_HEIGHT;
276a7ac7c95SAleksei Mamlin 		ts->max_touch_num = GOODIX_MAX_CONTACTS;
277ca96ea86SBastien Nocera 	}
2788b5a359cSBastien Nocera 
2798b5a359cSBastien Nocera 	ts->rotated_screen = dmi_check_system(rotated_screen);
2808b5a359cSBastien Nocera 	if (ts->rotated_screen)
2818b5a359cSBastien Nocera 		dev_dbg(&ts->client->dev,
2828b5a359cSBastien Nocera 			 "Applying '180 degrees rotated screen' quirk\n");
283ca96ea86SBastien Nocera }
284ca96ea86SBastien Nocera 
285ca96ea86SBastien Nocera /**
286ca96ea86SBastien Nocera  * goodix_read_version - Read goodix touchscreen version
287ca96ea86SBastien Nocera  *
288ca96ea86SBastien Nocera  * @client: the i2c client
289ca96ea86SBastien Nocera  * @version: output buffer containing the version on success
290e70b0307SIrina Tirdea  * @id: output buffer containing the id on success
291ca96ea86SBastien Nocera  */
292e70b0307SIrina Tirdea static int goodix_read_version(struct i2c_client *client, u16 *version, u16 *id)
293ca96ea86SBastien Nocera {
294ca96ea86SBastien Nocera 	int error;
295ca96ea86SBastien Nocera 	u8 buf[6];
296e70b0307SIrina Tirdea 	char id_str[5];
297ca96ea86SBastien Nocera 
298e70b0307SIrina Tirdea 	error = goodix_i2c_read(client, GOODIX_REG_ID, buf, sizeof(buf));
299ca96ea86SBastien Nocera 	if (error) {
300ca96ea86SBastien Nocera 		dev_err(&client->dev, "read version failed: %d\n", error);
301ca96ea86SBastien Nocera 		return error;
302ca96ea86SBastien Nocera 	}
303ca96ea86SBastien Nocera 
304e70b0307SIrina Tirdea 	memcpy(id_str, buf, 4);
305e70b0307SIrina Tirdea 	id_str[4] = 0;
306e70b0307SIrina Tirdea 	if (kstrtou16(id_str, 10, id))
307e70b0307SIrina Tirdea 		*id = 0x1001;
308e70b0307SIrina Tirdea 
309ca96ea86SBastien Nocera 	*version = get_unaligned_le16(&buf[4]);
310ca96ea86SBastien Nocera 
311e70b0307SIrina Tirdea 	dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version);
312ca96ea86SBastien Nocera 
313ca96ea86SBastien Nocera 	return 0;
314ca96ea86SBastien Nocera }
315ca96ea86SBastien Nocera 
316ca96ea86SBastien Nocera /**
317ca96ea86SBastien Nocera  * goodix_i2c_test - I2C test function to check if the device answers.
318ca96ea86SBastien Nocera  *
319ca96ea86SBastien Nocera  * @client: the i2c client
320ca96ea86SBastien Nocera  */
321ca96ea86SBastien Nocera static int goodix_i2c_test(struct i2c_client *client)
322ca96ea86SBastien Nocera {
323ca96ea86SBastien Nocera 	int retry = 0;
324ca96ea86SBastien Nocera 	int error;
325ca96ea86SBastien Nocera 	u8 test;
326ca96ea86SBastien Nocera 
327ca96ea86SBastien Nocera 	while (retry++ < 2) {
328ca96ea86SBastien Nocera 		error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
329ca96ea86SBastien Nocera 					&test, 1);
330ca96ea86SBastien Nocera 		if (!error)
331ca96ea86SBastien Nocera 			return 0;
332ca96ea86SBastien Nocera 
333ca96ea86SBastien Nocera 		dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
334ca96ea86SBastien Nocera 			retry, error);
335ca96ea86SBastien Nocera 		msleep(20);
336ca96ea86SBastien Nocera 	}
337ca96ea86SBastien Nocera 
338ca96ea86SBastien Nocera 	return error;
339ca96ea86SBastien Nocera }
340ca96ea86SBastien Nocera 
341ca96ea86SBastien Nocera /**
342ca96ea86SBastien Nocera  * goodix_request_input_dev - Allocate, populate and register the input device
343ca96ea86SBastien Nocera  *
344ca96ea86SBastien Nocera  * @ts: our goodix_ts_data pointer
345e70b0307SIrina Tirdea  * @version: device firmware version
346e70b0307SIrina Tirdea  * @id: device ID
347ca96ea86SBastien Nocera  *
348ca96ea86SBastien Nocera  * Must be called during probe
349ca96ea86SBastien Nocera  */
350e70b0307SIrina Tirdea static int goodix_request_input_dev(struct goodix_ts_data *ts, u16 version,
351e70b0307SIrina Tirdea 				    u16 id)
352ca96ea86SBastien Nocera {
353ca96ea86SBastien Nocera 	int error;
354ca96ea86SBastien Nocera 
355ca96ea86SBastien Nocera 	ts->input_dev = devm_input_allocate_device(&ts->client->dev);
356ca96ea86SBastien Nocera 	if (!ts->input_dev) {
357ca96ea86SBastien Nocera 		dev_err(&ts->client->dev, "Failed to allocate input device.");
358ca96ea86SBastien Nocera 		return -ENOMEM;
359ca96ea86SBastien Nocera 	}
360ca96ea86SBastien Nocera 
3610dfb35bdSIrina Tirdea 	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
3620dfb35bdSIrina Tirdea 			     0, ts->abs_x_max, 0, 0);
3630dfb35bdSIrina Tirdea 	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
3640dfb35bdSIrina Tirdea 			     0, ts->abs_y_max, 0, 0);
365ca96ea86SBastien Nocera 	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
366ca96ea86SBastien Nocera 	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
367ca96ea86SBastien Nocera 
368a7ac7c95SAleksei Mamlin 	input_mt_init_slots(ts->input_dev, ts->max_touch_num,
369ca96ea86SBastien Nocera 			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
370ca96ea86SBastien Nocera 
371ca96ea86SBastien Nocera 	ts->input_dev->name = "Goodix Capacitive TouchScreen";
372ca96ea86SBastien Nocera 	ts->input_dev->phys = "input/ts";
373ca96ea86SBastien Nocera 	ts->input_dev->id.bustype = BUS_I2C;
374ca96ea86SBastien Nocera 	ts->input_dev->id.vendor = 0x0416;
375e70b0307SIrina Tirdea 	ts->input_dev->id.product = id;
376e70b0307SIrina Tirdea 	ts->input_dev->id.version = version;
377ca96ea86SBastien Nocera 
378ca96ea86SBastien Nocera 	error = input_register_device(ts->input_dev);
379ca96ea86SBastien Nocera 	if (error) {
380ca96ea86SBastien Nocera 		dev_err(&ts->client->dev,
381ca96ea86SBastien Nocera 			"Failed to register input device: %d", error);
382ca96ea86SBastien Nocera 		return error;
383ca96ea86SBastien Nocera 	}
384ca96ea86SBastien Nocera 
385ca96ea86SBastien Nocera 	return 0;
386ca96ea86SBastien Nocera }
387ca96ea86SBastien Nocera 
388ca96ea86SBastien Nocera static int goodix_ts_probe(struct i2c_client *client,
389ca96ea86SBastien Nocera 			   const struct i2c_device_id *id)
390ca96ea86SBastien Nocera {
391ca96ea86SBastien Nocera 	struct goodix_ts_data *ts;
392ca96ea86SBastien Nocera 	unsigned long irq_flags;
393ca96ea86SBastien Nocera 	int error;
394e70b0307SIrina Tirdea 	u16 version_info, id_info;
395ca96ea86SBastien Nocera 
396ca96ea86SBastien Nocera 	dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
397ca96ea86SBastien Nocera 
398ca96ea86SBastien Nocera 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
399ca96ea86SBastien Nocera 		dev_err(&client->dev, "I2C check functionality failed.\n");
400ca96ea86SBastien Nocera 		return -ENXIO;
401ca96ea86SBastien Nocera 	}
402ca96ea86SBastien Nocera 
403ca96ea86SBastien Nocera 	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
404ca96ea86SBastien Nocera 	if (!ts)
405ca96ea86SBastien Nocera 		return -ENOMEM;
406ca96ea86SBastien Nocera 
407ca96ea86SBastien Nocera 	ts->client = client;
408ca96ea86SBastien Nocera 	i2c_set_clientdata(client, ts);
409ca96ea86SBastien Nocera 
410ca96ea86SBastien Nocera 	error = goodix_i2c_test(client);
411ca96ea86SBastien Nocera 	if (error) {
412ca96ea86SBastien Nocera 		dev_err(&client->dev, "I2C communication failure: %d\n", error);
413ca96ea86SBastien Nocera 		return error;
414ca96ea86SBastien Nocera 	}
415ca96ea86SBastien Nocera 
416e70b0307SIrina Tirdea 	error = goodix_read_version(client, &version_info, &id_info);
417ca96ea86SBastien Nocera 	if (error) {
418ca96ea86SBastien Nocera 		dev_err(&client->dev, "Read version failed.\n");
419ca96ea86SBastien Nocera 		return error;
420ca96ea86SBastien Nocera 	}
421ca96ea86SBastien Nocera 
422a779fbc6SIrina Tirdea 	ts->cfg_len = goodix_get_cfg_len(id_info);
423a779fbc6SIrina Tirdea 
424ca96ea86SBastien Nocera 	goodix_read_config(ts);
425ca96ea86SBastien Nocera 
426e70b0307SIrina Tirdea 	error = goodix_request_input_dev(ts, version_info, id_info);
427ca96ea86SBastien Nocera 	if (error)
428ca96ea86SBastien Nocera 		return error;
429ca96ea86SBastien Nocera 
430ca96ea86SBastien Nocera 	irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
431ca96ea86SBastien Nocera 	error = devm_request_threaded_irq(&ts->client->dev, client->irq,
432ca96ea86SBastien Nocera 					  NULL, goodix_ts_irq_handler,
433ca96ea86SBastien Nocera 					  irq_flags, client->name, ts);
434ca96ea86SBastien Nocera 	if (error) {
435ca96ea86SBastien Nocera 		dev_err(&client->dev, "request IRQ failed: %d\n", error);
436ca96ea86SBastien Nocera 		return error;
437ca96ea86SBastien Nocera 	}
438ca96ea86SBastien Nocera 
439ca96ea86SBastien Nocera 	return 0;
440ca96ea86SBastien Nocera }
441ca96ea86SBastien Nocera 
442ca96ea86SBastien Nocera static const struct i2c_device_id goodix_ts_id[] = {
443ca96ea86SBastien Nocera 	{ "GDIX1001:00", 0 },
444ca96ea86SBastien Nocera 	{ }
445ca96ea86SBastien Nocera };
4462e9e910eSJavier Martinez Canillas MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
447ca96ea86SBastien Nocera 
448771d8f1bSAleksei Mamlin #ifdef CONFIG_ACPI
449ca96ea86SBastien Nocera static const struct acpi_device_id goodix_acpi_match[] = {
450ca96ea86SBastien Nocera 	{ "GDIX1001", 0 },
451ca96ea86SBastien Nocera 	{ }
452ca96ea86SBastien Nocera };
453ca96ea86SBastien Nocera MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
454771d8f1bSAleksei Mamlin #endif
455771d8f1bSAleksei Mamlin 
456771d8f1bSAleksei Mamlin #ifdef CONFIG_OF
457771d8f1bSAleksei Mamlin static const struct of_device_id goodix_of_match[] = {
458771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt911" },
459771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt9110" },
460771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt912" },
461771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt927" },
462771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt9271" },
463771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt928" },
464771d8f1bSAleksei Mamlin 	{ .compatible = "goodix,gt967" },
465771d8f1bSAleksei Mamlin 	{ }
466771d8f1bSAleksei Mamlin };
467771d8f1bSAleksei Mamlin MODULE_DEVICE_TABLE(of, goodix_of_match);
468771d8f1bSAleksei Mamlin #endif
469ca96ea86SBastien Nocera 
470ca96ea86SBastien Nocera static struct i2c_driver goodix_ts_driver = {
471ca96ea86SBastien Nocera 	.probe = goodix_ts_probe,
472ca96ea86SBastien Nocera 	.id_table = goodix_ts_id,
473ca96ea86SBastien Nocera 	.driver = {
474ca96ea86SBastien Nocera 		.name = "Goodix-TS",
475771d8f1bSAleksei Mamlin 		.acpi_match_table = ACPI_PTR(goodix_acpi_match),
476771d8f1bSAleksei Mamlin 		.of_match_table = of_match_ptr(goodix_of_match),
477ca96ea86SBastien Nocera 	},
478ca96ea86SBastien Nocera };
479ca96ea86SBastien Nocera module_i2c_driver(goodix_ts_driver);
480ca96ea86SBastien Nocera 
481ca96ea86SBastien Nocera MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
482ca96ea86SBastien Nocera MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
483ca96ea86SBastien Nocera MODULE_DESCRIPTION("Goodix touchscreen driver");
484ca96ea86SBastien Nocera MODULE_LICENSE("GPL v2");
485