1 // SPDX-License-Identifier: GPL-2.0-only
2 #include <linux/module.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>
15 #define ILI210X_TOUCHES 2
16 #define ILI251X_TOUCHES 10
17 #define DEFAULT_POLL_PERIOD 20
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
25 struct firmware_version
{
37 struct i2c_client
*client
;
38 struct input_dev
*input
;
39 unsigned int poll_period
;
40 struct delayed_work dwork
;
41 struct gpio_desc
*reset_gpio
;
42 struct touchscreen_properties prop
;
43 enum ili2xxx_model model
;
44 unsigned int max_touches
;
47 static int ili210x_read_reg(struct i2c_client
*client
, u8 reg
, void *buf
,
50 struct ili210x
*priv
= i2c_get_clientdata(client
);
51 struct i2c_msg msg
[2] = {
66 if (priv
->model
== MODEL_ILI251X
) {
67 if (i2c_transfer(client
->adapter
, msg
, 1) != 1) {
68 dev_err(&client
->dev
, "i2c transfer failed\n");
72 usleep_range(5000, 5500);
74 if (i2c_transfer(client
->adapter
, msg
+ 1, 1) != 1) {
75 dev_err(&client
->dev
, "i2c transfer failed\n");
79 if (i2c_transfer(client
->adapter
, msg
, 2) != 2) {
80 dev_err(&client
->dev
, "i2c transfer failed\n");
88 static int ili210x_read(struct i2c_client
*client
, void *buf
, size_t len
)
90 struct i2c_msg msg
= {
97 if (i2c_transfer(client
->adapter
, &msg
, 1) != 1) {
98 dev_err(&client
->dev
, "i2c transfer failed\n");
105 static bool ili210x_touchdata_to_coords(struct ili210x
*priv
, u8
*touchdata
,
107 unsigned int *x
, unsigned int *y
)
109 if (finger
>= ILI210X_TOUCHES
)
112 if (touchdata
[0] & BIT(finger
))
115 *x
= get_unaligned_be16(touchdata
+ 1 + (finger
* 4) + 0);
116 *y
= get_unaligned_be16(touchdata
+ 1 + (finger
* 4) + 2);
121 static bool ili251x_touchdata_to_coords(struct ili210x
*priv
, u8
*touchdata
,
123 unsigned int *x
, unsigned int *y
)
125 if (finger
>= ILI251X_TOUCHES
)
128 *x
= get_unaligned_be16(touchdata
+ 1 + (finger
* 5) + 0);
129 if (!(*x
& BIT(15))) /* Touch indication */
133 *y
= get_unaligned_be16(touchdata
+ 1 + (finger
* 5) + 2);
138 static bool ili210x_report_events(struct ili210x
*priv
, u8
*touchdata
)
140 struct input_dev
*input
= priv
->input
;
142 bool contact
= false, touch
= false;
143 unsigned int x
= 0, y
= 0;
145 for (i
= 0; i
< priv
->max_touches
; i
++) {
146 if (priv
->model
== MODEL_ILI210X
) {
147 touch
= ili210x_touchdata_to_coords(priv
, touchdata
,
149 } else if (priv
->model
== MODEL_ILI251X
) {
150 touch
= ili251x_touchdata_to_coords(priv
, touchdata
,
156 input_mt_slot(input
, i
);
157 input_mt_report_slot_state(input
, MT_TOOL_FINGER
, touch
);
160 touchscreen_report_pos(input
, &priv
->prop
, x
, y
,
164 input_mt_report_pointer_emulation(input
, false);
167 if (priv
->model
== MODEL_ILI210X
)
168 contact
= touchdata
[0] & 0xf3;
173 static void ili210x_work(struct work_struct
*work
)
175 struct ili210x
*priv
= container_of(work
, struct ili210x
,
177 struct i2c_client
*client
= priv
->client
;
178 u8 touchdata
[64] = { 0 };
182 if (priv
->model
== MODEL_ILI210X
) {
183 error
= ili210x_read_reg(client
, REG_TOUCHDATA
,
184 touchdata
, sizeof(touchdata
));
185 } else if (priv
->model
== MODEL_ILI251X
) {
186 error
= ili210x_read_reg(client
, REG_TOUCHDATA
,
188 if (!error
&& touchdata
[0] == 2)
189 error
= ili210x_read(client
, &touchdata
[31], 20);
193 dev_err(&client
->dev
,
194 "Unable to get touchdata, err = %d\n", error
);
198 touch
= ili210x_report_events(priv
, touchdata
);
201 schedule_delayed_work(&priv
->dwork
,
202 msecs_to_jiffies(priv
->poll_period
));
205 static irqreturn_t
ili210x_irq(int irq
, void *irq_data
)
207 struct ili210x
*priv
= irq_data
;
209 schedule_delayed_work(&priv
->dwork
, 0);
214 static ssize_t
ili210x_calibrate(struct device
*dev
,
215 struct device_attribute
*attr
,
216 const char *buf
, size_t count
)
218 struct i2c_client
*client
= to_i2c_client(dev
);
219 struct ili210x
*priv
= i2c_get_clientdata(client
);
220 unsigned long calibrate
;
222 u8 cmd
= REG_CALIBRATE
;
224 if (kstrtoul(buf
, 10, &calibrate
))
231 rc
= i2c_master_send(priv
->client
, &cmd
, sizeof(cmd
));
232 if (rc
!= sizeof(cmd
))
238 static DEVICE_ATTR(calibrate
, S_IWUSR
, NULL
, ili210x_calibrate
);
240 static struct attribute
*ili210x_attributes
[] = {
241 &dev_attr_calibrate
.attr
,
245 static const struct attribute_group ili210x_attr_group
= {
246 .attrs
= ili210x_attributes
,
249 static void ili210x_power_down(void *data
)
251 struct gpio_desc
*reset_gpio
= data
;
253 gpiod_set_value_cansleep(reset_gpio
, 1);
256 static void ili210x_cancel_work(void *data
)
258 struct ili210x
*priv
= data
;
260 cancel_delayed_work_sync(&priv
->dwork
);
263 static int ili210x_i2c_probe(struct i2c_client
*client
,
264 const struct i2c_device_id
*id
)
266 struct device
*dev
= &client
->dev
;
267 struct ili210x
*priv
;
268 struct gpio_desc
*reset_gpio
;
269 struct input_dev
*input
;
270 struct firmware_version firmware
;
271 enum ili2xxx_model model
;
274 model
= (enum ili2xxx_model
)id
->driver_data
;
276 dev_dbg(dev
, "Probing for ILI210X I2C Touschreen driver");
278 if (client
->irq
<= 0) {
279 dev_err(dev
, "No IRQ!\n");
283 reset_gpio
= devm_gpiod_get_optional(dev
, "reset", GPIOD_OUT_HIGH
);
284 if (IS_ERR(reset_gpio
))
285 return PTR_ERR(reset_gpio
);
288 error
= devm_add_action_or_reset(dev
, ili210x_power_down
,
293 usleep_range(50, 100);
294 gpiod_set_value_cansleep(reset_gpio
, 0);
298 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
302 input
= devm_input_allocate_device(dev
);
306 priv
->client
= client
;
308 priv
->poll_period
= DEFAULT_POLL_PERIOD
;
309 INIT_DELAYED_WORK(&priv
->dwork
, ili210x_work
);
310 priv
->reset_gpio
= reset_gpio
;
312 if (model
== MODEL_ILI210X
)
313 priv
->max_touches
= ILI210X_TOUCHES
;
314 if (model
== MODEL_ILI251X
)
315 priv
->max_touches
= ILI251X_TOUCHES
;
317 i2c_set_clientdata(client
, priv
);
319 /* Get firmware version */
320 error
= ili210x_read_reg(client
, REG_FIRMWARE_VERSION
,
321 &firmware
, sizeof(firmware
));
323 dev_err(dev
, "Failed to get firmware version, err: %d\n",
328 /* Setup input device */
329 input
->name
= "ILI210x Touchscreen";
330 input
->id
.bustype
= BUS_I2C
;
331 input
->dev
.parent
= dev
;
334 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, 0xffff, 0, 0);
335 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, 0xffff, 0, 0);
336 touchscreen_parse_properties(input
, true, &priv
->prop
);
337 input_mt_init_slots(input
, priv
->max_touches
, INPUT_MT_DIRECT
);
339 error
= devm_add_action(dev
, ili210x_cancel_work
, priv
);
343 error
= devm_request_irq(dev
, client
->irq
, ili210x_irq
, 0,
346 dev_err(dev
, "Unable to request touchscreen IRQ, err: %d\n",
351 error
= devm_device_add_group(dev
, &ili210x_attr_group
);
353 dev_err(dev
, "Unable to create sysfs attributes, err: %d\n",
358 error
= input_register_device(priv
->input
);
360 dev_err(dev
, "Cannot register input device, err: %d\n", error
);
364 device_init_wakeup(dev
, 1);
367 "ILI210x initialized (IRQ: %d), firmware version %d.%d.%d",
368 client
->irq
, firmware
.id
, firmware
.major
, firmware
.minor
);
373 static int __maybe_unused
ili210x_i2c_suspend(struct device
*dev
)
375 struct i2c_client
*client
= to_i2c_client(dev
);
377 if (device_may_wakeup(&client
->dev
))
378 enable_irq_wake(client
->irq
);
383 static int __maybe_unused
ili210x_i2c_resume(struct device
*dev
)
385 struct i2c_client
*client
= to_i2c_client(dev
);
387 if (device_may_wakeup(&client
->dev
))
388 disable_irq_wake(client
->irq
);
393 static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm
,
394 ili210x_i2c_suspend
, ili210x_i2c_resume
);
396 static const struct i2c_device_id ili210x_i2c_id
[] = {
397 { "ili210x", MODEL_ILI210X
},
398 { "ili251x", MODEL_ILI251X
},
401 MODULE_DEVICE_TABLE(i2c
, ili210x_i2c_id
);
403 static const struct of_device_id ili210x_dt_ids
[] = {
404 { .compatible
= "ilitek,ili210x", .data
= (void *)MODEL_ILI210X
},
405 { .compatible
= "ilitek,ili251x", .data
= (void *)MODEL_ILI251X
},
408 MODULE_DEVICE_TABLE(of
, ili210x_dt_ids
);
410 static struct i2c_driver ili210x_ts_driver
= {
412 .name
= "ili210x_i2c",
413 .pm
= &ili210x_i2c_pm
,
414 .of_match_table
= ili210x_dt_ids
,
416 .id_table
= ili210x_i2c_id
,
417 .probe
= ili210x_i2c_probe
,
420 module_i2c_driver(ili210x_ts_driver
);
422 MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
423 MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver");
424 MODULE_LICENSE("GPL");