| .. | .. |
|---|
| 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 }, |
|---|