linux/drivers/input/touchscreen/wm831x-ts.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Touchscreen driver for WM831x PMICs
   4 *
   5 * Copyright 2011 Wolfson Microelectronics plc.
   6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
   7 */
   8
   9#include <linux/module.h>
  10#include <linux/moduleparam.h>
  11#include <linux/kernel.h>
  12#include <linux/string.h>
  13#include <linux/pm.h>
  14#include <linux/input.h>
  15#include <linux/interrupt.h>
  16#include <linux/io.h>
  17#include <linux/mfd/wm831x/core.h>
  18#include <linux/mfd/wm831x/irq.h>
  19#include <linux/mfd/wm831x/pdata.h>
  20#include <linux/platform_device.h>
  21#include <linux/slab.h>
  22#include <linux/types.h>
  23
  24/*
  25 * R16424 (0x4028) - Touch Control 1
  26 */
  27#define WM831X_TCH_ENA                          0x8000  /* TCH_ENA */
  28#define WM831X_TCH_CVT_ENA                      0x4000  /* TCH_CVT_ENA */
  29#define WM831X_TCH_SLPENA                       0x1000  /* TCH_SLPENA */
  30#define WM831X_TCH_Z_ENA                        0x0400  /* TCH_Z_ENA */
  31#define WM831X_TCH_Y_ENA                        0x0200  /* TCH_Y_ENA */
  32#define WM831X_TCH_X_ENA                        0x0100  /* TCH_X_ENA */
  33#define WM831X_TCH_DELAY_MASK                   0x00E0  /* TCH_DELAY - [7:5] */
  34#define WM831X_TCH_DELAY_SHIFT                       5  /* TCH_DELAY - [7:5] */
  35#define WM831X_TCH_DELAY_WIDTH                       3  /* TCH_DELAY - [7:5] */
  36#define WM831X_TCH_RATE_MASK                    0x001F  /* TCH_RATE - [4:0] */
  37#define WM831X_TCH_RATE_SHIFT                        0  /* TCH_RATE - [4:0] */
  38#define WM831X_TCH_RATE_WIDTH                        5  /* TCH_RATE - [4:0] */
  39
  40/*
  41 * R16425 (0x4029) - Touch Control 2
  42 */
  43#define WM831X_TCH_PD_WK                        0x2000  /* TCH_PD_WK */
  44#define WM831X_TCH_5WIRE                        0x1000  /* TCH_5WIRE */
  45#define WM831X_TCH_PDONLY                       0x0800  /* TCH_PDONLY */
  46#define WM831X_TCH_ISEL                         0x0100  /* TCH_ISEL */
  47#define WM831X_TCH_RPU_MASK                     0x000F  /* TCH_RPU - [3:0] */
  48#define WM831X_TCH_RPU_SHIFT                         0  /* TCH_RPU - [3:0] */
  49#define WM831X_TCH_RPU_WIDTH                         4  /* TCH_RPU - [3:0] */
  50
  51/*
  52 * R16426-8 (0x402A-C) - Touch Data X/Y/X
  53 */
  54#define WM831X_TCH_PD                           0x8000  /* TCH_PD1 */
  55#define WM831X_TCH_DATA_MASK                    0x0FFF  /* TCH_DATA - [11:0] */
  56#define WM831X_TCH_DATA_SHIFT                        0  /* TCH_DATA - [11:0] */
  57#define WM831X_TCH_DATA_WIDTH                       12  /* TCH_DATA - [11:0] */
  58
  59struct wm831x_ts {
  60        struct input_dev *input_dev;
  61        struct wm831x *wm831x;
  62        unsigned int data_irq;
  63        unsigned int pd_irq;
  64        bool pressure;
  65        bool pen_down;
  66        struct work_struct pd_data_work;
  67};
  68
  69static void wm831x_pd_data_work(struct work_struct *work)
  70{
  71        struct wm831x_ts *wm831x_ts =
  72                container_of(work, struct wm831x_ts, pd_data_work);
  73
  74        if (wm831x_ts->pen_down) {
  75                enable_irq(wm831x_ts->data_irq);
  76                dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
  77        } else {
  78                enable_irq(wm831x_ts->pd_irq);
  79                dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
  80        }
  81}
  82
  83static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
  84{
  85        struct wm831x_ts *wm831x_ts = irq_data;
  86        struct wm831x *wm831x = wm831x_ts->wm831x;
  87        static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE };
  88        u16 data[3];
  89        int count;
  90        int i, ret;
  91
  92        if (wm831x_ts->pressure)
  93                count = 3;
  94        else
  95                count = 2;
  96
  97        wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
  98                        WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
  99
 100        ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count,
 101                               data);
 102        if (ret != 0) {
 103                dev_err(wm831x->dev, "Failed to read touch data: %d\n",
 104                        ret);
 105                return IRQ_NONE;
 106        }
 107
 108        /*
 109         * We get a pen down reading on every reading, report pen up if any
 110         * individual reading does so.
 111         */
 112        wm831x_ts->pen_down = true;
 113        for (i = 0; i < count; i++) {
 114                if (!(data[i] & WM831X_TCH_PD)) {
 115                        wm831x_ts->pen_down = false;
 116                        continue;
 117                }
 118                input_report_abs(wm831x_ts->input_dev, data_types[i],
 119                                 data[i] & WM831X_TCH_DATA_MASK);
 120        }
 121
 122        if (!wm831x_ts->pen_down) {
 123                /* Switch from data to pen down */
 124                dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
 125
 126                disable_irq_nosync(wm831x_ts->data_irq);
 127
 128                /* Don't need data any more */
 129                wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 130                                WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
 131                                WM831X_TCH_Z_ENA, 0);
 132
 133                /* Flush any final samples that arrived while reading */
 134                wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
 135                                WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
 136
 137                wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data);
 138
 139                if (wm831x_ts->pressure)
 140                        input_report_abs(wm831x_ts->input_dev,
 141                                         ABS_PRESSURE, 0);
 142
 143                input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
 144
 145                schedule_work(&wm831x_ts->pd_data_work);
 146        } else {
 147                input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
 148        }
 149
 150        input_sync(wm831x_ts->input_dev);
 151
 152        return IRQ_HANDLED;
 153}
 154
 155static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
 156{
 157        struct wm831x_ts *wm831x_ts = irq_data;
 158        struct wm831x *wm831x = wm831x_ts->wm831x;
 159        int ena = 0;
 160
 161        if (wm831x_ts->pen_down)
 162                return IRQ_HANDLED;
 163
 164        disable_irq_nosync(wm831x_ts->pd_irq);
 165
 166        /* Start collecting data */
 167        if (wm831x_ts->pressure)
 168                ena |= WM831X_TCH_Z_ENA;
 169
 170        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 171                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
 172                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
 173
 174        wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
 175                        WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
 176
 177        wm831x_ts->pen_down = true;
 178
 179        /* Switch from pen down to data */
 180        dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
 181        schedule_work(&wm831x_ts->pd_data_work);
 182
 183        return IRQ_HANDLED;
 184}
 185
 186static int wm831x_ts_input_open(struct input_dev *idev)
 187{
 188        struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
 189        struct wm831x *wm831x = wm831x_ts->wm831x;
 190
 191        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 192                        WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
 193                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
 194                        WM831X_TCH_Z_ENA, WM831X_TCH_ENA);
 195
 196        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 197                        WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA);
 198
 199        return 0;
 200}
 201
 202static void wm831x_ts_input_close(struct input_dev *idev)
 203{
 204        struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
 205        struct wm831x *wm831x = wm831x_ts->wm831x;
 206
 207        /* Shut the controller down, disabling all other functionality too */
 208        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 209                        WM831X_TCH_ENA | WM831X_TCH_X_ENA |
 210                        WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
 211
 212        /* Make sure any pending IRQs are done, the above will prevent
 213         * new ones firing.
 214         */
 215        synchronize_irq(wm831x_ts->data_irq);
 216        synchronize_irq(wm831x_ts->pd_irq);
 217
 218        /* Make sure the IRQ completion work is quiesced */
 219        flush_work(&wm831x_ts->pd_data_work);
 220
 221        /* If we ended up with the pen down then make sure we revert back
 222         * to pen detection state for the next time we start up.
 223         */
 224        if (wm831x_ts->pen_down) {
 225                disable_irq(wm831x_ts->data_irq);
 226                enable_irq(wm831x_ts->pd_irq);
 227                wm831x_ts->pen_down = false;
 228        }
 229}
 230
 231static int wm831x_ts_probe(struct platform_device *pdev)
 232{
 233        struct wm831x_ts *wm831x_ts;
 234        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
 235        struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
 236        struct wm831x_touch_pdata *pdata = NULL;
 237        struct input_dev *input_dev;
 238        int error, irqf;
 239
 240        if (core_pdata)
 241                pdata = core_pdata->touch;
 242
 243        wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts),
 244                                 GFP_KERNEL);
 245        input_dev = devm_input_allocate_device(&pdev->dev);
 246        if (!wm831x_ts || !input_dev) {
 247                error = -ENOMEM;
 248                goto err_alloc;
 249        }
 250
 251        wm831x_ts->wm831x = wm831x;
 252        wm831x_ts->input_dev = input_dev;
 253        INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
 254
 255        /*
 256         * If we have a direct IRQ use it, otherwise use the interrupt
 257         * from the WM831x IRQ controller.
 258         */
 259        wm831x_ts->data_irq = wm831x_irq(wm831x,
 260                                         platform_get_irq_byname(pdev,
 261                                                                 "TCHDATA"));
 262        if (pdata && pdata->data_irq)
 263                wm831x_ts->data_irq = pdata->data_irq;
 264
 265        wm831x_ts->pd_irq = wm831x_irq(wm831x,
 266                                       platform_get_irq_byname(pdev, "TCHPD"));
 267        if (pdata && pdata->pd_irq)
 268                wm831x_ts->pd_irq = pdata->pd_irq;
 269
 270        if (pdata)
 271                wm831x_ts->pressure = pdata->pressure;
 272        else
 273                wm831x_ts->pressure = true;
 274
 275        /* Five wire touchscreens can't report pressure */
 276        if (pdata && pdata->fivewire) {
 277                wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
 278                                WM831X_TCH_5WIRE, WM831X_TCH_5WIRE);
 279
 280                /* Pressure measurements are not possible for five wire mode */
 281                WARN_ON(pdata->pressure && pdata->fivewire);
 282                wm831x_ts->pressure = false;
 283        } else {
 284                wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
 285                                WM831X_TCH_5WIRE, 0);
 286        }
 287
 288        if (pdata) {
 289                switch (pdata->isel) {
 290                default:
 291                        dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n",
 292                                pdata->isel);
 293                        fallthrough;
 294                case 200:
 295                case 0:
 296                        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
 297                                        WM831X_TCH_ISEL, 0);
 298                        break;
 299                case 400:
 300                        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
 301                                        WM831X_TCH_ISEL, WM831X_TCH_ISEL);
 302                        break;
 303                }
 304        }
 305
 306        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
 307                        WM831X_TCH_PDONLY, 0);
 308
 309        /* Default to 96 samples/sec */
 310        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
 311                        WM831X_TCH_RATE_MASK, 6);
 312
 313        if (pdata && pdata->data_irqf)
 314                irqf = pdata->data_irqf;
 315        else
 316                irqf = IRQF_TRIGGER_HIGH;
 317
 318        error = request_threaded_irq(wm831x_ts->data_irq,
 319                                     NULL, wm831x_ts_data_irq,
 320                                     irqf | IRQF_ONESHOT | IRQF_NO_AUTOEN,
 321                                     "Touchscreen data", wm831x_ts);
 322        if (error) {
 323                dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
 324                        wm831x_ts->data_irq, error);
 325                goto err_alloc;
 326        }
 327
 328        if (pdata && pdata->pd_irqf)
 329                irqf = pdata->pd_irqf;
 330        else
 331                irqf = IRQF_TRIGGER_HIGH;
 332
 333        error = request_threaded_irq(wm831x_ts->pd_irq,
 334                                     NULL, wm831x_ts_pen_down_irq,
 335                                     irqf | IRQF_ONESHOT,
 336                                     "Touchscreen pen down", wm831x_ts);
 337        if (error) {
 338                dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
 339                        wm831x_ts->pd_irq, error);
 340                goto err_data_irq;
 341        }
 342
 343        /* set up touch configuration */
 344        input_dev->name = "WM831x touchscreen";
 345        input_dev->phys = "wm831x";
 346        input_dev->open = wm831x_ts_input_open;
 347        input_dev->close = wm831x_ts_input_close;
 348
 349        __set_bit(EV_ABS, input_dev->evbit);
 350        __set_bit(EV_KEY, input_dev->evbit);
 351        __set_bit(BTN_TOUCH, input_dev->keybit);
 352
 353        input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
 354        input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
 355        if (wm831x_ts->pressure)
 356                input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
 357
 358        input_set_drvdata(input_dev, wm831x_ts);
 359        input_dev->dev.parent = &pdev->dev;
 360
 361        error = input_register_device(input_dev);
 362        if (error)
 363                goto err_pd_irq;
 364
 365        platform_set_drvdata(pdev, wm831x_ts);
 366        return 0;
 367
 368err_pd_irq:
 369        free_irq(wm831x_ts->pd_irq, wm831x_ts);
 370err_data_irq:
 371        free_irq(wm831x_ts->data_irq, wm831x_ts);
 372err_alloc:
 373
 374        return error;
 375}
 376
 377static int wm831x_ts_remove(struct platform_device *pdev)
 378{
 379        struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
 380
 381        free_irq(wm831x_ts->pd_irq, wm831x_ts);
 382        free_irq(wm831x_ts->data_irq, wm831x_ts);
 383
 384        return 0;
 385}
 386
 387static struct platform_driver wm831x_ts_driver = {
 388        .driver = {
 389                .name = "wm831x-touch",
 390        },
 391        .probe = wm831x_ts_probe,
 392        .remove = wm831x_ts_remove,
 393};
 394module_platform_driver(wm831x_ts_driver);
 395
 396/* Module information */
 397MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 398MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
 399MODULE_LICENSE("GPL");
 400MODULE_ALIAS("platform:wm831x-touch");
 401