linux/drivers/input/touchscreen/tsc2007.c
<<
>>
Prefs
   1/*
   2 * drivers/input/touchscreen/tsc2007.c
   3 *
   4 * Copyright (c) 2008 MtekVision Co., Ltd.
   5 *      Kwangwoo Lee <kwlee@mtekvision.com>
   6 *
   7 * Using code from:
   8 *  - ads7846.c
   9 *      Copyright (c) 2005 David Brownell
  10 *      Copyright (c) 2006 Nokia Corporation
  11 *  - corgi_ts.c
  12 *      Copyright (C) 2004-2005 Richard Purdie
  13 *  - omap_ts.[hc], ads7846.h, ts_osk.c
  14 *      Copyright (C) 2002 MontaVista Software
  15 *      Copyright (C) 2004 Texas Instruments
  16 *      Copyright (C) 2005 Dirk Behme
  17 *
  18 *  This program is free software; you can redistribute it and/or modify
  19 *  it under the terms of the GNU General Public License version 2 as
  20 *  published by the Free Software Foundation.
  21 */
  22
  23#include <linux/module.h>
  24#include <linux/hrtimer.h>
  25#include <linux/slab.h>
  26#include <linux/input.h>
  27#include <linux/interrupt.h>
  28#include <linux/i2c.h>
  29#include <linux/i2c/tsc2007.h>
  30
  31#define TS_POLL_DELAY   (10 * 1000)     /* ns delay before the first sample */
  32#define TS_POLL_PERIOD  (5 * 1000)      /* ns delay between samples */
  33
  34#define TSC2007_MEASURE_TEMP0           (0x0 << 4)
  35#define TSC2007_MEASURE_AUX             (0x2 << 4)
  36#define TSC2007_MEASURE_TEMP1           (0x4 << 4)
  37#define TSC2007_ACTIVATE_XN             (0x8 << 4)
  38#define TSC2007_ACTIVATE_YN             (0x9 << 4)
  39#define TSC2007_ACTIVATE_YP_XN          (0xa << 4)
  40#define TSC2007_SETUP                   (0xb << 4)
  41#define TSC2007_MEASURE_X               (0xc << 4)
  42#define TSC2007_MEASURE_Y               (0xd << 4)
  43#define TSC2007_MEASURE_Z1              (0xe << 4)
  44#define TSC2007_MEASURE_Z2              (0xf << 4)
  45
  46#define TSC2007_POWER_OFF_IRQ_EN        (0x0 << 2)
  47#define TSC2007_ADC_ON_IRQ_DIS0         (0x1 << 2)
  48#define TSC2007_ADC_OFF_IRQ_EN          (0x2 << 2)
  49#define TSC2007_ADC_ON_IRQ_DIS1         (0x3 << 2)
  50
  51#define TSC2007_12BIT                   (0x0 << 1)
  52#define TSC2007_8BIT                    (0x1 << 1)
  53
  54#define MAX_12BIT                       ((1 << 12) - 1)
  55
  56#define ADC_ON_12BIT    (TSC2007_12BIT | TSC2007_ADC_ON_IRQ_DIS0)
  57
  58#define READ_Y          (ADC_ON_12BIT | TSC2007_MEASURE_Y)
  59#define READ_Z1         (ADC_ON_12BIT | TSC2007_MEASURE_Z1)
  60#define READ_Z2         (ADC_ON_12BIT | TSC2007_MEASURE_Z2)
  61#define READ_X          (ADC_ON_12BIT | TSC2007_MEASURE_X)
  62#define PWRDOWN         (TSC2007_12BIT | TSC2007_POWER_OFF_IRQ_EN)
  63
  64struct ts_event {
  65        u16     x;
  66        u16     y;
  67        u16     z1, z2;
  68};
  69
  70struct tsc2007 {
  71        struct input_dev        *input;
  72        char                    phys[32];
  73        struct hrtimer          timer;
  74        struct ts_event         tc;
  75
  76        struct i2c_client       *client;
  77
  78        spinlock_t              lock;
  79
  80        u16                     model;
  81        u16                     x_plate_ohms;
  82
  83        unsigned                pendown;
  84        int                     irq;
  85
  86        int                     (*get_pendown_state)(void);
  87        void                    (*clear_penirq)(void);
  88};
  89
  90static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
  91{
  92        s32 data;
  93        u16 val;
  94
  95        data = i2c_smbus_read_word_data(tsc->client, cmd);
  96        if (data < 0) {
  97                dev_err(&tsc->client->dev, "i2c io error: %d\n", data);
  98                return data;
  99        }
 100
 101        /* The protocol and raw data format from i2c interface:
 102         * S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
 103         * Where DataLow has [D11-D4], DataHigh has [D3-D0 << 4 | Dummy 4bit].
 104         */
 105        val = swab16(data) >> 4;
 106
 107        dev_dbg(&tsc->client->dev, "data: 0x%x, val: 0x%x\n", data, val);
 108
 109        return val;
 110}
 111
 112static void tsc2007_send_event(void *tsc)
 113{
 114        struct tsc2007  *ts = tsc;
 115        u32             rt;
 116        u16             x, y, z1, z2;
 117
 118        x = ts->tc.x;
 119        y = ts->tc.y;
 120        z1 = ts->tc.z1;
 121        z2 = ts->tc.z2;
 122
 123        /* range filtering */
 124        if (x == MAX_12BIT)
 125                x = 0;
 126
 127        if (likely(x && z1)) {
 128                /* compute touch pressure resistance using equation #1 */
 129                rt = z2;
 130                rt -= z1;
 131                rt *= x;
 132                rt *= ts->x_plate_ohms;
 133                rt /= z1;
 134                rt = (rt + 2047) >> 12;
 135        } else
 136                rt = 0;
 137
 138        /* Sample found inconsistent by debouncing or pressure is beyond
 139         * the maximum. Don't report it to user space, repeat at least
 140         * once more the measurement
 141         */
 142        if (rt > MAX_12BIT) {
 143                dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
 144
 145                hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
 146                              HRTIMER_MODE_REL);
 147                return;
 148        }
 149
 150        /* NOTE: We can't rely on the pressure to determine the pen down
 151         * state, even this controller has a pressure sensor.  The pressure
 152         * value can fluctuate for quite a while after lifting the pen and
 153         * in some cases may not even settle at the expected value.
 154         *
 155         * The only safe way to check for the pen up condition is in the
 156         * timer by reading the pen signal state (it's a GPIO _and_ IRQ).
 157         */
 158        if (rt) {
 159                struct input_dev *input = ts->input;
 160
 161                if (!ts->pendown) {
 162                        dev_dbg(&ts->client->dev, "DOWN\n");
 163
 164                        input_report_key(input, BTN_TOUCH, 1);
 165                        ts->pendown = 1;
 166                }
 167
 168                input_report_abs(input, ABS_X, x);
 169                input_report_abs(input, ABS_Y, y);
 170                input_report_abs(input, ABS_PRESSURE, rt);
 171
 172                input_sync(input);
 173
 174                dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
 175                        x, y, rt);
 176        }
 177
 178        hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
 179                        HRTIMER_MODE_REL);
 180}
 181
 182static int tsc2007_read_values(struct tsc2007 *tsc)
 183{
 184        /* y- still on; turn on only y+ (and ADC) */
 185        tsc->tc.y = tsc2007_xfer(tsc, READ_Y);
 186
 187        /* turn y- off, x+ on, then leave in lowpower */
 188        tsc->tc.x = tsc2007_xfer(tsc, READ_X);
 189
 190        /* turn y+ off, x- on; we'll use formula #1 */
 191        tsc->tc.z1 = tsc2007_xfer(tsc, READ_Z1);
 192        tsc->tc.z2 = tsc2007_xfer(tsc, READ_Z2);
 193
 194        /* power down */
 195        tsc2007_xfer(tsc, PWRDOWN);
 196
 197        return 0;
 198}
 199
 200static enum hrtimer_restart tsc2007_timer(struct hrtimer *handle)
 201{
 202        struct tsc2007 *ts = container_of(handle, struct tsc2007, timer);
 203        unsigned long flags;
 204
 205        spin_lock_irqsave(&ts->lock, flags);
 206
 207        if (unlikely(!ts->get_pendown_state() && ts->pendown)) {
 208                struct input_dev *input = ts->input;
 209
 210                dev_dbg(&ts->client->dev, "UP\n");
 211
 212                input_report_key(input, BTN_TOUCH, 0);
 213                input_report_abs(input, ABS_PRESSURE, 0);
 214                input_sync(input);
 215
 216                ts->pendown = 0;
 217                enable_irq(ts->irq);
 218        } else {
 219                /* pen is still down, continue with the measurement */
 220                dev_dbg(&ts->client->dev, "pen is still down\n");
 221
 222                tsc2007_read_values(ts);
 223                tsc2007_send_event(ts);
 224        }
 225
 226        spin_unlock_irqrestore(&ts->lock, flags);
 227
 228        return HRTIMER_NORESTART;
 229}
 230
 231static irqreturn_t tsc2007_irq(int irq, void *handle)
 232{
 233        struct tsc2007 *ts = handle;
 234        unsigned long flags;
 235
 236        spin_lock_irqsave(&ts->lock, flags);
 237
 238        if (likely(ts->get_pendown_state())) {
 239                disable_irq_nosync(ts->irq);
 240                hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
 241                                        HRTIMER_MODE_REL);
 242        }
 243
 244        if (ts->clear_penirq)
 245                ts->clear_penirq();
 246
 247        spin_unlock_irqrestore(&ts->lock, flags);
 248
 249        return IRQ_HANDLED;
 250}
 251
 252static int tsc2007_probe(struct i2c_client *client,
 253                        const struct i2c_device_id *id)
 254{
 255        struct tsc2007 *ts;
 256        struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
 257        struct input_dev *input_dev;
 258        int err;
 259
 260        if (!pdata) {
 261                dev_err(&client->dev, "platform data is required!\n");
 262                return -EINVAL;
 263        }
 264
 265        if (!i2c_check_functionality(client->adapter,
 266                                     I2C_FUNC_SMBUS_READ_WORD_DATA))
 267                return -EIO;
 268
 269        ts = kzalloc(sizeof(struct tsc2007), GFP_KERNEL);
 270        input_dev = input_allocate_device();
 271        if (!ts || !input_dev) {
 272                err = -ENOMEM;
 273                goto err_free_mem;
 274        }
 275
 276        ts->client = client;
 277        i2c_set_clientdata(client, ts);
 278
 279        ts->input = input_dev;
 280
 281        hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 282        ts->timer.function = tsc2007_timer;
 283
 284        spin_lock_init(&ts->lock);
 285
 286        ts->model             = pdata->model;
 287        ts->x_plate_ohms      = pdata->x_plate_ohms;
 288        ts->get_pendown_state = pdata->get_pendown_state;
 289        ts->clear_penirq      = pdata->clear_penirq;
 290
 291        pdata->init_platform_hw();
 292
 293        snprintf(ts->phys, sizeof(ts->phys),
 294                 "%s/input0", dev_name(&client->dev));
 295
 296        input_dev->name = "TSC2007 Touchscreen";
 297        input_dev->phys = ts->phys;
 298        input_dev->id.bustype = BUS_I2C;
 299
 300        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 301        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 302
 303        input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
 304        input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
 305        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
 306
 307        tsc2007_read_values(ts);
 308
 309        ts->irq = client->irq;
 310
 311        err = request_irq(ts->irq, tsc2007_irq, 0,
 312                        client->dev.driver->name, ts);
 313        if (err < 0) {
 314                dev_err(&client->dev, "irq %d busy?\n", ts->irq);
 315                goto err_free_mem;
 316        }
 317
 318        err = input_register_device(input_dev);
 319        if (err)
 320                goto err_free_irq;
 321
 322        dev_info(&client->dev, "registered with irq (%d)\n", ts->irq);
 323
 324        return 0;
 325
 326 err_free_irq:
 327        free_irq(ts->irq, ts);
 328        hrtimer_cancel(&ts->timer);
 329 err_free_mem:
 330        input_free_device(input_dev);
 331        kfree(ts);
 332        return err;
 333}
 334
 335static int tsc2007_remove(struct i2c_client *client)
 336{
 337        struct tsc2007  *ts = i2c_get_clientdata(client);
 338        struct tsc2007_platform_data *pdata;
 339
 340        pdata = client->dev.platform_data;
 341        pdata->exit_platform_hw();
 342
 343        free_irq(ts->irq, ts);
 344        hrtimer_cancel(&ts->timer);
 345        input_unregister_device(ts->input);
 346        kfree(ts);
 347
 348        return 0;
 349}
 350
 351static struct i2c_device_id tsc2007_idtable[] = {
 352        { "tsc2007", 0 },
 353        { }
 354};
 355
 356MODULE_DEVICE_TABLE(i2c, tsc2007_idtable);
 357
 358static struct i2c_driver tsc2007_driver = {
 359        .driver = {
 360                .owner  = THIS_MODULE,
 361                .name   = "tsc2007"
 362        },
 363        .id_table       = tsc2007_idtable,
 364        .probe          = tsc2007_probe,
 365        .remove         = tsc2007_remove,
 366};
 367
 368static int __init tsc2007_init(void)
 369{
 370        return i2c_add_driver(&tsc2007_driver);
 371}
 372
 373static void __exit tsc2007_exit(void)
 374{
 375        i2c_del_driver(&tsc2007_driver);
 376}
 377
 378module_init(tsc2007_init);
 379module_exit(tsc2007_exit);
 380
 381MODULE_AUTHOR("Kwangwoo Lee <kwlee@mtekvision.com>");
 382MODULE_DESCRIPTION("TSC2007 TouchScreen Driver");
 383MODULE_LICENSE("GPL");
 384