linux/drivers/input/touchscreen/tps6507x-ts.c
<<
>>
Prefs
   1/*
   2 * Touchscreen driver for the tps6507x chip.
   3 *
   4 * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com)
   5 *
   6 * Credits:
   7 *
   8 *    Using code from tsc2007, MtekVision Co., Ltd.
   9 *
  10 * For licencing details see kernel-base/COPYING
  11 *
  12 * TPS65070, TPS65073, TPS650731, and TPS650732 support
  13 * 10 bit touch screen interface.
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/workqueue.h>
  18#include <linux/slab.h>
  19#include <linux/input.h>
  20#include <linux/platform_device.h>
  21#include <linux/mfd/tps6507x.h>
  22#include <linux/input/tps6507x-ts.h>
  23#include <linux/delay.h>
  24
  25#define TSC_DEFAULT_POLL_PERIOD 30 /* ms */
  26#define TPS_DEFAULT_MIN_PRESSURE 0x30
  27#define MAX_10BIT ((1 << 10) - 1)
  28
  29#define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \
  30                                         TPS6507X_ADCONFIG_START_CONVERSION | \
  31                                         TPS6507X_ADCONFIG_INPUT_REAL_TSC)
  32#define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC)
  33
  34struct ts_event {
  35        u16     x;
  36        u16     y;
  37        u16     pressure;
  38};
  39
  40struct tps6507x_ts {
  41        struct input_dev        *input_dev;
  42        struct device           *dev;
  43        char                    phys[32];
  44        struct delayed_work     work;
  45        unsigned                polling;        /* polling is active */
  46        struct ts_event         tc;
  47        struct tps6507x_dev     *mfd;
  48        u16                     model;
  49        unsigned                pendown;
  50        int                     irq;
  51        void                    (*clear_penirq)(void);
  52        unsigned long           poll_period;    /* ms */
  53        u16                     min_pressure;
  54        int                     vref;           /* non-zero to leave vref on */
  55};
  56
  57static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data)
  58{
  59        int err;
  60
  61        err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data);
  62
  63        if (err)
  64                return err;
  65
  66        return 0;
  67}
  68
  69static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data)
  70{
  71        return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data);
  72}
  73
  74static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc,
  75                                   u8 tsc_mode, u16 *value)
  76{
  77        s32 ret;
  78        u8 adc_status;
  79        u8 result;
  80
  81        /* Route input signal to A/D converter */
  82
  83        ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode);
  84        if (ret) {
  85                dev_err(tsc->dev, "TSC mode read failed\n");
  86                goto err;
  87        }
  88
  89        /* Start A/D conversion */
  90
  91        ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG,
  92                                TPS6507X_ADCONFIG_CONVERT_TS);
  93        if (ret) {
  94                dev_err(tsc->dev, "ADC config write failed\n");
  95                return ret;
  96        }
  97
  98        do {
  99                ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG,
 100                                       &adc_status);
 101                if (ret) {
 102                        dev_err(tsc->dev, "ADC config read failed\n");
 103                        goto err;
 104                }
 105        } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION);
 106
 107        ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result);
 108        if (ret) {
 109                dev_err(tsc->dev, "ADC result 2 read failed\n");
 110                goto err;
 111        }
 112
 113        *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8;
 114
 115        ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result);
 116        if (ret) {
 117                dev_err(tsc->dev, "ADC result 1 read failed\n");
 118                goto err;
 119        }
 120
 121        *value |= result;
 122
 123        dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value);
 124
 125err:
 126        return ret;
 127}
 128
 129/* Need to call tps6507x_adc_standby() after using A/D converter for the
 130 * touch screen interrupt to work properly.
 131 */
 132
 133static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc)
 134{
 135        s32 ret;
 136        s32 loops = 0;
 137        u8 val;
 138
 139        ret = tps6507x_write_u8(tsc,  TPS6507X_REG_ADCONFIG,
 140                                TPS6507X_ADCONFIG_INPUT_TSC);
 141        if (ret)
 142                return ret;
 143
 144        ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE,
 145                                TPS6507X_TSCMODE_STANDBY);
 146        if (ret)
 147                return ret;
 148
 149        ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
 150        if (ret)
 151                return ret;
 152
 153        while (val & TPS6507X_REG_TSC_INT) {
 154                mdelay(10);
 155                ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val);
 156                if (ret)
 157                        return ret;
 158                loops++;
 159        }
 160
 161        return ret;
 162}
 163
 164static void tps6507x_ts_handler(struct work_struct *work)
 165{
 166        struct tps6507x_ts *tsc =  container_of(work,
 167                                struct tps6507x_ts, work.work);
 168        struct input_dev *input_dev = tsc->input_dev;
 169        int pendown;
 170        int schd;
 171        int poll = 0;
 172        s32 ret;
 173
 174        ret =  tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE,
 175                                       &tsc->tc.pressure);
 176        if (ret)
 177                goto done;
 178
 179        pendown = tsc->tc.pressure > tsc->min_pressure;
 180
 181        if (unlikely(!pendown && tsc->pendown)) {
 182                dev_dbg(tsc->dev, "UP\n");
 183                input_report_key(input_dev, BTN_TOUCH, 0);
 184                input_report_abs(input_dev, ABS_PRESSURE, 0);
 185                input_sync(input_dev);
 186                tsc->pendown = 0;
 187        }
 188
 189        if (pendown) {
 190
 191                if (!tsc->pendown) {
 192                        dev_dbg(tsc->dev, "DOWN\n");
 193                        input_report_key(input_dev, BTN_TOUCH, 1);
 194                } else
 195                        dev_dbg(tsc->dev, "still down\n");
 196
 197                ret =  tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION,
 198                                               &tsc->tc.x);
 199                if (ret)
 200                        goto done;
 201
 202                ret =  tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION,
 203                                               &tsc->tc.y);
 204                if (ret)
 205                        goto done;
 206
 207                input_report_abs(input_dev, ABS_X, tsc->tc.x);
 208                input_report_abs(input_dev, ABS_Y, tsc->tc.y);
 209                input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure);
 210                input_sync(input_dev);
 211                tsc->pendown = 1;
 212                poll = 1;
 213        }
 214
 215done:
 216        /* always poll if not using interrupts */
 217        poll = 1;
 218
 219        if (poll) {
 220                schd = schedule_delayed_work(&tsc->work,
 221                                        msecs_to_jiffies(tsc->poll_period));
 222                if (schd)
 223                        tsc->polling = 1;
 224                else {
 225                        tsc->polling = 0;
 226                        dev_err(tsc->dev, "re-schedule failed");
 227                }
 228        } else
 229                tsc->polling = 0;
 230
 231        ret = tps6507x_adc_standby(tsc);
 232}
 233
 234static int tps6507x_ts_probe(struct platform_device *pdev)
 235{
 236        int error;
 237        struct tps6507x_ts *tsc;
 238        struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
 239        struct touchscreen_init_data *init_data;
 240        struct input_dev *input_dev;
 241        struct tps6507x_board *tps_board;
 242        int schd;
 243
 244        /**
 245         * tps_board points to pmic related constants
 246         * coming from the board-evm file.
 247         */
 248
 249        tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data;
 250
 251        if (!tps_board) {
 252                dev_err(tps6507x_dev->dev,
 253                        "Could not find tps6507x platform data\n");
 254                return -EIO;
 255        }
 256
 257        /**
 258         * init_data points to array of regulator_init structures
 259         * coming from the board-evm file.
 260         */
 261
 262        init_data = tps_board->tps6507x_ts_init_data;
 263
 264        tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL);
 265        if (!tsc) {
 266                dev_err(tps6507x_dev->dev, "failed to allocate driver data\n");
 267                error = -ENOMEM;
 268                goto err0;
 269        }
 270
 271        tps6507x_dev->ts = tsc;
 272        tsc->mfd = tps6507x_dev;
 273        tsc->dev = tps6507x_dev->dev;
 274        input_dev = input_allocate_device();
 275        if (!input_dev) {
 276                dev_err(tsc->dev, "Failed to allocate input device.\n");
 277                error = -ENOMEM;
 278                goto err1;
 279        }
 280
 281        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 282        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 283
 284        input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0);
 285        input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0);
 286        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0);
 287
 288        input_dev->name = "TPS6507x Touchscreen";
 289        input_dev->id.bustype = BUS_I2C;
 290        input_dev->dev.parent = tsc->dev;
 291
 292        snprintf(tsc->phys, sizeof(tsc->phys),
 293                 "%s/input0", dev_name(tsc->dev));
 294        input_dev->phys = tsc->phys;
 295
 296        dev_dbg(tsc->dev, "device: %s\n", input_dev->phys);
 297
 298        input_set_drvdata(input_dev, tsc);
 299
 300        tsc->input_dev = input_dev;
 301
 302        INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
 303
 304        if (init_data) {
 305                tsc->poll_period = init_data->poll_period;
 306                tsc->vref = init_data->vref;
 307                tsc->min_pressure = init_data->min_pressure;
 308                input_dev->id.vendor = init_data->vendor;
 309                input_dev->id.product = init_data->product;
 310                input_dev->id.version = init_data->version;
 311        } else {
 312                tsc->poll_period = TSC_DEFAULT_POLL_PERIOD;
 313                tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE;
 314        }
 315
 316        error = tps6507x_adc_standby(tsc);
 317        if (error)
 318                goto err2;
 319
 320        error = input_register_device(input_dev);
 321        if (error)
 322                goto err2;
 323
 324        schd = schedule_delayed_work(&tsc->work,
 325                                     msecs_to_jiffies(tsc->poll_period));
 326
 327        if (schd)
 328                tsc->polling = 1;
 329        else {
 330                tsc->polling = 0;
 331                dev_err(tsc->dev, "schedule failed");
 332                goto err2;
 333         }
 334        platform_set_drvdata(pdev, tps6507x_dev);
 335
 336        return 0;
 337
 338err2:
 339        cancel_delayed_work_sync(&tsc->work);
 340        input_free_device(input_dev);
 341err1:
 342        kfree(tsc);
 343        tps6507x_dev->ts = NULL;
 344err0:
 345        return error;
 346}
 347
 348static int tps6507x_ts_remove(struct platform_device *pdev)
 349{
 350        struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
 351        struct tps6507x_ts *tsc = tps6507x_dev->ts;
 352        struct input_dev *input_dev = tsc->input_dev;
 353
 354        cancel_delayed_work_sync(&tsc->work);
 355
 356        input_unregister_device(input_dev);
 357
 358        tps6507x_dev->ts = NULL;
 359        kfree(tsc);
 360
 361        return 0;
 362}
 363
 364static struct platform_driver tps6507x_ts_driver = {
 365        .driver = {
 366                .name = "tps6507x-ts",
 367                .owner = THIS_MODULE,
 368        },
 369        .probe = tps6507x_ts_probe,
 370        .remove = tps6507x_ts_remove,
 371};
 372module_platform_driver(tps6507x_ts_driver);
 373
 374MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>");
 375MODULE_DESCRIPTION("TPS6507x - TouchScreen driver");
 376MODULE_LICENSE("GPL v2");
 377MODULE_ALIAS("platform:tps6507x-ts");
 378