linux/drivers/input/touchscreen/cyttsp_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Core Source for:
   4 * Cypress TrueTouch(TM) Standard Product (TTSP) touchscreen drivers.
   5 * For use with Cypress Txx3xx parts.
   6 * Supported parts include:
   7 * CY8CTST341
   8 * CY8CTMA340
   9 *
  10 * Copyright (C) 2009, 2010, 2011 Cypress Semiconductor, Inc.
  11 * Copyright (C) 2012 Javier Martinez Canillas <javier@dowhile0.org>
  12 *
  13 * Contact Cypress Semiconductor at www.cypress.com <kev@cypress.com>
  14 */
  15
  16#include <linux/delay.h>
  17#include <linux/input.h>
  18#include <linux/input/mt.h>
  19#include <linux/input/touchscreen.h>
  20#include <linux/gpio.h>
  21#include <linux/interrupt.h>
  22#include <linux/slab.h>
  23#include <linux/property.h>
  24#include <linux/gpio/consumer.h>
  25
  26#include "cyttsp_core.h"
  27
  28/* Bootloader number of command keys */
  29#define CY_NUM_BL_KEYS          8
  30
  31/* helpers */
  32#define GET_NUM_TOUCHES(x)              ((x) & 0x0F)
  33#define IS_LARGE_AREA(x)                (((x) & 0x10) >> 4)
  34#define IS_BAD_PKT(x)                   ((x) & 0x20)
  35#define IS_VALID_APP(x)                 ((x) & 0x01)
  36#define IS_OPERATIONAL_ERR(x)           ((x) & 0x3F)
  37#define GET_HSTMODE(reg)                (((reg) & 0x70) >> 4)
  38#define GET_BOOTLOADERMODE(reg)         (((reg) & 0x10) >> 4)
  39
  40#define CY_REG_BASE                     0x00
  41#define CY_REG_ACT_DIST                 0x1E
  42#define CY_REG_ACT_INTRVL               0x1D
  43#define CY_REG_TCH_TMOUT                (CY_REG_ACT_INTRVL + 1)
  44#define CY_REG_LP_INTRVL                (CY_REG_TCH_TMOUT + 1)
  45#define CY_MAXZ                         255
  46#define CY_DELAY_DFLT                   20 /* ms */
  47#define CY_DELAY_MAX                    500
  48#define CY_ACT_DIST_DFLT                0xF8
  49#define CY_ACT_DIST_MASK                0x0F
  50#define CY_HNDSHK_BIT                   0x80
  51/* device mode bits */
  52#define CY_OPERATE_MODE                 0x00
  53#define CY_SYSINFO_MODE                 0x10
  54/* power mode select bits */
  55#define CY_SOFT_RESET_MODE              0x01 /* return to Bootloader mode */
  56#define CY_DEEP_SLEEP_MODE              0x02
  57#define CY_LOW_POWER_MODE               0x04
  58
  59/* Slots management */
  60#define CY_MAX_FINGER                   4
  61#define CY_MAX_ID                       16
  62
  63static const u8 bl_command[] = {
  64        0x00,                   /* file offset */
  65        0xFF,                   /* command */
  66        0xA5,                   /* exit bootloader command */
  67        0, 1, 2, 3, 4, 5, 6, 7  /* default keys */
  68};
  69
  70static int ttsp_read_block_data(struct cyttsp *ts, u8 command,
  71                                u8 length, void *buf)
  72{
  73        int error;
  74        int tries;
  75
  76        for (tries = 0; tries < CY_NUM_RETRY; tries++) {
  77                error = ts->bus_ops->read(ts->dev, ts->xfer_buf, command,
  78                                length, buf);
  79                if (!error)
  80                        return 0;
  81
  82                msleep(CY_DELAY_DFLT);
  83        }
  84
  85        return -EIO;
  86}
  87
  88static int ttsp_write_block_data(struct cyttsp *ts, u8 command,
  89                                 u8 length, void *buf)
  90{
  91        int error;
  92        int tries;
  93
  94        for (tries = 0; tries < CY_NUM_RETRY; tries++) {
  95                error = ts->bus_ops->write(ts->dev, ts->xfer_buf, command,
  96                                length, buf);
  97                if (!error)
  98                        return 0;
  99
 100                msleep(CY_DELAY_DFLT);
 101        }
 102
 103        return -EIO;
 104}
 105
 106static int ttsp_send_command(struct cyttsp *ts, u8 cmd)
 107{
 108        return ttsp_write_block_data(ts, CY_REG_BASE, sizeof(cmd), &cmd);
 109}
 110
 111static int cyttsp_handshake(struct cyttsp *ts)
 112{
 113        if (ts->use_hndshk)
 114                return ttsp_send_command(ts,
 115                                ts->xy_data.hst_mode ^ CY_HNDSHK_BIT);
 116
 117        return 0;
 118}
 119
 120static int cyttsp_load_bl_regs(struct cyttsp *ts)
 121{
 122        memset(&ts->bl_data, 0, sizeof(ts->bl_data));
 123        ts->bl_data.bl_status = 0x10;
 124
 125        return ttsp_read_block_data(ts, CY_REG_BASE,
 126                                    sizeof(ts->bl_data), &ts->bl_data);
 127}
 128
 129static int cyttsp_exit_bl_mode(struct cyttsp *ts)
 130{
 131        int error;
 132        u8 bl_cmd[sizeof(bl_command)];
 133
 134        memcpy(bl_cmd, bl_command, sizeof(bl_command));
 135        if (ts->bl_keys)
 136                memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS],
 137                        ts->bl_keys, CY_NUM_BL_KEYS);
 138
 139        error = ttsp_write_block_data(ts, CY_REG_BASE,
 140                                      sizeof(bl_cmd), bl_cmd);
 141        if (error)
 142                return error;
 143
 144        /* wait for TTSP Device to complete the operation */
 145        msleep(CY_DELAY_DFLT);
 146
 147        error = cyttsp_load_bl_regs(ts);
 148        if (error)
 149                return error;
 150
 151        if (GET_BOOTLOADERMODE(ts->bl_data.bl_status))
 152                return -EIO;
 153
 154        return 0;
 155}
 156
 157static int cyttsp_set_operational_mode(struct cyttsp *ts)
 158{
 159        int error;
 160
 161        error = ttsp_send_command(ts, CY_OPERATE_MODE);
 162        if (error)
 163                return error;
 164
 165        /* wait for TTSP Device to complete switch to Operational mode */
 166        error = ttsp_read_block_data(ts, CY_REG_BASE,
 167                                     sizeof(ts->xy_data), &ts->xy_data);
 168        if (error)
 169                return error;
 170
 171        error = cyttsp_handshake(ts);
 172        if (error)
 173                return error;
 174
 175        return ts->xy_data.act_dist == CY_ACT_DIST_DFLT ? -EIO : 0;
 176}
 177
 178static int cyttsp_set_sysinfo_mode(struct cyttsp *ts)
 179{
 180        int error;
 181
 182        memset(&ts->sysinfo_data, 0, sizeof(ts->sysinfo_data));
 183
 184        /* switch to sysinfo mode */
 185        error = ttsp_send_command(ts, CY_SYSINFO_MODE);
 186        if (error)
 187                return error;
 188
 189        /* read sysinfo registers */
 190        msleep(CY_DELAY_DFLT);
 191        error = ttsp_read_block_data(ts, CY_REG_BASE, sizeof(ts->sysinfo_data),
 192                                      &ts->sysinfo_data);
 193        if (error)
 194                return error;
 195
 196        error = cyttsp_handshake(ts);
 197        if (error)
 198                return error;
 199
 200        if (!ts->sysinfo_data.tts_verh && !ts->sysinfo_data.tts_verl)
 201                return -EIO;
 202
 203        return 0;
 204}
 205
 206static int cyttsp_set_sysinfo_regs(struct cyttsp *ts)
 207{
 208        int retval = 0;
 209
 210        if (ts->act_intrvl != CY_ACT_INTRVL_DFLT ||
 211            ts->tch_tmout != CY_TCH_TMOUT_DFLT ||
 212            ts->lp_intrvl != CY_LP_INTRVL_DFLT) {
 213
 214                u8 intrvl_ray[] = {
 215                        ts->act_intrvl,
 216                        ts->tch_tmout,
 217                        ts->lp_intrvl
 218                };
 219
 220                /* set intrvl registers */
 221                retval = ttsp_write_block_data(ts, CY_REG_ACT_INTRVL,
 222                                        sizeof(intrvl_ray), intrvl_ray);
 223                msleep(CY_DELAY_DFLT);
 224        }
 225
 226        return retval;
 227}
 228
 229static void cyttsp_hard_reset(struct cyttsp *ts)
 230{
 231        if (ts->reset_gpio) {
 232                gpiod_set_value_cansleep(ts->reset_gpio, 1);
 233                msleep(CY_DELAY_DFLT);
 234                gpiod_set_value_cansleep(ts->reset_gpio, 0);
 235                msleep(CY_DELAY_DFLT);
 236        }
 237}
 238
 239static int cyttsp_soft_reset(struct cyttsp *ts)
 240{
 241        unsigned long timeout;
 242        int retval;
 243
 244        /* wait for interrupt to set ready completion */
 245        reinit_completion(&ts->bl_ready);
 246        ts->state = CY_BL_STATE;
 247
 248        enable_irq(ts->irq);
 249
 250        retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);
 251        if (retval)
 252                goto out;
 253
 254        timeout = wait_for_completion_timeout(&ts->bl_ready,
 255                        msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));
 256        retval = timeout ? 0 : -EIO;
 257
 258out:
 259        ts->state = CY_IDLE_STATE;
 260        disable_irq(ts->irq);
 261        return retval;
 262}
 263
 264static int cyttsp_act_dist_setup(struct cyttsp *ts)
 265{
 266        u8 act_dist_setup = ts->act_dist;
 267
 268        /* Init gesture; active distance setup */
 269        return ttsp_write_block_data(ts, CY_REG_ACT_DIST,
 270                                sizeof(act_dist_setup), &act_dist_setup);
 271}
 272
 273static void cyttsp_extract_track_ids(struct cyttsp_xydata *xy_data, int *ids)
 274{
 275        ids[0] = xy_data->touch12_id >> 4;
 276        ids[1] = xy_data->touch12_id & 0xF;
 277        ids[2] = xy_data->touch34_id >> 4;
 278        ids[3] = xy_data->touch34_id & 0xF;
 279}
 280
 281static const struct cyttsp_tch *cyttsp_get_tch(struct cyttsp_xydata *xy_data,
 282                                               int idx)
 283{
 284        switch (idx) {
 285        case 0:
 286                return &xy_data->tch1;
 287        case 1:
 288                return &xy_data->tch2;
 289        case 2:
 290                return &xy_data->tch3;
 291        case 3:
 292                return &xy_data->tch4;
 293        default:
 294                return NULL;
 295        }
 296}
 297
 298static void cyttsp_report_tchdata(struct cyttsp *ts)
 299{
 300        struct cyttsp_xydata *xy_data = &ts->xy_data;
 301        struct input_dev *input = ts->input;
 302        int num_tch = GET_NUM_TOUCHES(xy_data->tt_stat);
 303        const struct cyttsp_tch *tch;
 304        int ids[CY_MAX_ID];
 305        int i;
 306        DECLARE_BITMAP(used, CY_MAX_ID);
 307
 308        if (IS_LARGE_AREA(xy_data->tt_stat) == 1) {
 309                /* terminate all active tracks */
 310                num_tch = 0;
 311                dev_dbg(ts->dev, "%s: Large area detected\n", __func__);
 312        } else if (num_tch > CY_MAX_FINGER) {
 313                /* terminate all active tracks */
 314                num_tch = 0;
 315                dev_dbg(ts->dev, "%s: Num touch error detected\n", __func__);
 316        } else if (IS_BAD_PKT(xy_data->tt_mode)) {
 317                /* terminate all active tracks */
 318                num_tch = 0;
 319                dev_dbg(ts->dev, "%s: Invalid buffer detected\n", __func__);
 320        }
 321
 322        cyttsp_extract_track_ids(xy_data, ids);
 323
 324        bitmap_zero(used, CY_MAX_ID);
 325
 326        for (i = 0; i < num_tch; i++) {
 327                tch = cyttsp_get_tch(xy_data, i);
 328
 329                input_mt_slot(input, ids[i]);
 330                input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
 331                input_report_abs(input, ABS_MT_POSITION_X, be16_to_cpu(tch->x));
 332                input_report_abs(input, ABS_MT_POSITION_Y, be16_to_cpu(tch->y));
 333                input_report_abs(input, ABS_MT_TOUCH_MAJOR, tch->z);
 334
 335                __set_bit(ids[i], used);
 336        }
 337
 338        for (i = 0; i < CY_MAX_ID; i++) {
 339                if (test_bit(i, used))
 340                        continue;
 341
 342                input_mt_slot(input, i);
 343                input_mt_report_slot_inactive(input);
 344        }
 345
 346        input_sync(input);
 347}
 348
 349static irqreturn_t cyttsp_irq(int irq, void *handle)
 350{
 351        struct cyttsp *ts = handle;
 352        int error;
 353
 354        if (unlikely(ts->state == CY_BL_STATE)) {
 355                complete(&ts->bl_ready);
 356                goto out;
 357        }
 358
 359        /* Get touch data from CYTTSP device */
 360        error = ttsp_read_block_data(ts, CY_REG_BASE,
 361                                 sizeof(struct cyttsp_xydata), &ts->xy_data);
 362        if (error)
 363                goto out;
 364
 365        /* provide flow control handshake */
 366        error = cyttsp_handshake(ts);
 367        if (error)
 368                goto out;
 369
 370        if (unlikely(ts->state == CY_IDLE_STATE))
 371                goto out;
 372
 373        if (GET_BOOTLOADERMODE(ts->xy_data.tt_mode)) {
 374                /*
 375                 * TTSP device has reset back to bootloader mode.
 376                 * Restore to operational mode.
 377                 */
 378                error = cyttsp_exit_bl_mode(ts);
 379                if (error) {
 380                        dev_err(ts->dev,
 381                                "Could not return to operational mode, err: %d\n",
 382                                error);
 383                        ts->state = CY_IDLE_STATE;
 384                }
 385        } else {
 386                cyttsp_report_tchdata(ts);
 387        }
 388
 389out:
 390        return IRQ_HANDLED;
 391}
 392
 393static int cyttsp_power_on(struct cyttsp *ts)
 394{
 395        int error;
 396
 397        error = cyttsp_soft_reset(ts);
 398        if (error)
 399                return error;
 400
 401        error = cyttsp_load_bl_regs(ts);
 402        if (error)
 403                return error;
 404
 405        if (GET_BOOTLOADERMODE(ts->bl_data.bl_status) &&
 406            IS_VALID_APP(ts->bl_data.bl_status)) {
 407                error = cyttsp_exit_bl_mode(ts);
 408                if (error)
 409                        return error;
 410        }
 411
 412        if (GET_HSTMODE(ts->bl_data.bl_file) != CY_OPERATE_MODE ||
 413            IS_OPERATIONAL_ERR(ts->bl_data.bl_status)) {
 414                return -ENODEV;
 415        }
 416
 417        error = cyttsp_set_sysinfo_mode(ts);
 418        if (error)
 419                return error;
 420
 421        error = cyttsp_set_sysinfo_regs(ts);
 422        if (error)
 423                return error;
 424
 425        error = cyttsp_set_operational_mode(ts);
 426        if (error)
 427                return error;
 428
 429        /* init active distance */
 430        error = cyttsp_act_dist_setup(ts);
 431        if (error)
 432                return error;
 433
 434        ts->state = CY_ACTIVE_STATE;
 435
 436        return 0;
 437}
 438
 439static int cyttsp_enable(struct cyttsp *ts)
 440{
 441        int error;
 442
 443        /*
 444         * The device firmware can wake on an I2C or SPI memory slave
 445         * address match. So just reading a register is sufficient to
 446         * wake up the device. The first read attempt will fail but it
 447         * will wake it up making the second read attempt successful.
 448         */
 449        error = ttsp_read_block_data(ts, CY_REG_BASE,
 450                                     sizeof(ts->xy_data), &ts->xy_data);
 451        if (error)
 452                return error;
 453
 454        if (GET_HSTMODE(ts->xy_data.hst_mode))
 455                return -EIO;
 456
 457        enable_irq(ts->irq);
 458
 459        return 0;
 460}
 461
 462static int cyttsp_disable(struct cyttsp *ts)
 463{
 464        int error;
 465
 466        error = ttsp_send_command(ts, CY_LOW_POWER_MODE);
 467        if (error)
 468                return error;
 469
 470        disable_irq(ts->irq);
 471
 472        return 0;
 473}
 474
 475static int __maybe_unused cyttsp_suspend(struct device *dev)
 476{
 477        struct cyttsp *ts = dev_get_drvdata(dev);
 478        int retval = 0;
 479
 480        mutex_lock(&ts->input->mutex);
 481
 482        if (input_device_enabled(ts->input)) {
 483                retval = cyttsp_disable(ts);
 484                if (retval == 0)
 485                        ts->suspended = true;
 486        }
 487
 488        mutex_unlock(&ts->input->mutex);
 489
 490        return retval;
 491}
 492
 493static int __maybe_unused cyttsp_resume(struct device *dev)
 494{
 495        struct cyttsp *ts = dev_get_drvdata(dev);
 496
 497        mutex_lock(&ts->input->mutex);
 498
 499        if (input_device_enabled(ts->input))
 500                cyttsp_enable(ts);
 501
 502        ts->suspended = false;
 503
 504        mutex_unlock(&ts->input->mutex);
 505
 506        return 0;
 507}
 508
 509SIMPLE_DEV_PM_OPS(cyttsp_pm_ops, cyttsp_suspend, cyttsp_resume);
 510EXPORT_SYMBOL_GPL(cyttsp_pm_ops);
 511
 512static int cyttsp_open(struct input_dev *dev)
 513{
 514        struct cyttsp *ts = input_get_drvdata(dev);
 515        int retval = 0;
 516
 517        if (!ts->suspended)
 518                retval = cyttsp_enable(ts);
 519
 520        return retval;
 521}
 522
 523static void cyttsp_close(struct input_dev *dev)
 524{
 525        struct cyttsp *ts = input_get_drvdata(dev);
 526
 527        if (!ts->suspended)
 528                cyttsp_disable(ts);
 529}
 530
 531static int cyttsp_parse_properties(struct cyttsp *ts)
 532{
 533        struct device *dev = ts->dev;
 534        u32 dt_value;
 535        int ret;
 536
 537        ts->bl_keys = devm_kzalloc(dev, CY_NUM_BL_KEYS, GFP_KERNEL);
 538        if (!ts->bl_keys)
 539                return -ENOMEM;
 540
 541        /* Set some default values */
 542        ts->use_hndshk = false;
 543        ts->act_dist = CY_ACT_DIST_DFLT;
 544        ts->act_intrvl = CY_ACT_INTRVL_DFLT;
 545        ts->tch_tmout = CY_TCH_TMOUT_DFLT;
 546        ts->lp_intrvl = CY_LP_INTRVL_DFLT;
 547
 548        ret = device_property_read_u8_array(dev, "bootloader-key",
 549                                            ts->bl_keys, CY_NUM_BL_KEYS);
 550        if (ret) {
 551                dev_err(dev,
 552                        "bootloader-key property could not be retrieved\n");
 553                return ret;
 554        }
 555
 556        ts->use_hndshk = device_property_present(dev, "use-handshake");
 557
 558        if (!device_property_read_u32(dev, "active-distance", &dt_value)) {
 559                if (dt_value > 15) {
 560                        dev_err(dev, "active-distance (%u) must be [0-15]\n",
 561                                dt_value);
 562                        return -EINVAL;
 563                }
 564                ts->act_dist &= ~CY_ACT_DIST_MASK;
 565                ts->act_dist |= dt_value;
 566        }
 567
 568        if (!device_property_read_u32(dev, "active-interval-ms", &dt_value)) {
 569                if (dt_value > 255) {
 570                        dev_err(dev, "active-interval-ms (%u) must be [0-255]\n",
 571                                dt_value);
 572                        return -EINVAL;
 573                }
 574                ts->act_intrvl = dt_value;
 575        }
 576
 577        if (!device_property_read_u32(dev, "lowpower-interval-ms", &dt_value)) {
 578                if (dt_value > 2550) {
 579                        dev_err(dev, "lowpower-interval-ms (%u) must be [0-2550]\n",
 580                                dt_value);
 581                        return -EINVAL;
 582                }
 583                /* Register value is expressed in 0.01s / bit */
 584                ts->lp_intrvl = dt_value / 10;
 585        }
 586
 587        if (!device_property_read_u32(dev, "touch-timeout-ms", &dt_value)) {
 588                if (dt_value > 2550) {
 589                        dev_err(dev, "touch-timeout-ms (%u) must be [0-2550]\n",
 590                                dt_value);
 591                        return -EINVAL;
 592                }
 593                /* Register value is expressed in 0.01s / bit */
 594                ts->tch_tmout = dt_value / 10;
 595        }
 596
 597        return 0;
 598}
 599
 600struct cyttsp *cyttsp_probe(const struct cyttsp_bus_ops *bus_ops,
 601                            struct device *dev, int irq, size_t xfer_buf_size)
 602{
 603        struct cyttsp *ts;
 604        struct input_dev *input_dev;
 605        int error;
 606
 607        ts = devm_kzalloc(dev, sizeof(*ts) + xfer_buf_size, GFP_KERNEL);
 608        if (!ts)
 609                return ERR_PTR(-ENOMEM);
 610
 611        input_dev = devm_input_allocate_device(dev);
 612        if (!input_dev)
 613                return ERR_PTR(-ENOMEM);
 614
 615        ts->dev = dev;
 616        ts->input = input_dev;
 617        ts->bus_ops = bus_ops;
 618        ts->irq = irq;
 619
 620        ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 621        if (IS_ERR(ts->reset_gpio)) {
 622                error = PTR_ERR(ts->reset_gpio);
 623                dev_err(dev, "Failed to request reset gpio, error %d\n", error);
 624                return ERR_PTR(error);
 625        }
 626
 627        error = cyttsp_parse_properties(ts);
 628        if (error)
 629                return ERR_PTR(error);
 630
 631        init_completion(&ts->bl_ready);
 632        snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(dev));
 633
 634        input_dev->name = "Cypress TTSP TouchScreen";
 635        input_dev->phys = ts->phys;
 636        input_dev->id.bustype = bus_ops->bustype;
 637        input_dev->dev.parent = ts->dev;
 638
 639        input_dev->open = cyttsp_open;
 640        input_dev->close = cyttsp_close;
 641
 642        input_set_drvdata(input_dev, ts);
 643
 644        input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
 645        input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
 646        touchscreen_parse_properties(input_dev, true, NULL);
 647
 648        error = input_mt_init_slots(input_dev, CY_MAX_ID, 0);
 649        if (error) {
 650                dev_err(dev, "Unable to init MT slots.\n");
 651                return ERR_PTR(error);
 652        }
 653
 654        error = devm_request_threaded_irq(dev, ts->irq, NULL, cyttsp_irq,
 655                                          IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 656                                          "cyttsp", ts);
 657        if (error) {
 658                dev_err(ts->dev, "failed to request IRQ %d, err: %d\n",
 659                        ts->irq, error);
 660                return ERR_PTR(error);
 661        }
 662
 663        disable_irq(ts->irq);
 664
 665        cyttsp_hard_reset(ts);
 666
 667        error = cyttsp_power_on(ts);
 668        if (error)
 669                return ERR_PTR(error);
 670
 671        error = input_register_device(input_dev);
 672        if (error) {
 673                dev_err(ts->dev, "failed to register input device: %d\n",
 674                        error);
 675                return ERR_PTR(error);
 676        }
 677
 678        return ts;
 679}
 680EXPORT_SYMBOL_GPL(cyttsp_probe);
 681
 682MODULE_LICENSE("GPL");
 683MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver core");
 684MODULE_AUTHOR("Cypress");
 685