linux/drivers/input/touchscreen/surface3_spi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  Driver for Ntrig/Microsoft Touchscreens over SPI
   4 *
   5 *  Copyright (c) 2016 Red Hat Inc.
   6 */
   7
   8
   9#include <linux/kernel.h>
  10
  11#include <linux/delay.h>
  12#include <linux/gpio/consumer.h>
  13#include <linux/input.h>
  14#include <linux/input/mt.h>
  15#include <linux/interrupt.h>
  16#include <linux/module.h>
  17#include <linux/slab.h>
  18#include <linux/spi/spi.h>
  19#include <linux/acpi.h>
  20
  21#include <asm/unaligned.h>
  22
  23#define SURFACE3_PACKET_SIZE    264
  24
  25#define SURFACE3_REPORT_TOUCH   0xd2
  26#define SURFACE3_REPORT_PEN     0x16
  27
  28struct surface3_ts_data {
  29        struct spi_device *spi;
  30        struct gpio_desc *gpiod_rst[2];
  31        struct input_dev *input_dev;
  32        struct input_dev *pen_input_dev;
  33        int pen_tool;
  34
  35        u8 rd_buf[SURFACE3_PACKET_SIZE]         ____cacheline_aligned;
  36};
  37
  38struct surface3_ts_data_finger {
  39        u8 status;
  40        __le16 tracking_id;
  41        __le16 x;
  42        __le16 cx;
  43        __le16 y;
  44        __le16 cy;
  45        __le16 width;
  46        __le16 height;
  47        u32 padding;
  48} __packed;
  49
  50struct surface3_ts_data_pen {
  51        u8 status;
  52        __le16 x;
  53        __le16 y;
  54        __le16 pressure;
  55        u8 padding;
  56} __packed;
  57
  58static int surface3_spi_read(struct surface3_ts_data *ts_data)
  59{
  60        struct spi_device *spi = ts_data->spi;
  61
  62        memset(ts_data->rd_buf, 0, sizeof(ts_data->rd_buf));
  63        return spi_read(spi, ts_data->rd_buf, sizeof(ts_data->rd_buf));
  64}
  65
  66static void surface3_spi_report_touch(struct surface3_ts_data *ts_data,
  67                                   struct surface3_ts_data_finger *finger)
  68{
  69        int st = finger->status & 0x01;
  70        int slot;
  71
  72        slot = input_mt_get_slot_by_key(ts_data->input_dev,
  73                                get_unaligned_le16(&finger->tracking_id));
  74        if (slot < 0)
  75                return;
  76
  77        input_mt_slot(ts_data->input_dev, slot);
  78        input_mt_report_slot_state(ts_data->input_dev, MT_TOOL_FINGER, st);
  79        if (st) {
  80                input_report_abs(ts_data->input_dev,
  81                                 ABS_MT_POSITION_X,
  82                                 get_unaligned_le16(&finger->x));
  83                input_report_abs(ts_data->input_dev,
  84                                 ABS_MT_POSITION_Y,
  85                                 get_unaligned_le16(&finger->y));
  86                input_report_abs(ts_data->input_dev,
  87                                 ABS_MT_WIDTH_MAJOR,
  88                                 get_unaligned_le16(&finger->width));
  89                input_report_abs(ts_data->input_dev,
  90                                 ABS_MT_WIDTH_MINOR,
  91                                 get_unaligned_le16(&finger->height));
  92        }
  93}
  94
  95static void surface3_spi_process_touch(struct surface3_ts_data *ts_data, u8 *data)
  96{
  97        u16 timestamp;
  98        unsigned int i;
  99        timestamp = get_unaligned_le16(&data[15]);
 100
 101        for (i = 0; i < 13; i++) {
 102                struct surface3_ts_data_finger *finger;
 103
 104                finger = (struct surface3_ts_data_finger *)&data[17 +
 105                                i * sizeof(struct surface3_ts_data_finger)];
 106
 107                /*
 108                 * When bit 5 of status is 1, it marks the end of the report:
 109                 * - touch present: 0xe7
 110                 * - touch released: 0xe4
 111                 * - nothing valuable: 0xff
 112                 */
 113                if (finger->status & 0x10)
 114                        break;
 115
 116                surface3_spi_report_touch(ts_data, finger);
 117        }
 118
 119        input_mt_sync_frame(ts_data->input_dev);
 120        input_sync(ts_data->input_dev);
 121}
 122
 123static void surface3_spi_report_pen(struct surface3_ts_data *ts_data,
 124                                    struct surface3_ts_data_pen *pen)
 125{
 126        struct input_dev *dev = ts_data->pen_input_dev;
 127        int st = pen->status;
 128        int prox = st & 0x01;
 129        int rubber = st & 0x18;
 130        int tool = (prox && rubber) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 131
 132        /* fake proximity out to switch tools */
 133        if (ts_data->pen_tool != tool) {
 134                input_report_key(dev, ts_data->pen_tool, 0);
 135                input_sync(dev);
 136                ts_data->pen_tool = tool;
 137        }
 138
 139        input_report_key(dev, BTN_TOUCH, st & 0x12);
 140
 141        input_report_key(dev, ts_data->pen_tool, prox);
 142
 143        if (st) {
 144                input_report_key(dev,
 145                                 BTN_STYLUS,
 146                                 st & 0x04);
 147
 148                input_report_abs(dev,
 149                                 ABS_X,
 150                                 get_unaligned_le16(&pen->x));
 151                input_report_abs(dev,
 152                                 ABS_Y,
 153                                 get_unaligned_le16(&pen->y));
 154                input_report_abs(dev,
 155                                 ABS_PRESSURE,
 156                                 get_unaligned_le16(&pen->pressure));
 157        }
 158}
 159
 160static void surface3_spi_process_pen(struct surface3_ts_data *ts_data, u8 *data)
 161{
 162        struct surface3_ts_data_pen *pen;
 163
 164        pen = (struct surface3_ts_data_pen *)&data[15];
 165
 166        surface3_spi_report_pen(ts_data, pen);
 167        input_sync(ts_data->pen_input_dev);
 168}
 169
 170static void surface3_spi_process(struct surface3_ts_data *ts_data)
 171{
 172        static const char header[] = {
 173                0xff, 0xff, 0xff, 0xff, 0xa5, 0x5a, 0xe7, 0x7e, 0x01
 174        };
 175        u8 *data = ts_data->rd_buf;
 176
 177        if (memcmp(header, data, sizeof(header)))
 178                dev_err(&ts_data->spi->dev,
 179                        "%s header error: %*ph, ignoring...\n",
 180                        __func__, (int)sizeof(header), data);
 181
 182        switch (data[9]) {
 183        case SURFACE3_REPORT_TOUCH:
 184                surface3_spi_process_touch(ts_data, data);
 185                break;
 186        case SURFACE3_REPORT_PEN:
 187                surface3_spi_process_pen(ts_data, data);
 188                break;
 189        default:
 190                dev_err(&ts_data->spi->dev,
 191                        "%s unknown packet type: %x, ignoring...\n",
 192                        __func__, data[9]);
 193                break;
 194        }
 195}
 196
 197static irqreturn_t surface3_spi_irq_handler(int irq, void *dev_id)
 198{
 199        struct surface3_ts_data *data = dev_id;
 200
 201        if (surface3_spi_read(data))
 202                return IRQ_HANDLED;
 203
 204        dev_dbg(&data->spi->dev, "%s received -> %*ph\n",
 205                __func__, SURFACE3_PACKET_SIZE, data->rd_buf);
 206        surface3_spi_process(data);
 207
 208        return IRQ_HANDLED;
 209}
 210
 211static void surface3_spi_power(struct surface3_ts_data *data, bool on)
 212{
 213        gpiod_set_value(data->gpiod_rst[0], on);
 214        gpiod_set_value(data->gpiod_rst[1], on);
 215        /* let the device settle a little */
 216        msleep(20);
 217}
 218
 219/**
 220 * surface3_spi_get_gpio_config - Get GPIO config from ACPI/DT
 221 *
 222 * @ts: surface3_spi_ts_data pointer
 223 */
 224static int surface3_spi_get_gpio_config(struct surface3_ts_data *data)
 225{
 226        int error;
 227        struct device *dev;
 228        struct gpio_desc *gpiod;
 229        int i;
 230
 231        dev = &data->spi->dev;
 232
 233        /* Get the reset lines GPIO pin number */
 234        for (i = 0; i < 2; i++) {
 235                gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_OUT_LOW);
 236                if (IS_ERR(gpiod)) {
 237                        error = PTR_ERR(gpiod);
 238                        if (error != -EPROBE_DEFER)
 239                                dev_err(dev,
 240                                        "Failed to get power GPIO %d: %d\n",
 241                                        i,
 242                                        error);
 243                        return error;
 244                }
 245
 246                data->gpiod_rst[i] = gpiod;
 247        }
 248
 249        return 0;
 250}
 251
 252static int surface3_spi_create_touch_input(struct surface3_ts_data *data)
 253{
 254        struct input_dev *input;
 255        int error;
 256
 257        input = devm_input_allocate_device(&data->spi->dev);
 258        if (!input)
 259                return -ENOMEM;
 260
 261        data->input_dev = input;
 262
 263        input_set_abs_params(input, ABS_MT_POSITION_X, 0, 9600, 0, 0);
 264        input_abs_set_res(input, ABS_MT_POSITION_X, 40);
 265        input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 7200, 0, 0);
 266        input_abs_set_res(input, ABS_MT_POSITION_Y, 48);
 267        input_set_abs_params(input, ABS_MT_WIDTH_MAJOR, 0, 1024, 0, 0);
 268        input_set_abs_params(input, ABS_MT_WIDTH_MINOR, 0, 1024, 0, 0);
 269        input_mt_init_slots(input, 10, INPUT_MT_DIRECT);
 270
 271        input->name = "Surface3 SPI Capacitive TouchScreen";
 272        input->phys = "input/ts";
 273        input->id.bustype = BUS_SPI;
 274        input->id.vendor = 0x045e;      /* Microsoft */
 275        input->id.product = 0x0001;
 276        input->id.version = 0x0000;
 277
 278        error = input_register_device(input);
 279        if (error) {
 280                dev_err(&data->spi->dev,
 281                        "Failed to register input device: %d", error);
 282                return error;
 283        }
 284
 285        return 0;
 286}
 287
 288static int surface3_spi_create_pen_input(struct surface3_ts_data *data)
 289{
 290        struct input_dev *input;
 291        int error;
 292
 293        input = devm_input_allocate_device(&data->spi->dev);
 294        if (!input)
 295                return -ENOMEM;
 296
 297        data->pen_input_dev = input;
 298        data->pen_tool = BTN_TOOL_PEN;
 299
 300        __set_bit(INPUT_PROP_DIRECT, input->propbit);
 301        __set_bit(INPUT_PROP_POINTER, input->propbit);
 302        input_set_abs_params(input, ABS_X, 0, 9600, 0, 0);
 303        input_abs_set_res(input, ABS_X, 40);
 304        input_set_abs_params(input, ABS_Y, 0, 7200, 0, 0);
 305        input_abs_set_res(input, ABS_Y, 48);
 306        input_set_abs_params(input, ABS_PRESSURE, 0, 1024, 0, 0);
 307        input_set_capability(input, EV_KEY, BTN_TOUCH);
 308        input_set_capability(input, EV_KEY, BTN_STYLUS);
 309        input_set_capability(input, EV_KEY, BTN_TOOL_PEN);
 310        input_set_capability(input, EV_KEY, BTN_TOOL_RUBBER);
 311
 312        input->name = "Surface3 SPI Pen Input";
 313        input->phys = "input/ts";
 314        input->id.bustype = BUS_SPI;
 315        input->id.vendor = 0x045e;     /* Microsoft */
 316        input->id.product = 0x0002;
 317        input->id.version = 0x0000;
 318
 319        error = input_register_device(input);
 320        if (error) {
 321                dev_err(&data->spi->dev,
 322                        "Failed to register input device: %d", error);
 323                return error;
 324        }
 325
 326        return 0;
 327}
 328
 329static int surface3_spi_probe(struct spi_device *spi)
 330{
 331        struct surface3_ts_data *data;
 332        int error;
 333
 334        /* Set up SPI*/
 335        spi->bits_per_word = 8;
 336        spi->mode = SPI_MODE_0;
 337        error = spi_setup(spi);
 338        if (error)
 339                return error;
 340
 341        data = devm_kzalloc(&spi->dev, sizeof(*data), GFP_KERNEL);
 342        if (!data)
 343                return -ENOMEM;
 344
 345        data->spi = spi;
 346        spi_set_drvdata(spi, data);
 347
 348        error = surface3_spi_get_gpio_config(data);
 349        if (error)
 350                return error;
 351
 352        surface3_spi_power(data, true);
 353        surface3_spi_power(data, false);
 354        surface3_spi_power(data, true);
 355
 356        error = surface3_spi_create_touch_input(data);
 357        if (error)
 358                return error;
 359
 360        error = surface3_spi_create_pen_input(data);
 361        if (error)
 362                return error;
 363
 364        error = devm_request_threaded_irq(&spi->dev, spi->irq,
 365                                          NULL, surface3_spi_irq_handler,
 366                                          IRQF_ONESHOT,
 367                                          "Surface3-irq", data);
 368        if (error)
 369                return error;
 370
 371        return 0;
 372}
 373
 374static int __maybe_unused surface3_spi_suspend(struct device *dev)
 375{
 376        struct spi_device *spi = to_spi_device(dev);
 377        struct surface3_ts_data *data = spi_get_drvdata(spi);
 378
 379        disable_irq(data->spi->irq);
 380
 381        surface3_spi_power(data, false);
 382
 383        return 0;
 384}
 385
 386static int __maybe_unused surface3_spi_resume(struct device *dev)
 387{
 388        struct spi_device *spi = to_spi_device(dev);
 389        struct surface3_ts_data *data = spi_get_drvdata(spi);
 390
 391        surface3_spi_power(data, true);
 392
 393        enable_irq(data->spi->irq);
 394
 395        return 0;
 396}
 397
 398static SIMPLE_DEV_PM_OPS(surface3_spi_pm_ops,
 399                         surface3_spi_suspend,
 400                         surface3_spi_resume);
 401
 402#ifdef CONFIG_ACPI
 403static const struct acpi_device_id surface3_spi_acpi_match[] = {
 404        { "MSHW0037", 0 },
 405        { }
 406};
 407MODULE_DEVICE_TABLE(acpi, surface3_spi_acpi_match);
 408#endif
 409
 410static struct spi_driver surface3_spi_driver = {
 411        .driver = {
 412                .name   = "Surface3-spi",
 413                .acpi_match_table = ACPI_PTR(surface3_spi_acpi_match),
 414                .pm = &surface3_spi_pm_ops,
 415        },
 416        .probe = surface3_spi_probe,
 417};
 418
 419module_spi_driver(surface3_spi_driver);
 420
 421MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
 422MODULE_DESCRIPTION("Surface 3 SPI touchscreen driver");
 423MODULE_LICENSE("GPL v2");
 424