blob: 5479aa17dba80273dee4b93eb762a4076f5477b3 [file] [log] [blame]
Bastien Noceraca96ea82014-10-31 09:26:16 -07001/*
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>
Bastien Nocera8b5a3592015-07-24 09:08:53 -070018#include <linux/dmi.h>
Bastien Noceraca96ea82014-10-31 09:26:16 -070019#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>
Aleksei Mamlin771d8f12015-03-06 16:43:38 -080027#include <linux/acpi.h>
28#include <linux/of.h>
Bastien Noceraca96ea82014-10-31 09:26:16 -070029#include <asm/unaligned.h>
30
31struct 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;
Bastien Nocera8b5a3592015-07-24 09:08:53 -070038 bool rotated_screen;
Irina Tirdeaa779fbc2015-12-17 15:55:21 -080039 int cfg_len;
Bastien Noceraca96ea82014-10-31 09:26:16 -070040};
41
42#define GOODIX_MAX_HEIGHT 4096
43#define GOODIX_MAX_WIDTH 4096
44#define GOODIX_INT_TRIGGER 1
45#define GOODIX_CONTACT_SIZE 8
46#define GOODIX_MAX_CONTACTS 10
47
48#define GOODIX_CONFIG_MAX_LENGTH 240
Irina Tirdeaa779fbc2015-12-17 15:55:21 -080049#define GOODIX_CONFIG_911_LENGTH 186
50#define GOODIX_CONFIG_967_LENGTH 228
Bastien Noceraca96ea82014-10-31 09:26:16 -070051
52/* Register defines */
53#define GOODIX_READ_COOR_ADDR 0x814E
54#define GOODIX_REG_CONFIG_DATA 0x8047
Irina Tirdeae70b0302015-06-09 11:04:40 -070055#define GOODIX_REG_ID 0x8140
Bastien Noceraca96ea82014-10-31 09:26:16 -070056
57#define RESOLUTION_LOC 1
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -080058#define MAX_CONTACTS_LOC 5
Bastien Noceraca96ea82014-10-31 09:26:16 -070059#define TRIGGER_LOC 6
60
61static const unsigned long goodix_irq_flags[] = {
62 IRQ_TYPE_EDGE_RISING,
63 IRQ_TYPE_EDGE_FALLING,
64 IRQ_TYPE_LEVEL_LOW,
65 IRQ_TYPE_LEVEL_HIGH,
66};
67
Bastien Nocera8b5a3592015-07-24 09:08:53 -070068/*
69 * Those tablets have their coordinates origin at the bottom right
70 * of the tablet, as if rotated 180 degrees
71 */
72static const struct dmi_system_id rotated_screen[] = {
73#if defined(CONFIG_DMI) && defined(CONFIG_X86)
74 {
75 .ident = "WinBook TW100",
76 .matches = {
77 DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
78 DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
79 }
80 },
81 {
82 .ident = "WinBook TW700",
83 .matches = {
84 DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
85 DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
86 },
87 },
88#endif
89 {}
90};
91
Bastien Noceraca96ea82014-10-31 09:26:16 -070092/**
93 * goodix_i2c_read - read data from a register of the i2c slave device.
94 *
95 * @client: i2c device.
96 * @reg: the register to read from.
97 * @buf: raw write data buffer.
98 * @len: length of the buffer to write
99 */
100static int goodix_i2c_read(struct i2c_client *client,
Irina Tirdea0dfb35b2015-06-09 11:01:38 -0700101 u16 reg, u8 *buf, int len)
Bastien Noceraca96ea82014-10-31 09:26:16 -0700102{
103 struct i2c_msg msgs[2];
104 u16 wbuf = cpu_to_be16(reg);
105 int ret;
106
107 msgs[0].flags = 0;
108 msgs[0].addr = client->addr;
109 msgs[0].len = 2;
Irina Tirdea0dfb35b2015-06-09 11:01:38 -0700110 msgs[0].buf = (u8 *)&wbuf;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700111
112 msgs[1].flags = I2C_M_RD;
113 msgs[1].addr = client->addr;
114 msgs[1].len = len;
115 msgs[1].buf = buf;
116
117 ret = i2c_transfer(client->adapter, msgs, 2);
118 return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
119}
120
Irina Tirdeaa779fbc2015-12-17 15:55:21 -0800121static int goodix_get_cfg_len(u16 id)
122{
123 switch (id) {
124 case 911:
125 case 9271:
126 case 9110:
127 case 927:
128 case 928:
129 return GOODIX_CONFIG_911_LENGTH;
130
131 case 912:
132 case 967:
133 return GOODIX_CONFIG_967_LENGTH;
134
135 default:
136 return GOODIX_CONFIG_MAX_LENGTH;
137 }
138}
139
Bastien Noceraca96ea82014-10-31 09:26:16 -0700140static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
141{
142 int touch_num;
143 int error;
144
145 error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
146 GOODIX_CONTACT_SIZE + 1);
147 if (error) {
148 dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
149 return error;
150 }
151
Paul Cercueil5f6f1172015-05-06 16:52:13 -0700152 if (!(data[0] & 0x80))
153 return -EAGAIN;
154
Bastien Noceraca96ea82014-10-31 09:26:16 -0700155 touch_num = data[0] & 0x0f;
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -0800156 if (touch_num > ts->max_touch_num)
Bastien Noceraca96ea82014-10-31 09:26:16 -0700157 return -EPROTO;
158
159 if (touch_num > 1) {
160 data += 1 + GOODIX_CONTACT_SIZE;
161 error = goodix_i2c_read(ts->client,
162 GOODIX_READ_COOR_ADDR +
163 1 + GOODIX_CONTACT_SIZE,
164 data,
165 GOODIX_CONTACT_SIZE * (touch_num - 1));
166 if (error)
167 return error;
168 }
169
170 return touch_num;
171}
172
173static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
174{
175 int id = coor_data[0] & 0x0F;
176 int input_x = get_unaligned_le16(&coor_data[1]);
177 int input_y = get_unaligned_le16(&coor_data[3]);
178 int input_w = get_unaligned_le16(&coor_data[5]);
179
Bastien Nocera8b5a3592015-07-24 09:08:53 -0700180 if (ts->rotated_screen) {
181 input_x = ts->abs_x_max - input_x;
182 input_y = ts->abs_y_max - input_y;
183 }
184
Bastien Noceraca96ea82014-10-31 09:26:16 -0700185 input_mt_slot(ts->input_dev, id);
186 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
187 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
188 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
189 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
190 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
191}
192
193/**
194 * goodix_process_events - Process incoming events
195 *
196 * @ts: our goodix_ts_data pointer
197 *
198 * Called when the IRQ is triggered. Read the current device state, and push
199 * the input events to the user space.
200 */
201static void goodix_process_events(struct goodix_ts_data *ts)
202{
Irina Tirdea0e0432f2015-06-09 11:03:15 -0700203 u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
Bastien Noceraca96ea82014-10-31 09:26:16 -0700204 int touch_num;
205 int i;
206
207 touch_num = goodix_ts_read_input_report(ts, point_data);
208 if (touch_num < 0)
209 return;
210
211 for (i = 0; i < touch_num; i++)
212 goodix_ts_report_touch(ts,
213 &point_data[1 + GOODIX_CONTACT_SIZE * i]);
214
215 input_mt_sync_frame(ts->input_dev);
216 input_sync(ts->input_dev);
217}
218
219/**
220 * goodix_ts_irq_handler - The IRQ handler
221 *
222 * @irq: interrupt number.
223 * @dev_id: private data pointer.
224 */
225static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
226{
227 static const u8 end_cmd[] = {
228 GOODIX_READ_COOR_ADDR >> 8,
229 GOODIX_READ_COOR_ADDR & 0xff,
230 0
231 };
232 struct goodix_ts_data *ts = dev_id;
233
234 goodix_process_events(ts);
235
236 if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0)
237 dev_err(&ts->client->dev, "I2C write end_cmd error\n");
238
239 return IRQ_HANDLED;
240}
241
242/**
243 * goodix_read_config - Read the embedded configuration of the panel
244 *
245 * @ts: our goodix_ts_data pointer
246 *
247 * Must be called during probe
248 */
249static void goodix_read_config(struct goodix_ts_data *ts)
250{
251 u8 config[GOODIX_CONFIG_MAX_LENGTH];
252 int error;
253
254 error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
Irina Tirdeaa779fbc2015-12-17 15:55:21 -0800255 config, ts->cfg_len);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700256 if (error) {
257 dev_warn(&ts->client->dev,
258 "Error reading config (%d), using defaults\n",
259 error);
260 ts->abs_x_max = GOODIX_MAX_WIDTH;
261 ts->abs_y_max = GOODIX_MAX_HEIGHT;
262 ts->int_trigger_type = GOODIX_INT_TRIGGER;
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -0800263 ts->max_touch_num = GOODIX_MAX_CONTACTS;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700264 return;
265 }
266
267 ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
268 ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -0800269 ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
270 ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
271 if (!ts->abs_x_max || !ts->abs_y_max || !ts->max_touch_num) {
Bastien Noceraca96ea82014-10-31 09:26:16 -0700272 dev_err(&ts->client->dev,
273 "Invalid config, using defaults\n");
274 ts->abs_x_max = GOODIX_MAX_WIDTH;
275 ts->abs_y_max = GOODIX_MAX_HEIGHT;
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -0800276 ts->max_touch_num = GOODIX_MAX_CONTACTS;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700277 }
Bastien Nocera8b5a3592015-07-24 09:08:53 -0700278
279 ts->rotated_screen = dmi_check_system(rotated_screen);
280 if (ts->rotated_screen)
281 dev_dbg(&ts->client->dev,
282 "Applying '180 degrees rotated screen' quirk\n");
Bastien Noceraca96ea82014-10-31 09:26:16 -0700283}
284
Bastien Noceraca96ea82014-10-31 09:26:16 -0700285/**
286 * goodix_read_version - Read goodix touchscreen version
287 *
288 * @client: the i2c client
289 * @version: output buffer containing the version on success
Irina Tirdeae70b0302015-06-09 11:04:40 -0700290 * @id: output buffer containing the id on success
Bastien Noceraca96ea82014-10-31 09:26:16 -0700291 */
Irina Tirdeae70b0302015-06-09 11:04:40 -0700292static int goodix_read_version(struct i2c_client *client, u16 *version, u16 *id)
Bastien Noceraca96ea82014-10-31 09:26:16 -0700293{
294 int error;
295 u8 buf[6];
Irina Tirdeae70b0302015-06-09 11:04:40 -0700296 char id_str[5];
Bastien Noceraca96ea82014-10-31 09:26:16 -0700297
Irina Tirdeae70b0302015-06-09 11:04:40 -0700298 error = goodix_i2c_read(client, GOODIX_REG_ID, buf, sizeof(buf));
Bastien Noceraca96ea82014-10-31 09:26:16 -0700299 if (error) {
300 dev_err(&client->dev, "read version failed: %d\n", error);
301 return error;
302 }
303
Irina Tirdeae70b0302015-06-09 11:04:40 -0700304 memcpy(id_str, buf, 4);
305 id_str[4] = 0;
306 if (kstrtou16(id_str, 10, id))
307 *id = 0x1001;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700308
Irina Tirdeae70b0302015-06-09 11:04:40 -0700309 *version = get_unaligned_le16(&buf[4]);
310
311 dev_info(&client->dev, "ID %d, version: %04x\n", *id, *version);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700312
313 return 0;
314}
315
316/**
317 * goodix_i2c_test - I2C test function to check if the device answers.
318 *
319 * @client: the i2c client
320 */
321static int goodix_i2c_test(struct i2c_client *client)
322{
323 int retry = 0;
324 int error;
325 u8 test;
326
327 while (retry++ < 2) {
328 error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
329 &test, 1);
330 if (!error)
331 return 0;
332
333 dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
334 retry, error);
335 msleep(20);
336 }
337
338 return error;
339}
340
341/**
342 * goodix_request_input_dev - Allocate, populate and register the input device
343 *
344 * @ts: our goodix_ts_data pointer
Irina Tirdeae70b0302015-06-09 11:04:40 -0700345 * @version: device firmware version
346 * @id: device ID
Bastien Noceraca96ea82014-10-31 09:26:16 -0700347 *
348 * Must be called during probe
349 */
Irina Tirdeae70b0302015-06-09 11:04:40 -0700350static int goodix_request_input_dev(struct goodix_ts_data *ts, u16 version,
351 u16 id)
Bastien Noceraca96ea82014-10-31 09:26:16 -0700352{
353 int error;
354
355 ts->input_dev = devm_input_allocate_device(&ts->client->dev);
356 if (!ts->input_dev) {
357 dev_err(&ts->client->dev, "Failed to allocate input device.");
358 return -ENOMEM;
359 }
360
Irina Tirdea0dfb35b2015-06-09 11:01:38 -0700361 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
362 0, ts->abs_x_max, 0, 0);
363 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
364 0, ts->abs_y_max, 0, 0);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700365 input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
366 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
367
Aleksei Mamlina7ac7c92015-03-06 16:38:16 -0800368 input_mt_init_slots(ts->input_dev, ts->max_touch_num,
Bastien Noceraca96ea82014-10-31 09:26:16 -0700369 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
370
371 ts->input_dev->name = "Goodix Capacitive TouchScreen";
372 ts->input_dev->phys = "input/ts";
373 ts->input_dev->id.bustype = BUS_I2C;
374 ts->input_dev->id.vendor = 0x0416;
Irina Tirdeae70b0302015-06-09 11:04:40 -0700375 ts->input_dev->id.product = id;
376 ts->input_dev->id.version = version;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700377
378 error = input_register_device(ts->input_dev);
379 if (error) {
380 dev_err(&ts->client->dev,
381 "Failed to register input device: %d", error);
382 return error;
383 }
384
385 return 0;
386}
387
388static int goodix_ts_probe(struct i2c_client *client,
389 const struct i2c_device_id *id)
390{
391 struct goodix_ts_data *ts;
392 unsigned long irq_flags;
393 int error;
Irina Tirdeae70b0302015-06-09 11:04:40 -0700394 u16 version_info, id_info;
Bastien Noceraca96ea82014-10-31 09:26:16 -0700395
396 dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
397
398 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
399 dev_err(&client->dev, "I2C check functionality failed.\n");
400 return -ENXIO;
401 }
402
403 ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
404 if (!ts)
405 return -ENOMEM;
406
407 ts->client = client;
408 i2c_set_clientdata(client, ts);
409
410 error = goodix_i2c_test(client);
411 if (error) {
412 dev_err(&client->dev, "I2C communication failure: %d\n", error);
413 return error;
414 }
415
Irina Tirdeae70b0302015-06-09 11:04:40 -0700416 error = goodix_read_version(client, &version_info, &id_info);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700417 if (error) {
418 dev_err(&client->dev, "Read version failed.\n");
419 return error;
420 }
421
Irina Tirdeaa779fbc2015-12-17 15:55:21 -0800422 ts->cfg_len = goodix_get_cfg_len(id_info);
423
Bastien Noceraca96ea82014-10-31 09:26:16 -0700424 goodix_read_config(ts);
425
Irina Tirdeae70b0302015-06-09 11:04:40 -0700426 error = goodix_request_input_dev(ts, version_info, id_info);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700427 if (error)
428 return error;
429
430 irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
431 error = devm_request_threaded_irq(&ts->client->dev, client->irq,
432 NULL, goodix_ts_irq_handler,
433 irq_flags, client->name, ts);
434 if (error) {
435 dev_err(&client->dev, "request IRQ failed: %d\n", error);
436 return error;
437 }
438
439 return 0;
440}
441
442static const struct i2c_device_id goodix_ts_id[] = {
443 { "GDIX1001:00", 0 },
444 { }
445};
Javier Martinez Canillas2e9e9102015-07-30 10:38:52 -0700446MODULE_DEVICE_TABLE(i2c, goodix_ts_id);
Bastien Noceraca96ea82014-10-31 09:26:16 -0700447
Aleksei Mamlin771d8f12015-03-06 16:43:38 -0800448#ifdef CONFIG_ACPI
Bastien Noceraca96ea82014-10-31 09:26:16 -0700449static const struct acpi_device_id goodix_acpi_match[] = {
450 { "GDIX1001", 0 },
451 { }
452};
453MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
Aleksei Mamlin771d8f12015-03-06 16:43:38 -0800454#endif
455
456#ifdef CONFIG_OF
457static const struct of_device_id goodix_of_match[] = {
458 { .compatible = "goodix,gt911" },
459 { .compatible = "goodix,gt9110" },
460 { .compatible = "goodix,gt912" },
461 { .compatible = "goodix,gt927" },
462 { .compatible = "goodix,gt9271" },
463 { .compatible = "goodix,gt928" },
464 { .compatible = "goodix,gt967" },
465 { }
466};
467MODULE_DEVICE_TABLE(of, goodix_of_match);
468#endif
Bastien Noceraca96ea82014-10-31 09:26:16 -0700469
470static struct i2c_driver goodix_ts_driver = {
471 .probe = goodix_ts_probe,
472 .id_table = goodix_ts_id,
473 .driver = {
474 .name = "Goodix-TS",
Aleksei Mamlin771d8f12015-03-06 16:43:38 -0800475 .acpi_match_table = ACPI_PTR(goodix_acpi_match),
476 .of_match_table = of_match_ptr(goodix_of_match),
Bastien Noceraca96ea82014-10-31 09:26:16 -0700477 },
478};
479module_i2c_driver(goodix_ts_driver);
480
481MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
482MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
483MODULE_DESCRIPTION("Goodix touchscreen driver");
484MODULE_LICENSE("GPL v2");