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/kernel.h>
  18#include <linux/err.h>
  19#include <linux/module.h>
  20#include <linux/input.h>
  21#include <linux/slab.h>
  22#include <linux/interrupt.h>
  23#include <linux/clk.h>
  24#include <linux/platform_device.h>
  25#include <linux/io.h>
  26#include <linux/delay.h>
  27#include <linux/of.h>
  28#include <linux/of_device.h>
  29#include <linux/sort.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        u32                     charge_delay;
  57};
  58
  59static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
  60{
  61        return readl(ts->mfd_tscadc->tscadc_base + reg);
  62}
  63
  64static void titsc_writel(struct titsc *tsc, unsigned int reg,
  65                                        unsigned int val)
  66{
  67        writel(val, tsc->mfd_tscadc->tscadc_base + reg);
  68}
  69
  70static int titsc_config_wires(struct titsc *ts_dev)
  71{
  72        u32 analog_line[4];
  73        u32 wire_order[4];
  74        int i, bit_cfg;
  75
  76        for (i = 0; i < 4; i++) {
  77                /*
  78                 * Get the order in which TSC wires are attached
  79                 * w.r.t. each of the analog input lines on the EVM.
  80                 */
  81                analog_line[i] = (ts_dev->config_inp[i] & 0xF0) >> 4;
  82                wire_order[i] = ts_dev->config_inp[i] & 0x0F;
  83                if (WARN_ON(analog_line[i] > 7))
  84                        return -EINVAL;
  85                if (WARN_ON(wire_order[i] > ARRAY_SIZE(config_pins)))
  86                        return -EINVAL;
  87        }
  88
  89        for (i = 0; i < 4; i++) {
  90                int an_line;
  91                int wi_order;
  92
  93                an_line = analog_line[i];
  94                wi_order = wire_order[i];
  95                bit_cfg = config_pins[wi_order];
  96                if (bit_cfg == 0)
  97                        return -EINVAL;
  98                switch (wi_order) {
  99                case 0:
 100                        ts_dev->bit_xp = bit_cfg;
 101                        ts_dev->inp_xp = an_line;
 102                        break;
 103
 104                case 1:
 105                        ts_dev->bit_xn = bit_cfg;
 106                        ts_dev->inp_xn = an_line;
 107                        break;
 108
 109                case 2:
 110                        ts_dev->bit_yp = bit_cfg;
 111                        ts_dev->inp_yp = an_line;
 112                        break;
 113                case 3:
 114                        ts_dev->bit_yn = bit_cfg;
 115                        ts_dev->inp_yn = an_line;
 116                        break;
 117                }
 118        }
 119        return 0;
 120}
 121
 122static void titsc_step_config(struct titsc *ts_dev)
 123{
 124        unsigned int    config;
 125        int i;
 126        int end_step, first_step, tsc_steps;
 127        u32 stepenable;
 128
 129        config = STEPCONFIG_MODE_HWSYNC |
 130                        STEPCONFIG_AVG_16 | ts_dev->bit_xp;
 131        switch (ts_dev->wires) {
 132        case 4:
 133                config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 134                break;
 135        case 5:
 136                config |= ts_dev->bit_yn |
 137                                STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
 138                                ts_dev->bit_yp;
 139                break;
 140        case 8:
 141                config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 142                break;
 143        }
 144
 145        tsc_steps = ts_dev->coordinate_readouts * 2 + 2;
 146        first_step = TOTAL_STEPS - tsc_steps;
 147        /* Steps 16 to 16-coordinate_readouts is for X */
 148        end_step = first_step + tsc_steps;
 149        for (i = end_step - ts_dev->coordinate_readouts; i < end_step; i++) {
 150                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
 151                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
 152        }
 153
 154        config = 0;
 155        config = STEPCONFIG_MODE_HWSYNC |
 156                        STEPCONFIG_AVG_16 | ts_dev->bit_yn |
 157                        STEPCONFIG_INM_ADCREFM;
 158        switch (ts_dev->wires) {
 159        case 4:
 160                config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 161                break;
 162        case 5:
 163                config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
 164                                ts_dev->bit_xn | ts_dev->bit_yp;
 165                break;
 166        case 8:
 167                config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 168                break;
 169        }
 170
 171        /* 1 ... coordinate_readouts is for Y */
 172        end_step = first_step + ts_dev->coordinate_readouts;
 173        for (i = first_step; i < end_step; i++) {
 174                titsc_writel(ts_dev, REG_STEPCONFIG(i), config);
 175                titsc_writel(ts_dev, REG_STEPDELAY(i), STEPCONFIG_OPENDLY);
 176        }
 177
 178        /* Make CHARGECONFIG same as IDLECONFIG */
 179
 180        config = titsc_readl(ts_dev, REG_IDLECONFIG);
 181        titsc_writel(ts_dev, REG_CHARGECONFIG, config);
 182        titsc_writel(ts_dev, REG_CHARGEDELAY, ts_dev->charge_delay);
 183
 184        /* coordinate_readouts + 1 ... coordinate_readouts + 2 is for Z */
 185        config = STEPCONFIG_MODE_HWSYNC |
 186                        STEPCONFIG_AVG_16 | ts_dev->bit_yp |
 187                        ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
 188                        STEPCONFIG_INP(ts_dev->inp_xp);
 189        titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 190        titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 191                        STEPCONFIG_OPENDLY);
 192
 193        end_step++;
 194        config |= STEPCONFIG_INP(ts_dev->inp_yn);
 195        titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
 196        titsc_writel(ts_dev, REG_STEPDELAY(end_step),
 197                        STEPCONFIG_OPENDLY);
 198
 199        /* The steps end ... end - readouts * 2 + 2 and bit 0 for TS_Charge */
 200        stepenable = 1;
 201        for (i = 0; i < tsc_steps; i++)
 202                stepenable |= 1 << (first_step + i + 1);
 203
 204        ts_dev->step_mask = stepenable;
 205        am335x_tsc_se_set_cache(ts_dev->mfd_tscadc, ts_dev->step_mask);
 206}
 207
 208static int titsc_cmp_coord(const void *a, const void *b)
 209{
 210        return *(int *)a - *(int *)b;
 211}
 212
 213static void titsc_read_coordinates(struct titsc *ts_dev,
 214                u32 *x, u32 *y, u32 *z1, u32 *z2)
 215{
 216        unsigned int yvals[7], xvals[7];
 217        unsigned int i, xsum = 0, ysum = 0;
 218        unsigned int creads = ts_dev->coordinate_readouts;
 219
 220        for (i = 0; i < creads; i++) {
 221                yvals[i] = titsc_readl(ts_dev, REG_FIFO0);
 222                yvals[i] &= 0xfff;
 223        }
 224
 225        *z1 = titsc_readl(ts_dev, REG_FIFO0);
 226        *z1 &= 0xfff;
 227        *z2 = titsc_readl(ts_dev, REG_FIFO0);
 228        *z2 &= 0xfff;
 229
 230        for (i = 0; i < creads; i++) {
 231                xvals[i] = titsc_readl(ts_dev, REG_FIFO0);
 232                xvals[i] &= 0xfff;
 233        }
 234
 235        /*
 236         * If co-ordinates readouts is less than 4 then
 237         * report the average. In case of 4 or more
 238         * readouts, sort the co-ordinate samples, drop
 239         * min and max values and report the average of
 240         * remaining values.
 241         */
 242        if (creads <=  3) {
 243                for (i = 0; i < creads; i++) {
 244                        ysum += yvals[i];
 245                        xsum += xvals[i];
 246                }
 247                ysum /= creads;
 248                xsum /= creads;
 249        } else {
 250                sort(yvals, creads, sizeof(unsigned int),
 251                     titsc_cmp_coord, NULL);
 252                sort(xvals, creads, sizeof(unsigned int),
 253                     titsc_cmp_coord, NULL);
 254                for (i = 1; i < creads - 1; i++) {
 255                        ysum += yvals[i];
 256                        xsum += xvals[i];
 257                }
 258                ysum /= creads - 2;
 259                xsum /= creads - 2;
 260        }
 261        *y = ysum;
 262        *x = xsum;
 263}
 264
 265static irqreturn_t titsc_irq(int irq, void *dev)
 266{
 267        struct titsc *ts_dev = dev;
 268        struct input_dev *input_dev = ts_dev->input;
 269        unsigned int fsm, status, irqclr = 0;
 270        unsigned int x = 0, y = 0;
 271        unsigned int z1, z2, z;
 272
 273        status = titsc_readl(ts_dev, REG_RAWIRQSTATUS);
 274        if (status & IRQENB_HW_PEN) {
 275                ts_dev->pen_down = true;
 276                titsc_writel(ts_dev, REG_IRQWAKEUP, 0x00);
 277                titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
 278                irqclr |= IRQENB_HW_PEN;
 279        }
 280
 281        if (status & IRQENB_PENUP) {
 282                fsm = titsc_readl(ts_dev, REG_ADCFSM);
 283                if (fsm == ADCFSM_STEPID) {
 284                        ts_dev->pen_down = false;
 285                        input_report_key(input_dev, BTN_TOUCH, 0);
 286                        input_report_abs(input_dev, ABS_PRESSURE, 0);
 287                        input_sync(input_dev);
 288                } else {
 289                        ts_dev->pen_down = true;
 290                }
 291                irqclr |= IRQENB_PENUP;
 292        }
 293
 294        if (status & IRQENB_EOS)
 295                irqclr |= IRQENB_EOS;
 296
 297        /*
 298         * ADC and touchscreen share the IRQ line.
 299         * FIFO1 interrupts are used by ADC. Handle FIFO0 IRQs here only
 300         */
 301        if (status & IRQENB_FIFO0THRES) {
 302
 303                titsc_read_coordinates(ts_dev, &x, &y, &z1, &z2);
 304
 305                if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
 306                        /*
 307                         * Calculate pressure using formula
 308                         * Resistance(touch) = x plate resistance *
 309                         * x postion/4096 * ((z2 / z1) - 1)
 310                         */
 311                        z = z1 - z2;
 312                        z *= x;
 313                        z *= ts_dev->x_plate_resistance;
 314                        z /= z2;
 315                        z = (z + 2047) >> 12;
 316
 317                        if (z <= MAX_12BIT) {
 318                                input_report_abs(input_dev, ABS_X, x);
 319                                input_report_abs(input_dev, ABS_Y, y);
 320                                input_report_abs(input_dev, ABS_PRESSURE, z);
 321                                input_report_key(input_dev, BTN_TOUCH, 1);
 322                                input_sync(input_dev);
 323                        }
 324                }
 325                irqclr |= IRQENB_FIFO0THRES;
 326        }
 327        if (irqclr) {
 328                titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
 329                if (status & IRQENB_EOS)
 330                        am335x_tsc_se_set_cache(ts_dev->mfd_tscadc,
 331                                                ts_dev->step_mask);
 332                return IRQ_HANDLED;
 333        }
 334        return IRQ_NONE;
 335}
 336
 337static int titsc_parse_dt(struct platform_device *pdev,
 338                                        struct titsc *ts_dev)
 339{
 340        struct device_node *node = pdev->dev.of_node;
 341        int err;
 342
 343        if (!node)
 344                return -EINVAL;
 345
 346        err = of_property_read_u32(node, "ti,wires", &ts_dev->wires);
 347        if (err < 0)
 348                return err;
 349        switch (ts_dev->wires) {
 350        case 4:
 351        case 5:
 352        case 8:
 353                break;
 354        default:
 355                return -EINVAL;
 356        }
 357
 358        err = of_property_read_u32(node, "ti,x-plate-resistance",
 359                        &ts_dev->x_plate_resistance);
 360        if (err < 0)
 361                return err;
 362
 363        /*
 364         * Try with the new binding first. If it fails, try again with
 365         * bogus, miss-spelled version.
 366         */
 367        err = of_property_read_u32(node, "ti,coordinate-readouts",
 368                        &ts_dev->coordinate_readouts);
 369        if (err < 0) {
 370                dev_warn(&pdev->dev, "please use 'ti,coordinate-readouts' instead\n");
 371                err = of_property_read_u32(node, "ti,coordiante-readouts",
 372                                &ts_dev->coordinate_readouts);
 373        }
 374
 375        if (err < 0)
 376                return err;
 377
 378        if (ts_dev->coordinate_readouts <= 0) {
 379                dev_warn(&pdev->dev,
 380                         "invalid co-ordinate readouts, resetting it to 5\n");
 381                ts_dev->coordinate_readouts = 5;
 382        }
 383
 384        err = of_property_read_u32(node, "ti,charge-delay",
 385                                   &ts_dev->charge_delay);
 386        /*
 387         * If ti,charge-delay value is not specified, then use
 388         * CHARGEDLY_OPENDLY as the default value.
 389         */
 390        if (err < 0) {
 391                ts_dev->charge_delay = CHARGEDLY_OPENDLY;
 392                dev_warn(&pdev->dev, "ti,charge-delay not specified\n");
 393        }
 394
 395        return of_property_read_u32_array(node, "ti,wire-config",
 396                        ts_dev->config_inp, ARRAY_SIZE(ts_dev->config_inp));
 397}
 398
 399/*
 400 * The functions for inserting/removing driver as a module.
 401 */
 402
 403static int titsc_probe(struct platform_device *pdev)
 404{
 405        struct titsc *ts_dev;
 406        struct input_dev *input_dev;
 407        struct ti_tscadc_dev *tscadc_dev = ti_tscadc_dev_get(pdev);
 408        int err;
 409
 410        /* Allocate memory for device */
 411        ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
 412        input_dev = input_allocate_device();
 413        if (!ts_dev || !input_dev) {
 414                dev_err(&pdev->dev, "failed to allocate memory.\n");
 415                err = -ENOMEM;
 416                goto err_free_mem;
 417        }
 418
 419        tscadc_dev->tsc = ts_dev;
 420        ts_dev->mfd_tscadc = tscadc_dev;
 421        ts_dev->input = input_dev;
 422        ts_dev->irq = tscadc_dev->irq;
 423
 424        err = titsc_parse_dt(pdev, ts_dev);
 425        if (err) {
 426                dev_err(&pdev->dev, "Could not find valid DT data.\n");
 427                goto err_free_mem;
 428        }
 429
 430        err = request_irq(ts_dev->irq, titsc_irq,
 431                          IRQF_SHARED, pdev->dev.driver->name, ts_dev);
 432        if (err) {
 433                dev_err(&pdev->dev, "failed to allocate irq.\n");
 434                goto err_free_mem;
 435        }
 436
 437        titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
 438        titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_EOS);
 439        err = titsc_config_wires(ts_dev);
 440        if (err) {
 441                dev_err(&pdev->dev, "wrong i/p wire configuration\n");
 442                goto err_free_irq;
 443        }
 444        titsc_step_config(ts_dev);
 445        titsc_writel(ts_dev, REG_FIFO0THR,
 446                        ts_dev->coordinate_readouts * 2 + 2 - 1);
 447
 448        input_dev->name = "ti-tsc";
 449        input_dev->dev.parent = &pdev->dev;
 450
 451        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 452        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 453
 454        input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
 455        input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
 456        input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
 457
 458        /* register to the input system */
 459        err = input_register_device(input_dev);
 460        if (err)
 461                goto err_free_irq;
 462
 463        platform_set_drvdata(pdev, ts_dev);
 464        return 0;
 465
 466err_free_irq:
 467        free_irq(ts_dev->irq, ts_dev);
 468err_free_mem:
 469        input_free_device(input_dev);
 470        kfree(ts_dev);
 471        return err;
 472}
 473
 474static int titsc_remove(struct platform_device *pdev)
 475{
 476        struct titsc *ts_dev = platform_get_drvdata(pdev);
 477        u32 steps;
 478
 479        free_irq(ts_dev->irq, ts_dev);
 480
 481        /* total steps followed by the enable mask */
 482        steps = 2 * ts_dev->coordinate_readouts + 2;
 483        steps = (1 << steps) - 1;
 484        am335x_tsc_se_clr(ts_dev->mfd_tscadc, steps);
 485
 486        input_unregister_device(ts_dev->input);
 487
 488        kfree(ts_dev);
 489        return 0;
 490}
 491
 492#ifdef CONFIG_PM
 493static int titsc_suspend(struct device *dev)
 494{
 495        struct titsc *ts_dev = dev_get_drvdata(dev);
 496        struct ti_tscadc_dev *tscadc_dev;
 497        unsigned int idle;
 498
 499        tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 500        if (device_may_wakeup(tscadc_dev->dev)) {
 501                idle = titsc_readl(ts_dev, REG_IRQENABLE);
 502                titsc_writel(ts_dev, REG_IRQENABLE,
 503                                (idle | IRQENB_HW_PEN));
 504                titsc_writel(ts_dev, REG_IRQWAKEUP, IRQWKUP_ENB);
 505        }
 506        return 0;
 507}
 508
 509static int titsc_resume(struct device *dev)
 510{
 511        struct titsc *ts_dev = dev_get_drvdata(dev);
 512        struct ti_tscadc_dev *tscadc_dev;
 513
 514        tscadc_dev = ti_tscadc_dev_get(to_platform_device(dev));
 515        if (device_may_wakeup(tscadc_dev->dev)) {
 516                titsc_writel(ts_dev, REG_IRQWAKEUP,
 517                                0x00);
 518                titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
 519        }
 520        titsc_step_config(ts_dev);
 521        titsc_writel(ts_dev, REG_FIFO0THR,
 522                        ts_dev->coordinate_readouts * 2 + 2 - 1);
 523        return 0;
 524}
 525
 526static const struct dev_pm_ops titsc_pm_ops = {
 527        .suspend = titsc_suspend,
 528        .resume  = titsc_resume,
 529};
 530#define TITSC_PM_OPS (&titsc_pm_ops)
 531#else
 532#define TITSC_PM_OPS NULL
 533#endif
 534
 535static const struct of_device_id ti_tsc_dt_ids[] = {
 536        { .compatible = "ti,am3359-tsc", },
 537        { }
 538};
 539MODULE_DEVICE_TABLE(of, ti_tsc_dt_ids);
 540
 541static struct platform_driver ti_tsc_driver = {
 542        .probe  = titsc_probe,
 543        .remove = titsc_remove,
 544        .driver = {
 545                .name   = "TI-am335x-tsc",
 546                .pm     = TITSC_PM_OPS,
 547                .of_match_table = ti_tsc_dt_ids,
 548        },
 549};
 550module_platform_driver(ti_tsc_driver);
 551
 552MODULE_DESCRIPTION("TI touchscreen controller driver");
 553MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
 554MODULE_LICENSE("GPL");
 555