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 <asm/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 regulator
*vcc
;
29 struct regulator
*vio
;
30 struct touchscreen_properties prop
;
31 struct regulator_bulk_data supplies
[2];
37 static int zet6223_start(struct input_dev
*dev
)
39 struct zet6223_ts
*ts
= input_get_drvdata(dev
);
41 enable_irq(ts
->client
->irq
);
46 static void zet6223_stop(struct input_dev
*dev
)
48 struct zet6223_ts
*ts
= input_get_drvdata(dev
);
50 disable_irq(ts
->client
->irq
);
53 static irqreturn_t
zet6223_irq(int irq
, void *dev_id
)
55 struct zet6223_ts
*ts
= dev_id
;
59 * First 3 bytes are an identifier, two bytes of finger data.
60 * X, Y data per finger is 4 bytes.
62 u8 bufsize
= 3 + 4 * ts
->fingernum
;
63 u8 buf
[ZET6223_MAX_PKT_SIZE
];
68 ret
= i2c_master_recv(ts
->client
, buf
, bufsize
);
70 error
= ret
< 0 ? ret
: -EIO
;
71 dev_err_ratelimited(&ts
->client
->dev
,
72 "Error reading input data: %d\n", error
);
76 if (buf
[0] != ZET6223_VALID_PACKET
)
79 finger_bits
= get_unaligned_be16(buf
+ 1);
80 for (i
= 0; i
< ts
->fingernum
; i
++) {
81 if (!(finger_bits
& BIT(15 - i
)))
84 input_mt_slot(ts
->input
, i
);
85 input_mt_report_slot_state(ts
->input
, MT_TOOL_FINGER
, true);
86 input_event(ts
->input
, EV_ABS
, ABS_MT_POSITION_X
,
87 ((buf
[i
+ 3] >> 4) << 8) + buf
[i
+ 4]);
88 input_event(ts
->input
, EV_ABS
, ABS_MT_POSITION_Y
,
89 ((buf
[i
+ 3] & 0xF) << 8) + buf
[i
+ 5]);
92 input_mt_sync_frame(ts
->input
);
93 input_sync(ts
->input
);
98 static void zet6223_power_off(void *_ts
)
100 struct zet6223_ts
*ts
= _ts
;
102 regulator_bulk_disable(ARRAY_SIZE(ts
->supplies
), ts
->supplies
);
105 static int zet6223_power_on(struct zet6223_ts
*ts
)
107 struct device
*dev
= &ts
->client
->dev
;
110 ts
->supplies
[0].supply
= "vio";
111 ts
->supplies
[1].supply
= "vcc";
113 error
= devm_regulator_bulk_get(dev
, ARRAY_SIZE(ts
->supplies
),
118 error
= regulator_bulk_enable(ARRAY_SIZE(ts
->supplies
), ts
->supplies
);
122 msleep(ZET6223_POWER_ON_DELAY_MSEC
);
124 error
= devm_add_action_or_reset(dev
, zet6223_power_off
, ts
);
126 dev_err(dev
, "failed to install poweroff action: %d\n", error
);
133 static int zet6223_query_device(struct zet6223_ts
*ts
)
135 u8 buf
[ZET6223_CMD_INFO_LENGTH
];
136 u8 cmd
= ZET6223_CMD_INFO
;
140 ret
= i2c_master_send(ts
->client
, &cmd
, sizeof(cmd
));
141 if (ret
!= sizeof(cmd
)) {
142 error
= ret
< 0 ? ret
: -EIO
;
143 dev_err(&ts
->client
->dev
,
144 "touchpanel info cmd failed: %d\n", error
);
148 ret
= i2c_master_recv(ts
->client
, buf
, sizeof(buf
));
149 if (ret
!= sizeof(buf
)) {
150 error
= ret
< 0 ? ret
: -EIO
;
151 dev_err(&ts
->client
->dev
,
152 "failed to retrieve touchpanel info: %d\n", error
);
156 ts
->fingernum
= buf
[15] & 0x7F;
157 if (ts
->fingernum
> ZET6223_MAX_FINGERS
) {
158 dev_warn(&ts
->client
->dev
,
159 "touchpanel reports %d fingers, limiting to %d\n",
160 ts
->fingernum
, ZET6223_MAX_FINGERS
);
161 ts
->fingernum
= ZET6223_MAX_FINGERS
;
164 ts
->max_x
= get_unaligned_le16(&buf
[8]);
165 ts
->max_y
= get_unaligned_le16(&buf
[10]);
170 static int zet6223_probe(struct i2c_client
*client
,
171 const struct i2c_device_id
*id
)
173 struct device
*dev
= &client
->dev
;
174 struct zet6223_ts
*ts
;
175 struct input_dev
*input
;
179 dev_err(dev
, "no irq specified\n");
183 ts
= devm_kzalloc(dev
, sizeof(*ts
), GFP_KERNEL
);
189 error
= zet6223_power_on(ts
);
193 error
= zet6223_query_device(ts
);
197 ts
->input
= input
= devm_input_allocate_device(dev
);
201 input_set_drvdata(input
, ts
);
203 input
->name
= client
->name
;
204 input
->id
.bustype
= BUS_I2C
;
205 input
->open
= zet6223_start
;
206 input
->close
= zet6223_stop
;
208 input_set_abs_params(input
, ABS_MT_POSITION_X
, 0, ts
->max_x
, 0, 0);
209 input_set_abs_params(input
, ABS_MT_POSITION_Y
, 0, ts
->max_y
, 0, 0);
211 touchscreen_parse_properties(input
, true, &ts
->prop
);
213 error
= input_mt_init_slots(input
, ts
->fingernum
,
214 INPUT_MT_DIRECT
| INPUT_MT_DROP_UNUSED
);
218 error
= devm_request_threaded_irq(dev
, client
->irq
, NULL
, zet6223_irq
,
219 IRQF_ONESHOT
, client
->name
, ts
);
221 dev_err(dev
, "failed to request irq %d: %d\n",
228 error
= input_register_device(input
);
235 static const struct of_device_id zet6223_of_match
[] = {
236 { .compatible
= "zeitec,zet6223" },
239 MODULE_DEVICE_TABLE(of
, zet6223_of_match
);
241 static const struct i2c_device_id zet6223_id
[] = {
245 MODULE_DEVICE_TABLE(i2c
, zet6223_id
);
247 static struct i2c_driver zet6223_driver
= {
250 .of_match_table
= zet6223_of_match
,
252 .probe
= zet6223_probe
,
253 .id_table
= zet6223_id
255 module_i2c_driver(zet6223_driver
);
257 MODULE_AUTHOR("Jelle van der Waa <jelle@vdwaa.nl>");
258 MODULE_DESCRIPTION("ZEITEC zet622x I2C touchscreen driver");
259 MODULE_LICENSE("GPL");