Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Touchscreen driver for WM831x PMICs
0004  *
0005  * Copyright 2011 Wolfson Microelectronics plc.
0006  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
0007  */
0008 
0009 #include <linux/module.h>
0010 #include <linux/moduleparam.h>
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/pm.h>
0014 #include <linux/input.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/io.h>
0017 #include <linux/mfd/wm831x/core.h>
0018 #include <linux/mfd/wm831x/irq.h>
0019 #include <linux/mfd/wm831x/pdata.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/slab.h>
0022 #include <linux/types.h>
0023 
0024 /*
0025  * R16424 (0x4028) - Touch Control 1
0026  */
0027 #define WM831X_TCH_ENA                          0x8000  /* TCH_ENA */
0028 #define WM831X_TCH_CVT_ENA                      0x4000  /* TCH_CVT_ENA */
0029 #define WM831X_TCH_SLPENA                       0x1000  /* TCH_SLPENA */
0030 #define WM831X_TCH_Z_ENA                        0x0400  /* TCH_Z_ENA */
0031 #define WM831X_TCH_Y_ENA                        0x0200  /* TCH_Y_ENA */
0032 #define WM831X_TCH_X_ENA                        0x0100  /* TCH_X_ENA */
0033 #define WM831X_TCH_DELAY_MASK                   0x00E0  /* TCH_DELAY - [7:5] */
0034 #define WM831X_TCH_DELAY_SHIFT                       5  /* TCH_DELAY - [7:5] */
0035 #define WM831X_TCH_DELAY_WIDTH                       3  /* TCH_DELAY - [7:5] */
0036 #define WM831X_TCH_RATE_MASK                    0x001F  /* TCH_RATE - [4:0] */
0037 #define WM831X_TCH_RATE_SHIFT                        0  /* TCH_RATE - [4:0] */
0038 #define WM831X_TCH_RATE_WIDTH                        5  /* TCH_RATE - [4:0] */
0039 
0040 /*
0041  * R16425 (0x4029) - Touch Control 2
0042  */
0043 #define WM831X_TCH_PD_WK                        0x2000  /* TCH_PD_WK */
0044 #define WM831X_TCH_5WIRE                        0x1000  /* TCH_5WIRE */
0045 #define WM831X_TCH_PDONLY                       0x0800  /* TCH_PDONLY */
0046 #define WM831X_TCH_ISEL                         0x0100  /* TCH_ISEL */
0047 #define WM831X_TCH_RPU_MASK                     0x000F  /* TCH_RPU - [3:0] */
0048 #define WM831X_TCH_RPU_SHIFT                         0  /* TCH_RPU - [3:0] */
0049 #define WM831X_TCH_RPU_WIDTH                         4  /* TCH_RPU - [3:0] */
0050 
0051 /*
0052  * R16426-8 (0x402A-C) - Touch Data X/Y/X
0053  */
0054 #define WM831X_TCH_PD                           0x8000  /* TCH_PD1 */
0055 #define WM831X_TCH_DATA_MASK                    0x0FFF  /* TCH_DATA - [11:0] */
0056 #define WM831X_TCH_DATA_SHIFT                        0  /* TCH_DATA - [11:0] */
0057 #define WM831X_TCH_DATA_WIDTH                       12  /* TCH_DATA - [11:0] */
0058 
0059 struct wm831x_ts {
0060     struct input_dev *input_dev;
0061     struct wm831x *wm831x;
0062     unsigned int data_irq;
0063     unsigned int pd_irq;
0064     bool pressure;
0065     bool pen_down;
0066     struct work_struct pd_data_work;
0067 };
0068 
0069 static void wm831x_pd_data_work(struct work_struct *work)
0070 {
0071     struct wm831x_ts *wm831x_ts =
0072         container_of(work, struct wm831x_ts, pd_data_work);
0073 
0074     if (wm831x_ts->pen_down) {
0075         enable_irq(wm831x_ts->data_irq);
0076         dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
0077     } else {
0078         enable_irq(wm831x_ts->pd_irq);
0079         dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
0080     }
0081 }
0082 
0083 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
0084 {
0085     struct wm831x_ts *wm831x_ts = irq_data;
0086     struct wm831x *wm831x = wm831x_ts->wm831x;
0087     static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE };
0088     u16 data[3];
0089     int count;
0090     int i, ret;
0091 
0092     if (wm831x_ts->pressure)
0093         count = 3;
0094     else
0095         count = 2;
0096 
0097     wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
0098             WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
0099 
0100     ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count,
0101                    data);
0102     if (ret != 0) {
0103         dev_err(wm831x->dev, "Failed to read touch data: %d\n",
0104             ret);
0105         return IRQ_NONE;
0106     }
0107 
0108     /*
0109      * We get a pen down reading on every reading, report pen up if any
0110      * individual reading does so.
0111      */
0112     wm831x_ts->pen_down = true;
0113     for (i = 0; i < count; i++) {
0114         if (!(data[i] & WM831X_TCH_PD)) {
0115             wm831x_ts->pen_down = false;
0116             continue;
0117         }
0118         input_report_abs(wm831x_ts->input_dev, data_types[i],
0119                  data[i] & WM831X_TCH_DATA_MASK);
0120     }
0121 
0122     if (!wm831x_ts->pen_down) {
0123         /* Switch from data to pen down */
0124         dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
0125 
0126         disable_irq_nosync(wm831x_ts->data_irq);
0127 
0128         /* Don't need data any more */
0129         wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0130                 WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
0131                 WM831X_TCH_Z_ENA, 0);
0132 
0133         /* Flush any final samples that arrived while reading */
0134         wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
0135                 WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
0136 
0137         wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data);
0138 
0139         if (wm831x_ts->pressure)
0140             input_report_abs(wm831x_ts->input_dev,
0141                      ABS_PRESSURE, 0);
0142 
0143         input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
0144 
0145         schedule_work(&wm831x_ts->pd_data_work);
0146     } else {
0147         input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
0148     }
0149 
0150     input_sync(wm831x_ts->input_dev);
0151 
0152     return IRQ_HANDLED;
0153 }
0154 
0155 static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
0156 {
0157     struct wm831x_ts *wm831x_ts = irq_data;
0158     struct wm831x *wm831x = wm831x_ts->wm831x;
0159     int ena = 0;
0160 
0161     if (wm831x_ts->pen_down)
0162         return IRQ_HANDLED;
0163 
0164     disable_irq_nosync(wm831x_ts->pd_irq);
0165 
0166     /* Start collecting data */
0167     if (wm831x_ts->pressure)
0168         ena |= WM831X_TCH_Z_ENA;
0169 
0170     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0171             WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
0172             WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
0173 
0174     wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
0175             WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
0176 
0177     wm831x_ts->pen_down = true;
0178 
0179     /* Switch from pen down to data */
0180     dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
0181     schedule_work(&wm831x_ts->pd_data_work);
0182 
0183     return IRQ_HANDLED;
0184 }
0185 
0186 static int wm831x_ts_input_open(struct input_dev *idev)
0187 {
0188     struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
0189     struct wm831x *wm831x = wm831x_ts->wm831x;
0190 
0191     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0192             WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
0193             WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
0194             WM831X_TCH_Z_ENA, WM831X_TCH_ENA);
0195 
0196     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0197             WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA);
0198 
0199     return 0;
0200 }
0201 
0202 static void wm831x_ts_input_close(struct input_dev *idev)
0203 {
0204     struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
0205     struct wm831x *wm831x = wm831x_ts->wm831x;
0206 
0207     /* Shut the controller down, disabling all other functionality too */
0208     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0209             WM831X_TCH_ENA | WM831X_TCH_X_ENA |
0210             WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
0211 
0212     /* Make sure any pending IRQs are done, the above will prevent
0213      * new ones firing.
0214      */
0215     synchronize_irq(wm831x_ts->data_irq);
0216     synchronize_irq(wm831x_ts->pd_irq);
0217 
0218     /* Make sure the IRQ completion work is quiesced */
0219     flush_work(&wm831x_ts->pd_data_work);
0220 
0221     /* If we ended up with the pen down then make sure we revert back
0222      * to pen detection state for the next time we start up.
0223      */
0224     if (wm831x_ts->pen_down) {
0225         disable_irq(wm831x_ts->data_irq);
0226         enable_irq(wm831x_ts->pd_irq);
0227         wm831x_ts->pen_down = false;
0228     }
0229 }
0230 
0231 static int wm831x_ts_probe(struct platform_device *pdev)
0232 {
0233     struct wm831x_ts *wm831x_ts;
0234     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
0235     struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
0236     struct wm831x_touch_pdata *pdata = NULL;
0237     struct input_dev *input_dev;
0238     int error, irqf;
0239 
0240     if (core_pdata)
0241         pdata = core_pdata->touch;
0242 
0243     wm831x_ts = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_ts),
0244                  GFP_KERNEL);
0245     input_dev = devm_input_allocate_device(&pdev->dev);
0246     if (!wm831x_ts || !input_dev) {
0247         error = -ENOMEM;
0248         goto err_alloc;
0249     }
0250 
0251     wm831x_ts->wm831x = wm831x;
0252     wm831x_ts->input_dev = input_dev;
0253     INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
0254 
0255     /*
0256      * If we have a direct IRQ use it, otherwise use the interrupt
0257      * from the WM831x IRQ controller.
0258      */
0259     wm831x_ts->data_irq = wm831x_irq(wm831x,
0260                      platform_get_irq_byname(pdev,
0261                                  "TCHDATA"));
0262     if (pdata && pdata->data_irq)
0263         wm831x_ts->data_irq = pdata->data_irq;
0264 
0265     wm831x_ts->pd_irq = wm831x_irq(wm831x,
0266                        platform_get_irq_byname(pdev, "TCHPD"));
0267     if (pdata && pdata->pd_irq)
0268         wm831x_ts->pd_irq = pdata->pd_irq;
0269 
0270     if (pdata)
0271         wm831x_ts->pressure = pdata->pressure;
0272     else
0273         wm831x_ts->pressure = true;
0274 
0275     /* Five wire touchscreens can't report pressure */
0276     if (pdata && pdata->fivewire) {
0277         wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
0278                 WM831X_TCH_5WIRE, WM831X_TCH_5WIRE);
0279 
0280         /* Pressure measurements are not possible for five wire mode */
0281         WARN_ON(pdata->pressure && pdata->fivewire);
0282         wm831x_ts->pressure = false;
0283     } else {
0284         wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
0285                 WM831X_TCH_5WIRE, 0);
0286     }
0287 
0288     if (pdata) {
0289         switch (pdata->isel) {
0290         default:
0291             dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n",
0292                 pdata->isel);
0293             fallthrough;
0294         case 200:
0295         case 0:
0296             wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
0297                     WM831X_TCH_ISEL, 0);
0298             break;
0299         case 400:
0300             wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
0301                     WM831X_TCH_ISEL, WM831X_TCH_ISEL);
0302             break;
0303         }
0304     }
0305 
0306     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
0307             WM831X_TCH_PDONLY, 0);
0308 
0309     /* Default to 96 samples/sec */
0310     wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
0311             WM831X_TCH_RATE_MASK, 6);
0312 
0313     if (pdata && pdata->data_irqf)
0314         irqf = pdata->data_irqf;
0315     else
0316         irqf = IRQF_TRIGGER_HIGH;
0317 
0318     error = request_threaded_irq(wm831x_ts->data_irq,
0319                      NULL, wm831x_ts_data_irq,
0320                      irqf | IRQF_ONESHOT | IRQF_NO_AUTOEN,
0321                      "Touchscreen data", wm831x_ts);
0322     if (error) {
0323         dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
0324             wm831x_ts->data_irq, error);
0325         goto err_alloc;
0326     }
0327 
0328     if (pdata && pdata->pd_irqf)
0329         irqf = pdata->pd_irqf;
0330     else
0331         irqf = IRQF_TRIGGER_HIGH;
0332 
0333     error = request_threaded_irq(wm831x_ts->pd_irq,
0334                      NULL, wm831x_ts_pen_down_irq,
0335                      irqf | IRQF_ONESHOT,
0336                      "Touchscreen pen down", wm831x_ts);
0337     if (error) {
0338         dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
0339             wm831x_ts->pd_irq, error);
0340         goto err_data_irq;
0341     }
0342 
0343     /* set up touch configuration */
0344     input_dev->name = "WM831x touchscreen";
0345     input_dev->phys = "wm831x";
0346     input_dev->open = wm831x_ts_input_open;
0347     input_dev->close = wm831x_ts_input_close;
0348 
0349     __set_bit(EV_ABS, input_dev->evbit);
0350     __set_bit(EV_KEY, input_dev->evbit);
0351     __set_bit(BTN_TOUCH, input_dev->keybit);
0352 
0353     input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
0354     input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
0355     if (wm831x_ts->pressure)
0356         input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
0357 
0358     input_set_drvdata(input_dev, wm831x_ts);
0359     input_dev->dev.parent = &pdev->dev;
0360 
0361     error = input_register_device(input_dev);
0362     if (error)
0363         goto err_pd_irq;
0364 
0365     platform_set_drvdata(pdev, wm831x_ts);
0366     return 0;
0367 
0368 err_pd_irq:
0369     free_irq(wm831x_ts->pd_irq, wm831x_ts);
0370 err_data_irq:
0371     free_irq(wm831x_ts->data_irq, wm831x_ts);
0372 err_alloc:
0373 
0374     return error;
0375 }
0376 
0377 static int wm831x_ts_remove(struct platform_device *pdev)
0378 {
0379     struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
0380 
0381     free_irq(wm831x_ts->pd_irq, wm831x_ts);
0382     free_irq(wm831x_ts->data_irq, wm831x_ts);
0383 
0384     return 0;
0385 }
0386 
0387 static struct platform_driver wm831x_ts_driver = {
0388     .driver = {
0389         .name = "wm831x-touch",
0390     },
0391     .probe = wm831x_ts_probe,
0392     .remove = wm831x_ts_remove,
0393 };
0394 module_platform_driver(wm831x_ts_driver);
0395 
0396 /* Module information */
0397 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
0398 MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
0399 MODULE_LICENSE("GPL");
0400 MODULE_ALIAS("platform:wm831x-touch");