linux/drivers/input/touchscreen/sx8654.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Driver for Semtech SX8654 I2C touchscreen controller.
   4 *
   5 * Copyright (c) 2015 Armadeus Systems
   6 *      Sébastien Szymanski <sebastien.szymanski@armadeus.com>
   7 *
   8 * Using code from:
   9 *  - sx865x.c
  10 *      Copyright (c) 2013 U-MoBo Srl
  11 *      Pierluigi Passaro <p.passaro@u-mobo.com>
  12 *  - sx8650.c
  13 *      Copyright (c) 2009 Wayne Roberts
  14 *  - tsc2007.c
  15 *      Copyright (c) 2008 Kwangwoo Lee
  16 *  - ads7846.c
  17 *      Copyright (c) 2005 David Brownell
  18 *      Copyright (c) 2006 Nokia Corporation
  19 *  - corgi_ts.c
  20 *      Copyright (C) 2004-2005 Richard Purdie
  21 *  - omap_ts.[hc], ads7846.h, ts_osk.c
  22 *      Copyright (C) 2002 MontaVista Software
  23 *      Copyright (C) 2004 Texas Instruments
  24 *      Copyright (C) 2005 Dirk Behme
  25 */
  26
  27#include <linux/bitops.h>
  28#include <linux/delay.h>
  29#include <linux/gpio/consumer.h>
  30#include <linux/i2c.h>
  31#include <linux/input.h>
  32#include <linux/input/touchscreen.h>
  33#include <linux/interrupt.h>
  34#include <linux/irq.h>
  35#include <linux/module.h>
  36#include <linux/of.h>
  37
  38/* register addresses */
  39#define I2C_REG_TOUCH0                  0x00
  40#define I2C_REG_TOUCH1                  0x01
  41#define I2C_REG_CHANMASK                0x04
  42#define I2C_REG_IRQMASK                 0x22
  43#define I2C_REG_IRQSRC                  0x23
  44#define I2C_REG_SOFTRESET               0x3f
  45
  46#define I2C_REG_SX8650_STAT             0x05
  47#define SX8650_STAT_CONVIRQ             BIT(7)
  48
  49/* commands */
  50#define CMD_READ_REGISTER               0x40
  51#define CMD_PENTRG                      0xe0
  52
  53/* value for I2C_REG_SOFTRESET */
  54#define SOFTRESET_VALUE                 0xde
  55
  56/* bits for I2C_REG_IRQSRC */
  57#define IRQ_PENTOUCH_TOUCHCONVDONE      BIT(3)
  58#define IRQ_PENRELEASE                  BIT(2)
  59
  60/* bits for RegTouch1 */
  61#define CONDIRQ                         0x20
  62#define RPDNT_100K                      0x00
  63#define FILT_7SA                        0x03
  64
  65/* bits for I2C_REG_CHANMASK */
  66#define CONV_X                          BIT(7)
  67#define CONV_Y                          BIT(6)
  68
  69/* coordinates rate: higher nibble of CTRL0 register */
  70#define RATE_MANUAL                     0x00
  71#define RATE_5000CPS                    0xf0
  72
  73/* power delay: lower nibble of CTRL0 register */
  74#define POWDLY_1_1MS                    0x0b
  75
  76/* for sx8650, as we have no pen release IRQ there: timeout in ns following the
  77 * last PENIRQ after which we assume the pen is lifted.
  78 */
  79#define SX8650_PENIRQ_TIMEOUT           msecs_to_jiffies(10)
  80
  81#define MAX_12BIT                       ((1 << 12) - 1)
  82#define MAX_I2C_READ_LEN                10 /* see datasheet section 5.1.5 */
  83
  84/* channel definition */
  85#define CH_X                            0x00
  86#define CH_Y                            0x01
  87
  88struct sx865x_data {
  89        u8 cmd_manual;
  90        u8 chan_mask;
  91        bool has_irq_penrelease;
  92        bool has_reg_irqmask;
  93        irq_handler_t irqh;
  94};
  95
  96struct sx8654 {
  97        struct input_dev *input;
  98        struct i2c_client *client;
  99        struct gpio_desc *gpio_reset;
 100
 101        spinlock_t lock;        /* for input reporting from irq/timer */
 102        struct timer_list timer;
 103
 104        struct touchscreen_properties props;
 105
 106        const struct sx865x_data *data;
 107};
 108
 109static inline void sx865x_penrelease(struct sx8654 *ts)
 110{
 111        struct input_dev *input_dev = ts->input;
 112
 113        input_report_key(input_dev, BTN_TOUCH, 0);
 114        input_sync(input_dev);
 115}
 116
 117static void sx865x_penrelease_timer_handler(struct timer_list *t)
 118{
 119        struct sx8654 *ts = from_timer(ts, t, timer);
 120        unsigned long flags;
 121
 122        spin_lock_irqsave(&ts->lock, flags);
 123        sx865x_penrelease(ts);
 124        spin_unlock_irqrestore(&ts->lock, flags);
 125        dev_dbg(&ts->client->dev, "penrelease by timer\n");
 126}
 127
 128static irqreturn_t sx8650_irq(int irq, void *handle)
 129{
 130        struct sx8654 *ts = handle;
 131        struct device *dev = &ts->client->dev;
 132        int len, i;
 133        unsigned long flags;
 134        u8 stat;
 135        u16 x, y;
 136        u16 ch;
 137        u16 chdata;
 138        __be16 data[MAX_I2C_READ_LEN / sizeof(__be16)];
 139        u8 nchan = hweight32(ts->data->chan_mask);
 140        u8 readlen = nchan * sizeof(*data);
 141
 142        stat = i2c_smbus_read_byte_data(ts->client, CMD_READ_REGISTER
 143                                                    | I2C_REG_SX8650_STAT);
 144
 145        if (!(stat & SX8650_STAT_CONVIRQ)) {
 146                dev_dbg(dev, "%s ignore stat [0x%02x]", __func__, stat);
 147                return IRQ_HANDLED;
 148        }
 149
 150        len = i2c_master_recv(ts->client, (u8 *)data, readlen);
 151        if (len != readlen) {
 152                dev_dbg(dev, "ignore short recv (%d)\n", len);
 153                return IRQ_HANDLED;
 154        }
 155
 156        spin_lock_irqsave(&ts->lock, flags);
 157
 158        x = 0;
 159        y = 0;
 160        for (i = 0; i < nchan; i++) {
 161                chdata = be16_to_cpu(data[i]);
 162
 163                if (unlikely(chdata == 0xFFFF)) {
 164                        dev_dbg(dev, "invalid qualified data @ %d\n", i);
 165                        continue;
 166                } else if (unlikely(chdata & 0x8000)) {
 167                        dev_warn(dev, "hibit @ %d [0x%04x]\n", i, chdata);
 168                        continue;
 169                }
 170
 171                ch = chdata >> 12;
 172                if (ch == CH_X)
 173                        x = chdata & MAX_12BIT;
 174                else if (ch == CH_Y)
 175                        y = chdata & MAX_12BIT;
 176                else
 177                        dev_warn(dev, "unknown channel %d [0x%04x]\n", ch,
 178                                 chdata);
 179        }
 180
 181        touchscreen_report_pos(ts->input, &ts->props, x, y, false);
 182        input_report_key(ts->input, BTN_TOUCH, 1);
 183        input_sync(ts->input);
 184        dev_dbg(dev, "point(%4d,%4d)\n", x, y);
 185
 186        mod_timer(&ts->timer, jiffies + SX8650_PENIRQ_TIMEOUT);
 187        spin_unlock_irqrestore(&ts->lock, flags);
 188
 189        return IRQ_HANDLED;
 190}
 191
 192static irqreturn_t sx8654_irq(int irq, void *handle)
 193{
 194        struct sx8654 *sx8654 = handle;
 195        int irqsrc;
 196        u8 data[4];
 197        unsigned int x, y;
 198        int retval;
 199
 200        irqsrc = i2c_smbus_read_byte_data(sx8654->client,
 201                                          CMD_READ_REGISTER | I2C_REG_IRQSRC);
 202        dev_dbg(&sx8654->client->dev, "irqsrc = 0x%x", irqsrc);
 203
 204        if (irqsrc < 0)
 205                goto out;
 206
 207        if (irqsrc & IRQ_PENRELEASE) {
 208                dev_dbg(&sx8654->client->dev, "pen release interrupt");
 209
 210                input_report_key(sx8654->input, BTN_TOUCH, 0);
 211                input_sync(sx8654->input);
 212        }
 213
 214        if (irqsrc & IRQ_PENTOUCH_TOUCHCONVDONE) {
 215                dev_dbg(&sx8654->client->dev, "pen touch interrupt");
 216
 217                retval = i2c_master_recv(sx8654->client, data, sizeof(data));
 218                if (retval != sizeof(data))
 219                        goto out;
 220
 221                /* invalid data */
 222                if (unlikely(data[0] & 0x80 || data[2] & 0x80))
 223                        goto out;
 224
 225                x = ((data[0] & 0xf) << 8) | (data[1]);
 226                y = ((data[2] & 0xf) << 8) | (data[3]);
 227
 228                touchscreen_report_pos(sx8654->input, &sx8654->props, x, y,
 229                                       false);
 230                input_report_key(sx8654->input, BTN_TOUCH, 1);
 231                input_sync(sx8654->input);
 232
 233                dev_dbg(&sx8654->client->dev, "point(%4d,%4d)\n", x, y);
 234        }
 235
 236out:
 237        return IRQ_HANDLED;
 238}
 239
 240static int sx8654_reset(struct sx8654 *ts)
 241{
 242        int err;
 243
 244        if (ts->gpio_reset) {
 245                gpiod_set_value_cansleep(ts->gpio_reset, 1);
 246                udelay(2); /* Tpulse > 1µs */
 247                gpiod_set_value_cansleep(ts->gpio_reset, 0);
 248        } else {
 249                dev_dbg(&ts->client->dev, "NRST unavailable, try softreset\n");
 250                err = i2c_smbus_write_byte_data(ts->client, I2C_REG_SOFTRESET,
 251                                                SOFTRESET_VALUE);
 252                if (err)
 253                        return err;
 254        }
 255
 256        return 0;
 257}
 258
 259static int sx8654_open(struct input_dev *dev)
 260{
 261        struct sx8654 *sx8654 = input_get_drvdata(dev);
 262        struct i2c_client *client = sx8654->client;
 263        int error;
 264
 265        /* enable pen trigger mode */
 266        error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0,
 267                                          RATE_5000CPS | POWDLY_1_1MS);
 268        if (error) {
 269                dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
 270                return error;
 271        }
 272
 273        error = i2c_smbus_write_byte(client, CMD_PENTRG);
 274        if (error) {
 275                dev_err(&client->dev, "writing command CMD_PENTRG failed");
 276                return error;
 277        }
 278
 279        enable_irq(client->irq);
 280
 281        return 0;
 282}
 283
 284static void sx8654_close(struct input_dev *dev)
 285{
 286        struct sx8654 *sx8654 = input_get_drvdata(dev);
 287        struct i2c_client *client = sx8654->client;
 288        int error;
 289
 290        disable_irq(client->irq);
 291
 292        if (!sx8654->data->has_irq_penrelease)
 293                del_timer_sync(&sx8654->timer);
 294
 295        /* enable manual mode mode */
 296        error = i2c_smbus_write_byte(client, sx8654->data->cmd_manual);
 297        if (error) {
 298                dev_err(&client->dev, "writing command CMD_MANUAL failed");
 299                return;
 300        }
 301
 302        error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH0, RATE_MANUAL);
 303        if (error) {
 304                dev_err(&client->dev, "writing to I2C_REG_TOUCH0 failed");
 305                return;
 306        }
 307}
 308
 309static int sx8654_probe(struct i2c_client *client,
 310                        const struct i2c_device_id *id)
 311{
 312        struct sx8654 *sx8654;
 313        struct input_dev *input;
 314        int error;
 315
 316        if (!i2c_check_functionality(client->adapter,
 317                                     I2C_FUNC_SMBUS_READ_WORD_DATA))
 318                return -ENXIO;
 319
 320        sx8654 = devm_kzalloc(&client->dev, sizeof(*sx8654), GFP_KERNEL);
 321        if (!sx8654)
 322                return -ENOMEM;
 323
 324        sx8654->gpio_reset = devm_gpiod_get_optional(&client->dev, "reset",
 325                                                     GPIOD_OUT_HIGH);
 326        if (IS_ERR(sx8654->gpio_reset)) {
 327                error = PTR_ERR(sx8654->gpio_reset);
 328                if (error != -EPROBE_DEFER)
 329                        dev_err(&client->dev, "unable to get reset-gpio: %d\n",
 330                                error);
 331                return error;
 332        }
 333        dev_dbg(&client->dev, "got GPIO reset pin\n");
 334
 335        sx8654->data = device_get_match_data(&client->dev);
 336        if (!sx8654->data)
 337                sx8654->data = (const struct sx865x_data *)id->driver_data;
 338        if (!sx8654->data) {
 339                dev_err(&client->dev, "invalid or missing device data\n");
 340                return -EINVAL;
 341        }
 342
 343        if (!sx8654->data->has_irq_penrelease) {
 344                dev_dbg(&client->dev, "use timer for penrelease\n");
 345                timer_setup(&sx8654->timer, sx865x_penrelease_timer_handler, 0);
 346                spin_lock_init(&sx8654->lock);
 347        }
 348
 349        input = devm_input_allocate_device(&client->dev);
 350        if (!input)
 351                return -ENOMEM;
 352
 353        input->name = "SX8654 I2C Touchscreen";
 354        input->id.bustype = BUS_I2C;
 355        input->dev.parent = &client->dev;
 356        input->open = sx8654_open;
 357        input->close = sx8654_close;
 358
 359        __set_bit(INPUT_PROP_DIRECT, input->propbit);
 360        input_set_capability(input, EV_KEY, BTN_TOUCH);
 361        input_set_abs_params(input, ABS_X, 0, MAX_12BIT, 0, 0);
 362        input_set_abs_params(input, ABS_Y, 0, MAX_12BIT, 0, 0);
 363
 364        touchscreen_parse_properties(input, false, &sx8654->props);
 365
 366        sx8654->client = client;
 367        sx8654->input = input;
 368
 369        input_set_drvdata(sx8654->input, sx8654);
 370
 371        error = sx8654_reset(sx8654);
 372        if (error) {
 373                dev_err(&client->dev, "reset failed");
 374                return error;
 375        }
 376
 377        error = i2c_smbus_write_byte_data(client, I2C_REG_CHANMASK,
 378                                          sx8654->data->chan_mask);
 379        if (error) {
 380                dev_err(&client->dev, "writing to I2C_REG_CHANMASK failed");
 381                return error;
 382        }
 383
 384        if (sx8654->data->has_reg_irqmask) {
 385                error = i2c_smbus_write_byte_data(client, I2C_REG_IRQMASK,
 386                                                  IRQ_PENTOUCH_TOUCHCONVDONE |
 387                                                        IRQ_PENRELEASE);
 388                if (error) {
 389                        dev_err(&client->dev, "writing I2C_REG_IRQMASK failed");
 390                        return error;
 391                }
 392        }
 393
 394        error = i2c_smbus_write_byte_data(client, I2C_REG_TOUCH1,
 395                                          CONDIRQ | RPDNT_100K | FILT_7SA);
 396        if (error) {
 397                dev_err(&client->dev, "writing to I2C_REG_TOUCH1 failed");
 398                return error;
 399        }
 400
 401        error = devm_request_threaded_irq(&client->dev, client->irq,
 402                                          NULL, sx8654->data->irqh,
 403                                          IRQF_ONESHOT,
 404                                          client->name, sx8654);
 405        if (error) {
 406                dev_err(&client->dev,
 407                        "Failed to enable IRQ %d, error: %d\n",
 408                        client->irq, error);
 409                return error;
 410        }
 411
 412        /* Disable the IRQ, we'll enable it in sx8654_open() */
 413        disable_irq(client->irq);
 414
 415        error = input_register_device(sx8654->input);
 416        if (error)
 417                return error;
 418
 419        return 0;
 420}
 421
 422static const struct sx865x_data sx8650_data = {
 423        .cmd_manual             = 0xb0,
 424        .has_irq_penrelease     = false,
 425        .has_reg_irqmask        = false,
 426        .chan_mask              = (CONV_X | CONV_Y),
 427        .irqh                   = sx8650_irq,
 428};
 429
 430static const struct sx865x_data sx8654_data = {
 431        .cmd_manual             = 0xc0,
 432        .has_irq_penrelease     = true,
 433        .has_reg_irqmask        = true,
 434        .chan_mask              = (CONV_X | CONV_Y),
 435        .irqh                   = sx8654_irq,
 436};
 437
 438#ifdef CONFIG_OF
 439static const struct of_device_id sx8654_of_match[] = {
 440        {
 441                .compatible = "semtech,sx8650",
 442                .data = &sx8650_data,
 443        }, {
 444                .compatible = "semtech,sx8654",
 445                .data = &sx8654_data,
 446        }, {
 447                .compatible = "semtech,sx8655",
 448                .data = &sx8654_data,
 449        }, {
 450                .compatible = "semtech,sx8656",
 451                .data = &sx8654_data,
 452        },
 453        { }
 454};
 455MODULE_DEVICE_TABLE(of, sx8654_of_match);
 456#endif
 457
 458static const struct i2c_device_id sx8654_id_table[] = {
 459        { .name = "semtech_sx8650", .driver_data = (long)&sx8650_data },
 460        { .name = "semtech_sx8654", .driver_data = (long)&sx8654_data },
 461        { .name = "semtech_sx8655", .driver_data = (long)&sx8654_data },
 462        { .name = "semtech_sx8656", .driver_data = (long)&sx8654_data },
 463        { }
 464};
 465MODULE_DEVICE_TABLE(i2c, sx8654_id_table);
 466
 467static struct i2c_driver sx8654_driver = {
 468        .driver = {
 469                .name = "sx8654",
 470                .of_match_table = of_match_ptr(sx8654_of_match),
 471        },
 472        .id_table = sx8654_id_table,
 473        .probe = sx8654_probe,
 474};
 475module_i2c_driver(sx8654_driver);
 476
 477MODULE_AUTHOR("Sébastien Szymanski <sebastien.szymanski@armadeus.com>");
 478MODULE_DESCRIPTION("Semtech SX8654 I2C Touchscreen Driver");
 479MODULE_LICENSE("GPL");
 480