Commit | Line | Data |
---|---|---|
4aeba641 | 1 | // SPDX-License-Identifier: GPL-2.0 |
56a8bd6d TS |
2 | /* |
3 | * ST1232 Touchscreen Controller Driver | |
4 | * | |
5 | * Copyright (C) 2010 Renesas Solutions Corp. | |
6 | * Tony SIM <chinyeow.sim.xt@renesas.com> | |
7 | * | |
8 | * Using code from: | |
9 | * - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c | |
10 | * Copyright (C) 2007 Google, Inc. | |
56a8bd6d TS |
11 | */ |
12 | ||
13 | #include <linux/delay.h> | |
e3dd12f0 | 14 | #include <linux/gpio/consumer.h> |
56a8bd6d TS |
15 | #include <linux/i2c.h> |
16 | #include <linux/input.h> | |
a1b92973 DT |
17 | #include <linux/input/mt.h> |
18 | #include <linux/input/touchscreen.h> | |
56a8bd6d TS |
19 | #include <linux/interrupt.h> |
20 | #include <linux/module.h> | |
4d6e4826 | 21 | #include <linux/of.h> |
9ee27ffb | 22 | #include <linux/pm_qos.h> |
56a8bd6d TS |
23 | #include <linux/slab.h> |
24 | #include <linux/types.h> | |
25 | ||
26 | #define ST1232_TS_NAME "st1232-ts" | |
351e0592 | 27 | #define ST1633_TS_NAME "st1633-ts" |
56a8bd6d | 28 | |
f605be6a GU |
29 | #define REG_STATUS 0x01 /* Device Status | Error Code */ |
30 | ||
31 | #define STATUS_NORMAL 0x00 | |
32 | #define STATUS_INIT 0x01 | |
33 | #define STATUS_ERROR 0x02 | |
34 | #define STATUS_AUTO_TUNING 0x03 | |
35 | #define STATUS_IDLE 0x04 | |
36 | #define STATUS_POWER_DOWN 0x05 | |
37 | ||
38 | #define ERROR_NONE 0x00 | |
39 | #define ERROR_INVALID_ADDRESS 0x10 | |
40 | #define ERROR_INVALID_VALUE 0x20 | |
41 | #define ERROR_INVALID_PLATFORM 0x30 | |
42 | ||
3a54a215 AV |
43 | #define REG_XY_RESOLUTION 0x04 |
44 | #define REG_XY_COORDINATES 0x12 | |
a1b92973 | 45 | #define ST_TS_MAX_FINGERS 10 |
56a8bd6d | 46 | |
351e0592 MK |
47 | struct st_chip_info { |
48 | bool have_z; | |
351e0592 MK |
49 | u16 max_area; |
50 | u16 max_fingers; | |
351e0592 MK |
51 | }; |
52 | ||
56a8bd6d TS |
53 | struct st1232_ts_data { |
54 | struct i2c_client *client; | |
55 | struct input_dev *input_dev; | |
16ab4f43 | 56 | struct touchscreen_properties prop; |
9ee27ffb | 57 | struct dev_pm_qos_request low_latency_req; |
e3dd12f0 | 58 | struct gpio_desc *reset_gpio; |
351e0592 MK |
59 | const struct st_chip_info *chip_info; |
60 | int read_buf_len; | |
61 | u8 *read_buf; | |
56a8bd6d TS |
62 | }; |
63 | ||
b999dbea GU |
64 | static int st1232_ts_read_data(struct st1232_ts_data *ts, u8 reg, |
65 | unsigned int n) | |
56a8bd6d | 66 | { |
56a8bd6d | 67 | struct i2c_client *client = ts->client; |
95c9ea96 DT |
68 | struct i2c_msg msg[] = { |
69 | { | |
70 | .addr = client->addr, | |
3a54a215 AV |
71 | .len = sizeof(reg), |
72 | .buf = ®, | |
95c9ea96 DT |
73 | }, |
74 | { | |
75 | .addr = client->addr, | |
833c2c08 | 76 | .flags = I2C_M_RD | I2C_M_DMA_SAFE, |
b999dbea | 77 | .len = n, |
95c9ea96 DT |
78 | .buf = ts->read_buf, |
79 | } | |
80 | }; | |
81 | int ret; | |
56a8bd6d | 82 | |
95c9ea96 DT |
83 | ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); |
84 | if (ret != ARRAY_SIZE(msg)) | |
85 | return ret < 0 ? ret : -EIO; | |
56a8bd6d | 86 | |
a1b92973 DT |
87 | return 0; |
88 | } | |
89 | ||
f605be6a GU |
90 | static int st1232_ts_wait_ready(struct st1232_ts_data *ts) |
91 | { | |
92 | unsigned int retries; | |
93 | int error; | |
94 | ||
2667f6b7 | 95 | for (retries = 100; retries; retries--) { |
f605be6a | 96 | error = st1232_ts_read_data(ts, REG_STATUS, 1); |
1bff77f4 GU |
97 | if (!error) { |
98 | switch (ts->read_buf[0]) { | |
99 | case STATUS_NORMAL | ERROR_NONE: | |
100 | case STATUS_IDLE | ERROR_NONE: | |
101 | return 0; | |
102 | } | |
103 | } | |
f605be6a GU |
104 | |
105 | usleep_range(1000, 2000); | |
106 | } | |
107 | ||
108 | return -ENXIO; | |
109 | } | |
110 | ||
3a54a215 AV |
111 | static int st1232_ts_read_resolution(struct st1232_ts_data *ts, u16 *max_x, |
112 | u16 *max_y) | |
113 | { | |
114 | u8 *buf; | |
115 | int error; | |
116 | ||
117 | /* select resolution register */ | |
b999dbea | 118 | error = st1232_ts_read_data(ts, REG_XY_RESOLUTION, 3); |
3a54a215 AV |
119 | if (error) |
120 | return error; | |
121 | ||
122 | buf = ts->read_buf; | |
123 | ||
928eedf0 GU |
124 | *max_x = (((buf[0] & 0x0070) << 4) | buf[1]) - 1; |
125 | *max_y = (((buf[0] & 0x0007) << 8) | buf[2]) - 1; | |
3a54a215 AV |
126 | |
127 | return 0; | |
128 | } | |
129 | ||
a1b92973 DT |
130 | static int st1232_ts_parse_and_report(struct st1232_ts_data *ts) |
131 | { | |
132 | struct input_dev *input = ts->input_dev; | |
133 | struct input_mt_pos pos[ST_TS_MAX_FINGERS]; | |
134 | u8 z[ST_TS_MAX_FINGERS]; | |
135 | int slots[ST_TS_MAX_FINGERS]; | |
136 | int n_contacts = 0; | |
137 | int i; | |
138 | ||
95c9ea96 | 139 | for (i = 0; i < ts->chip_info->max_fingers; i++) { |
a1b92973 DT |
140 | u8 *buf = &ts->read_buf[i * 4]; |
141 | ||
142 | if (buf[0] & BIT(7)) { | |
143 | unsigned int x = ((buf[0] & 0x70) << 4) | buf[1]; | |
144 | unsigned int y = ((buf[0] & 0x07) << 8) | buf[2]; | |
145 | ||
146 | touchscreen_set_mt_pos(&pos[n_contacts], | |
147 | &ts->prop, x, y); | |
56a8bd6d | 148 | |
351e0592 MK |
149 | /* st1232 includes a z-axis / touch strength */ |
150 | if (ts->chip_info->have_z) | |
a1b92973 DT |
151 | z[n_contacts] = ts->read_buf[i + 6]; |
152 | ||
153 | n_contacts++; | |
351e0592 | 154 | } |
56a8bd6d TS |
155 | } |
156 | ||
a1b92973 DT |
157 | input_mt_assign_slots(input, slots, pos, n_contacts, 0); |
158 | for (i = 0; i < n_contacts; i++) { | |
159 | input_mt_slot(input, slots[i]); | |
160 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | |
161 | input_report_abs(input, ABS_MT_POSITION_X, pos[i].x); | |
162 | input_report_abs(input, ABS_MT_POSITION_Y, pos[i].y); | |
163 | if (ts->chip_info->have_z) | |
164 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, z[i]); | |
165 | } | |
166 | ||
167 | input_mt_sync_frame(input); | |
168 | input_sync(input); | |
169 | ||
170 | return n_contacts; | |
56a8bd6d TS |
171 | } |
172 | ||
173 | static irqreturn_t st1232_ts_irq_handler(int irq, void *dev_id) | |
174 | { | |
175 | struct st1232_ts_data *ts = dev_id; | |
a1b92973 DT |
176 | int count; |
177 | int error; | |
56a8bd6d | 178 | |
b999dbea | 179 | error = st1232_ts_read_data(ts, REG_XY_COORDINATES, ts->read_buf_len); |
a1b92973 DT |
180 | if (error) |
181 | goto out; | |
351e0592 | 182 | |
a1b92973 | 183 | count = st1232_ts_parse_and_report(ts); |
9ee27ffb | 184 | if (!count) { |
9ee27ffb RW |
185 | if (ts->low_latency_req.dev) { |
186 | dev_pm_qos_remove_request(&ts->low_latency_req); | |
187 | ts->low_latency_req.dev = NULL; | |
188 | } | |
189 | } else if (!ts->low_latency_req.dev) { | |
190 | /* First contact, request 100 us latency. */ | |
191 | dev_pm_qos_add_ancestor_request(&ts->client->dev, | |
71d821fd RW |
192 | &ts->low_latency_req, |
193 | DEV_PM_QOS_RESUME_LATENCY, 100); | |
9ee27ffb | 194 | } |
56a8bd6d | 195 | |
a1b92973 | 196 | out: |
56a8bd6d TS |
197 | return IRQ_HANDLED; |
198 | } | |
199 | ||
e6a90810 BH |
200 | static void st1232_ts_power(struct st1232_ts_data *ts, bool poweron) |
201 | { | |
e3dd12f0 MK |
202 | if (ts->reset_gpio) |
203 | gpiod_set_value_cansleep(ts->reset_gpio, !poweron); | |
e6a90810 BH |
204 | } |
205 | ||
efd7bb08 DT |
206 | static void st1232_ts_power_off(void *data) |
207 | { | |
208 | st1232_ts_power(data, false); | |
209 | } | |
210 | ||
351e0592 MK |
211 | static const struct st_chip_info st1232_chip_info = { |
212 | .have_z = true, | |
351e0592 MK |
213 | .max_area = 0xff, |
214 | .max_fingers = 2, | |
351e0592 MK |
215 | }; |
216 | ||
217 | static const struct st_chip_info st1633_chip_info = { | |
218 | .have_z = false, | |
351e0592 MK |
219 | .max_area = 0x00, |
220 | .max_fingers = 5, | |
351e0592 MK |
221 | }; |
222 | ||
8ff48be3 | 223 | static int st1232_ts_probe(struct i2c_client *client) |
56a8bd6d | 224 | { |
8ff48be3 | 225 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
351e0592 | 226 | const struct st_chip_info *match; |
56a8bd6d TS |
227 | struct st1232_ts_data *ts; |
228 | struct input_dev *input_dev; | |
3a54a215 | 229 | u16 max_x, max_y; |
56a8bd6d TS |
230 | int error; |
231 | ||
351e0592 MK |
232 | match = device_get_match_data(&client->dev); |
233 | if (!match && id) | |
234 | match = (const void *)id->driver_data; | |
235 | if (!match) { | |
236 | dev_err(&client->dev, "unknown device model\n"); | |
237 | return -ENODEV; | |
238 | } | |
239 | ||
56a8bd6d TS |
240 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
241 | dev_err(&client->dev, "need I2C_FUNC_I2C\n"); | |
242 | return -EIO; | |
243 | } | |
244 | ||
245 | if (!client->irq) { | |
246 | dev_err(&client->dev, "no IRQ?\n"); | |
247 | return -EINVAL; | |
248 | } | |
249 | ||
a1b92973 | 250 | ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); |
95b24d22 LP |
251 | if (!ts) |
252 | return -ENOMEM; | |
56a8bd6d | 253 | |
351e0592 | 254 | ts->chip_info = match; |
351e0592 MK |
255 | |
256 | /* allocate a buffer according to the number of registers to read */ | |
257 | ts->read_buf_len = ts->chip_info->max_fingers * 4; | |
258 | ts->read_buf = devm_kzalloc(&client->dev, ts->read_buf_len, GFP_KERNEL); | |
259 | if (!ts->read_buf) | |
260 | return -ENOMEM; | |
261 | ||
95b24d22 LP |
262 | input_dev = devm_input_allocate_device(&client->dev); |
263 | if (!input_dev) | |
264 | return -ENOMEM; | |
56a8bd6d TS |
265 | |
266 | ts->client = client; | |
267 | ts->input_dev = input_dev; | |
268 | ||
e3dd12f0 MK |
269 | ts->reset_gpio = devm_gpiod_get_optional(&client->dev, NULL, |
270 | GPIOD_OUT_HIGH); | |
271 | if (IS_ERR(ts->reset_gpio)) { | |
272 | error = PTR_ERR(ts->reset_gpio); | |
273 | dev_err(&client->dev, "Unable to request GPIO pin: %d.\n", | |
274 | error); | |
275 | return error; | |
e6a90810 BH |
276 | } |
277 | ||
278 | st1232_ts_power(ts, true); | |
279 | ||
efd7bb08 DT |
280 | error = devm_add_action_or_reset(&client->dev, st1232_ts_power_off, ts); |
281 | if (error) { | |
282 | dev_err(&client->dev, | |
283 | "Failed to install power off action: %d\n", error); | |
284 | return error; | |
285 | } | |
286 | ||
56a8bd6d TS |
287 | input_dev->name = "st1232-touchscreen"; |
288 | input_dev->id.bustype = BUS_I2C; | |
56a8bd6d | 289 | |
f605be6a GU |
290 | /* Wait until device is ready */ |
291 | error = st1232_ts_wait_ready(ts); | |
292 | if (error) | |
293 | return error; | |
294 | ||
3a54a215 AV |
295 | /* Read resolution from the chip */ |
296 | error = st1232_ts_read_resolution(ts, &max_x, &max_y); | |
297 | if (error) { | |
298 | dev_err(&client->dev, | |
299 | "Failed to read resolution: %d\n", error); | |
300 | return error; | |
301 | } | |
302 | ||
351e0592 MK |
303 | if (ts->chip_info->have_z) |
304 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, | |
305 | ts->chip_info->max_area, 0, 0); | |
306 | ||
307 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | |
3a54a215 | 308 | 0, max_x, 0, 0); |
351e0592 | 309 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, |
3a54a215 | 310 | 0, max_y, 0, 0); |
56a8bd6d | 311 | |
16ab4f43 MF |
312 | touchscreen_parse_properties(input_dev, true, &ts->prop); |
313 | ||
a1b92973 DT |
314 | error = input_mt_init_slots(input_dev, ts->chip_info->max_fingers, |
315 | INPUT_MT_DIRECT | INPUT_MT_TRACK | | |
316 | INPUT_MT_DROP_UNUSED); | |
317 | if (error) { | |
318 | dev_err(&client->dev, "failed to initialize MT slots\n"); | |
319 | return error; | |
320 | } | |
321 | ||
95b24d22 LP |
322 | error = devm_request_threaded_irq(&client->dev, client->irq, |
323 | NULL, st1232_ts_irq_handler, | |
324 | IRQF_ONESHOT, | |
325 | client->name, ts); | |
56a8bd6d TS |
326 | if (error) { |
327 | dev_err(&client->dev, "Failed to register interrupt\n"); | |
95b24d22 | 328 | return error; |
56a8bd6d TS |
329 | } |
330 | ||
331 | error = input_register_device(ts->input_dev); | |
332 | if (error) { | |
333 | dev_err(&client->dev, "Unable to register %s input device\n", | |
334 | input_dev->name); | |
95b24d22 | 335 | return error; |
56a8bd6d TS |
336 | } |
337 | ||
338 | i2c_set_clientdata(client, ts); | |
56a8bd6d TS |
339 | |
340 | return 0; | |
56a8bd6d TS |
341 | } |
342 | ||
7c8d436d | 343 | static int st1232_ts_suspend(struct device *dev) |
56a8bd6d TS |
344 | { |
345 | struct i2c_client *client = to_i2c_client(dev); | |
e6a90810 | 346 | struct st1232_ts_data *ts = i2c_get_clientdata(client); |
56a8bd6d | 347 | |
95dc58a9 DT |
348 | disable_irq(client->irq); |
349 | ||
350 | if (!device_may_wakeup(&client->dev)) | |
e6a90810 | 351 | st1232_ts_power(ts, false); |
56a8bd6d TS |
352 | |
353 | return 0; | |
354 | } | |
355 | ||
7c8d436d | 356 | static int st1232_ts_resume(struct device *dev) |
56a8bd6d TS |
357 | { |
358 | struct i2c_client *client = to_i2c_client(dev); | |
e6a90810 | 359 | struct st1232_ts_data *ts = i2c_get_clientdata(client); |
56a8bd6d | 360 | |
95dc58a9 | 361 | if (!device_may_wakeup(&client->dev)) |
e6a90810 | 362 | st1232_ts_power(ts, true); |
95dc58a9 DT |
363 | |
364 | enable_irq(client->irq); | |
56a8bd6d TS |
365 | |
366 | return 0; | |
367 | } | |
368 | ||
7c8d436d JC |
369 | static DEFINE_SIMPLE_DEV_PM_OPS(st1232_ts_pm_ops, |
370 | st1232_ts_suspend, st1232_ts_resume); | |
b3571400 | 371 | |
56a8bd6d | 372 | static const struct i2c_device_id st1232_ts_id[] = { |
351e0592 MK |
373 | { ST1232_TS_NAME, (unsigned long)&st1232_chip_info }, |
374 | { ST1633_TS_NAME, (unsigned long)&st1633_chip_info }, | |
56a8bd6d TS |
375 | { } |
376 | }; | |
377 | MODULE_DEVICE_TABLE(i2c, st1232_ts_id); | |
378 | ||
78f50c24 | 379 | static const struct of_device_id st1232_ts_dt_ids[] = { |
351e0592 MK |
380 | { .compatible = "sitronix,st1232", .data = &st1232_chip_info }, |
381 | { .compatible = "sitronix,st1633", .data = &st1633_chip_info }, | |
e6293d2f MD |
382 | { } |
383 | }; | |
384 | MODULE_DEVICE_TABLE(of, st1232_ts_dt_ids); | |
e6293d2f | 385 | |
56a8bd6d | 386 | static struct i2c_driver st1232_ts_driver = { |
d8bde56d | 387 | .probe = st1232_ts_probe, |
56a8bd6d TS |
388 | .id_table = st1232_ts_id, |
389 | .driver = { | |
390 | .name = ST1232_TS_NAME, | |
4a1a57df | 391 | .of_match_table = st1232_ts_dt_ids, |
b415ed4f | 392 | .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
7c8d436d | 393 | .pm = pm_sleep_ptr(&st1232_ts_pm_ops), |
56a8bd6d TS |
394 | }, |
395 | }; | |
396 | ||
1b92c1cf | 397 | module_i2c_driver(st1232_ts_driver); |
56a8bd6d TS |
398 | |
399 | MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>"); | |
4dbb7119 | 400 | MODULE_AUTHOR("Martin Kepplinger <martin.kepplinger@ginzinger.com>"); |
56a8bd6d | 401 | MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); |
4aeba641 | 402 | MODULE_LICENSE("GPL v2"); |