linux/drivers/input/touchscreen/ili210x.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/delay.h>
   3#include <linux/gpio/consumer.h>
   4#include <linux/i2c.h>
   5#include <linux/input.h>
   6#include <linux/input/mt.h>
   7#include <linux/input/touchscreen.h>
   8#include <linux/interrupt.h>
   9#include <linux/module.h>
  10#include <linux/of_device.h>
  11#include <linux/sizes.h>
  12#include <linux/slab.h>
  13#include <asm/unaligned.h>
  14
  15#define ILI2XXX_POLL_PERIOD     20
  16
  17#define ILI210X_DATA_SIZE       64
  18#define ILI211X_DATA_SIZE       43
  19#define ILI251X_DATA_SIZE1      31
  20#define ILI251X_DATA_SIZE2      20
  21
  22/* Touchscreen commands */
  23#define REG_TOUCHDATA           0x10
  24#define REG_PANEL_INFO          0x20
  25#define REG_CALIBRATE           0xcc
  26
  27struct ili2xxx_chip {
  28        int (*read_reg)(struct i2c_client *client, u8 reg,
  29                        void *buf, size_t len);
  30        int (*get_touch_data)(struct i2c_client *client, u8 *data);
  31        bool (*parse_touch_data)(const u8 *data, unsigned int finger,
  32                                 unsigned int *x, unsigned int *y,
  33                                 unsigned int *z);
  34        bool (*continue_polling)(const u8 *data, bool touch);
  35        unsigned int max_touches;
  36        unsigned int resolution;
  37        bool has_calibrate_reg;
  38        bool has_pressure_reg;
  39};
  40
  41struct ili210x {
  42        struct i2c_client *client;
  43        struct input_dev *input;
  44        struct gpio_desc *reset_gpio;
  45        struct touchscreen_properties prop;
  46        const struct ili2xxx_chip *chip;
  47        bool stop;
  48};
  49
  50static int ili210x_read_reg(struct i2c_client *client,
  51                            u8 reg, void *buf, size_t len)
  52{
  53        struct i2c_msg msg[] = {
  54                {
  55                        .addr   = client->addr,
  56                        .flags  = 0,
  57                        .len    = 1,
  58                        .buf    = &reg,
  59                },
  60                {
  61                        .addr   = client->addr,
  62                        .flags  = I2C_M_RD,
  63                        .len    = len,
  64                        .buf    = buf,
  65                }
  66        };
  67        int error, ret;
  68
  69        ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
  70        if (ret != ARRAY_SIZE(msg)) {
  71                error = ret < 0 ? ret : -EIO;
  72                dev_err(&client->dev, "%s failed: %d\n", __func__, error);
  73                return error;
  74        }
  75
  76        return 0;
  77}
  78
  79static int ili210x_read_touch_data(struct i2c_client *client, u8 *data)
  80{
  81        return ili210x_read_reg(client, REG_TOUCHDATA,
  82                                data, ILI210X_DATA_SIZE);
  83}
  84
  85static bool ili210x_touchdata_to_coords(const u8 *touchdata,
  86                                        unsigned int finger,
  87                                        unsigned int *x, unsigned int *y,
  88                                        unsigned int *z)
  89{
  90        if (!(touchdata[0] & BIT(finger)))
  91                return false;
  92
  93        *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
  94        *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
  95
  96        return true;
  97}
  98
  99static bool ili210x_check_continue_polling(const u8 *data, bool touch)
 100{
 101        return data[0] & 0xf3;
 102}
 103
 104static const struct ili2xxx_chip ili210x_chip = {
 105        .read_reg               = ili210x_read_reg,
 106        .get_touch_data         = ili210x_read_touch_data,
 107        .parse_touch_data       = ili210x_touchdata_to_coords,
 108        .continue_polling       = ili210x_check_continue_polling,
 109        .max_touches            = 2,
 110        .has_calibrate_reg      = true,
 111};
 112
 113static int ili211x_read_touch_data(struct i2c_client *client, u8 *data)
 114{
 115        s16 sum = 0;
 116        int error;
 117        int ret;
 118        int i;
 119
 120        ret = i2c_master_recv(client, data, ILI211X_DATA_SIZE);
 121        if (ret != ILI211X_DATA_SIZE) {
 122                error = ret < 0 ? ret : -EIO;
 123                dev_err(&client->dev, "%s failed: %d\n", __func__, error);
 124                return error;
 125        }
 126
 127        /* This chip uses custom checksum at the end of data */
 128        for (i = 0; i < ILI211X_DATA_SIZE - 1; i++)
 129                sum = (sum + data[i]) & 0xff;
 130
 131        if ((-sum & 0xff) != data[ILI211X_DATA_SIZE - 1]) {
 132                dev_err(&client->dev,
 133                        "CRC error (crc=0x%02x expected=0x%02x)\n",
 134                        sum, data[ILI211X_DATA_SIZE - 1]);
 135                return -EIO;
 136        }
 137
 138        return 0;
 139}
 140
 141static bool ili211x_touchdata_to_coords(const u8 *touchdata,
 142                                        unsigned int finger,
 143                                        unsigned int *x, unsigned int *y,
 144                                        unsigned int *z)
 145{
 146        u32 data;
 147
 148        data = get_unaligned_be32(touchdata + 1 + (finger * 4) + 0);
 149        if (data == 0xffffffff) /* Finger up */
 150                return false;
 151
 152        *x = ((touchdata[1 + (finger * 4) + 0] & 0xf0) << 4) |
 153             touchdata[1 + (finger * 4) + 1];
 154        *y = ((touchdata[1 + (finger * 4) + 0] & 0x0f) << 8) |
 155             touchdata[1 + (finger * 4) + 2];
 156
 157        return true;
 158}
 159
 160static bool ili211x_decline_polling(const u8 *data, bool touch)
 161{
 162        return false;
 163}
 164
 165static const struct ili2xxx_chip ili211x_chip = {
 166        .read_reg               = ili210x_read_reg,
 167        .get_touch_data         = ili211x_read_touch_data,
 168        .parse_touch_data       = ili211x_touchdata_to_coords,
 169        .continue_polling       = ili211x_decline_polling,
 170        .max_touches            = 10,
 171        .resolution             = 2048,
 172};
 173
 174static bool ili212x_touchdata_to_coords(const u8 *touchdata,
 175                                        unsigned int finger,
 176                                        unsigned int *x, unsigned int *y,
 177                                        unsigned int *z)
 178{
 179        u16 val;
 180
 181        val = get_unaligned_be16(touchdata + 3 + (finger * 5) + 0);
 182        if (!(val & BIT(15)))   /* Touch indication */
 183                return false;
 184
 185        *x = val & 0x3fff;
 186        *y = get_unaligned_be16(touchdata + 3 + (finger * 5) + 2);
 187
 188        return true;
 189}
 190
 191static bool ili212x_check_continue_polling(const u8 *data, bool touch)
 192{
 193        return touch;
 194}
 195
 196static const struct ili2xxx_chip ili212x_chip = {
 197        .read_reg               = ili210x_read_reg,
 198        .get_touch_data         = ili210x_read_touch_data,
 199        .parse_touch_data       = ili212x_touchdata_to_coords,
 200        .continue_polling       = ili212x_check_continue_polling,
 201        .max_touches            = 10,
 202        .has_calibrate_reg      = true,
 203};
 204
 205static int ili251x_read_reg(struct i2c_client *client,
 206                            u8 reg, void *buf, size_t len)
 207{
 208        int error;
 209        int ret;
 210
 211        ret = i2c_master_send(client, &reg, 1);
 212        if (ret == 1) {
 213                usleep_range(5000, 5500);
 214
 215                ret = i2c_master_recv(client, buf, len);
 216                if (ret == len)
 217                        return 0;
 218        }
 219
 220        error = ret < 0 ? ret : -EIO;
 221        dev_err(&client->dev, "%s failed: %d\n", __func__, error);
 222        return ret;
 223}
 224
 225static int ili251x_read_touch_data(struct i2c_client *client, u8 *data)
 226{
 227        int error;
 228
 229        error = ili251x_read_reg(client, REG_TOUCHDATA,
 230                                 data, ILI251X_DATA_SIZE1);
 231        if (!error && data[0] == 2) {
 232                error = i2c_master_recv(client, data + ILI251X_DATA_SIZE1,
 233                                        ILI251X_DATA_SIZE2);
 234                if (error >= 0 && error != ILI251X_DATA_SIZE2)
 235                        error = -EIO;
 236        }
 237
 238        return error;
 239}
 240
 241static bool ili251x_touchdata_to_coords(const u8 *touchdata,
 242                                        unsigned int finger,
 243                                        unsigned int *x, unsigned int *y,
 244                                        unsigned int *z)
 245{
 246        u16 val;
 247
 248        val = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
 249        if (!(val & BIT(15)))   /* Touch indication */
 250                return false;
 251
 252        *x = val & 0x3fff;
 253        *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
 254        *z = touchdata[1 + (finger * 5) + 4];
 255
 256        return true;
 257}
 258
 259static bool ili251x_check_continue_polling(const u8 *data, bool touch)
 260{
 261        return touch;
 262}
 263
 264static const struct ili2xxx_chip ili251x_chip = {
 265        .read_reg               = ili251x_read_reg,
 266        .get_touch_data         = ili251x_read_touch_data,
 267        .parse_touch_data       = ili251x_touchdata_to_coords,
 268        .continue_polling       = ili251x_check_continue_polling,
 269        .max_touches            = 10,
 270        .has_calibrate_reg      = true,
 271        .has_pressure_reg       = true,
 272};
 273
 274static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
 275{
 276        struct input_dev *input = priv->input;
 277        int i;
 278        bool contact = false, touch;
 279        unsigned int x = 0, y = 0, z = 0;
 280
 281        for (i = 0; i < priv->chip->max_touches; i++) {
 282                touch = priv->chip->parse_touch_data(touchdata, i, &x, &y, &z);
 283
 284                input_mt_slot(input, i);
 285                if (input_mt_report_slot_state(input, MT_TOOL_FINGER, touch)) {
 286                        touchscreen_report_pos(input, &priv->prop, x, y, true);
 287                        if (priv->chip->has_pressure_reg)
 288                                input_report_abs(input, ABS_MT_PRESSURE, z);
 289                        contact = true;
 290                }
 291        }
 292
 293        input_mt_report_pointer_emulation(input, false);
 294        input_sync(input);
 295
 296        return contact;
 297}
 298
 299static irqreturn_t ili210x_irq(int irq, void *irq_data)
 300{
 301        struct ili210x *priv = irq_data;
 302        struct i2c_client *client = priv->client;
 303        const struct ili2xxx_chip *chip = priv->chip;
 304        u8 touchdata[ILI210X_DATA_SIZE] = { 0 };
 305        bool keep_polling;
 306        bool touch;
 307        int error;
 308
 309        do {
 310                error = chip->get_touch_data(client, touchdata);
 311                if (error) {
 312                        dev_err(&client->dev,
 313                                "Unable to get touch data: %d\n", error);
 314                        break;
 315                }
 316
 317                touch = ili210x_report_events(priv, touchdata);
 318                keep_polling = chip->continue_polling(touchdata, touch);
 319                if (keep_polling)
 320                        msleep(ILI2XXX_POLL_PERIOD);
 321        } while (!priv->stop && keep_polling);
 322
 323        return IRQ_HANDLED;
 324}
 325
 326static ssize_t ili210x_calibrate(struct device *dev,
 327                                 struct device_attribute *attr,
 328                                 const char *buf, size_t count)
 329{
 330        struct i2c_client *client = to_i2c_client(dev);
 331        struct ili210x *priv = i2c_get_clientdata(client);
 332        unsigned long calibrate;
 333        int rc;
 334        u8 cmd = REG_CALIBRATE;
 335
 336        if (kstrtoul(buf, 10, &calibrate))
 337                return -EINVAL;
 338
 339        if (calibrate > 1)
 340                return -EINVAL;
 341
 342        if (calibrate) {
 343                rc = i2c_master_send(priv->client, &cmd, sizeof(cmd));
 344                if (rc != sizeof(cmd))
 345                        return -EIO;
 346        }
 347
 348        return count;
 349}
 350static DEVICE_ATTR(calibrate, S_IWUSR, NULL, ili210x_calibrate);
 351
 352static struct attribute *ili210x_attributes[] = {
 353        &dev_attr_calibrate.attr,
 354        NULL,
 355};
 356
 357static umode_t ili210x_calibrate_visible(struct kobject *kobj,
 358                                          struct attribute *attr, int index)
 359{
 360        struct device *dev = kobj_to_dev(kobj);
 361        struct i2c_client *client = to_i2c_client(dev);
 362        struct ili210x *priv = i2c_get_clientdata(client);
 363
 364        return priv->chip->has_calibrate_reg ? attr->mode : 0;
 365}
 366
 367static const struct attribute_group ili210x_attr_group = {
 368        .attrs = ili210x_attributes,
 369        .is_visible = ili210x_calibrate_visible,
 370};
 371
 372static void ili210x_power_down(void *data)
 373{
 374        struct gpio_desc *reset_gpio = data;
 375
 376        gpiod_set_value_cansleep(reset_gpio, 1);
 377}
 378
 379static void ili210x_stop(void *data)
 380{
 381        struct ili210x *priv = data;
 382
 383        /* Tell ISR to quit even if there is a contact. */
 384        priv->stop = true;
 385}
 386
 387static int ili210x_i2c_probe(struct i2c_client *client,
 388                             const struct i2c_device_id *id)
 389{
 390        struct device *dev = &client->dev;
 391        const struct ili2xxx_chip *chip;
 392        struct ili210x *priv;
 393        struct gpio_desc *reset_gpio;
 394        struct input_dev *input;
 395        int error;
 396        unsigned int max_xy;
 397
 398        dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
 399
 400        chip = device_get_match_data(dev);
 401        if (!chip && id)
 402                chip = (const struct ili2xxx_chip *)id->driver_data;
 403        if (!chip) {
 404                dev_err(&client->dev, "unknown device model\n");
 405                return -ENODEV;
 406        }
 407
 408        if (client->irq <= 0) {
 409                dev_err(dev, "No IRQ!\n");
 410                return -EINVAL;
 411        }
 412
 413        reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
 414        if (IS_ERR(reset_gpio))
 415                return PTR_ERR(reset_gpio);
 416
 417        if (reset_gpio) {
 418                error = devm_add_action_or_reset(dev, ili210x_power_down,
 419                                                 reset_gpio);
 420                if (error)
 421                        return error;
 422
 423                usleep_range(50, 100);
 424                gpiod_set_value_cansleep(reset_gpio, 0);
 425                msleep(100);
 426        }
 427
 428        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 429        if (!priv)
 430                return -ENOMEM;
 431
 432        input = devm_input_allocate_device(dev);
 433        if (!input)
 434                return -ENOMEM;
 435
 436        priv->client = client;
 437        priv->input = input;
 438        priv->reset_gpio = reset_gpio;
 439        priv->chip = chip;
 440        i2c_set_clientdata(client, priv);
 441
 442        /* Setup input device */
 443        input->name = "ILI210x Touchscreen";
 444        input->id.bustype = BUS_I2C;
 445
 446        /* Multi touch */
 447        max_xy = (chip->resolution ?: SZ_64K) - 1;
 448        input_set_abs_params(input, ABS_MT_POSITION_X, 0, max_xy, 0, 0);
 449        input_set_abs_params(input, ABS_MT_POSITION_Y, 0, max_xy, 0, 0);
 450        if (priv->chip->has_pressure_reg)
 451                input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xa, 0, 0);
 452        touchscreen_parse_properties(input, true, &priv->prop);
 453
 454        error = input_mt_init_slots(input, priv->chip->max_touches,
 455                                    INPUT_MT_DIRECT);
 456        if (error) {
 457                dev_err(dev, "Unable to set up slots, err: %d\n", error);
 458                return error;
 459        }
 460
 461        error = devm_request_threaded_irq(dev, client->irq, NULL, ili210x_irq,
 462                                          IRQF_ONESHOT, client->name, priv);
 463        if (error) {
 464                dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
 465                        error);
 466                return error;
 467        }
 468
 469        error = devm_add_action_or_reset(dev, ili210x_stop, priv);
 470        if (error)
 471                return error;
 472
 473        error = devm_device_add_group(dev, &ili210x_attr_group);
 474        if (error) {
 475                dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
 476                        error);
 477                return error;
 478        }
 479
 480        error = input_register_device(priv->input);
 481        if (error) {
 482                dev_err(dev, "Cannot register input device, err: %d\n", error);
 483                return error;
 484        }
 485
 486        return 0;
 487}
 488
 489static const struct i2c_device_id ili210x_i2c_id[] = {
 490        { "ili210x", (long)&ili210x_chip },
 491        { "ili2117", (long)&ili211x_chip },
 492        { "ili2120", (long)&ili212x_chip },
 493        { "ili251x", (long)&ili251x_chip },
 494        { }
 495};
 496MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
 497
 498static const struct of_device_id ili210x_dt_ids[] = {
 499        { .compatible = "ilitek,ili210x", .data = &ili210x_chip },
 500        { .compatible = "ilitek,ili2117", .data = &ili211x_chip },
 501        { .compatible = "ilitek,ili2120", .data = &ili212x_chip },
 502        { .compatible = "ilitek,ili251x", .data = &ili251x_chip },
 503        { }
 504};
 505MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
 506
 507static struct i2c_driver ili210x_ts_driver = {
 508        .driver = {
 509                .name = "ili210x_i2c",
 510                .of_match_table = ili210x_dt_ids,
 511        },
 512        .id_table = ili210x_i2c_id,
 513        .probe = ili210x_i2c_probe,
 514};
 515
 516module_i2c_driver(ili210x_ts_driver);
 517
 518MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
 519MODULE_DESCRIPTION("ILI210X I2C Touchscreen Driver");
 520MODULE_LICENSE("GPL");
 521