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

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

DEFINITIONS

This source file includes following definitions.
  1. __stmpe_reset_fifo
  2. stmpe_work
  3. stmpe_ts_handler
  4. stmpe_init_hw
  5. stmpe_ts_open
  6. stmpe_ts_close
  7. stmpe_ts_get_platform_info
  8. stmpe_input_probe
  9. stmpe_ts_remove

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * STMicroelectronics STMPE811 Touchscreen Driver
   4  *
   5  * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
   6  * All rights reserved.
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/module.h>
  11 #include <linux/sched.h>
  12 #include <linux/interrupt.h>
  13 #include <linux/device.h>
  14 #include <linux/of.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/input.h>
  17 #include <linux/slab.h>
  18 #include <linux/delay.h>
  19 #include <linux/i2c.h>
  20 #include <linux/workqueue.h>
  21 
  22 #include <linux/mfd/stmpe.h>
  23 
  24 /* Register layouts and functionalities are identical on all stmpexxx variants
  25  * with touchscreen controller
  26  */
  27 #define STMPE_REG_INT_STA               0x0B
  28 #define STMPE_REG_TSC_CTRL              0x40
  29 #define STMPE_REG_TSC_CFG               0x41
  30 #define STMPE_REG_FIFO_TH               0x4A
  31 #define STMPE_REG_FIFO_STA              0x4B
  32 #define STMPE_REG_FIFO_SIZE             0x4C
  33 #define STMPE_REG_TSC_DATA_XYZ          0x52
  34 #define STMPE_REG_TSC_FRACTION_Z        0x56
  35 #define STMPE_REG_TSC_I_DRIVE           0x58
  36 
  37 #define OP_MOD_XYZ                      0
  38 
  39 #define STMPE_TSC_CTRL_TSC_EN           (1<<0)
  40 
  41 #define STMPE_FIFO_STA_RESET            (1<<0)
  42 
  43 #define STMPE_IRQ_TOUCH_DET             0
  44 
  45 #define STMPE_TS_NAME                   "stmpe-ts"
  46 #define XY_MASK                         0xfff
  47 
  48 /**
  49  * struct stmpe_touch - stmpe811 touch screen controller state
  50  * @stmpe: pointer back to STMPE MFD container
  51  * @idev: registered input device
  52  * @work: a work item used to scan the device
  53  * @dev: a pointer back to the MFD cell struct device*
  54  * @ave_ctrl: Sample average control
  55  * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
  56  * @touch_det_delay: Touch detect interrupt delay
  57  * (0 -> 10 us, 1 -> 50 us, 2 -> 100 us, 3 -> 500 us,
  58  * 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms)
  59  * recommended is 3
  60  * @settling: Panel driver settling time
  61  * (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 -> 1 ms,
  62  * 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms)
  63  * recommended is 2
  64  * @fraction_z: Length of the fractional part in z
  65  * (fraction_z ([0..7]) = Count of the fractional part)
  66  * recommended is 7
  67  * @i_drive: current limit value of the touchscreen drivers
  68  * (0 -> 20 mA typical 35 mA max, 1 -> 50 mA typical 80 mA max)
  69  */
  70 struct stmpe_touch {
  71         struct stmpe *stmpe;
  72         struct input_dev *idev;
  73         struct delayed_work work;
  74         struct device *dev;
  75         u8 ave_ctrl;
  76         u8 touch_det_delay;
  77         u8 settling;
  78         u8 fraction_z;
  79         u8 i_drive;
  80 };
  81 
  82 static int __stmpe_reset_fifo(struct stmpe *stmpe)
  83 {
  84         int ret;
  85 
  86         ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
  87                         STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
  88         if (ret)
  89                 return ret;
  90 
  91         return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
  92                         STMPE_FIFO_STA_RESET, 0);
  93 }
  94 
  95 static void stmpe_work(struct work_struct *work)
  96 {
  97         int int_sta;
  98         u32 timeout = 40;
  99 
 100         struct stmpe_touch *ts =
 101             container_of(work, struct stmpe_touch, work.work);
 102 
 103         int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
 104 
 105         /*
 106          * touch_det sometimes get desasserted or just get stuck. This appears
 107          * to be a silicon bug, We still have to clearify this with the
 108          * manufacture. As a workaround We release the key anyway if the
 109          * touch_det keeps coming in after 4ms, while the FIFO contains no value
 110          * during the whole time.
 111          */
 112         while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
 113                 timeout--;
 114                 int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
 115                 udelay(100);
 116         }
 117 
 118         /* reset the FIFO before we report release event */
 119         __stmpe_reset_fifo(ts->stmpe);
 120 
 121         input_report_abs(ts->idev, ABS_PRESSURE, 0);
 122         input_report_key(ts->idev, BTN_TOUCH, 0);
 123         input_sync(ts->idev);
 124 }
 125 
 126 static irqreturn_t stmpe_ts_handler(int irq, void *data)
 127 {
 128         u8 data_set[4];
 129         int x, y, z;
 130         struct stmpe_touch *ts = data;
 131 
 132         /*
 133          * Cancel scheduled polling for release if we have new value
 134          * available. Wait if the polling is already running.
 135          */
 136         cancel_delayed_work_sync(&ts->work);
 137 
 138         /*
 139          * The FIFO sometimes just crashes and stops generating interrupts. This
 140          * appears to be a silicon bug. We still have to clearify this with
 141          * the manufacture. As a workaround we disable the TSC while we are
 142          * collecting data and flush the FIFO after reading
 143          */
 144         stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
 145                                 STMPE_TSC_CTRL_TSC_EN, 0);
 146 
 147         stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
 148 
 149         x = (data_set[0] << 4) | (data_set[1] >> 4);
 150         y = ((data_set[1] & 0xf) << 8) | data_set[2];
 151         z = data_set[3];
 152 
 153         input_report_abs(ts->idev, ABS_X, x);
 154         input_report_abs(ts->idev, ABS_Y, y);
 155         input_report_abs(ts->idev, ABS_PRESSURE, z);
 156         input_report_key(ts->idev, BTN_TOUCH, 1);
 157         input_sync(ts->idev);
 158 
 159        /* flush the FIFO after we have read out our values. */
 160         __stmpe_reset_fifo(ts->stmpe);
 161 
 162         /* reenable the tsc */
 163         stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
 164                         STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
 165 
 166         /* start polling for touch_det to detect release */
 167         schedule_delayed_work(&ts->work, msecs_to_jiffies(50));
 168 
 169         return IRQ_HANDLED;
 170 }
 171 
 172 static int stmpe_init_hw(struct stmpe_touch *ts)
 173 {
 174         int ret;
 175         u8 tsc_cfg, tsc_cfg_mask;
 176         struct stmpe *stmpe = ts->stmpe;
 177         struct device *dev = ts->dev;
 178 
 179         ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
 180         if (ret) {
 181                 dev_err(dev, "Could not enable clock for ADC and TS\n");
 182                 return ret;
 183         }
 184 
 185         ret = stmpe811_adc_common_init(stmpe);
 186         if (ret) {
 187                 stmpe_disable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
 188                 return ret;
 189         }
 190 
 191         tsc_cfg = STMPE_AVE_CTRL(ts->ave_ctrl) |
 192                   STMPE_DET_DELAY(ts->touch_det_delay) |
 193                   STMPE_SETTLING(ts->settling);
 194         tsc_cfg_mask = STMPE_AVE_CTRL(0xff) | STMPE_DET_DELAY(0xff) |
 195                        STMPE_SETTLING(0xff);
 196 
 197         ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
 198         if (ret) {
 199                 dev_err(dev, "Could not config touch\n");
 200                 return ret;
 201         }
 202 
 203         ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
 204                         STMPE_FRACTION_Z(0xff), STMPE_FRACTION_Z(ts->fraction_z));
 205         if (ret) {
 206                 dev_err(dev, "Could not config touch\n");
 207                 return ret;
 208         }
 209 
 210         ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
 211                         STMPE_I_DRIVE(0xff), STMPE_I_DRIVE(ts->i_drive));
 212         if (ret) {
 213                 dev_err(dev, "Could not config touch\n");
 214                 return ret;
 215         }
 216 
 217         /* set FIFO to 1 for single point reading */
 218         ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
 219         if (ret) {
 220                 dev_err(dev, "Could not set FIFO\n");
 221                 return ret;
 222         }
 223 
 224         ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
 225                         STMPE_OP_MODE(0xff), STMPE_OP_MODE(OP_MOD_XYZ));
 226         if (ret) {
 227                 dev_err(dev, "Could not set mode\n");
 228                 return ret;
 229         }
 230 
 231         return 0;
 232 }
 233 
 234 static int stmpe_ts_open(struct input_dev *dev)
 235 {
 236         struct stmpe_touch *ts = input_get_drvdata(dev);
 237         int ret = 0;
 238 
 239         ret = __stmpe_reset_fifo(ts->stmpe);
 240         if (ret)
 241                 return ret;
 242 
 243         return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
 244                         STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
 245 }
 246 
 247 static void stmpe_ts_close(struct input_dev *dev)
 248 {
 249         struct stmpe_touch *ts = input_get_drvdata(dev);
 250 
 251         cancel_delayed_work_sync(&ts->work);
 252 
 253         stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
 254                         STMPE_TSC_CTRL_TSC_EN, 0);
 255 }
 256 
 257 static void stmpe_ts_get_platform_info(struct platform_device *pdev,
 258                                         struct stmpe_touch *ts)
 259 {
 260         struct device_node *np = pdev->dev.of_node;
 261         u32 val;
 262 
 263         if (np) {
 264                 if (!of_property_read_u32(np, "st,sample-time", &val))
 265                         ts->stmpe->sample_time = val;
 266                 if (!of_property_read_u32(np, "st,mod-12b", &val))
 267                         ts->stmpe->mod_12b = val;
 268                 if (!of_property_read_u32(np, "st,ref-sel", &val))
 269                         ts->stmpe->ref_sel = val;
 270                 if (!of_property_read_u32(np, "st,adc-freq", &val))
 271                         ts->stmpe->adc_freq = val;
 272                 if (!of_property_read_u32(np, "st,ave-ctrl", &val))
 273                         ts->ave_ctrl = val;
 274                 if (!of_property_read_u32(np, "st,touch-det-delay", &val))
 275                         ts->touch_det_delay = val;
 276                 if (!of_property_read_u32(np, "st,settling", &val))
 277                         ts->settling = val;
 278                 if (!of_property_read_u32(np, "st,fraction-z", &val))
 279                         ts->fraction_z = val;
 280                 if (!of_property_read_u32(np, "st,i-drive", &val))
 281                         ts->i_drive = val;
 282         }
 283 }
 284 
 285 static int stmpe_input_probe(struct platform_device *pdev)
 286 {
 287         struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
 288         struct stmpe_touch *ts;
 289         struct input_dev *idev;
 290         int error;
 291         int ts_irq;
 292 
 293         ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
 294         if (ts_irq < 0)
 295                 return ts_irq;
 296 
 297         ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
 298         if (!ts)
 299                 return -ENOMEM;
 300 
 301         idev = devm_input_allocate_device(&pdev->dev);
 302         if (!idev)
 303                 return -ENOMEM;
 304 
 305         platform_set_drvdata(pdev, ts);
 306         ts->stmpe = stmpe;
 307         ts->idev = idev;
 308         ts->dev = &pdev->dev;
 309 
 310         stmpe_ts_get_platform_info(pdev, ts);
 311 
 312         INIT_DELAYED_WORK(&ts->work, stmpe_work);
 313 
 314         error = devm_request_threaded_irq(&pdev->dev, ts_irq,
 315                                           NULL, stmpe_ts_handler,
 316                                           IRQF_ONESHOT, STMPE_TS_NAME, ts);
 317         if (error) {
 318                 dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
 319                 return error;
 320         }
 321 
 322         error = stmpe_init_hw(ts);
 323         if (error)
 324                 return error;
 325 
 326         idev->name = STMPE_TS_NAME;
 327         idev->phys = STMPE_TS_NAME"/input0";
 328         idev->id.bustype = BUS_I2C;
 329 
 330         idev->open = stmpe_ts_open;
 331         idev->close = stmpe_ts_close;
 332 
 333         input_set_drvdata(idev, ts);
 334 
 335         input_set_capability(idev, EV_KEY, BTN_TOUCH);
 336         input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
 337         input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
 338         input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
 339 
 340         error = input_register_device(idev);
 341         if (error) {
 342                 dev_err(&pdev->dev, "Could not register input device\n");
 343                 return error;
 344         }
 345 
 346         return 0;
 347 }
 348 
 349 static int stmpe_ts_remove(struct platform_device *pdev)
 350 {
 351         struct stmpe_touch *ts = platform_get_drvdata(pdev);
 352 
 353         stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
 354 
 355         return 0;
 356 }
 357 
 358 static struct platform_driver stmpe_ts_driver = {
 359         .driver = {
 360                 .name = STMPE_TS_NAME,
 361         },
 362         .probe = stmpe_input_probe,
 363         .remove = stmpe_ts_remove,
 364 };
 365 module_platform_driver(stmpe_ts_driver);
 366 
 367 static const struct of_device_id stmpe_ts_ids[] = {
 368         { .compatible = "st,stmpe-ts", },
 369         { },
 370 };
 371 MODULE_DEVICE_TABLE(of, stmpe_ts_ids);
 372 
 373 MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
 374 MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
 375 MODULE_LICENSE("GPL");

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