1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Melfas MMS114/MMS136/MMS152 touchscreen device driver |
3 | // |
4 | // Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | // Author: Joonyoung Shim <jy0922.shim@samsung.com> |
6 | |
7 | #include <linux/module.h> |
8 | #include <linux/delay.h> |
9 | #include <linux/of.h> |
10 | #include <linux/i2c.h> |
11 | #include <linux/input/mt.h> |
12 | #include <linux/input/touchscreen.h> |
13 | #include <linux/interrupt.h> |
14 | #include <linux/regulator/consumer.h> |
15 | #include <linux/slab.h> |
16 | |
17 | /* Write only registers */ |
18 | #define MMS114_MODE_CONTROL 0x01 |
19 | #define MMS114_OPERATION_MODE_MASK 0xE |
20 | #define MMS114_ACTIVE BIT(1) |
21 | |
22 | #define MMS114_XY_RESOLUTION_H 0x02 |
23 | #define MMS114_X_RESOLUTION 0x03 |
24 | #define MMS114_Y_RESOLUTION 0x04 |
25 | #define MMS114_CONTACT_THRESHOLD 0x05 |
26 | #define MMS114_MOVING_THRESHOLD 0x06 |
27 | |
28 | /* Read only registers */ |
29 | #define MMS114_PACKET_SIZE 0x0F |
30 | #define MMS114_INFORMATION 0x10 |
31 | #define MMS114_TSP_REV 0xF0 |
32 | |
33 | #define MMS152_FW_REV 0xE1 |
34 | #define MMS152_COMPAT_GROUP 0xF2 |
35 | |
36 | /* Minimum delay time is 50us between stop and start signal of i2c */ |
37 | #define MMS114_I2C_DELAY 50 |
38 | |
39 | /* 200ms needs after power on */ |
40 | #define MMS114_POWERON_DELAY 200 |
41 | |
42 | /* Touchscreen absolute values */ |
43 | #define MMS114_MAX_AREA 0xff |
44 | |
45 | #define MMS114_MAX_TOUCHKEYS 15 |
46 | #define MMS114_MAX_TOUCH 10 |
47 | #define MMS114_EVENT_SIZE 8 |
48 | #define MMS136_EVENT_SIZE 6 |
49 | |
50 | /* Touch type */ |
51 | #define MMS114_TYPE_NONE 0 |
52 | #define MMS114_TYPE_TOUCHSCREEN 1 |
53 | #define MMS114_TYPE_TOUCHKEY 2 |
54 | |
55 | enum mms_type { |
56 | TYPE_MMS114 = 114, |
57 | TYPE_MMS134S = 134, |
58 | TYPE_MMS136 = 136, |
59 | TYPE_MMS152 = 152, |
60 | TYPE_MMS345L = 345, |
61 | }; |
62 | |
63 | struct mms114_data { |
64 | struct i2c_client *client; |
65 | struct input_dev *input_dev; |
66 | struct regulator *core_reg; |
67 | struct regulator *io_reg; |
68 | struct touchscreen_properties props; |
69 | enum mms_type type; |
70 | unsigned int contact_threshold; |
71 | unsigned int moving_threshold; |
72 | |
73 | u32 keycodes[MMS114_MAX_TOUCHKEYS]; |
74 | int num_keycodes; |
75 | |
76 | /* Use cache data for mode control register(write only) */ |
77 | u8 cache_mode_control; |
78 | }; |
79 | |
80 | struct mms114_touch { |
81 | u8 id:4, reserved_bit4:1, type:2, pressed:1; |
82 | u8 x_hi:4, y_hi:4; |
83 | u8 x_lo; |
84 | u8 y_lo; |
85 | u8 width; |
86 | u8 strength; |
87 | u8 reserved[2]; |
88 | } __packed; |
89 | |
90 | static int __mms114_read_reg(struct mms114_data *data, unsigned int reg, |
91 | unsigned int len, u8 *val) |
92 | { |
93 | struct i2c_client *client = data->client; |
94 | struct i2c_msg xfer[2]; |
95 | u8 buf = reg & 0xff; |
96 | int error; |
97 | |
98 | if (reg <= MMS114_MODE_CONTROL && reg + len > MMS114_MODE_CONTROL) |
99 | BUG(); |
100 | |
101 | /* Write register */ |
102 | xfer[0].addr = client->addr; |
103 | xfer[0].flags = client->flags & I2C_M_TEN; |
104 | xfer[0].len = 1; |
105 | xfer[0].buf = &buf; |
106 | |
107 | /* Read data */ |
108 | xfer[1].addr = client->addr; |
109 | xfer[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD; |
110 | xfer[1].len = len; |
111 | xfer[1].buf = val; |
112 | |
113 | error = i2c_transfer(adap: client->adapter, msgs: xfer, num: 2); |
114 | if (error != 2) { |
115 | dev_err(&client->dev, |
116 | "%s: i2c transfer failed (%d)\n" , __func__, error); |
117 | return error < 0 ? error : -EIO; |
118 | } |
119 | udelay(MMS114_I2C_DELAY); |
120 | |
121 | return 0; |
122 | } |
123 | |
124 | static int mms114_read_reg(struct mms114_data *data, unsigned int reg) |
125 | { |
126 | u8 val; |
127 | int error; |
128 | |
129 | if (reg == MMS114_MODE_CONTROL) |
130 | return data->cache_mode_control; |
131 | |
132 | error = __mms114_read_reg(data, reg, len: 1, val: &val); |
133 | return error < 0 ? error : val; |
134 | } |
135 | |
136 | static int mms114_write_reg(struct mms114_data *data, unsigned int reg, |
137 | unsigned int val) |
138 | { |
139 | struct i2c_client *client = data->client; |
140 | u8 buf[2]; |
141 | int error; |
142 | |
143 | buf[0] = reg & 0xff; |
144 | buf[1] = val & 0xff; |
145 | |
146 | error = i2c_master_send(client, buf, count: 2); |
147 | if (error != 2) { |
148 | dev_err(&client->dev, |
149 | "%s: i2c send failed (%d)\n" , __func__, error); |
150 | return error < 0 ? error : -EIO; |
151 | } |
152 | udelay(MMS114_I2C_DELAY); |
153 | |
154 | if (reg == MMS114_MODE_CONTROL) |
155 | data->cache_mode_control = val; |
156 | |
157 | return 0; |
158 | } |
159 | |
160 | static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *touch) |
161 | { |
162 | struct i2c_client *client = data->client; |
163 | struct input_dev *input_dev = data->input_dev; |
164 | unsigned int id; |
165 | unsigned int x; |
166 | unsigned int y; |
167 | |
168 | if (touch->id > MMS114_MAX_TOUCH) { |
169 | dev_err(&client->dev, "Wrong touch id (%d)\n" , touch->id); |
170 | return; |
171 | } |
172 | |
173 | id = touch->id - 1; |
174 | x = touch->x_lo | touch->x_hi << 8; |
175 | y = touch->y_lo | touch->y_hi << 8; |
176 | |
177 | dev_dbg(&client->dev, |
178 | "id: %d, type: %d, pressed: %d, x: %d, y: %d, width: %d, strength: %d\n" , |
179 | id, touch->type, touch->pressed, |
180 | x, y, touch->width, touch->strength); |
181 | |
182 | input_mt_slot(dev: input_dev, slot: id); |
183 | input_mt_report_slot_state(dev: input_dev, MT_TOOL_FINGER, active: touch->pressed); |
184 | |
185 | if (touch->pressed) { |
186 | touchscreen_report_pos(input: input_dev, prop: &data->props, x, y, multitouch: true); |
187 | input_report_abs(dev: input_dev, ABS_MT_TOUCH_MAJOR, value: touch->width); |
188 | input_report_abs(dev: input_dev, ABS_MT_PRESSURE, value: touch->strength); |
189 | } |
190 | } |
191 | |
192 | static void mms114_process_touchkey(struct mms114_data *data, |
193 | struct mms114_touch *touch) |
194 | { |
195 | struct i2c_client *client = data->client; |
196 | struct input_dev *input_dev = data->input_dev; |
197 | unsigned int keycode_id; |
198 | |
199 | if (touch->id == 0) |
200 | return; |
201 | |
202 | if (touch->id > data->num_keycodes) { |
203 | dev_err(&client->dev, "Wrong touch id for touchkey (%d)\n" , |
204 | touch->id); |
205 | return; |
206 | } |
207 | |
208 | keycode_id = touch->id - 1; |
209 | dev_dbg(&client->dev, "keycode id: %d, pressed: %d\n" , keycode_id, |
210 | touch->pressed); |
211 | |
212 | input_report_key(dev: input_dev, code: data->keycodes[keycode_id], value: touch->pressed); |
213 | } |
214 | |
215 | static irqreturn_t mms114_interrupt(int irq, void *dev_id) |
216 | { |
217 | struct mms114_data *data = dev_id; |
218 | struct i2c_client *client = data->client; |
219 | struct input_dev *input_dev = data->input_dev; |
220 | struct mms114_touch touch[MMS114_MAX_TOUCH]; |
221 | int packet_size; |
222 | int touch_size; |
223 | int index; |
224 | int error; |
225 | |
226 | mutex_lock(&input_dev->mutex); |
227 | if (!input_device_enabled(dev: input_dev)) { |
228 | mutex_unlock(lock: &input_dev->mutex); |
229 | goto out; |
230 | } |
231 | mutex_unlock(lock: &input_dev->mutex); |
232 | |
233 | packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE); |
234 | if (packet_size <= 0) |
235 | goto out; |
236 | |
237 | /* MMS136 has slightly different event size */ |
238 | if (data->type == TYPE_MMS134S || data->type == TYPE_MMS136) |
239 | touch_size = packet_size / MMS136_EVENT_SIZE; |
240 | else |
241 | touch_size = packet_size / MMS114_EVENT_SIZE; |
242 | |
243 | error = __mms114_read_reg(data, MMS114_INFORMATION, len: packet_size, |
244 | val: (u8 *)touch); |
245 | if (error < 0) |
246 | goto out; |
247 | |
248 | for (index = 0; index < touch_size; index++) { |
249 | switch (touch[index].type) { |
250 | case MMS114_TYPE_TOUCHSCREEN: |
251 | mms114_process_mt(data, touch: touch + index); |
252 | break; |
253 | |
254 | case MMS114_TYPE_TOUCHKEY: |
255 | mms114_process_touchkey(data, touch: touch + index); |
256 | break; |
257 | |
258 | default: |
259 | dev_err(&client->dev, "Wrong touch type (%d)\n" , |
260 | touch[index].type); |
261 | break; |
262 | } |
263 | } |
264 | |
265 | input_mt_report_pointer_emulation(dev: data->input_dev, use_count: true); |
266 | input_sync(dev: data->input_dev); |
267 | |
268 | out: |
269 | return IRQ_HANDLED; |
270 | } |
271 | |
272 | static int mms114_set_active(struct mms114_data *data, bool active) |
273 | { |
274 | int val; |
275 | |
276 | val = mms114_read_reg(data, MMS114_MODE_CONTROL); |
277 | if (val < 0) |
278 | return val; |
279 | |
280 | val &= ~MMS114_OPERATION_MODE_MASK; |
281 | |
282 | /* If active is false, sleep mode */ |
283 | if (active) |
284 | val |= MMS114_ACTIVE; |
285 | |
286 | return mms114_write_reg(data, MMS114_MODE_CONTROL, val); |
287 | } |
288 | |
289 | static int mms114_get_version(struct mms114_data *data) |
290 | { |
291 | struct device *dev = &data->client->dev; |
292 | u8 buf[6]; |
293 | int group; |
294 | int error; |
295 | |
296 | switch (data->type) { |
297 | case TYPE_MMS345L: |
298 | error = __mms114_read_reg(data, MMS152_FW_REV, len: 3, val: buf); |
299 | if (error) |
300 | return error; |
301 | |
302 | dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x\n" , |
303 | buf[0], buf[1], buf[2]); |
304 | break; |
305 | |
306 | case TYPE_MMS152: |
307 | error = __mms114_read_reg(data, MMS152_FW_REV, len: 3, val: buf); |
308 | if (error) |
309 | return error; |
310 | |
311 | group = i2c_smbus_read_byte_data(client: data->client, |
312 | MMS152_COMPAT_GROUP); |
313 | if (group < 0) |
314 | return group; |
315 | |
316 | dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x, Compat group: %c\n" , |
317 | buf[0], buf[1], buf[2], group); |
318 | break; |
319 | |
320 | case TYPE_MMS114: |
321 | case TYPE_MMS134S: |
322 | case TYPE_MMS136: |
323 | error = __mms114_read_reg(data, MMS114_TSP_REV, len: 6, val: buf); |
324 | if (error) |
325 | return error; |
326 | |
327 | dev_info(dev, "TSP Rev: 0x%x, HW Rev: 0x%x, Firmware Ver: 0x%x\n" , |
328 | buf[0], buf[1], buf[3]); |
329 | break; |
330 | } |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int mms114_setup_regs(struct mms114_data *data) |
336 | { |
337 | const struct touchscreen_properties *props = &data->props; |
338 | int val; |
339 | int error; |
340 | |
341 | error = mms114_get_version(data); |
342 | if (error < 0) |
343 | return error; |
344 | |
345 | /* MMS114, MMS134S and MMS136 have configuration and power on registers */ |
346 | if (data->type != TYPE_MMS114 && data->type != TYPE_MMS134S && |
347 | data->type != TYPE_MMS136) |
348 | return 0; |
349 | |
350 | error = mms114_set_active(data, active: true); |
351 | if (error < 0) |
352 | return error; |
353 | |
354 | val = (props->max_x >> 8) & 0xf; |
355 | val |= ((props->max_y >> 8) & 0xf) << 4; |
356 | error = mms114_write_reg(data, MMS114_XY_RESOLUTION_H, val); |
357 | if (error < 0) |
358 | return error; |
359 | |
360 | val = props->max_x & 0xff; |
361 | error = mms114_write_reg(data, MMS114_X_RESOLUTION, val); |
362 | if (error < 0) |
363 | return error; |
364 | |
365 | val = props->max_x & 0xff; |
366 | error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val); |
367 | if (error < 0) |
368 | return error; |
369 | |
370 | if (data->contact_threshold) { |
371 | error = mms114_write_reg(data, MMS114_CONTACT_THRESHOLD, |
372 | val: data->contact_threshold); |
373 | if (error < 0) |
374 | return error; |
375 | } |
376 | |
377 | if (data->moving_threshold) { |
378 | error = mms114_write_reg(data, MMS114_MOVING_THRESHOLD, |
379 | val: data->moving_threshold); |
380 | if (error < 0) |
381 | return error; |
382 | } |
383 | |
384 | return 0; |
385 | } |
386 | |
387 | static int mms114_start(struct mms114_data *data) |
388 | { |
389 | struct i2c_client *client = data->client; |
390 | int error; |
391 | |
392 | error = regulator_enable(regulator: data->core_reg); |
393 | if (error) { |
394 | dev_err(&client->dev, "Failed to enable avdd: %d\n" , error); |
395 | return error; |
396 | } |
397 | |
398 | error = regulator_enable(regulator: data->io_reg); |
399 | if (error) { |
400 | dev_err(&client->dev, "Failed to enable vdd: %d\n" , error); |
401 | regulator_disable(regulator: data->core_reg); |
402 | return error; |
403 | } |
404 | |
405 | msleep(MMS114_POWERON_DELAY); |
406 | |
407 | error = mms114_setup_regs(data); |
408 | if (error < 0) { |
409 | regulator_disable(regulator: data->io_reg); |
410 | regulator_disable(regulator: data->core_reg); |
411 | return error; |
412 | } |
413 | |
414 | enable_irq(irq: client->irq); |
415 | |
416 | return 0; |
417 | } |
418 | |
419 | static void mms114_stop(struct mms114_data *data) |
420 | { |
421 | struct i2c_client *client = data->client; |
422 | int error; |
423 | |
424 | disable_irq(irq: client->irq); |
425 | |
426 | error = regulator_disable(regulator: data->io_reg); |
427 | if (error) |
428 | dev_warn(&client->dev, "Failed to disable vdd: %d\n" , error); |
429 | |
430 | error = regulator_disable(regulator: data->core_reg); |
431 | if (error) |
432 | dev_warn(&client->dev, "Failed to disable avdd: %d\n" , error); |
433 | } |
434 | |
435 | static int mms114_input_open(struct input_dev *dev) |
436 | { |
437 | struct mms114_data *data = input_get_drvdata(dev); |
438 | |
439 | return mms114_start(data); |
440 | } |
441 | |
442 | static void mms114_input_close(struct input_dev *dev) |
443 | { |
444 | struct mms114_data *data = input_get_drvdata(dev); |
445 | |
446 | mms114_stop(data); |
447 | } |
448 | |
449 | static int mms114_parse_legacy_bindings(struct mms114_data *data) |
450 | { |
451 | struct device *dev = &data->client->dev; |
452 | struct touchscreen_properties *props = &data->props; |
453 | |
454 | if (device_property_read_u32(dev, propname: "x-size" , val: &props->max_x)) { |
455 | dev_dbg(dev, "failed to get legacy x-size property\n" ); |
456 | return -EINVAL; |
457 | } |
458 | |
459 | if (device_property_read_u32(dev, propname: "y-size" , val: &props->max_y)) { |
460 | dev_dbg(dev, "failed to get legacy y-size property\n" ); |
461 | return -EINVAL; |
462 | } |
463 | |
464 | device_property_read_u32(dev, propname: "contact-threshold" , |
465 | val: &data->contact_threshold); |
466 | device_property_read_u32(dev, propname: "moving-threshold" , |
467 | val: &data->moving_threshold); |
468 | |
469 | if (device_property_read_bool(dev, propname: "x-invert" )) |
470 | props->invert_x = true; |
471 | if (device_property_read_bool(dev, propname: "y-invert" )) |
472 | props->invert_y = true; |
473 | |
474 | props->swap_x_y = false; |
475 | |
476 | return 0; |
477 | } |
478 | |
479 | static int mms114_probe(struct i2c_client *client) |
480 | { |
481 | struct mms114_data *data; |
482 | struct input_dev *input_dev; |
483 | const void *match_data; |
484 | int error; |
485 | int i; |
486 | |
487 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C)) { |
488 | dev_err(&client->dev, "Not supported I2C adapter\n" ); |
489 | return -ENODEV; |
490 | } |
491 | |
492 | data = devm_kzalloc(dev: &client->dev, size: sizeof(struct mms114_data), |
493 | GFP_KERNEL); |
494 | input_dev = devm_input_allocate_device(&client->dev); |
495 | if (!data || !input_dev) { |
496 | dev_err(&client->dev, "Failed to allocate memory\n" ); |
497 | return -ENOMEM; |
498 | } |
499 | |
500 | data->client = client; |
501 | data->input_dev = input_dev; |
502 | |
503 | match_data = device_get_match_data(dev: &client->dev); |
504 | if (!match_data) |
505 | return -EINVAL; |
506 | |
507 | data->type = (enum mms_type)match_data; |
508 | |
509 | data->num_keycodes = device_property_count_u32(dev: &client->dev, |
510 | propname: "linux,keycodes" ); |
511 | if (data->num_keycodes == -EINVAL) { |
512 | data->num_keycodes = 0; |
513 | } else if (data->num_keycodes < 0) { |
514 | dev_err(&client->dev, |
515 | "Unable to parse linux,keycodes property: %d\n" , |
516 | data->num_keycodes); |
517 | return data->num_keycodes; |
518 | } else if (data->num_keycodes > MMS114_MAX_TOUCHKEYS) { |
519 | dev_warn(&client->dev, |
520 | "Found %d linux,keycodes but max is %d, ignoring the rest\n" , |
521 | data->num_keycodes, MMS114_MAX_TOUCHKEYS); |
522 | data->num_keycodes = MMS114_MAX_TOUCHKEYS; |
523 | } |
524 | |
525 | if (data->num_keycodes > 0) { |
526 | error = device_property_read_u32_array(dev: &client->dev, |
527 | propname: "linux,keycodes" , |
528 | val: data->keycodes, |
529 | nval: data->num_keycodes); |
530 | if (error) { |
531 | dev_err(&client->dev, |
532 | "Unable to read linux,keycodes values: %d\n" , |
533 | error); |
534 | return error; |
535 | } |
536 | |
537 | input_dev->keycode = data->keycodes; |
538 | input_dev->keycodemax = data->num_keycodes; |
539 | input_dev->keycodesize = sizeof(data->keycodes[0]); |
540 | for (i = 0; i < data->num_keycodes; i++) |
541 | input_set_capability(dev: input_dev, |
542 | EV_KEY, code: data->keycodes[i]); |
543 | } |
544 | |
545 | input_set_capability(dev: input_dev, EV_ABS, ABS_MT_POSITION_X); |
546 | input_set_capability(dev: input_dev, EV_ABS, ABS_MT_POSITION_Y); |
547 | input_set_abs_params(dev: input_dev, ABS_MT_PRESSURE, min: 0, max: 255, fuzz: 0, flat: 0); |
548 | input_set_abs_params(dev: input_dev, ABS_MT_TOUCH_MAJOR, |
549 | min: 0, MMS114_MAX_AREA, fuzz: 0, flat: 0); |
550 | |
551 | touchscreen_parse_properties(input: input_dev, multitouch: true, prop: &data->props); |
552 | if (!data->props.max_x || !data->props.max_y) { |
553 | dev_dbg(&client->dev, |
554 | "missing X/Y size properties, trying legacy bindings\n" ); |
555 | error = mms114_parse_legacy_bindings(data); |
556 | if (error) |
557 | return error; |
558 | |
559 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_X, |
560 | min: 0, max: data->props.max_x, fuzz: 0, flat: 0); |
561 | input_set_abs_params(dev: input_dev, ABS_MT_POSITION_Y, |
562 | min: 0, max: data->props.max_y, fuzz: 0, flat: 0); |
563 | } |
564 | |
565 | if (data->type == TYPE_MMS114 || data->type == TYPE_MMS134S || |
566 | data->type == TYPE_MMS136) { |
567 | /* |
568 | * The firmware handles movement and pressure fuzz, so |
569 | * don't duplicate that in software. |
570 | */ |
571 | data->moving_threshold = input_abs_get_fuzz(dev: input_dev, |
572 | ABS_MT_POSITION_X); |
573 | data->contact_threshold = input_abs_get_fuzz(dev: input_dev, |
574 | ABS_MT_PRESSURE); |
575 | input_abs_set_fuzz(dev: input_dev, ABS_MT_POSITION_X, val: 0); |
576 | input_abs_set_fuzz(dev: input_dev, ABS_MT_POSITION_Y, val: 0); |
577 | input_abs_set_fuzz(dev: input_dev, ABS_MT_PRESSURE, val: 0); |
578 | } |
579 | |
580 | input_dev->name = devm_kasprintf(dev: &client->dev, GFP_KERNEL, |
581 | fmt: "MELFAS MMS%d Touchscreen" , |
582 | data->type); |
583 | if (!input_dev->name) |
584 | return -ENOMEM; |
585 | |
586 | input_dev->id.bustype = BUS_I2C; |
587 | input_dev->dev.parent = &client->dev; |
588 | input_dev->open = mms114_input_open; |
589 | input_dev->close = mms114_input_close; |
590 | |
591 | error = input_mt_init_slots(dev: input_dev, MMS114_MAX_TOUCH, |
592 | INPUT_MT_DIRECT); |
593 | if (error) |
594 | return error; |
595 | |
596 | input_set_drvdata(dev: input_dev, data); |
597 | i2c_set_clientdata(client, data); |
598 | |
599 | data->core_reg = devm_regulator_get(dev: &client->dev, id: "avdd" ); |
600 | if (IS_ERR(ptr: data->core_reg)) { |
601 | error = PTR_ERR(ptr: data->core_reg); |
602 | dev_err(&client->dev, |
603 | "Unable to get the Core regulator (%d)\n" , error); |
604 | return error; |
605 | } |
606 | |
607 | data->io_reg = devm_regulator_get(dev: &client->dev, id: "vdd" ); |
608 | if (IS_ERR(ptr: data->io_reg)) { |
609 | error = PTR_ERR(ptr: data->io_reg); |
610 | dev_err(&client->dev, |
611 | "Unable to get the IO regulator (%d)\n" , error); |
612 | return error; |
613 | } |
614 | |
615 | error = devm_request_threaded_irq(dev: &client->dev, irq: client->irq, |
616 | NULL, thread_fn: mms114_interrupt, |
617 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
618 | devname: dev_name(dev: &client->dev), dev_id: data); |
619 | if (error) { |
620 | dev_err(&client->dev, "Failed to register interrupt\n" ); |
621 | return error; |
622 | } |
623 | |
624 | error = input_register_device(data->input_dev); |
625 | if (error) { |
626 | dev_err(&client->dev, "Failed to register input device\n" ); |
627 | return error; |
628 | } |
629 | |
630 | return 0; |
631 | } |
632 | |
633 | static int mms114_suspend(struct device *dev) |
634 | { |
635 | struct i2c_client *client = to_i2c_client(dev); |
636 | struct mms114_data *data = i2c_get_clientdata(client); |
637 | struct input_dev *input_dev = data->input_dev; |
638 | int id; |
639 | |
640 | /* Release all touch */ |
641 | for (id = 0; id < MMS114_MAX_TOUCH; id++) { |
642 | input_mt_slot(dev: input_dev, slot: id); |
643 | input_mt_report_slot_inactive(dev: input_dev); |
644 | } |
645 | |
646 | input_mt_report_pointer_emulation(dev: input_dev, use_count: true); |
647 | input_sync(dev: input_dev); |
648 | |
649 | mutex_lock(&input_dev->mutex); |
650 | if (input_device_enabled(dev: input_dev)) |
651 | mms114_stop(data); |
652 | mutex_unlock(lock: &input_dev->mutex); |
653 | |
654 | return 0; |
655 | } |
656 | |
657 | static int mms114_resume(struct device *dev) |
658 | { |
659 | struct i2c_client *client = to_i2c_client(dev); |
660 | struct mms114_data *data = i2c_get_clientdata(client); |
661 | struct input_dev *input_dev = data->input_dev; |
662 | int error; |
663 | |
664 | mutex_lock(&input_dev->mutex); |
665 | if (input_device_enabled(dev: input_dev)) { |
666 | error = mms114_start(data); |
667 | if (error < 0) { |
668 | mutex_unlock(lock: &input_dev->mutex); |
669 | return error; |
670 | } |
671 | } |
672 | mutex_unlock(lock: &input_dev->mutex); |
673 | |
674 | return 0; |
675 | } |
676 | |
677 | static DEFINE_SIMPLE_DEV_PM_OPS(mms114_pm_ops, mms114_suspend, mms114_resume); |
678 | |
679 | static const struct i2c_device_id mms114_id[] = { |
680 | { "mms114" , 0 }, |
681 | { } |
682 | }; |
683 | MODULE_DEVICE_TABLE(i2c, mms114_id); |
684 | |
685 | #ifdef CONFIG_OF |
686 | static const struct of_device_id mms114_dt_match[] = { |
687 | { |
688 | .compatible = "melfas,mms114" , |
689 | .data = (void *)TYPE_MMS114, |
690 | }, { |
691 | .compatible = "melfas,mms134s" , |
692 | .data = (void *)TYPE_MMS134S, |
693 | }, { |
694 | .compatible = "melfas,mms136" , |
695 | .data = (void *)TYPE_MMS136, |
696 | }, { |
697 | .compatible = "melfas,mms152" , |
698 | .data = (void *)TYPE_MMS152, |
699 | }, { |
700 | .compatible = "melfas,mms345l" , |
701 | .data = (void *)TYPE_MMS345L, |
702 | }, |
703 | { } |
704 | }; |
705 | MODULE_DEVICE_TABLE(of, mms114_dt_match); |
706 | #endif |
707 | |
708 | static struct i2c_driver mms114_driver = { |
709 | .driver = { |
710 | .name = "mms114" , |
711 | .pm = pm_sleep_ptr(&mms114_pm_ops), |
712 | .of_match_table = of_match_ptr(mms114_dt_match), |
713 | }, |
714 | .probe = mms114_probe, |
715 | .id_table = mms114_id, |
716 | }; |
717 | |
718 | module_i2c_driver(mms114_driver); |
719 | |
720 | /* Module information */ |
721 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>" ); |
722 | MODULE_DESCRIPTION("MELFAS mms114 Touchscreen driver" ); |
723 | MODULE_LICENSE("GPL v2" ); |
724 | |