linux/drivers/input/touchscreen/ti_am335x_tsc.c
<<
>>
Prefs
   1/*
   2 * TI Touch Screen driver
   3 *
   4 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation version 2.
   9 *
  10 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
  11 * kind, whether express or implied; without even the implied warranty
  12 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16
  17#include <linux/init.h>
  18#include <linux/kernel.h>
  19#include <linux/err.h>
  20#include <linux/module.h>
  21#include <linux/input.h>
  22#include <linux/slab.h>
  23#include <linux/interrupt.h>
  24#include <linux/clk.h>
  25#include <linux/platform_device.h>
  26#include <linux/io.h>
  27#include <linux/delay.h>
  28#include <linux/of.h>
  29#include <linux/of_device.h>
  30
  31#include <linux/mfd/ti_am335x_tscadc.h>
  32
  33#define ADCFSM_STEPID           0x10
  34#define SEQ_SETTLE              275
  35#define MAX_12BIT               ((1 << 12) - 1)
  36
  37static const int config_pins[] = {
  38        STEPCONFIG_XPP,
  39        STEPCONFIG_XNN,
  40        STEPCONFIG_YPP,
  41        STEPCONFIG_YNN,
  42};
  43
  44struct titsc {
  45        struct input_dev        *input;
  46        struct ti_tscadc_dev    *mfd_tscadc;
  47        unsigned int            irq;
  48        unsigned int            wires;
  49        unsigned int            x_plate_resistance;
  50        bool                    pen_down;
  51        int                     coordinate_readouts;
  52        u32                     config_inp[4];
  53        u32                     bit_xp, bit_xn, bit_yp, bit_yn;
  54        u32                     inp_xp, inp_xn, inp_yp, inp_yn;
  55        u32                     step_mask;
  56};
  57
  58static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
  59{
  60        return readl(ts->mfd_tscadc->tscadc_base + reg);
  61}
  62
  63static void titsc_writel(struct titsc *tsc, unsigned int reg,
  64                                        unsigned int val)
  65{
  66        writel(val, tsc->mfd_tscadc->tscadc_base + reg);
  67}
  68
  69static int titsc_config_wires(struct titsc *ts_dev)
  70{
  71        u32 analog_line[4];
  72        u32 wire_order[4];
  73        int i, bit_cfg;
  74
  75        for (i = 0; i < 4; i++) {
  76                /*
  77                 * Get the order in which TSC wires are attached
  78                 * w.r.t. each of the analog input lines on the EVM.
  79                 */
  80                analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
  81                wire_order[i] = ts_dev->config_inp[i] & 0x0F;
  82                if (WARN_ON(analog_line[i] > 7))
  83                        return -EINVAL;
  84                if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
  85                        return -EINVAL;
  86        }
  87
  88        for (i = 0; i < 4; i++) {
  89                int an_line;
  90                int wi_order;
  91
  92                an_line = analog_line[i];
  93                wi_order = wire_order[i];
  94                bit_cfg = config_pins[wi_order];
  95                if (bit_cfg == 0)
  96                        return -EINVAL;
  97                switch (wi_order) {
  98                case 0:
  99                        ts_dev->bit_xp = bit_cfg;
 100                        ts_dev->inp_xp = an_line;
 101                        break;
 102
 103                case 1:
 104                        ts_dev->bit_xn = bit_cfg;
 105                        ts_dev->inp_xn = an_line;
 106                        break;
 107
 108                case 2:
 109                        ts_dev->bit_yp = bit_cfg;
 110                        ts_dev->inp_yp = an_line;
 111                        break;
 112                case 3:
 113                        ts_dev->bit_yn = bit_cfg;
 114                        ts_dev->inp_yn = an_line;
 115                        break;
 116                }
 117        }
 118        return 0;
 119}
 120
 121static void titsc_step_config(struct titsc *ts_dev)
 122{
 123        unsigned int    config;
 124        int i;
 125        int end_step;
 126        u32 stepenable;
 127
 128        config = STEPCONFIG_MODE_HWSYNC |
 129                        STEPCONFIG_AVG_16 | ts_dev->bit_xp;
 130        switch (ts_dev->wires) {
 131        case 4:
 132                config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 133                break;
 134        case 5:
 135                config |= ts_dev->bit_yn |
 136                                STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
 137                                ts_dev->bit_yp;
 138                break;
 139        case 8:
 140                config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 141                break;
 142        }
 143
 144        /* 1 … coordinate_readouts is for X */
 145        end_step = ts_dev->coordinate_readouts;
 146        for (i = 0; i < end_step; i++) {
 147                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
 148                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
 149        }
 150
 151        config = 0;
 152        config = STEPCONFIG_MODE_HWSYNC |
 153                        STEPCONFIG_AVG_16 | ts_dev->bit_yn |
 154                        STEPCONFIG_INM_ADCREFM;
 155        switch (ts_dev->wires) {
 156        case 4:
 157                config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 158                break;
 159        case 5:
 160                config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
 161                                ts_dev->bit_xn | ts_dev->bit_yp;
 162                break;
 163        case 8:
 164                config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 165                break;
 166        }
 167
 168        /* coordinate_readouts … coordinate_readouts * 2 is for Y */
 169        end_step = ts_dev->coordinate_readouts * 2;
 170        for (i = ts_dev->coordinate_readouts; i < end_step; i++) {
 171                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
 172                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
 173        }
 174
 175        /* Charge step configuration */
 176        config = ts_dev->bit_xp | ts_dev->bit_yn |
 177                        STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
 178                        STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
 179
 180        titsc_writel(ts_dev, REG_CHARGECONFIG, config);
 181        titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
 182
 183        /* coordinate_readouts * 2 … coordinate_readouts * 2 + 2 is for Z */
 184        config = STEPCONFIG_MODE_HWSYNC |
 185                        STEPCONFIG_AVG_16 | ts_dev->bit_yp |
 186                        ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
 187                        STEPCONFIG_INP(ts_dev->inp_xp);
 188        titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 189        titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 190                        STEPCONFIG_OPENDLY);
 191
 192        end_step++;
 193        config |= STEPCONFIG_INP(ts_dev->inp_yn);
 194        titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 195        titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 196                        STEPCONFIG_OPENDLY);
 197
 198        /* The steps1 … end and bit 0 for TS_Charge */
 199        stepenable = (1 << (end_step + 2)) - 1;
 200        ts_dev->step_mask = stepenable;
 201        am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 202}
 203
 204static void titsc_read_coordinates(struct titsc *ts_dev,
 205                u32 *x, u32 *y, u32 *z1, u32 *z2)
 206{
 207        unsigned int fifocount = titsc_readl(ts_dev, REG_FIFO0CNT);
 208        unsigned int prev_val_x = ~0, prev_val_y = ~0;
 209        unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
 210        unsigned int read, diff;
 211        unsigned int i, channel;
 212        unsigned int creads = ts_dev->coordinate_readouts;
 213
 214        *z1 = *z2 = 0;
 215        if (fifocount % (creads * 2 + 2))
 216                fifocount -= fifocount % (creads * 2 + 2);
 217        /*
 218         * Delta filter is used to remove large variations in sampled
 219         * values from ADC. The filter tries to predict where the next
 220         * coordinate could be. This is done by taking a previous
 221         * coordinate and subtracting it form current one. Further the
 222         * algorithm compares the difference with that of a present value,
 223         * if true the value is reported to the sub system.
 224         */
 225        for (i = 0; i < fifocount; i++) {
 226                read = titsc_readl(ts_dev, REG_FIFO0);
 227
 228                channel = (read & 0xf0000) >> 16;
 229                read &= 0xfff;
 230                if (channel < creads) {
 231                        diff = abs(read - prev_val_x);
 232                        if (diff < prev_diff_x) {
 233                                prev_diff_x = diff;
 234                                *x = read;
 235                        }
 236                        prev_val_x = read;
 237
 238                } else if (channel < creads * 2) {
 239                        diff = abs(read - prev_val_y);
 240                        if (diff < prev_diff_y) {
 241                                prev_diff_y = diff;
 242                                *y = read;
 243                        }
 244                        prev_val_y = read;
 245
 246                } else if (channel < creads * 2 + 1) {
 247                        *z1 = read;
 248
 249                } else if (channel < creads * 2 + 2) {
 250                        *z2 = read;
 251                }
 252        }
 253}
 254
 255static irqreturn_t titsc_irq(int irq, void *dev)
 256{
 257        struct titsc *ts_dev = dev;
 258        struct input_dev *input_dev = ts_dev->input;
 259        unsigned int status, irqclr = 0;
 260        unsigned int x = 0, y = 0;
 261        unsigned int z1, z2, z;
 262        unsigned int fsm;
 263
 264        status = titsc_readl(ts_dev, REG_IRQSTATUS);
 265        /*
 266         * ADC and touchscreen share the IRQ line.
 267         * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
 268         */
 269        if (status & IRQENB_FIFO0THRES) {
 270
 271                titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
 272
 273                if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
 274                        /*
 275                         * Calculate pressure using formula
 276                         * Resistance(touch) = x plate resistance *
 277                         * x postion/4096 * ((z2 / z1) - 1)
 278                         */
 279                        z = z1 - z2;
 280                        z *= x;
 281                        z *= ts_dev->x_plate_resistance;
 282                        z /= z2;
 283                        z = (z + 2047) >> 12;
 284
 285                        if (z <= MAX_12BIT) {
 286                                input_report_abs(input_dev, ABS_X, x);
 287                                input_report_abs(input_dev, ABS_Y, y);
 288                                input_report_abs(input_dev, ABS_PRESSURE, z);
 289                                input_report_key(input_dev, BTN_TOUCH, 1);
 290                                input_sync(input_dev);
 291                        }
 292                }
 293                irqclr |= IRQENB_FIFO0THRES;
 294        }
 295
 296        /*
 297         * Time for sequencer to settle, to read
 298         * correct state of the sequencer.
 299         */
 300        udelay(SEQ_SETTLE);
 301
 302        status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
 303        if (status & IRQENB_PENUP) {
 304                /* Pen up event */
 305                fsm = titsc_readl(ts_dev, REG_ADCFSM);
 306                if (fsm == ADCFSM_STEPID) {
 307                        ts_dev->pen_down = false;
 308                        input_report_key(input_dev, BTN_TOUCH, 0);
 309                        input_report_abs(input_dev, ABS_PRESSURE, 0);
 310                        input_sync(input_dev);
 311                } else {
 312                        ts_dev->pen_down = true;
 313                }
 314                irqclr |= IRQENB_PENUP;
 315        }
 316
 317        if (status & IRQENB_HW_PEN) {
 318
 319                titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
 320                titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
 321        }
 322
 323        if (irqclr) {
 324                titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
 325                am335x_tsc_se_set(ts_dev->mfd_tscadc, ts_dev->step_mask);
 326                return IRQ_HANDLED;
 327        }
 328        return IRQ_NONE;
 329}
 330
 331static int titsc_parse_dt(struct platform_device *pdev,
 332                                        struct titsc *ts_dev)
 333{
 334        struct device_node *node = pdev->dev.of_node;
 335        int err;
 336
 337        if (!node)
 338                return -EINVAL;
 339
 340        err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
 341        if (err < 0)
 342                return err;
 343        switch (ts_dev->wires) {
 344        case 4:
 345        case 5:
 346        case 8:
 347                break;
 348        default:
 349                return -EINVAL;
 350        }
 351
 352        err = of_property_read_u32(node, "ti,x-plate-resistance",
 353                        &ts_dev->x_plate_resistance);
 354        if (err < 0)
 355                return err;
 356
 357        /*
 358         * Try with the new binding first. If it fails, try again with
 359         * bogus, miss-spelled version.
 360         */
 361        err = of_property_read_u32(node, "ti,coordinate-readouts",
 362                        &ts_dev->coordinate_readouts);
 363        if (err < 0)
 364                err = of_property_read_u32(node, "ti,coordiante-readouts",
 365                                &ts_dev->coordinate_readouts);
 366        if (err < 0)
 367                return err;
 368
 369        return of_property_read_u32_array(node, "ti,wire-config",
 370                        ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
 371}
 372
 373/*
 374 * The functions for inserting/removing driver as a module.
 375 */
 376
 377static int titsc_probe(struct platform_device *pdev)
 378{
 379        struct titsc *ts_dev;
 380        struct input_dev *input_dev;
 381        struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
 382        int err;
 383
 384        /* Allocate memory for device */
 385        ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
 386        input_dev = input_allocate_device();
 387        if (!ts_dev || !input_dev) {
 388                dev_err(&pdev->dev, "failed to allocate memory.\n");
 389                err = -ENOMEM;
 390                goto err_free_mem;
 391        }
 392
 393        tscadc_dev->tsc = ts_dev;
 394        ts_dev->mfd_tscadc = tscadc_dev;
 395        ts_dev->input = input_dev;
 396        ts_dev->irq = tscadc_dev->irq;
 397
 398        err = titsc_parse_dt(pdev, ts_dev);
 399        if (err) {
 400                dev_err(&pdev->dev, "Could not find valid DT data.\n");
 401                goto err_free_mem;
 402        }
 403
 404        err = request_irq(ts_dev->irq, titsc_irq,
 405                          IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 406        if (err) {
 407                dev_err(&pdev->dev, "failed to allocate irq.\n");
 408                goto err_free_mem;
 409        }
 410
 411        titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
 412        err = titsc_config_wires(ts_dev);
 413        if (err) {
 414                dev_err(&pdev->dev, "wrong i/p wire configuration\n");
 415                goto err_free_irq;
 416        }
 417        titsc_step_config(ts_dev);
 418        titsc_writel(ts_dev, REG_FIFO0THR,
 419                        ts_dev->coordinate_readouts * 2 + 2 - 1);
 420
 421        input_dev->name = "ti-tsc";
 422        input_dev->dev.parent = &pdev->dev;
 423
 424        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 425        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 426
 427        input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
 428        input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
 429        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
 430
 431        /* register to the input system */
 432        err = input_register_device(input_dev);
 433        if (err)
 434                goto err_free_irq;
 435
 436        platform_set_drvdata(pdev, ts_dev);
 437        return 0;
 438
 439err_free_irq:
 440        free_irq(ts_dev->irq, ts_dev);
 441err_free_mem:
 442        input_free_device(input_dev);
 443        kfree(ts_dev);
 444        return err;
 445}
 446
 447static int titsc_remove(struct platform_device *pdev)
 448{
 449        struct titsc *ts_dev = platform_get_drvdata(pdev);
 450        u32 steps;
 451
 452        free_irq(ts_dev->irq, ts_dev);
 453
 454        /* total steps followed by the enable mask */
 455        steps = 2 * ts_dev->coordinate_readouts + 2;
 456        steps = (1 << steps) - 1;
 457        am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
 458
 459        input_unregister_device(ts_dev->input);
 460
 461        kfree(ts_dev);
 462        return 0;
 463}
 464
 465#ifdef CONFIG_PM
 466static int titsc_suspend(struct device *dev)
 467{
 468        struct titsc *ts_dev = dev_get_drvdata(dev);
 469        struct ti_tscadc_dev *tscadc_dev;
 470        unsigned int idle;
 471
 472        tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 473        if (device_may_wakeup(tscadc_dev->dev)) {
 474                idle = titsc_readl(ts_dev, REG_IRQENABLE);
 475                titsc_writel(ts_dev, REG_IRQENABLE,
 476                                (idle | IRQENB_HW_PEN));
 477                titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
 478        }
 479        return 0;
 480}
 481
 482static int titsc_resume(struct device *dev)
 483{
 484        struct titsc *ts_dev = dev_get_drvdata(dev);
 485        struct ti_tscadc_dev *tscadc_dev;
 486
 487        tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 488        if (device_may_wakeup(tscadc_dev->dev)) {
 489                titsc_writel(ts_dev, REG_IRQWAKEUP,
 490                                0x00);
 491                titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
 492        }
 493        titsc_step_config(ts_dev);
 494        titsc_writel(ts_dev, REG_FIFO0THR,
 495                        ts_dev->coordinate_readouts * 2 + 2 - 1);
 496        return 0;
 497}
 498
 499static const struct dev_pm_ops titsc_pm_ops = {
 500        .suspend = titsc_suspend,
 501        .resume  = titsc_resume,
 502};
 503#define TITSC_PM_OPS (&titsc_pm_ops)
 504#else
 505#define TITSC_PM_OPS NULL
 506#endif
 507
 508static const struct of_device_id ti_tsc_dt_ids[] = {
 509        { .compatible = "ti,am3359-tsc", },
 510        { }
 511};
 512MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
 513
 514static struct platform_driver ti_tsc_driver = {
 515        .probe  = titsc_probe,
 516        .remove = titsc_remove,
 517        .driver = {
 518                .name   = "TI-am335x-tsc",
 519                .owner  = THIS_MODULE,
 520                .pm     = TITSC_PM_OPS,
 521                .of_match_table = ti_tsc_dt_ids,
 522        },
 523};
 524module_platform_driver(ti_tsc_driver);
 525
 526MODULE_DESCRIPTION("TI touchscreen controller driver");
 527MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
 528MODULE_LICENSE("GPL");
 529