aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2014-10-31 12:26:16 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2014-10-31 12:41:23 -0400
commitca96ea86eed4b2645637dfe3d38b7d05191a79fe (patch)
treedd853b7bf5e134cdf0bc0dbb3e205e927368aee1 /drivers/input
parent6696777c6506fa52b2a0282121195843ed855be6 (diff)
Input: add driver for the Goodix touchpanel
Add a driver for the Goodix touchscreen panel found in Onda v975w tablets. The driver is based off the Android driver gt9xx.c found in some Android code dumps, but now bears no resemblance to the original driver. The driver was tested on the aforementioned tablet. Signed-off-by: Bastien Nocera <hadess@hadess.net> Tested-by: Bastien Nocera <hadess@hadess.net> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/Kconfig13
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/goodix.c395
3 files changed, 409 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index e1d8003d01f8..568a0200fbc2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -295,6 +295,19 @@ config TOUCHSCREEN_FUJITSU
295 To compile this driver as a module, choose M here: the 295 To compile this driver as a module, choose M here: the
296 module will be called fujitsu-ts. 296 module will be called fujitsu-ts.
297 297
298config TOUCHSCREEN_GOODIX
299 tristate "Goodix I2C touchscreen"
300 depends on I2C && ACPI
301 help
302 Say Y here if you have the Goodix touchscreen (such as one
303 installed in Onda v975w tablets) connected to your
304 system.
305
306 If unsure, say N.
307
308 To compile this driver as a module, choose M here: the
309 module will be called goodix.
310
298config TOUCHSCREEN_ILI210X 311config TOUCHSCREEN_ILI210X
299 tristate "Ilitek ILI210X based touchscreen" 312 tristate "Ilitek ILI210X based touchscreen"
300 depends on I2C 313 depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 090e61cc9171..dab4a56ac98e 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
34obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o 34obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
35obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o 35obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
36obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o 36obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
37obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o
37obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o 38obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o
38obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o 39obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
39obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o 40obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
new file mode 100644
index 000000000000..ca196689f025
--- /dev/null
+++ b/drivers/input/touchscreen/goodix.c
@@ -0,0 +1,395 @@
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>
18#include <linux/i2c.h>
19#include <linux/input.h>
20#include <linux/input/mt.h>
21#include <linux/module.h>
22#include <linux/delay.h>
23#include <linux/irq.h>
24#include <linux/interrupt.h>
25#include <linux/slab.h>
26#include <asm/unaligned.h>
27
28struct goodix_ts_data {
29 struct i2c_client *client;
30 struct input_dev *input_dev;
31 int abs_x_max;
32 int abs_y_max;
33 unsigned int max_touch_num;
34 unsigned int int_trigger_type;
35};
36
37#define GOODIX_MAX_HEIGHT 4096
38#define GOODIX_MAX_WIDTH 4096
39#define GOODIX_INT_TRIGGER 1
40#define GOODIX_CONTACT_SIZE 8
41#define GOODIX_MAX_CONTACTS 10
42
43#define GOODIX_CONFIG_MAX_LENGTH 240
44
45/* Register defines */
46#define GOODIX_READ_COOR_ADDR 0x814E
47#define GOODIX_REG_CONFIG_DATA 0x8047
48#define GOODIX_REG_VERSION 0x8140
49
50#define RESOLUTION_LOC 1
51#define TRIGGER_LOC 6
52
53static const unsigned long goodix_irq_flags[] = {
54 IRQ_TYPE_EDGE_RISING,
55 IRQ_TYPE_EDGE_FALLING,
56 IRQ_TYPE_LEVEL_LOW,
57 IRQ_TYPE_LEVEL_HIGH,
58};
59
60/**
61 * goodix_i2c_read - read data from a register of the i2c slave device.
62 *
63 * @client: i2c device.
64 * @reg: the register to read from.
65 * @buf: raw write data buffer.
66 * @len: length of the buffer to write
67 */
68static int goodix_i2c_read(struct i2c_client *client,
69 u16 reg, u8 *buf, int len)
70{
71 struct i2c_msg msgs[2];
72 u16 wbuf = cpu_to_be16(reg);
73 int ret;
74
75 msgs[0].flags = 0;
76 msgs[0].addr = client->addr;
77 msgs[0].len = 2;
78 msgs[0].buf = (u8 *) &wbuf;
79
80 msgs[1].flags = I2C_M_RD;
81 msgs[1].addr = client->addr;
82 msgs[1].len = len;
83 msgs[1].buf = buf;
84
85 ret = i2c_transfer(client->adapter, msgs, 2);
86 return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
87}
88
89static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
90{
91 int touch_num;
92 int error;
93
94 error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data,
95 GOODIX_CONTACT_SIZE + 1);
96 if (error) {
97 dev_err(&ts->client->dev, "I2C transfer error: %d\n", error);
98 return error;
99 }
100
101 touch_num = data[0] & 0x0f;
102 if (touch_num > GOODIX_MAX_CONTACTS)
103 return -EPROTO;
104
105 if (touch_num > 1) {
106 data += 1 + GOODIX_CONTACT_SIZE;
107 error = goodix_i2c_read(ts->client,
108 GOODIX_READ_COOR_ADDR +
109 1 + GOODIX_CONTACT_SIZE,
110 data,
111 GOODIX_CONTACT_SIZE * (touch_num - 1));
112 if (error)
113 return error;
114 }
115
116 return touch_num;
117}
118
119static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
120{
121 int id = coor_data[0] & 0x0F;
122 int input_x = get_unaligned_le16(&coor_data[1]);
123 int input_y = get_unaligned_le16(&coor_data[3]);
124 int input_w = get_unaligned_le16(&coor_data[5]);
125
126 input_mt_slot(ts->input_dev, id);
127 input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
128 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
129 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
130 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
131 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, input_w);
132}
133
134/**
135 * goodix_process_events - Process incoming events
136 *
137 * @ts: our goodix_ts_data pointer
138 *
139 * Called when the IRQ is triggered. Read the current device state, and push
140 * the input events to the user space.
141 */
142static void goodix_process_events(struct goodix_ts_data *ts)
143{
144 u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
145 int touch_num;
146 int i;
147
148 touch_num = goodix_ts_read_input_report(ts, point_data);
149 if (touch_num < 0)
150 return;
151
152 for (i = 0; i < touch_num; i++)
153 goodix_ts_report_touch(ts,
154 &point_data[1 + GOODIX_CONTACT_SIZE * i]);
155
156 input_mt_sync_frame(ts->input_dev);
157 input_sync(ts->input_dev);
158}
159
160/**
161 * goodix_ts_irq_handler - The IRQ handler
162 *
163 * @irq: interrupt number.
164 * @dev_id: private data pointer.
165 */
166static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id)
167{
168 static const u8 end_cmd[] = {
169 GOODIX_READ_COOR_ADDR >> 8,
170 GOODIX_READ_COOR_ADDR & 0xff,
171 0
172 };
173 struct goodix_ts_data *ts = dev_id;
174
175 goodix_process_events(ts);
176
177 if (i2c_master_send(ts->client, end_cmd, sizeof(end_cmd)) < 0)
178 dev_err(&ts->client->dev, "I2C write end_cmd error\n");
179
180 return IRQ_HANDLED;
181}
182
183/**
184 * goodix_read_config - Read the embedded configuration of the panel
185 *
186 * @ts: our goodix_ts_data pointer
187 *
188 * Must be called during probe
189 */
190static void goodix_read_config(struct goodix_ts_data *ts)
191{
192 u8 config[GOODIX_CONFIG_MAX_LENGTH];
193 int error;
194
195 error = goodix_i2c_read(ts->client, GOODIX_REG_CONFIG_DATA,
196 config,
197 GOODIX_CONFIG_MAX_LENGTH);
198 if (error) {
199 dev_warn(&ts->client->dev,
200 "Error reading config (%d), using defaults\n",
201 error);
202 ts->abs_x_max = GOODIX_MAX_WIDTH;
203 ts->abs_y_max = GOODIX_MAX_HEIGHT;
204 ts->int_trigger_type = GOODIX_INT_TRIGGER;
205 return;
206 }
207
208 ts->abs_x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
209 ts->abs_y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
210 ts->int_trigger_type = (config[TRIGGER_LOC]) & 0x03;
211 if (!ts->abs_x_max || !ts->abs_y_max) {
212 dev_err(&ts->client->dev,
213 "Invalid config, using defaults\n");
214 ts->abs_x_max = GOODIX_MAX_WIDTH;
215 ts->abs_y_max = GOODIX_MAX_HEIGHT;
216 }
217}
218
219
220/**
221 * goodix_read_version - Read goodix touchscreen version
222 *
223 * @client: the i2c client
224 * @version: output buffer containing the version on success
225 */
226static int goodix_read_version(struct i2c_client *client, u16 *version)
227{
228 int error;
229 u8 buf[6];
230
231 error = goodix_i2c_read(client, GOODIX_REG_VERSION, buf, sizeof(buf));
232 if (error) {
233 dev_err(&client->dev, "read version failed: %d\n", error);
234 return error;
235 }
236
237 if (version)
238 *version = get_unaligned_le16(&buf[4]);
239
240 dev_info(&client->dev, "IC VERSION: %6ph\n", buf);
241
242 return 0;
243}
244
245/**
246 * goodix_i2c_test - I2C test function to check if the device answers.
247 *
248 * @client: the i2c client
249 */
250static int goodix_i2c_test(struct i2c_client *client)
251{
252 int retry = 0;
253 int error;
254 u8 test;
255
256 while (retry++ < 2) {
257 error = goodix_i2c_read(client, GOODIX_REG_CONFIG_DATA,
258 &test, 1);
259 if (!error)
260 return 0;
261
262 dev_err(&client->dev, "i2c test failed attempt %d: %d\n",
263 retry, error);
264 msleep(20);
265 }
266
267 return error;
268}
269
270/**
271 * goodix_request_input_dev - Allocate, populate and register the input device
272 *
273 * @ts: our goodix_ts_data pointer
274 *
275 * Must be called during probe
276 */
277static int goodix_request_input_dev(struct goodix_ts_data *ts)
278{
279 int error;
280
281 ts->input_dev = devm_input_allocate_device(&ts->client->dev);
282 if (!ts->input_dev) {
283 dev_err(&ts->client->dev, "Failed to allocate input device.");
284 return -ENOMEM;
285 }
286
287 ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) |
288 BIT_MASK(EV_KEY) |
289 BIT_MASK(EV_ABS);
290
291 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
292 ts->abs_x_max, 0, 0);
293 input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
294 ts->abs_y_max, 0, 0);
295 input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
296 input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
297
298 input_mt_init_slots(ts->input_dev, GOODIX_MAX_CONTACTS,
299 INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
300
301 ts->input_dev->name = "Goodix Capacitive TouchScreen";
302 ts->input_dev->phys = "input/ts";
303 ts->input_dev->id.bustype = BUS_I2C;
304 ts->input_dev->id.vendor = 0x0416;
305 ts->input_dev->id.product = 0x1001;
306 ts->input_dev->id.version = 10427;
307
308 error = input_register_device(ts->input_dev);
309 if (error) {
310 dev_err(&ts->client->dev,
311 "Failed to register input device: %d", error);
312 return error;
313 }
314
315 return 0;
316}
317
318static int goodix_ts_probe(struct i2c_client *client,
319 const struct i2c_device_id *id)
320{
321 struct goodix_ts_data *ts;
322 unsigned long irq_flags;
323 int error;
324 u16 version_info;
325
326 dev_dbg(&client->dev, "I2C Address: 0x%02x\n", client->addr);
327
328 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
329 dev_err(&client->dev, "I2C check functionality failed.\n");
330 return -ENXIO;
331 }
332
333 ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
334 if (!ts)
335 return -ENOMEM;
336
337 ts->client = client;
338 i2c_set_clientdata(client, ts);
339
340 error = goodix_i2c_test(client);
341 if (error) {
342 dev_err(&client->dev, "I2C communication failure: %d\n", error);
343 return error;
344 }
345
346 error = goodix_read_version(client, &version_info);
347 if (error) {
348 dev_err(&client->dev, "Read version failed.\n");
349 return error;
350 }
351
352 goodix_read_config(ts);
353
354 error = goodix_request_input_dev(ts);
355 if (error)
356 return error;
357
358 irq_flags = goodix_irq_flags[ts->int_trigger_type] | IRQF_ONESHOT;
359 error = devm_request_threaded_irq(&ts->client->dev, client->irq,
360 NULL, goodix_ts_irq_handler,
361 irq_flags, client->name, ts);
362 if (error) {
363 dev_err(&client->dev, "request IRQ failed: %d\n", error);
364 return error;
365 }
366
367 return 0;
368}
369
370static const struct i2c_device_id goodix_ts_id[] = {
371 { "GDIX1001:00", 0 },
372 { }
373};
374
375static const struct acpi_device_id goodix_acpi_match[] = {
376 { "GDIX1001", 0 },
377 { }
378};
379MODULE_DEVICE_TABLE(acpi, goodix_acpi_match);
380
381static struct i2c_driver goodix_ts_driver = {
382 .probe = goodix_ts_probe,
383 .id_table = goodix_ts_id,
384 .driver = {
385 .name = "Goodix-TS",
386 .owner = THIS_MODULE,
387 .acpi_match_table = goodix_acpi_match,
388 },
389};
390module_i2c_driver(goodix_ts_driver);
391
392MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
393MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
394MODULE_DESCRIPTION("Goodix touchscreen driver");
395MODULE_LICENSE("GPL v2");