ili210x.c (58e16d792a6a8c6b750f637a4649967fcac853dc) ili210x.c (eb91ecc9fc43fbefdfdfe1ea8b3f136ccbc02f66)
1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/module.h>
3#include <linux/i2c.h>
4#include <linux/interrupt.h>
5#include <linux/slab.h>
6#include <linux/input.h>
7#include <linux/input/mt.h>
8#include <linux/input/touchscreen.h>
9#include <linux/delay.h>
10#include <linux/workqueue.h>
11#include <linux/gpio/consumer.h>
12#include <linux/of_device.h>
13#include <asm/unaligned.h>
14
15#define ILI210X_TOUCHES 2
1// SPDX-License-Identifier: GPL-2.0-only
2#include <linux/module.h>
3#include <linux/i2c.h>
4#include <linux/interrupt.h>
5#include <linux/slab.h>
6#include <linux/input.h>
7#include <linux/input/mt.h>
8#include <linux/input/touchscreen.h>
9#include <linux/delay.h>
10#include <linux/workqueue.h>
11#include <linux/gpio/consumer.h>
12#include <linux/of_device.h>
13#include <asm/unaligned.h>
14
15#define ILI210X_TOUCHES 2
16#define ILI211X_TOUCHES 10
16#define ILI251X_TOUCHES 10
17#define DEFAULT_POLL_PERIOD 20
18
19/* Touchscreen commands */
20#define REG_TOUCHDATA 0x10
21#define REG_PANEL_INFO 0x20
22#define REG_FIRMWARE_VERSION 0x40
23#define REG_CALIBRATE 0xcc
24
25struct firmware_version {
26 u8 id;
27 u8 major;
28 u8 minor;
29} __packed;
30
31enum ili2xxx_model {
32 MODEL_ILI210X,
17#define ILI251X_TOUCHES 10
18#define DEFAULT_POLL_PERIOD 20
19
20/* Touchscreen commands */
21#define REG_TOUCHDATA 0x10
22#define REG_PANEL_INFO 0x20
23#define REG_FIRMWARE_VERSION 0x40
24#define REG_CALIBRATE 0xcc
25
26struct firmware_version {
27 u8 id;
28 u8 major;
29 u8 minor;
30} __packed;
31
32enum ili2xxx_model {
33 MODEL_ILI210X,
34 MODEL_ILI211X,
33 MODEL_ILI251X,
34};
35
36struct ili210x {
37 struct i2c_client *client;
38 struct input_dev *input;
39 unsigned int poll_period;
40 struct delayed_work dwork;

--- 72 unchanged lines hidden (view full) ---

113 return false;
114
115 *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
116 *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
117
118 return true;
119}
120
35 MODEL_ILI251X,
36};
37
38struct ili210x {
39 struct i2c_client *client;
40 struct input_dev *input;
41 unsigned int poll_period;
42 struct delayed_work dwork;

--- 72 unchanged lines hidden (view full) ---

115 return false;
116
117 *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
118 *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
119
120 return true;
121}
122
123static bool ili211x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
124 unsigned int finger,
125 unsigned int *x, unsigned int *y)
126{
127 u32 data;
128
129 if (finger >= ILI211X_TOUCHES)
130 return false;
131
132 data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0);
133 if (data == 0xffffffff) /* Finger up */
134 return false;
135
136 *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
137 touchdata[1 + (finger * 4) + 1];
138 *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) |
139 touchdata[1 + (finger * 4) + 2];
140
141 return true;
142}
143
121static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
122 unsigned int finger,
123 unsigned int *x, unsigned int *y)
124{
125 if (finger >= ILI251X_TOUCHES)
126 return false;
127
128 *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);

--- 12 unchanged lines hidden (view full) ---

141 int i;
142 bool contact = false, touch = false;
143 unsigned int x = 0, y = 0;
144
145 for (i = 0; i < priv->max_touches; i++) {
146 if (priv->model == MODEL_ILI210X) {
147 touch = ili210x_touchdata_to_coords(priv, touchdata,
148 i, &x, &y);
144static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
145 unsigned int finger,
146 unsigned int *x, unsigned int *y)
147{
148 if (finger >= ILI251X_TOUCHES)
149 return false;
150
151 *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);

--- 12 unchanged lines hidden (view full) ---

164 int i;
165 bool contact = false, touch = false;
166 unsigned int x = 0, y = 0;
167
168 for (i = 0; i < priv->max_touches; i++) {
169 if (priv->model == MODEL_ILI210X) {
170 touch = ili210x_touchdata_to_coords(priv, touchdata,
171 i, &x, &y);
172 } else if (priv->model == MODEL_ILI211X) {
173 touch = ili211x_touchdata_to_coords(priv, touchdata,
174 i, &x, &y);
149 } else if (priv->model == MODEL_ILI251X) {
150 touch = ili251x_touchdata_to_coords(priv, touchdata,
151 i, &x, &y);
152 if (touch)
153 contact = true;
154 }
155
156 input_mt_slot(input, i);

--- 14 unchanged lines hidden (view full) ---

171}
172
173static void ili210x_work(struct work_struct *work)
174{
175 struct ili210x *priv = container_of(work, struct ili210x,
176 dwork.work);
177 struct i2c_client *client = priv->client;
178 u8 touchdata[64] = { 0 };
175 } else if (priv->model == MODEL_ILI251X) {
176 touch = ili251x_touchdata_to_coords(priv, touchdata,
177 i, &x, &y);
178 if (touch)
179 contact = true;
180 }
181
182 input_mt_slot(input, i);

--- 14 unchanged lines hidden (view full) ---

197}
198
199static void ili210x_work(struct work_struct *work)
200{
201 struct ili210x *priv = container_of(work, struct ili210x,
202 dwork.work);
203 struct i2c_client *client = priv->client;
204 u8 touchdata[64] = { 0 };
205 s16 sum = 0;
179 bool touch;
206 bool touch;
180 int error = -EINVAL;
207 int i, error = -EINVAL;
181
182 if (priv->model == MODEL_ILI210X) {
183 error = ili210x_read_reg(client, REG_TOUCHDATA,
184 touchdata, sizeof(touchdata));
208
209 if (priv->model == MODEL_ILI210X) {
210 error = ili210x_read_reg(client, REG_TOUCHDATA,
211 touchdata, sizeof(touchdata));
212 } else if (priv->model == MODEL_ILI211X) {
213 error = ili210x_read(client, touchdata, 43);
214 if (!error) {
215 /* This chip uses custom checksum at the end of data */
216 for (i = 0; i <= 41; i++)
217 sum = (sum + touchdata[i]) & 0xff;
218 if ((-sum & 0xff) != touchdata[42]) {
219 dev_err(&client->dev,
220 "CRC error (crc=0x%02x expected=0x%02x)\n",
221 sum, touchdata[42]);
222 return;
223 }
224 }
185 } else if (priv->model == MODEL_ILI251X) {
186 error = ili210x_read_reg(client, REG_TOUCHDATA,
187 touchdata, 31);
188 if (!error && touchdata[0] == 2)
189 error = ili210x_read(client, &touchdata[31], 20);
190 }
191
192 if (error) {

--- 113 unchanged lines hidden (view full) ---

306 priv->client = client;
307 priv->input = input;
308 priv->poll_period = DEFAULT_POLL_PERIOD;
309 INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
310 priv->reset_gpio = reset_gpio;
311 priv->model = model;
312 if (model == MODEL_ILI210X)
313 priv->max_touches = ILI210X_TOUCHES;
225 } else if (priv->model == MODEL_ILI251X) {
226 error = ili210x_read_reg(client, REG_TOUCHDATA,
227 touchdata, 31);
228 if (!error && touchdata[0] == 2)
229 error = ili210x_read(client, &touchdata[31], 20);
230 }
231
232 if (error) {

--- 113 unchanged lines hidden (view full) ---

346 priv->client = client;
347 priv->input = input;
348 priv->poll_period = DEFAULT_POLL_PERIOD;
349 INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
350 priv->reset_gpio = reset_gpio;
351 priv->model = model;
352 if (model == MODEL_ILI210X)
353 priv->max_touches = ILI210X_TOUCHES;
354 if (model == MODEL_ILI211X)
355 priv->max_touches = ILI211X_TOUCHES;
314 if (model == MODEL_ILI251X)
315 priv->max_touches = ILI251X_TOUCHES;
316
317 i2c_set_clientdata(client, priv);
318
319 /* Get firmware version */
320 error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
321 &firmware, sizeof(firmware));

--- 68 unchanged lines hidden (view full) ---

390 return 0;
391}
392
393static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
394 ili210x_i2c_suspend, ili210x_i2c_resume);
395
396static const struct i2c_device_id ili210x_i2c_id[] = {
397 { "ili210x", MODEL_ILI210X },
356 if (model == MODEL_ILI251X)
357 priv->max_touches = ILI251X_TOUCHES;
358
359 i2c_set_clientdata(client, priv);
360
361 /* Get firmware version */
362 error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
363 &firmware, sizeof(firmware));

--- 68 unchanged lines hidden (view full) ---

432 return 0;
433}
434
435static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
436 ili210x_i2c_suspend, ili210x_i2c_resume);
437
438static const struct i2c_device_id ili210x_i2c_id[] = {
439 { "ili210x", MODEL_ILI210X },
440 { "ili2117", MODEL_ILI211X },
398 { "ili251x", MODEL_ILI251X },
399 { }
400};
401MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
402
403static const struct of_device_id ili210x_dt_ids[] = {
404 { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
441 { "ili251x", MODEL_ILI251X },
442 { }
443};
444MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
445
446static const struct of_device_id ili210x_dt_ids[] = {
447 { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
448 { .compatible = "ilitek,ili2117", .data = (void *)MODEL_ILI211X },
405 { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
406 { },
407};
408MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
409
410static struct i2c_driver ili210x_ts_driver = {
411 .driver = {
412 .name = "ili210x_i2c",

--- 12 unchanged lines hidden ---
449 { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
450 { },
451};
452MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
453
454static struct i2c_driver ili210x_ts_driver = {
455 .driver = {
456 .name = "ili210x_i2c",

--- 12 unchanged lines hidden ---