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