linux/drivers/input/touchscreen/tsc2007_core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * drivers/input/touchscreen/tsc2007.c
   4 *
   5 * Copyright (c) 2008 MtekVision Co., Ltd.
   6 *      Kwangwoo Lee <kwlee@mtekvision.com>
   7 *
   8 * Using code from:
   9 *  - ads7846.c
  10 *      Copyright (c) 2005 David Brownell
  11 *      Copyright (c) 2006 Nokia Corporation
  12 *  - corgi_ts.c
  13 *      Copyright (C) 2004-2005 Richard Purdie
  14 *  - omap_ts.[hc], ads7846.h, ts_osk.c
  15 *      Copyright (C) 2002 MontaVista Software
  16 *      Copyright (C) 2004 Texas Instruments
  17 *      Copyright (C) 2005 Dirk Behme
  18 */
  19
  20#include <linux/module.h>
  21#include <linux/slab.h>
  22#include <linux/input.h>
  23#include <linux/interrupt.h>
  24#include <linux/i2c.h>
  25#include <linux/of_device.h>
  26#include <linux/of_gpio.h>
  27#include <linux/platform_data/tsc2007.h>
  28#include "tsc2007.h"
  29
  30int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
  31{
  32        s32 data;
  33        u16 val;
  34
  35        data = i2c_smbus_read_word_data(tsc->client, cmd);
  36        if (data < 0) {
  37                dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
  38                return data;
  39        }
  40
  41        /* The protocol and raw data format from i2c interface:
  42         * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
  43         * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
  44         */
  45        val = swab16(data) >> 4;
  46
  47        dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
  48
  49        return val;
  50}
  51
  52static void tsc2007_read_values(struct tsc2007 *tsc, struct ts_event *tc)
  53{
  54        /* y- still on; turn on only y+ (and ADC) */
  55        tc->y = tsc2007_xfer(tsc, READ_Y);
  56
  57        /* turn y- off, x+ on, then leave in lowpower */
  58        tc->x = tsc2007_xfer(tsc, READ_X);
  59
  60        /* turn y+ off, x- on; we'll use formula #1 */
  61        tc->z1 = tsc2007_xfer(tsc, READ_Z1);
  62        tc->z2 = tsc2007_xfer(tsc, READ_Z2);
  63
  64        /* Prepare for next touch reading - power down ADC, enable PENIRQ */
  65        tsc2007_xfer(tsc, PWRDOWN);
  66}
  67
  68u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
  69{
  70        u32 rt = 0;
  71
  72        /* range filtering */
  73        if (tc->x == MAX_12BIT)
  74                tc->x = 0;
  75
  76        if (likely(tc->x && tc->z1)) {
  77                /* compute touch resistance using equation #1 */
  78                rt = tc->z2 - tc->z1;
  79                rt *= tc->x;
  80                rt *= tsc->x_plate_ohms;
  81                rt /= tc->z1;
  82                rt = (rt + 2047) >> 12;
  83        }
  84
  85        return rt;
  86}
  87
  88bool tsc2007_is_pen_down(struct tsc2007 *ts)
  89{
  90        /*
  91         * NOTE: We can't rely on the pressure to determine the pen down
  92         * state, even though this controller has a pressure sensor.
  93         * The pressure value can fluctuate for quite a while after
  94         * lifting the pen and in some cases may not even settle at the
  95         * expected value.
  96         *
  97         * The only safe way to check for the pen up condition is in the
  98         * work function by reading the pen signal state (it's a GPIO
  99         * and IRQ). Unfortunately such callback is not always available,
 100         * in that case we assume that the pen is down and expect caller
 101         * to fall back on the pressure reading.
 102         */
 103
 104        if (!ts->get_pendown_state)
 105                return true;
 106
 107        return ts->get_pendown_state(&ts->client->dev);
 108}
 109
 110static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
 111{
 112        struct tsc2007 *ts = handle;
 113        struct input_dev *input = ts->input;
 114        struct ts_event tc;
 115        u32 rt;
 116
 117        while (!ts->stopped && tsc2007_is_pen_down(ts)) {
 118
 119                /* pen is down, continue with the measurement */
 120
 121                mutex_lock(&ts->mlock);
 122                tsc2007_read_values(ts, &tc);
 123                mutex_unlock(&ts->mlock);
 124
 125                rt = tsc2007_calculate_resistance(ts, &tc);
 126
 127                if (!rt && !ts->get_pendown_state) {
 128                        /*
 129                         * If pressure reported is 0 and we don't have
 130                         * callback to check pendown state, we have to
 131                         * assume that pen was lifted up.
 132                         */
 133                        break;
 134                }
 135
 136                if (rt <= ts->max_rt) {
 137                        dev_dbg(&ts->client->dev,
 138                                "DOWN point(%4d,%4d), resistance (%4u)\n",
 139                                tc.x, tc.y, rt);
 140
 141                        rt = ts->max_rt - rt;
 142
 143                        input_report_key(input, BTN_TOUCH, 1);
 144                        input_report_abs(input, ABS_X, tc.x);
 145                        input_report_abs(input, ABS_Y, tc.y);
 146                        input_report_abs(input, ABS_PRESSURE, rt);
 147
 148                        input_sync(input);
 149
 150                } else {
 151                        /*
 152                         * Sample found inconsistent by debouncing or pressure is
 153                         * beyond the maximum. Don't report it to user space,
 154                         * repeat at least once more the measurement.
 155                         */
 156                        dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
 157                }
 158
 159                wait_event_timeout(ts->wait, ts->stopped, ts->poll_period);
 160        }
 161
 162        dev_dbg(&ts->client->dev, "UP\n");
 163
 164        input_report_key(input, BTN_TOUCH, 0);
 165        input_report_abs(input, ABS_PRESSURE, 0);
 166        input_sync(input);
 167
 168        if (ts->clear_penirq)
 169                ts->clear_penirq();
 170
 171        return IRQ_HANDLED;
 172}
 173
 174static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
 175{
 176        struct tsc2007 *ts = handle;
 177
 178        if (tsc2007_is_pen_down(ts))
 179                return IRQ_WAKE_THREAD;
 180
 181        if (ts->clear_penirq)
 182                ts->clear_penirq();
 183
 184        return IRQ_HANDLED;
 185}
 186
 187static void tsc2007_stop(struct tsc2007 *ts)
 188{
 189        ts->stopped = true;
 190        mb();
 191        wake_up(&ts->wait);
 192
 193        disable_irq(ts->irq);
 194}
 195
 196static int tsc2007_open(struct input_dev *input_dev)
 197{
 198        struct tsc2007 *ts = input_get_drvdata(input_dev);
 199        int err;
 200
 201        ts->stopped = false;
 202        mb();
 203
 204        enable_irq(ts->irq);
 205
 206        /* Prepare for touch readings - power down ADC and enable PENIRQ */
 207        err = tsc2007_xfer(ts, PWRDOWN);
 208        if (err < 0) {
 209                tsc2007_stop(ts);
 210                return err;
 211        }
 212
 213        return 0;
 214}
 215
 216static void tsc2007_close(struct input_dev *input_dev)
 217{
 218        struct tsc2007 *ts = input_get_drvdata(input_dev);
 219
 220        tsc2007_stop(ts);
 221}
 222
 223#ifdef CONFIG_OF
 224static int tsc2007_get_pendown_state_gpio(struct device *dev)
 225{
 226        struct i2c_client *client = to_i2c_client(dev);
 227        struct tsc2007 *ts = i2c_get_clientdata(client);
 228
 229        return !gpio_get_value(ts->gpio);
 230}
 231
 232static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
 233{
 234        struct device_node *np = client->dev.of_node;
 235        u32 val32;
 236        u64 val64;
 237
 238        if (!np) {
 239                dev_err(&client->dev, "missing device tree data\n");
 240                return -EINVAL;
 241        }
 242
 243        if (!of_property_read_u32(np, "ti,max-rt", &val32))
 244                ts->max_rt = val32;
 245        else
 246                ts->max_rt = MAX_12BIT;
 247
 248        if (!of_property_read_u32(np, "ti,fuzzx", &val32))
 249                ts->fuzzx = val32;
 250
 251        if (!of_property_read_u32(np, "ti,fuzzy", &val32))
 252                ts->fuzzy = val32;
 253
 254        if (!of_property_read_u32(np, "ti,fuzzz", &val32))
 255                ts->fuzzz = val32;
 256
 257        if (!of_property_read_u64(np, "ti,poll-period", &val64))
 258                ts->poll_period = msecs_to_jiffies(val64);
 259        else
 260                ts->poll_period = msecs_to_jiffies(1);
 261
 262        if (!of_property_read_u32(np, "ti,x-plate-ohms", &val32)) {
 263                ts->x_plate_ohms = val32;
 264        } else {
 265                dev_err(&client->dev, "missing ti,x-plate-ohms devicetree property.");
 266                return -EINVAL;
 267        }
 268
 269        ts->gpio = of_get_gpio(np, 0);
 270        if (gpio_is_valid(ts->gpio))
 271                ts->get_pendown_state = tsc2007_get_pendown_state_gpio;
 272        else
 273                dev_warn(&client->dev,
 274                         "GPIO not specified in DT (of_get_gpio returned %d)\n",
 275                         ts->gpio);
 276
 277        return 0;
 278}
 279#else
 280static int tsc2007_probe_dt(struct i2c_client *client, struct tsc2007 *ts)
 281{
 282        dev_err(&client->dev, "platform data is required!\n");
 283        return -EINVAL;
 284}
 285#endif
 286
 287static int tsc2007_probe_pdev(struct i2c_client *client, struct tsc2007 *ts,
 288                              const struct tsc2007_platform_data *pdata,
 289                              const struct i2c_device_id *id)
 290{
 291        ts->model             = pdata->model;
 292        ts->x_plate_ohms      = pdata->x_plate_ohms;
 293        ts->max_rt            = pdata->max_rt ? : MAX_12BIT;
 294        ts->poll_period       = msecs_to_jiffies(pdata->poll_period ? : 1);
 295        ts->get_pendown_state = pdata->get_pendown_state;
 296        ts->clear_penirq      = pdata->clear_penirq;
 297        ts->fuzzx             = pdata->fuzzx;
 298        ts->fuzzy             = pdata->fuzzy;
 299        ts->fuzzz             = pdata->fuzzz;
 300
 301        if (pdata->x_plate_ohms == 0) {
 302                dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
 303                return -EINVAL;
 304        }
 305
 306        return 0;
 307}
 308
 309static void tsc2007_call_exit_platform_hw(void *data)
 310{
 311        struct device *dev = data;
 312        const struct tsc2007_platform_data *pdata = dev_get_platdata(dev);
 313
 314        pdata->exit_platform_hw();
 315}
 316
 317static int tsc2007_probe(struct i2c_client *client,
 318                         const struct i2c_device_id *id)
 319{
 320        const struct tsc2007_platform_data *pdata =
 321                dev_get_platdata(&client->dev);
 322        struct tsc2007 *ts;
 323        struct input_dev *input_dev;
 324        int err;
 325
 326        if (!i2c_check_functionality(client->adapter,
 327                                     I2C_FUNC_SMBUS_READ_WORD_DATA))
 328                return -EIO;
 329
 330        ts = devm_kzalloc(&client->dev, sizeof(struct tsc2007), GFP_KERNEL);
 331        if (!ts)
 332                return -ENOMEM;
 333
 334        if (pdata)
 335                err = tsc2007_probe_pdev(client, ts, pdata, id);
 336        else
 337                err = tsc2007_probe_dt(client, ts);
 338        if (err)
 339                return err;
 340
 341        input_dev = devm_input_allocate_device(&client->dev);
 342        if (!input_dev)
 343                return -ENOMEM;
 344
 345        i2c_set_clientdata(client, ts);
 346
 347        ts->client = client;
 348        ts->irq = client->irq;
 349        ts->input = input_dev;
 350
 351        init_waitqueue_head(&ts->wait);
 352        mutex_init(&ts->mlock);
 353
 354        snprintf(ts->phys, sizeof(ts->phys),
 355                 "%s/input0", dev_name(&client->dev));
 356
 357        input_dev->name = "TSC2007 Touchscreen";
 358        input_dev->phys = ts->phys;
 359        input_dev->id.bustype = BUS_I2C;
 360
 361        input_dev->open = tsc2007_open;
 362        input_dev->close = tsc2007_close;
 363
 364        input_set_drvdata(input_dev, ts);
 365
 366        input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
 367
 368        input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, ts->fuzzx, 0);
 369        input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, ts->fuzzy, 0);
 370        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
 371                             ts->fuzzz, 0);
 372
 373        if (pdata) {
 374                if (pdata->exit_platform_hw) {
 375                        err = devm_add_action(&client->dev,
 376                                              tsc2007_call_exit_platform_hw,
 377                                              &client->dev);
 378                        if (err) {
 379                                dev_err(&client->dev,
 380                                        "Failed to register exit_platform_hw action, %d\n",
 381                                        err);
 382                                return err;
 383                        }
 384                }
 385
 386                if (pdata->init_platform_hw)
 387                        pdata->init_platform_hw();
 388        }
 389
 390        err = devm_request_threaded_irq(&client->dev, ts->irq,
 391                                        tsc2007_hard_irq, tsc2007_soft_irq,
 392                                        IRQF_ONESHOT,
 393                                        client->dev.driver->name, ts);
 394        if (err) {
 395                dev_err(&client->dev, "Failed to request irq %d: %d\n",
 396                        ts->irq, err);
 397                return err;
 398        }
 399
 400        tsc2007_stop(ts);
 401
 402        /* power down the chip (TSC2007_SETUP does not ACK on I2C) */
 403        err = tsc2007_xfer(ts, PWRDOWN);
 404        if (err < 0) {
 405                dev_err(&client->dev,
 406                        "Failed to setup chip: %d\n", err);
 407                return err;     /* chip does not respond */
 408        }
 409
 410        err = input_register_device(input_dev);
 411        if (err) {
 412                dev_err(&client->dev,
 413                        "Failed to register input device: %d\n", err);
 414                return err;
 415        }
 416
 417        err =  tsc2007_iio_configure(ts);
 418        if (err) {
 419                dev_err(&client->dev,
 420                        "Failed to register with IIO: %d\n", err);
 421                return err;
 422        }
 423
 424        return 0;
 425}
 426
 427static const struct i2c_device_id tsc2007_idtable[] = {
 428        { "tsc2007", 0 },
 429        { }
 430};
 431
 432MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
 433
 434#ifdef CONFIG_OF
 435static const struct of_device_id tsc2007_of_match[] = {
 436        { .compatible = "ti,tsc2007" },
 437        { /* sentinel */ }
 438};
 439MODULE_DEVICE_TABLE(of, tsc2007_of_match);
 440#endif
 441
 442static struct i2c_driver tsc2007_driver = {
 443        .driver = {
 444                .name   = "tsc2007",
 445                .of_match_table = of_match_ptr(tsc2007_of_match),
 446        },
 447        .id_table       = tsc2007_idtable,
 448        .probe          = tsc2007_probe,
 449};
 450
 451module_i2c_driver(tsc2007_driver);
 452
 453MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
 454MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");
 455MODULE_LICENSE("GPL");
 456