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