1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | |
3 | #include <linux/bitfield.h> |
4 | #include <linux/bits.h> |
5 | #include <linux/delay.h> |
6 | #include <linux/i2c.h> |
7 | #include <linux/input.h> |
8 | #include <linux/input/mt.h> |
9 | #include <linux/input/touchscreen.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/module.h> |
12 | #include <linux/property.h> |
13 | #include <linux/regulator/consumer.h> |
14 | |
15 | #define IST3032C_WHOAMI 0x32c |
16 | |
17 | #define IST3038B_REG_STATUS 0x20 |
18 | #define IST3038B_REG_CHIPID 0x30 |
19 | #define IST3038B_WHOAMI 0x30380b |
20 | |
21 | #define IST3038C_HIB_ACCESS (0x800B << 16) |
22 | #define IST3038C_DIRECT_ACCESS BIT(31) |
23 | #define IST3038C_REG_CHIPID (0x40001000 | IST3038C_DIRECT_ACCESS) |
24 | #define IST3038C_REG_HIB_BASE 0x30000100 |
25 | #define IST3038C_REG_TOUCH_STATUS (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS) |
26 | #define IST3038C_REG_TOUCH_COORD (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x8) |
27 | #define IST3038C_REG_INTR_MESSAGE (IST3038C_REG_HIB_BASE | IST3038C_HIB_ACCESS | 0x4) |
28 | #define IST3038C_WHOAMI 0x38c |
29 | #define IST3038C_CHIP_ON_DELAY_MS 60 |
30 | #define IST3038C_I2C_RETRY_COUNT 3 |
31 | #define IST3038C_MAX_FINGER_NUM 10 |
32 | #define IST3038C_X_MASK GENMASK(23, 12) |
33 | #define IST3038C_Y_MASK GENMASK(11, 0) |
34 | #define IST3038C_AREA_MASK GENMASK(27, 24) |
35 | #define IST3038C_FINGER_COUNT_MASK GENMASK(15, 12) |
36 | #define IST3038C_FINGER_STATUS_MASK GENMASK(9, 0) |
37 | #define IST3032C_KEY_STATUS_MASK GENMASK(20, 16) |
38 | |
39 | struct imagis_properties { |
40 | unsigned int interrupt_msg_cmd; |
41 | unsigned int touch_coord_cmd; |
42 | unsigned int whoami_cmd; |
43 | unsigned int whoami_val; |
44 | bool protocol_b; |
45 | bool touch_keys_supported; |
46 | }; |
47 | |
48 | struct imagis_ts { |
49 | struct i2c_client *client; |
50 | const struct imagis_properties *tdata; |
51 | struct input_dev *input_dev; |
52 | struct touchscreen_properties prop; |
53 | struct regulator_bulk_data supplies[2]; |
54 | u32 keycodes[5]; |
55 | int num_keycodes; |
56 | }; |
57 | |
58 | static int imagis_i2c_read_reg(struct imagis_ts *ts, |
59 | unsigned int reg, u32 *data) |
60 | { |
61 | __be32 ret_be; |
62 | __be32 reg_be = cpu_to_be32(reg); |
63 | struct i2c_msg msg[] = { |
64 | { |
65 | .addr = ts->client->addr, |
66 | .flags = 0, |
67 | .buf = (unsigned char *)®_be, |
68 | .len = sizeof(reg_be), |
69 | }, { |
70 | .addr = ts->client->addr, |
71 | .flags = I2C_M_RD, |
72 | .buf = (unsigned char *)&ret_be, |
73 | .len = sizeof(ret_be), |
74 | }, |
75 | }; |
76 | int ret, error; |
77 | int retry = IST3038C_I2C_RETRY_COUNT; |
78 | |
79 | /* Retry in case the controller fails to respond */ |
80 | do { |
81 | ret = i2c_transfer(adap: ts->client->adapter, msgs: msg, ARRAY_SIZE(msg)); |
82 | if (ret == ARRAY_SIZE(msg)) { |
83 | *data = be32_to_cpu(ret_be); |
84 | return 0; |
85 | } |
86 | |
87 | error = ret < 0 ? ret : -EIO; |
88 | dev_err(&ts->client->dev, |
89 | "%s - i2c_transfer failed: %d (%d)\n" , |
90 | __func__, error, ret); |
91 | } while (--retry); |
92 | |
93 | return error; |
94 | } |
95 | |
96 | static irqreturn_t imagis_interrupt(int irq, void *dev_id) |
97 | { |
98 | struct imagis_ts *ts = dev_id; |
99 | u32 intr_message, finger_status; |
100 | unsigned int finger_count, finger_pressed, key_pressed; |
101 | int i; |
102 | int error; |
103 | |
104 | error = imagis_i2c_read_reg(ts, reg: ts->tdata->interrupt_msg_cmd, data: &intr_message); |
105 | if (error) { |
106 | dev_err(&ts->client->dev, |
107 | "failed to read the interrupt message: %d\n" , error); |
108 | goto out; |
109 | } |
110 | |
111 | finger_count = FIELD_GET(IST3038C_FINGER_COUNT_MASK, intr_message); |
112 | if (finger_count > IST3038C_MAX_FINGER_NUM) { |
113 | dev_err(&ts->client->dev, |
114 | "finger count %d is more than maximum supported\n" , |
115 | finger_count); |
116 | goto out; |
117 | } |
118 | |
119 | finger_pressed = FIELD_GET(IST3038C_FINGER_STATUS_MASK, intr_message); |
120 | |
121 | for (i = 0; i < finger_count; i++) { |
122 | if (ts->tdata->protocol_b) |
123 | error = imagis_i2c_read_reg(ts, |
124 | reg: ts->tdata->touch_coord_cmd, data: &finger_status); |
125 | else |
126 | error = imagis_i2c_read_reg(ts, |
127 | reg: ts->tdata->touch_coord_cmd + (i * 4), |
128 | data: &finger_status); |
129 | if (error) { |
130 | dev_err(&ts->client->dev, |
131 | "failed to read coordinates for finger %d: %d\n" , |
132 | i, error); |
133 | goto out; |
134 | } |
135 | |
136 | input_mt_slot(dev: ts->input_dev, slot: i); |
137 | input_mt_report_slot_state(dev: ts->input_dev, MT_TOOL_FINGER, |
138 | active: finger_pressed & BIT(i)); |
139 | touchscreen_report_pos(input: ts->input_dev, prop: &ts->prop, |
140 | FIELD_GET(IST3038C_X_MASK, finger_status), |
141 | FIELD_GET(IST3038C_Y_MASK, finger_status), |
142 | multitouch: true); |
143 | input_report_abs(dev: ts->input_dev, ABS_MT_TOUCH_MAJOR, |
144 | FIELD_GET(IST3038C_AREA_MASK, finger_status)); |
145 | } |
146 | |
147 | key_pressed = FIELD_GET(IST3032C_KEY_STATUS_MASK, intr_message); |
148 | |
149 | for (int i = 0; i < ts->num_keycodes; i++) |
150 | input_report_key(dev: ts->input_dev, code: ts->keycodes[i], |
151 | value: key_pressed & BIT(i)); |
152 | |
153 | input_mt_sync_frame(dev: ts->input_dev); |
154 | input_sync(dev: ts->input_dev); |
155 | |
156 | out: |
157 | return IRQ_HANDLED; |
158 | } |
159 | |
160 | static void imagis_power_off(void *_ts) |
161 | { |
162 | struct imagis_ts *ts = _ts; |
163 | |
164 | regulator_bulk_disable(ARRAY_SIZE(ts->supplies), consumers: ts->supplies); |
165 | } |
166 | |
167 | static int imagis_power_on(struct imagis_ts *ts) |
168 | { |
169 | int error; |
170 | |
171 | error = regulator_bulk_enable(ARRAY_SIZE(ts->supplies), consumers: ts->supplies); |
172 | if (error) |
173 | return error; |
174 | |
175 | msleep(IST3038C_CHIP_ON_DELAY_MS); |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | static int imagis_start(struct imagis_ts *ts) |
181 | { |
182 | int error; |
183 | |
184 | error = imagis_power_on(ts); |
185 | if (error) |
186 | return error; |
187 | |
188 | enable_irq(irq: ts->client->irq); |
189 | |
190 | return 0; |
191 | } |
192 | |
193 | static int imagis_stop(struct imagis_ts *ts) |
194 | { |
195 | disable_irq(irq: ts->client->irq); |
196 | |
197 | imagis_power_off(ts: ts); |
198 | |
199 | return 0; |
200 | } |
201 | |
202 | static int imagis_input_open(struct input_dev *dev) |
203 | { |
204 | struct imagis_ts *ts = input_get_drvdata(dev); |
205 | |
206 | return imagis_start(ts); |
207 | } |
208 | |
209 | static void imagis_input_close(struct input_dev *dev) |
210 | { |
211 | struct imagis_ts *ts = input_get_drvdata(dev); |
212 | |
213 | imagis_stop(ts); |
214 | } |
215 | |
216 | static int imagis_init_input_dev(struct imagis_ts *ts) |
217 | { |
218 | struct input_dev *input_dev; |
219 | int error; |
220 | |
221 | input_dev = devm_input_allocate_device(&ts->client->dev); |
222 | if (!input_dev) |
223 | return -ENOMEM; |
224 | |
225 | ts->input_dev = input_dev; |
226 | |
227 | input_dev->name = "Imagis capacitive touchscreen" ; |
228 | input_dev->phys = "input/ts" ; |
229 | input_dev->id.bustype = BUS_I2C; |
230 | input_dev->open = imagis_input_open; |
231 | input_dev->close = imagis_input_close; |
232 | |
233 | input_set_drvdata(dev: input_dev, data: ts); |
234 | |
235 | input_set_capability(dev: input_dev, EV_ABS, ABS_MT_POSITION_X); |
236 | input_set_capability(dev: input_dev, EV_ABS, ABS_MT_POSITION_Y); |
237 | input_set_abs_params(dev: input_dev, ABS_MT_TOUCH_MAJOR, min: 0, max: 16, fuzz: 0, flat: 0); |
238 | if (ts->tdata->touch_keys_supported) { |
239 | ts->num_keycodes = of_property_read_variable_u32_array( |
240 | np: ts->client->dev.of_node, propname: "linux,keycodes" , |
241 | out_values: ts->keycodes, sz_min: 0, ARRAY_SIZE(ts->keycodes)); |
242 | if (ts->num_keycodes <= 0) { |
243 | ts->keycodes[0] = KEY_APPSELECT; |
244 | ts->keycodes[1] = KEY_BACK; |
245 | ts->num_keycodes = 2; |
246 | } |
247 | |
248 | input_dev->keycodemax = ts->num_keycodes; |
249 | input_dev->keycodesize = sizeof(ts->keycodes[0]); |
250 | input_dev->keycode = ts->keycodes; |
251 | } |
252 | |
253 | for (int i = 0; i < ts->num_keycodes; i++) |
254 | input_set_capability(dev: input_dev, EV_KEY, code: ts->keycodes[i]); |
255 | |
256 | touchscreen_parse_properties(input: input_dev, multitouch: true, prop: &ts->prop); |
257 | if (!ts->prop.max_x || !ts->prop.max_y) { |
258 | dev_err(&ts->client->dev, |
259 | "Touchscreen-size-x and/or touchscreen-size-y not set in dts\n" ); |
260 | return -EINVAL; |
261 | } |
262 | |
263 | error = input_mt_init_slots(dev: input_dev, |
264 | IST3038C_MAX_FINGER_NUM, |
265 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
266 | if (error) { |
267 | dev_err(&ts->client->dev, |
268 | "Failed to initialize MT slots: %d" , error); |
269 | return error; |
270 | } |
271 | |
272 | error = input_register_device(input_dev); |
273 | if (error) { |
274 | dev_err(&ts->client->dev, |
275 | "Failed to register input device: %d" , error); |
276 | return error; |
277 | } |
278 | |
279 | return 0; |
280 | } |
281 | |
282 | static int imagis_init_regulators(struct imagis_ts *ts) |
283 | { |
284 | struct i2c_client *client = ts->client; |
285 | |
286 | ts->supplies[0].supply = "vdd" ; |
287 | ts->supplies[1].supply = "vddio" ; |
288 | return devm_regulator_bulk_get(dev: &client->dev, |
289 | ARRAY_SIZE(ts->supplies), |
290 | consumers: ts->supplies); |
291 | } |
292 | |
293 | static int imagis_probe(struct i2c_client *i2c) |
294 | { |
295 | struct device *dev = &i2c->dev; |
296 | struct imagis_ts *ts; |
297 | int chip_id, error; |
298 | |
299 | ts = devm_kzalloc(dev, size: sizeof(*ts), GFP_KERNEL); |
300 | if (!ts) |
301 | return -ENOMEM; |
302 | |
303 | ts->client = i2c; |
304 | |
305 | ts->tdata = device_get_match_data(dev); |
306 | if (!ts->tdata) { |
307 | dev_err(dev, "missing chip data\n" ); |
308 | return -EINVAL; |
309 | } |
310 | |
311 | error = imagis_init_regulators(ts); |
312 | if (error) { |
313 | dev_err(dev, "regulator init error: %d\n" , error); |
314 | return error; |
315 | } |
316 | |
317 | error = imagis_power_on(ts); |
318 | if (error) { |
319 | dev_err(dev, "failed to enable regulators: %d\n" , error); |
320 | return error; |
321 | } |
322 | |
323 | error = devm_add_action_or_reset(dev, imagis_power_off, ts); |
324 | if (error) { |
325 | dev_err(dev, "failed to install poweroff action: %d\n" , error); |
326 | return error; |
327 | } |
328 | |
329 | error = imagis_i2c_read_reg(ts, reg: ts->tdata->whoami_cmd, data: &chip_id); |
330 | if (error) { |
331 | dev_err(dev, "chip ID read failure: %d\n" , error); |
332 | return error; |
333 | } |
334 | |
335 | if (chip_id != ts->tdata->whoami_val) { |
336 | dev_err(dev, "unknown chip ID: 0x%x\n" , chip_id); |
337 | return -EINVAL; |
338 | } |
339 | |
340 | error = devm_request_threaded_irq(dev, irq: i2c->irq, |
341 | NULL, thread_fn: imagis_interrupt, |
342 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
343 | devname: "imagis-touchscreen" , dev_id: ts); |
344 | if (error) { |
345 | dev_err(dev, "IRQ %d allocation failure: %d\n" , |
346 | i2c->irq, error); |
347 | return error; |
348 | } |
349 | |
350 | error = imagis_init_input_dev(ts); |
351 | if (error) |
352 | return error; |
353 | |
354 | return 0; |
355 | } |
356 | |
357 | static int imagis_suspend(struct device *dev) |
358 | { |
359 | struct i2c_client *client = to_i2c_client(dev); |
360 | struct imagis_ts *ts = i2c_get_clientdata(client); |
361 | int retval = 0; |
362 | |
363 | mutex_lock(&ts->input_dev->mutex); |
364 | |
365 | if (input_device_enabled(dev: ts->input_dev)) |
366 | retval = imagis_stop(ts); |
367 | |
368 | mutex_unlock(lock: &ts->input_dev->mutex); |
369 | |
370 | return retval; |
371 | } |
372 | |
373 | static int imagis_resume(struct device *dev) |
374 | { |
375 | struct i2c_client *client = to_i2c_client(dev); |
376 | struct imagis_ts *ts = i2c_get_clientdata(client); |
377 | int retval = 0; |
378 | |
379 | mutex_lock(&ts->input_dev->mutex); |
380 | |
381 | if (input_device_enabled(dev: ts->input_dev)) |
382 | retval = imagis_start(ts); |
383 | |
384 | mutex_unlock(lock: &ts->input_dev->mutex); |
385 | |
386 | return retval; |
387 | } |
388 | |
389 | static DEFINE_SIMPLE_DEV_PM_OPS(imagis_pm_ops, imagis_suspend, imagis_resume); |
390 | |
391 | static const struct imagis_properties imagis_3032c_data = { |
392 | .interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE, |
393 | .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, |
394 | .whoami_cmd = IST3038C_REG_CHIPID, |
395 | .whoami_val = IST3032C_WHOAMI, |
396 | .touch_keys_supported = true, |
397 | }; |
398 | |
399 | static const struct imagis_properties imagis_3038b_data = { |
400 | .interrupt_msg_cmd = IST3038B_REG_STATUS, |
401 | .touch_coord_cmd = IST3038B_REG_STATUS, |
402 | .whoami_cmd = IST3038B_REG_CHIPID, |
403 | .whoami_val = IST3038B_WHOAMI, |
404 | .protocol_b = true, |
405 | }; |
406 | |
407 | static const struct imagis_properties imagis_3038c_data = { |
408 | .interrupt_msg_cmd = IST3038C_REG_INTR_MESSAGE, |
409 | .touch_coord_cmd = IST3038C_REG_TOUCH_COORD, |
410 | .whoami_cmd = IST3038C_REG_CHIPID, |
411 | .whoami_val = IST3038C_WHOAMI, |
412 | }; |
413 | |
414 | #ifdef CONFIG_OF |
415 | static const struct of_device_id imagis_of_match[] = { |
416 | { .compatible = "imagis,ist3032c" , .data = &imagis_3032c_data }, |
417 | { .compatible = "imagis,ist3038b" , .data = &imagis_3038b_data }, |
418 | { .compatible = "imagis,ist3038c" , .data = &imagis_3038c_data }, |
419 | { }, |
420 | }; |
421 | MODULE_DEVICE_TABLE(of, imagis_of_match); |
422 | #endif |
423 | |
424 | static struct i2c_driver imagis_ts_driver = { |
425 | .driver = { |
426 | .name = "imagis-touchscreen" , |
427 | .pm = pm_sleep_ptr(&imagis_pm_ops), |
428 | .of_match_table = of_match_ptr(imagis_of_match), |
429 | }, |
430 | .probe = imagis_probe, |
431 | }; |
432 | |
433 | module_i2c_driver(imagis_ts_driver); |
434 | |
435 | MODULE_DESCRIPTION("Imagis IST3038C Touchscreen Driver" ); |
436 | MODULE_AUTHOR("Markuss Broks <markuss.broks@gmail.com>" ); |
437 | MODULE_LICENSE("GPL" ); |
438 | |