1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Hynitron cstxxx Touchscreen
5 * Copyright (c) 2022 Chris Morgan <macromorgan@hotmail.com>
7 * This code is based on hynitron_core.c authored by Hynitron.
8 * Note that no datasheet was available, so much of these registers
9 * are undocumented. This is essentially a cleaned-up version of the
10 * vendor driver with support removed for hardware I cannot test and
11 * device-specific functions replated with generic functions wherever
15 #include <linux/delay.h>
16 #include <linux/err.h>
17 #include <linux/gpio/consumer.h>
18 #include <linux/i2c.h>
19 #include <linux/input.h>
20 #include <linux/input/mt.h>
21 #include <linux/input/touchscreen.h>
22 #include <linux/mod_devicetable.h>
23 #include <linux/module.h>
24 #include <linux/property.h>
25 #include <linux/unaligned.h>
28 struct hynitron_ts_chip_data
{
29 unsigned int max_touch_num
;
31 int (*firmware_info
)(struct i2c_client
*client
);
32 int (*bootloader_enter
)(struct i2c_client
*client
);
33 int (*init_input
)(struct i2c_client
*client
);
34 void (*report_touch
)(struct i2c_client
*client
);
37 /* Data generic to all (supported and non-supported) controllers. */
38 struct hynitron_ts_data
{
39 const struct hynitron_ts_chip_data
*chip
;
40 struct i2c_client
*client
;
41 struct input_dev
*input_dev
;
42 struct touchscreen_properties prop
;
43 struct gpio_desc
*reset_gpio
;
47 * Since I have no datasheet, these values are guessed and/or assumed
48 * based on observation and testing.
50 #define CST3XX_FIRMWARE_INFO_START_CMD 0x01d1
51 #define CST3XX_FIRMWARE_INFO_END_CMD 0x09d1
52 #define CST3XX_FIRMWARE_CHK_CODE_REG 0xfcd1
53 #define CST3XX_FIRMWARE_VERSION_REG 0x08d2
54 #define CST3XX_FIRMWARE_VER_INVALID_VAL 0xa5a5a5a5
56 #define CST3XX_BOOTLDR_PROG_CMD 0xaa01a0
57 #define CST3XX_BOOTLDR_PROG_CHK_REG 0x02a0
58 #define CST3XX_BOOTLDR_CHK_VAL 0xac
60 #define CST3XX_TOUCH_DATA_PART_REG 0x00d0
61 #define CST3XX_TOUCH_DATA_FULL_REG 0x07d0
62 #define CST3XX_TOUCH_DATA_CHK_VAL 0xab
63 #define CST3XX_TOUCH_DATA_TOUCH_VAL 0x03
64 #define CST3XX_TOUCH_DATA_STOP_CMD 0xab00d0
65 #define CST3XX_TOUCH_COUNT_MASK GENMASK(6, 0)
69 * Hard coded reset delay value of 20ms not IC dependent in
72 static void hyn_reset_proc(struct i2c_client
*client
, int delay
)
74 struct hynitron_ts_data
*ts_data
= i2c_get_clientdata(client
);
76 gpiod_set_value_cansleep(ts_data
->reset_gpio
, 1);
78 gpiod_set_value_cansleep(ts_data
->reset_gpio
, 0);
83 static irqreturn_t
hyn_interrupt_handler(int irq
, void *dev_id
)
85 struct i2c_client
*client
= dev_id
;
86 struct hynitron_ts_data
*ts_data
= i2c_get_clientdata(client
);
88 ts_data
->chip
->report_touch(client
);
94 * The vendor driver would retry twice before failing to read or write
98 static int cst3xx_i2c_write(struct i2c_client
*client
,
99 unsigned char *buf
, int len
)
104 while (retries
< 2) {
105 ret
= i2c_master_send(client
, buf
, len
);
114 return ret
< 0 ? ret
: -EIO
;
117 static int cst3xx_i2c_read_register(struct i2c_client
*client
, u16 reg
,
120 __le16 buf
= cpu_to_le16(reg
);
121 struct i2c_msg msgs
[] = {
123 .addr
= client
->addr
,
129 .addr
= client
->addr
,
138 ret
= i2c_transfer(client
->adapter
, msgs
, ARRAY_SIZE(msgs
));
139 if (ret
== ARRAY_SIZE(msgs
))
142 err
= ret
< 0 ? ret
: -EIO
;
143 dev_err(&client
->dev
, "Error reading %d bytes from 0x%04x: %d (%d)\n",
149 static int cst3xx_firmware_info(struct i2c_client
*client
)
151 struct hynitron_ts_data
*ts_data
= i2c_get_clientdata(client
);
154 unsigned char buf
[4];
157 * Tests suggest this command needed to read firmware regs.
159 put_unaligned_le16(CST3XX_FIRMWARE_INFO_START_CMD
, buf
);
160 err
= cst3xx_i2c_write(client
, buf
, 2);
164 usleep_range(10000, 11000);
167 * Read register for check-code to determine if device detected
170 err
= cst3xx_i2c_read_register(client
, CST3XX_FIRMWARE_CHK_CODE_REG
,
175 tmp
= get_unaligned_le32(buf
);
176 if ((tmp
& 0xffff0000) != ts_data
->chip
->ic_chkcode
) {
177 dev_err(&client
->dev
, "%s ic mismatch, chkcode is %u\n",
182 usleep_range(10000, 11000);
184 /* Read firmware version and test if firmware missing. */
185 err
= cst3xx_i2c_read_register(client
, CST3XX_FIRMWARE_VERSION_REG
,
190 tmp
= get_unaligned_le32(buf
);
191 if (tmp
== CST3XX_FIRMWARE_VER_INVALID_VAL
) {
192 dev_err(&client
->dev
, "Device firmware missing\n");
197 * Tests suggest cmd required to exit reading firmware regs.
199 put_unaligned_le16(CST3XX_FIRMWARE_INFO_END_CMD
, buf
);
200 err
= cst3xx_i2c_write(client
, buf
, 2);
204 usleep_range(5000, 6000);
209 static int cst3xx_bootloader_enter(struct i2c_client
*client
)
214 unsigned char buf
[3];
216 for (retry
= 0; retry
< 5; retry
++) {
217 hyn_reset_proc(client
, (7 + retry
));
218 /* set cmd to enter program mode */
219 put_unaligned_le24(CST3XX_BOOTLDR_PROG_CMD
, buf
);
220 err
= cst3xx_i2c_write(client
, buf
, 3);
224 usleep_range(2000, 2500);
226 /* check whether in program mode */
227 err
= cst3xx_i2c_read_register(client
,
228 CST3XX_BOOTLDR_PROG_CHK_REG
,
233 tmp
= get_unaligned(buf
);
234 if (tmp
== CST3XX_BOOTLDR_CHK_VAL
)
238 if (tmp
!= CST3XX_BOOTLDR_CHK_VAL
) {
239 dev_err(&client
->dev
, "%s unable to enter bootloader mode\n",
244 hyn_reset_proc(client
, 40);
249 static void cst3xx_report_contact(struct hynitron_ts_data
*ts_data
,
250 u8 id
, unsigned int x
, unsigned int y
, u8 w
)
252 input_mt_slot(ts_data
->input_dev
, id
);
253 input_mt_report_slot_state(ts_data
->input_dev
, MT_TOOL_FINGER
, 1);
254 touchscreen_report_pos(ts_data
->input_dev
, &ts_data
->prop
, x
, y
, true);
255 input_report_abs(ts_data
->input_dev
, ABS_MT_TOUCH_MAJOR
, w
);
258 static int cst3xx_finish_touch_read(struct i2c_client
*client
)
260 unsigned char buf
[3];
263 put_unaligned_le24(CST3XX_TOUCH_DATA_STOP_CMD
, buf
);
264 err
= cst3xx_i2c_write(client
, buf
, 3);
266 dev_err(&client
->dev
,
267 "send read touch info ending failed: %d\n", err
);
275 * Handle events from IRQ. Note that for cst3xx it appears that IRQ
276 * fires continuously while touched, otherwise once every 1500ms
277 * when not touched (assume touchscreen waking up periodically).
278 * Note buffer is sized for 5 fingers, if more needed buffer must
279 * be increased. The buffer contains 5 bytes for each touch point,
280 * a touch count byte, a check byte, and then a second check byte after
281 * all other touch points.
283 * For example 1 touch would look like this:
284 * touch1[5]:touch_count[1]:chk_byte[1]
286 * 3 touches would look like this:
287 * touch1[5]:touch_count[1]:chk_byte[1]:touch2[5]:touch3[5]:chk_byte[1]
289 static void cst3xx_touch_report(struct i2c_client
*client
)
291 struct hynitron_ts_data
*ts_data
= i2c_get_clientdata(client
);
295 unsigned int touch_cnt
, end_byte
;
296 unsigned int idx
= 0;
300 /* Read and validate the first bits of input data. */
301 err
= cst3xx_i2c_read_register(client
, CST3XX_TOUCH_DATA_PART_REG
,
304 buf
[6] != CST3XX_TOUCH_DATA_CHK_VAL
||
305 buf
[0] == CST3XX_TOUCH_DATA_CHK_VAL
) {
306 dev_err(&client
->dev
, "cst3xx touch read failure\n");
310 /* Report to the device we're done reading the touch data. */
311 err
= cst3xx_finish_touch_read(client
);
315 touch_cnt
= buf
[5] & CST3XX_TOUCH_COUNT_MASK
;
317 * Check the check bit of the last touch slot. The check bit is
318 * always present after touch point 1 for valid data, and then
319 * appears as the last byte after all other touch data.
322 end_byte
= touch_cnt
* 5 + 2;
323 if (buf
[end_byte
] != CST3XX_TOUCH_DATA_CHK_VAL
) {
324 dev_err(&client
->dev
, "cst3xx touch read failure\n");
329 /* Parse through the buffer to capture touch data. */
330 for (i
= 0; i
< touch_cnt
; i
++) {
331 x
= ((buf
[idx
+ 1] << 4) | ((buf
[idx
+ 3] >> 4) & 0x0f));
332 y
= ((buf
[idx
+ 2] << 4) | (buf
[idx
+ 3] & 0x0f));
333 w
= (buf
[idx
+ 4] >> 3);
334 sw
= (buf
[idx
] & 0x0f) >> 1;
335 finger_id
= (buf
[idx
] >> 4) & 0x0f;
337 /* Sanity check we don't have more fingers than we expect */
338 if (ts_data
->chip
->max_touch_num
< finger_id
) {
339 dev_err(&client
->dev
, "cst3xx touch read failure\n");
343 /* sw value of 0 means no touch, 0x03 means touch */
344 if (sw
== CST3XX_TOUCH_DATA_TOUCH_VAL
)
345 cst3xx_report_contact(ts_data
, finger_id
, x
, y
, w
);
349 /* Skip the 2 bytes between point 1 and point 2 */
354 input_mt_sync_frame(ts_data
->input_dev
);
355 input_sync(ts_data
->input_dev
);
358 static int cst3xx_input_dev_int(struct i2c_client
*client
)
360 struct hynitron_ts_data
*ts_data
= i2c_get_clientdata(client
);
363 ts_data
->input_dev
= devm_input_allocate_device(&client
->dev
);
364 if (!ts_data
->input_dev
) {
365 dev_err(&client
->dev
, "Failed to allocate input device\n");
369 ts_data
->input_dev
->name
= "Hynitron cst3xx Touchscreen";
370 ts_data
->input_dev
->phys
= "input/ts";
371 ts_data
->input_dev
->id
.bustype
= BUS_I2C
;
373 input_set_drvdata(ts_data
->input_dev
, ts_data
);
375 input_set_capability(ts_data
->input_dev
, EV_ABS
, ABS_MT_POSITION_X
);
376 input_set_capability(ts_data
->input_dev
, EV_ABS
, ABS_MT_POSITION_Y
);
377 input_set_abs_params(ts_data
->input_dev
, ABS_MT_TOUCH_MAJOR
,
380 touchscreen_parse_properties(ts_data
->input_dev
, true, &ts_data
->prop
);
382 if (!ts_data
->prop
.max_x
|| !ts_data
->prop
.max_y
) {
383 dev_err(&client
->dev
,
384 "Invalid x/y (%d, %d), using defaults\n",
385 ts_data
->prop
.max_x
, ts_data
->prop
.max_y
);
386 ts_data
->prop
.max_x
= 1152;
387 ts_data
->prop
.max_y
= 1920;
388 input_abs_set_max(ts_data
->input_dev
,
389 ABS_MT_POSITION_X
, ts_data
->prop
.max_x
);
390 input_abs_set_max(ts_data
->input_dev
,
391 ABS_MT_POSITION_Y
, ts_data
->prop
.max_y
);
394 err
= input_mt_init_slots(ts_data
->input_dev
,
395 ts_data
->chip
->max_touch_num
,
396 INPUT_MT_DIRECT
| INPUT_MT_DROP_UNUSED
);
398 dev_err(&client
->dev
,
399 "Failed to initialize input slots: %d\n", err
);
403 err
= input_register_device(ts_data
->input_dev
);
405 dev_err(&client
->dev
,
406 "Input device registration failed: %d\n", err
);
413 static int hyn_probe(struct i2c_client
*client
)
415 struct hynitron_ts_data
*ts_data
;
418 ts_data
= devm_kzalloc(&client
->dev
, sizeof(*ts_data
), GFP_KERNEL
);
422 ts_data
->client
= client
;
423 i2c_set_clientdata(client
, ts_data
);
425 ts_data
->chip
= device_get_match_data(&client
->dev
);
429 ts_data
->reset_gpio
= devm_gpiod_get(&client
->dev
,
430 "reset", GPIOD_OUT_LOW
);
431 err
= PTR_ERR_OR_ZERO(ts_data
->reset_gpio
);
433 dev_err(&client
->dev
, "request reset gpio failed: %d\n", err
);
437 hyn_reset_proc(client
, 60);
439 err
= ts_data
->chip
->bootloader_enter(client
);
443 err
= ts_data
->chip
->init_input(client
);
447 err
= ts_data
->chip
->firmware_info(client
);
451 err
= devm_request_threaded_irq(&client
->dev
, client
->irq
,
452 NULL
, hyn_interrupt_handler
,
454 "Hynitron Touch Int", client
);
456 dev_err(&client
->dev
, "failed to request IRQ: %d\n", err
);
463 static const struct hynitron_ts_chip_data cst3xx_data
= {
465 .ic_chkcode
= 0xcaca0000,
466 .firmware_info
= &cst3xx_firmware_info
,
467 .bootloader_enter
= &cst3xx_bootloader_enter
,
468 .init_input
= &cst3xx_input_dev_int
,
469 .report_touch
= &cst3xx_touch_report
,
472 static const struct i2c_device_id hyn_tpd_id
[] = {
473 { .name
= "hynitron_ts" },
476 MODULE_DEVICE_TABLE(i2c
, hyn_tpd_id
);
478 static const struct of_device_id hyn_dt_match
[] = {
479 { .compatible
= "hynitron,cst340", .data
= &cst3xx_data
},
482 MODULE_DEVICE_TABLE(of
, hyn_dt_match
);
484 static struct i2c_driver hynitron_i2c_driver
= {
486 .name
= "Hynitron-TS",
487 .of_match_table
= hyn_dt_match
,
488 .probe_type
= PROBE_PREFER_ASYNCHRONOUS
,
490 .id_table
= hyn_tpd_id
,
494 module_i2c_driver(hynitron_i2c_driver
);
496 MODULE_AUTHOR("Chris Morgan");
497 MODULE_DESCRIPTION("Hynitron Touchscreen Driver");
498 MODULE_LICENSE("GPL");