.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for Pixcir I2C touchscreen controllers. |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2010-2011 Pixcir, Inc. |
---|
5 | | - * |
---|
6 | | - * This software is licensed under the terms of the GNU General Public |
---|
7 | | - * License version 2, as published by the Free Software Foundation, and |
---|
8 | | - * may be copied, distributed, and modified under those terms. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
| 8 | +#include <asm/unaligned.h> |
---|
16 | 9 | #include <linux/delay.h> |
---|
17 | | -#include <linux/module.h> |
---|
18 | | -#include <linux/interrupt.h> |
---|
19 | | -#include <linux/slab.h> |
---|
| 10 | +#include <linux/gpio/consumer.h> |
---|
20 | 11 | #include <linux/i2c.h> |
---|
21 | 12 | #include <linux/input.h> |
---|
22 | 13 | #include <linux/input/mt.h> |
---|
23 | 14 | #include <linux/input/touchscreen.h> |
---|
24 | | -#include <linux/gpio.h> |
---|
25 | | -#include <linux/gpio/consumer.h> |
---|
| 15 | +#include <linux/interrupt.h> |
---|
26 | 16 | #include <linux/of_device.h> |
---|
27 | | -#include <linux/platform_data/pixcir_i2c_ts.h> |
---|
28 | | -#include <asm/unaligned.h> |
---|
| 17 | +#include <linux/module.h> |
---|
| 18 | +#include <linux/slab.h> |
---|
29 | 19 | |
---|
30 | 20 | #define PIXCIR_MAX_SLOTS 5 /* Max fingers supported by driver */ |
---|
| 21 | + |
---|
| 22 | +/* |
---|
| 23 | + * Register map |
---|
| 24 | + */ |
---|
| 25 | +#define PIXCIR_REG_POWER_MODE 51 |
---|
| 26 | +#define PIXCIR_REG_INT_MODE 52 |
---|
| 27 | + |
---|
| 28 | +/* |
---|
| 29 | + * Power modes: |
---|
| 30 | + * active: max scan speed |
---|
| 31 | + * idle: lower scan speed with automatic transition to active on touch |
---|
| 32 | + * halt: datasheet says sleep but this is more like halt as the chip |
---|
| 33 | + * clocks are cut and it can only be brought out of this mode |
---|
| 34 | + * using the RESET pin. |
---|
| 35 | + */ |
---|
| 36 | +enum pixcir_power_mode { |
---|
| 37 | + PIXCIR_POWER_ACTIVE, |
---|
| 38 | + PIXCIR_POWER_IDLE, |
---|
| 39 | + PIXCIR_POWER_HALT, |
---|
| 40 | +}; |
---|
| 41 | + |
---|
| 42 | +#define PIXCIR_POWER_MODE_MASK 0x03 |
---|
| 43 | +#define PIXCIR_POWER_ALLOW_IDLE (1UL << 2) |
---|
| 44 | + |
---|
| 45 | +/* |
---|
| 46 | + * Interrupt modes: |
---|
| 47 | + * periodical: interrupt is asserted periodicaly |
---|
| 48 | + * diff coordinates: interrupt is asserted when coordinates change |
---|
| 49 | + * level on touch: interrupt level asserted during touch |
---|
| 50 | + * pulse on touch: interrupt pulse asserted during touch |
---|
| 51 | + * |
---|
| 52 | + */ |
---|
| 53 | +enum pixcir_int_mode { |
---|
| 54 | + PIXCIR_INT_PERIODICAL, |
---|
| 55 | + PIXCIR_INT_DIFF_COORD, |
---|
| 56 | + PIXCIR_INT_LEVEL_TOUCH, |
---|
| 57 | + PIXCIR_INT_PULSE_TOUCH, |
---|
| 58 | +}; |
---|
| 59 | + |
---|
| 60 | +#define PIXCIR_INT_MODE_MASK 0x03 |
---|
| 61 | +#define PIXCIR_INT_ENABLE (1UL << 3) |
---|
| 62 | +#define PIXCIR_INT_POL_HIGH (1UL << 2) |
---|
| 63 | + |
---|
| 64 | +/** |
---|
| 65 | + * struct pixcir_i2c_chip_data - chip related data |
---|
| 66 | + * @max_fingers: Max number of fingers reported simultaneously by h/w |
---|
| 67 | + * @has_hw_ids: Hardware supports finger tracking IDs |
---|
| 68 | + * |
---|
| 69 | + */ |
---|
| 70 | +struct pixcir_i2c_chip_data { |
---|
| 71 | + u8 max_fingers; |
---|
| 72 | + bool has_hw_ids; |
---|
| 73 | +}; |
---|
31 | 74 | |
---|
32 | 75 | struct pixcir_i2c_ts_data { |
---|
33 | 76 | struct i2c_client *client; |
---|
.. | .. |
---|
38 | 81 | struct gpio_desc *gpio_wake; |
---|
39 | 82 | const struct pixcir_i2c_chip_data *chip; |
---|
40 | 83 | struct touchscreen_properties prop; |
---|
41 | | - int max_fingers; /* Max fingers supported in this instance */ |
---|
42 | 84 | bool running; |
---|
43 | 85 | }; |
---|
44 | 86 | |
---|
.. | .. |
---|
62 | 104 | memset(report, 0, sizeof(struct pixcir_report_data)); |
---|
63 | 105 | |
---|
64 | 106 | i = chip->has_hw_ids ? 1 : 0; |
---|
65 | | - readsize = 2 + tsdata->max_fingers * (4 + i); |
---|
| 107 | + readsize = 2 + tsdata->chip->max_fingers * (4 + i); |
---|
66 | 108 | if (readsize > sizeof(rdbuf)) |
---|
67 | 109 | readsize = sizeof(rdbuf); |
---|
68 | 110 | |
---|
.. | .. |
---|
83 | 125 | } |
---|
84 | 126 | |
---|
85 | 127 | touch = rdbuf[0] & 0x7; |
---|
86 | | - if (touch > tsdata->max_fingers) |
---|
87 | | - touch = tsdata->max_fingers; |
---|
| 128 | + if (touch > tsdata->chip->max_fingers) |
---|
| 129 | + touch = tsdata->chip->max_fingers; |
---|
88 | 130 | |
---|
89 | 131 | report->num_touches = touch; |
---|
90 | 132 | bufptr = &rdbuf[2]; |
---|
.. | .. |
---|
200 | 242 | |
---|
201 | 243 | ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_POWER_MODE); |
---|
202 | 244 | if (ret < 0) { |
---|
203 | | - dev_err(dev, "%s: can't read reg 0x%x : %d\n", |
---|
| 245 | + dev_err(dev, "%s: can't read reg %d : %d\n", |
---|
204 | 246 | __func__, PIXCIR_REG_POWER_MODE, ret); |
---|
205 | 247 | return ret; |
---|
206 | 248 | } |
---|
.. | .. |
---|
213 | 255 | |
---|
214 | 256 | ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_POWER_MODE, ret); |
---|
215 | 257 | if (ret < 0) { |
---|
216 | | - dev_err(dev, "%s: can't write reg 0x%x : %d\n", |
---|
| 258 | + dev_err(dev, "%s: can't write reg %d : %d\n", |
---|
217 | 259 | __func__, PIXCIR_REG_POWER_MODE, ret); |
---|
218 | 260 | return ret; |
---|
219 | 261 | } |
---|
.. | .. |
---|
239 | 281 | |
---|
240 | 282 | ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); |
---|
241 | 283 | if (ret < 0) { |
---|
242 | | - dev_err(dev, "%s: can't read reg 0x%x : %d\n", |
---|
| 284 | + dev_err(dev, "%s: can't read reg %d : %d\n", |
---|
243 | 285 | __func__, PIXCIR_REG_INT_MODE, ret); |
---|
244 | 286 | return ret; |
---|
245 | 287 | } |
---|
.. | .. |
---|
254 | 296 | |
---|
255 | 297 | ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); |
---|
256 | 298 | if (ret < 0) { |
---|
257 | | - dev_err(dev, "%s: can't write reg 0x%x : %d\n", |
---|
| 299 | + dev_err(dev, "%s: can't write reg %d : %d\n", |
---|
258 | 300 | __func__, PIXCIR_REG_INT_MODE, ret); |
---|
259 | 301 | return ret; |
---|
260 | 302 | } |
---|
.. | .. |
---|
272 | 314 | |
---|
273 | 315 | ret = i2c_smbus_read_byte_data(ts->client, PIXCIR_REG_INT_MODE); |
---|
274 | 316 | if (ret < 0) { |
---|
275 | | - dev_err(dev, "%s: can't read reg 0x%x : %d\n", |
---|
| 317 | + dev_err(dev, "%s: can't read reg %d : %d\n", |
---|
276 | 318 | __func__, PIXCIR_REG_INT_MODE, ret); |
---|
277 | 319 | return ret; |
---|
278 | 320 | } |
---|
.. | .. |
---|
284 | 326 | |
---|
285 | 327 | ret = i2c_smbus_write_byte_data(ts->client, PIXCIR_REG_INT_MODE, ret); |
---|
286 | 328 | if (ret < 0) { |
---|
287 | | - dev_err(dev, "%s: can't write reg 0x%x : %d\n", |
---|
| 329 | + dev_err(dev, "%s: can't write reg %d : %d\n", |
---|
288 | 330 | __func__, PIXCIR_REG_INT_MODE, ret); |
---|
289 | 331 | return ret; |
---|
290 | 332 | } |
---|
.. | .. |
---|
420 | 462 | static SIMPLE_DEV_PM_OPS(pixcir_dev_pm_ops, |
---|
421 | 463 | pixcir_i2c_ts_suspend, pixcir_i2c_ts_resume); |
---|
422 | 464 | |
---|
423 | | -#ifdef CONFIG_OF |
---|
424 | | -static const struct of_device_id pixcir_of_match[]; |
---|
425 | | - |
---|
426 | | -static int pixcir_parse_dt(struct device *dev, |
---|
427 | | - struct pixcir_i2c_ts_data *tsdata) |
---|
428 | | -{ |
---|
429 | | - tsdata->chip = of_device_get_match_data(dev); |
---|
430 | | - if (!tsdata->chip) |
---|
431 | | - return -EINVAL; |
---|
432 | | - |
---|
433 | | - return 0; |
---|
434 | | -} |
---|
435 | | -#else |
---|
436 | | -static int pixcir_parse_dt(struct device *dev, |
---|
437 | | - struct pixcir_i2c_ts_data *tsdata) |
---|
438 | | -{ |
---|
439 | | - return -EINVAL; |
---|
440 | | -} |
---|
441 | | -#endif |
---|
442 | | - |
---|
443 | 465 | static int pixcir_i2c_ts_probe(struct i2c_client *client, |
---|
444 | 466 | const struct i2c_device_id *id) |
---|
445 | 467 | { |
---|
446 | | - const struct pixcir_ts_platform_data *pdata = |
---|
447 | | - dev_get_platdata(&client->dev); |
---|
448 | 468 | struct device *dev = &client->dev; |
---|
449 | 469 | struct pixcir_i2c_ts_data *tsdata; |
---|
450 | 470 | struct input_dev *input; |
---|
.. | .. |
---|
454 | 474 | if (!tsdata) |
---|
455 | 475 | return -ENOMEM; |
---|
456 | 476 | |
---|
457 | | - if (pdata) { |
---|
458 | | - tsdata->chip = &pdata->chip; |
---|
459 | | - } else if (dev->of_node) { |
---|
460 | | - error = pixcir_parse_dt(dev, tsdata); |
---|
461 | | - if (error) |
---|
462 | | - return error; |
---|
463 | | - } else { |
---|
464 | | - dev_err(dev, "platform data not defined\n"); |
---|
465 | | - return -EINVAL; |
---|
466 | | - } |
---|
467 | | - |
---|
468 | | - if (!tsdata->chip->max_fingers) { |
---|
469 | | - dev_err(dev, "Invalid max_fingers in chip data\n"); |
---|
| 477 | + tsdata->chip = device_get_match_data(dev); |
---|
| 478 | + if (!tsdata->chip && id) |
---|
| 479 | + tsdata->chip = (const void *)id->driver_data; |
---|
| 480 | + if (!tsdata->chip) { |
---|
| 481 | + dev_err(dev, "can't locate chip data\n"); |
---|
470 | 482 | return -EINVAL; |
---|
471 | 483 | } |
---|
472 | 484 | |
---|
.. | .. |
---|
483 | 495 | input->id.bustype = BUS_I2C; |
---|
484 | 496 | input->open = pixcir_input_open; |
---|
485 | 497 | input->close = pixcir_input_close; |
---|
486 | | - input->dev.parent = dev; |
---|
487 | 498 | |
---|
488 | | - if (pdata) { |
---|
489 | | - input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0); |
---|
490 | | - input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0); |
---|
491 | | - } else { |
---|
492 | | - input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); |
---|
493 | | - input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); |
---|
494 | | - touchscreen_parse_properties(input, true, &tsdata->prop); |
---|
495 | | - if (!input_abs_get_max(input, ABS_MT_POSITION_X) || |
---|
496 | | - !input_abs_get_max(input, ABS_MT_POSITION_Y)) { |
---|
497 | | - dev_err(dev, "Touchscreen size is not specified\n"); |
---|
498 | | - return -EINVAL; |
---|
499 | | - } |
---|
| 499 | + input_set_capability(input, EV_ABS, ABS_MT_POSITION_X); |
---|
| 500 | + input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y); |
---|
| 501 | + touchscreen_parse_properties(input, true, &tsdata->prop); |
---|
| 502 | + if (!input_abs_get_max(input, ABS_MT_POSITION_X) || |
---|
| 503 | + !input_abs_get_max(input, ABS_MT_POSITION_Y)) { |
---|
| 504 | + dev_err(dev, "Touchscreen size is not specified\n"); |
---|
| 505 | + return -EINVAL; |
---|
500 | 506 | } |
---|
501 | 507 | |
---|
502 | | - tsdata->max_fingers = tsdata->chip->max_fingers; |
---|
503 | | - if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) { |
---|
504 | | - tsdata->max_fingers = PIXCIR_MAX_SLOTS; |
---|
505 | | - dev_info(dev, "Limiting maximum fingers to %d\n", |
---|
506 | | - tsdata->max_fingers); |
---|
507 | | - } |
---|
508 | | - |
---|
509 | | - error = input_mt_init_slots(input, tsdata->max_fingers, |
---|
| 508 | + error = input_mt_init_slots(input, tsdata->chip->max_fingers, |
---|
510 | 509 | INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); |
---|
511 | 510 | if (error) { |
---|
512 | 511 | dev_err(dev, "Error initializing Multi-Touch slots\n"); |
---|
.. | .. |
---|
518 | 517 | tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN); |
---|
519 | 518 | if (IS_ERR(tsdata->gpio_attb)) { |
---|
520 | 519 | error = PTR_ERR(tsdata->gpio_attb); |
---|
521 | | - dev_err(dev, "Failed to request ATTB gpio: %d\n", error); |
---|
| 520 | + if (error != -EPROBE_DEFER) |
---|
| 521 | + dev_err(dev, "Failed to request ATTB gpio: %d\n", |
---|
| 522 | + error); |
---|
522 | 523 | return error; |
---|
523 | 524 | } |
---|
524 | 525 | |
---|
.. | .. |
---|
526 | 527 | GPIOD_OUT_LOW); |
---|
527 | 528 | if (IS_ERR(tsdata->gpio_reset)) { |
---|
528 | 529 | error = PTR_ERR(tsdata->gpio_reset); |
---|
529 | | - dev_err(dev, "Failed to request RESET gpio: %d\n", error); |
---|
| 530 | + if (error != -EPROBE_DEFER) |
---|
| 531 | + dev_err(dev, "Failed to request RESET gpio: %d\n", |
---|
| 532 | + error); |
---|
530 | 533 | return error; |
---|
531 | 534 | } |
---|
532 | 535 | |
---|
.. | .. |
---|
582 | 585 | return 0; |
---|
583 | 586 | } |
---|
584 | 587 | |
---|
585 | | -static const struct i2c_device_id pixcir_i2c_ts_id[] = { |
---|
586 | | - { "pixcir_ts", 0 }, |
---|
587 | | - { "pixcir_tangoc", 0 }, |
---|
588 | | - { } |
---|
589 | | -}; |
---|
590 | | -MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); |
---|
591 | | - |
---|
592 | | -#ifdef CONFIG_OF |
---|
593 | 588 | static const struct pixcir_i2c_chip_data pixcir_ts_data = { |
---|
594 | 589 | .max_fingers = 2, |
---|
595 | 590 | /* no hw id support */ |
---|
.. | .. |
---|
600 | 595 | .has_hw_ids = true, |
---|
601 | 596 | }; |
---|
602 | 597 | |
---|
| 598 | +static const struct i2c_device_id pixcir_i2c_ts_id[] = { |
---|
| 599 | + { "pixcir_ts", (unsigned long) &pixcir_ts_data }, |
---|
| 600 | + { "pixcir_tangoc", (unsigned long) &pixcir_tangoc_data }, |
---|
| 601 | + { } |
---|
| 602 | +}; |
---|
| 603 | +MODULE_DEVICE_TABLE(i2c, pixcir_i2c_ts_id); |
---|
| 604 | + |
---|
| 605 | +#ifdef CONFIG_OF |
---|
603 | 606 | static const struct of_device_id pixcir_of_match[] = { |
---|
604 | 607 | { .compatible = "pixcir,pixcir_ts", .data = &pixcir_ts_data }, |
---|
605 | 608 | { .compatible = "pixcir,pixcir_tangoc", .data = &pixcir_tangoc_data }, |
---|