1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016, Jelle van der Waa <jelle@vdwaa.nl>
6 #include <linux/delay.h>
8 #include <linux/input.h>
9 #include <linux/input/mt.h>
10 #include <linux/input/touchscreen.h>
11 #include <linux/interrupt.h>
12 #include <linux/module.h>
13 #include <linux/regulator/consumer.h>
14 #include <linux/unaligned.h>
16 #define ZET6223_MAX_FINGERS 16
17 #define ZET6223_MAX_PKT_SIZE (3 + 4 * ZET6223_MAX_FINGERS)
19 #define ZET6223_CMD_INFO 0xB2
20 #define ZET6223_CMD_INFO_LENGTH 17
21 #define ZET6223_VALID_PACKET 0x3c
23 #define ZET6223_POWER_ON_DELAY_MSEC 30
26 struct i2c_client
*client
;
27 struct input_dev
*input
;
28 struct touchscreen_properties prop
;
29 struct regulator_bulk_data supplies
[2];
35 static int zet6223_start(struct input_dev
*dev
)
37 struct zet6223_ts
*ts
= input_get_drvdata(dev
);
39 enable_irq(ts
->client
->irq
);
44 static void zet6223_stop(struct input_dev
*dev
)
46 struct zet6223_ts
*ts
= input_get_drvdata(dev
);
48 disable_irq(ts
->client
->irq
);
51 static irqreturn_t
zet6223_irq(int irq
, void *dev_id
)
53 struct zet6223_ts
*ts
= dev_id
;
57 * First 3 bytes are an identifier, two bytes of finger data.
58 * X, Y data per finger is 4 bytes.
60 u8 bufsize
= 3 + 4 * ts
->fingernum
;
61 u8 buf
[ZET6223_MAX_PKT_SIZE
];
66 ret
= i2c_master_recv(ts
->client
, buf
, bufsize
);
68 error
= ret
< 0 ? ret
: -EIO
;
69 dev_err_ratelimited(&ts
->client
->dev
,
70 "Error reading input data: %d\n", error
);
74 if (buf
[0] != ZET6223_VALID_PACKET
)
77 finger_bits
= get_unaligned_be16(buf
+ 1);
78 for (i
= 0; i
< ts
->fingernum
; i
++) {
79 if (!(finger_bits
& BIT(15 - i
)))
82 input_mt_slot(ts
->input
, i
);
83 input_mt_report_slot_state(ts
->input
, MT_TOOL_FINGER
, true);
84 input_event(ts
->input
, EV_ABS
, ABS_MT_POSITION_X
,
85 ((buf
[i
+ 3] >> 4) << 8) + buf
[i
+ 4]);
86 input_event(ts
->input
, EV_ABS
, ABS_MT_POSITION_Y
,
87 ((buf
[i
+ 3] & 0xF) << 8) + buf
[i
+ 5]);
90 input_mt_sync_frame(ts
->input
);
91 input_sync(ts
->input
);
96 static void zet6223_power_off(void *_ts
)
98 struct zet6223_ts
*ts
= _ts
;
100 regulator_bulk_disable(ARRAY_SIZE(ts
->supplies
), ts
->supplies
);
103 static int zet6223_power_on(struct zet6223_ts
*ts
)
105 struct device
*dev
= &ts
->client
->dev
;
108 ts
->supplies
[0].supply
= "vio";
109 ts
->supplies
[1].supply
= "vcc";
111 error
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(ts
->supplies
),
116 error
= regulator_bulk_enable(ARRAY_SIZE(ts
->supplies
), ts
->supplies
);
120 msleep(ZET6223_POWER_ON_DELAY_MSEC
);
122 error
= devm_add_action_or_reset(dev
, zet6223_power_off
, ts
);
124 dev_err(dev
, "failed to install poweroff action: %d\n", error
);
131 static int zet6223_query_device(struct zet6223_ts
*ts
)
133 u8 buf
[ZET6223_CMD_INFO_LENGTH
];
134 u8 cmd
= ZET6223_CMD_INFO
;
138 ret
= i2c_master_send(ts
->client
, &cmd
, sizeof(cmd
));
139 if (ret
!= sizeof(cmd
)) {
140 error
= ret
< 0 ? ret
: -EIO
;
141 dev_err(&ts
->client
->dev
,
142 "touchpanel info cmd failed: %d\n", error
);
146 ret
= i2c_master_recv(ts
->client
, buf
, sizeof(buf
));
147 if (ret
!= sizeof(buf
)) {
148 error
= ret
< 0 ? ret
: -EIO
;
149 dev_err(&ts
->client
->dev
,
150 "failed to retrieve touchpanel info: %d\n", error
);
154 ts
->fingernum
= buf
[15] & 0x7F;
155 if (ts
->fingernum
> ZET6223_MAX_FINGERS
) {
156 dev_warn(&ts
->client
->dev
,
157 "touchpanel reports %d fingers, limiting to %d\n",
158 ts
->fingernum
, ZET6223_MAX_FINGERS
);
159 ts
->fingernum
= ZET6223_MAX_FINGERS
;
162 ts
->max_x
= get_unaligned_le16(&buf
[8]);
163 ts
->max_y
= get_unaligned_le16(&buf
[10]);
168 static int zet6223_probe(struct i2c_client
*client
)
170 struct device
*dev
= &client
->dev
;
171 struct zet6223_ts
*ts
;
172 struct input_dev
*input
;
176 dev_err(dev
, "no irq specified\n");
180 ts
= devm_kzalloc(dev
, sizeof(*ts
), GFP_KERNEL
);
186 error
= zet6223_power_on(ts
);
190 error
= zet6223_query_device(ts
);
194 ts
->input
= input
= devm_input_allocate_device(dev
);
198 input_set_drvdata(input
, ts
);
200 input
->name
= client
->name
;
201 input
->id
.bustype
= BUS_I2C
;
202 input
->open
= zet6223_start
;
203 input
->close
= zet6223_stop
;
205 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, ts
->max_x
, 0, 0);
206 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, ts
->max_y
, 0, 0);
208 touchscreen_parse_properties(input
, true, &ts
->prop
);
210 error
= input_mt_init_slots(input
, ts
->fingernum
,
211 INPUT_MT_DIRECT
| INPUT_MT_DROP_UNUSED
);
215 error
= devm_request_threaded_irq(dev
, client
->irq
, NULL
, zet6223_irq
,
216 IRQF_ONESHOT
, client
->name
, ts
);
218 dev_err(dev
, "failed to request irq %d: %d\n",
225 error
= input_register_device(input
);
232 static const struct of_device_id zet6223_of_match
[] = {
233 { .compatible
= "zeitec,zet6223" },
236 MODULE_DEVICE_TABLE(of
, zet6223_of_match
);
238 static const struct i2c_device_id zet6223_id
[] = {
242 MODULE_DEVICE_TABLE(i2c
, zet6223_id
);
244 static struct i2c_driver zet6223_driver
= {
247 .of_match_table
= zet6223_of_match
,
249 .probe
= zet6223_probe
,
250 .id_table
= zet6223_id
252 module_i2c_driver(zet6223_driver
);
254 MODULE_AUTHOR("Jelle van der Waa <jelle@vdwaa.nl>");
255 MODULE_DESCRIPTION("ZEITEC zet622x I2C touchscreen driver");
256 MODULE_LICENSE("GPL");