root/drivers/input/touchscreen/wm831x-ts.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wm831x_pd_data_work
  2. wm831x_ts_data_irq
  3. wm831x_ts_pen_down_irq
  4. wm831x_ts_input_open
  5. wm831x_ts_input_close
  6. wm831x_ts_probe
  7. wm831x_ts_remove

   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 
  59 struct 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 
  69 static 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 
  83 static 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 
 155 static 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 
 186 static 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 
 202 static 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 
 231 static 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                         /* Fall through */
 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,
 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         disable_irq(wm831x_ts->data_irq);
 328 
 329         if (pdata && pdata->pd_irqf)
 330                 irqf = pdata->pd_irqf;
 331         else
 332                 irqf = IRQF_TRIGGER_HIGH;
 333 
 334         error = request_threaded_irq(wm831x_ts->pd_irq,
 335                                      NULL, wm831x_ts_pen_down_irq,
 336                                      irqf | IRQF_ONESHOT,
 337                                      "Touchscreen pen down", wm831x_ts);
 338         if (error) {
 339                 dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
 340                         wm831x_ts->pd_irq, error);
 341                 goto err_data_irq;
 342         }
 343 
 344         /* set up touch configuration */
 345         input_dev->name = "WM831x touchscreen";
 346         input_dev->phys = "wm831x";
 347         input_dev->open = wm831x_ts_input_open;
 348         input_dev->close = wm831x_ts_input_close;
 349 
 350         __set_bit(EV_ABS, input_dev->evbit);
 351         __set_bit(EV_KEY, input_dev->evbit);
 352         __set_bit(BTN_TOUCH, input_dev->keybit);
 353 
 354         input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
 355         input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
 356         if (wm831x_ts->pressure)
 357                 input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
 358 
 359         input_set_drvdata(input_dev, wm831x_ts);
 360         input_dev->dev.parent = &pdev->dev;
 361 
 362         error = input_register_device(input_dev);
 363         if (error)
 364                 goto err_pd_irq;
 365 
 366         platform_set_drvdata(pdev, wm831x_ts);
 367         return 0;
 368 
 369 err_pd_irq:
 370         free_irq(wm831x_ts->pd_irq, wm831x_ts);
 371 err_data_irq:
 372         free_irq(wm831x_ts->data_irq, wm831x_ts);
 373 err_alloc:
 374 
 375         return error;
 376 }
 377 
 378 static int wm831x_ts_remove(struct platform_device *pdev)
 379 {
 380         struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
 381 
 382         free_irq(wm831x_ts->pd_irq, wm831x_ts);
 383         free_irq(wm831x_ts->data_irq, wm831x_ts);
 384 
 385         return 0;
 386 }
 387 
 388 static struct platform_driver wm831x_ts_driver = {
 389         .driver = {
 390                 .name = "wm831x-touch",
 391         },
 392         .probe = wm831x_ts_probe,
 393         .remove = wm831x_ts_remove,
 394 };
 395 module_platform_driver(wm831x_ts_driver);
 396 
 397 /* Module information */
 398 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 399 MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
 400 MODULE_LICENSE("GPL");
 401 MODULE_ALIAS("platform:wm831x-touch");

/* [<][>][^][v][top][bottom][index][help] */