Merge tag 'v5.3-rc4' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 12 Aug 2019 06:24:46 +0000 (23:24 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 12 Aug 2019 06:24:46 +0000 (23:24 -0700)
Sync up with mainline to bring in device_property_count_u32 andother
newer APIs.

28 files changed:
Documentation/devicetree/bindings/input/touchscreen/ads7846.txt
MAINTAINERS
drivers/input/evdev.c
drivers/input/input.c
drivers/input/joystick/Kconfig
drivers/input/joystick/Makefile
drivers/input/joystick/fsia6b.c [new file with mode: 0644]
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/w90p910_keypad.c [deleted file]
drivers/input/misc/Kconfig
drivers/input/misc/soc_button_array.c
drivers/input/mouse/cyapa.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/mouse/synaptics.c
drivers/input/rmi4/rmi_2d_sensor.c
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/fsl-imx25-tcq.c
drivers/input/touchscreen/mxs-lradc-ts.c
drivers/input/touchscreen/sun4i-ts.c
drivers/input/touchscreen/ts4800-ts.c
drivers/input/touchscreen/w90p910_ts.c [deleted file]
drivers/platform/x86/surfacepro3_button.c
include/linux/input.h
include/linux/platform_data/keypad-w90p910.h [deleted file]
include/uapi/linux/serio.h

index 04413da51391f2007f7118ca0d984992eb89b3ab..81f6bda97d3c73d9dbc2899c777b6a708c12ed09 100644 (file)
@@ -32,7 +32,6 @@ Optional properties:
                                        (ADS7846).
        ti,keep-vref-on                 set to keep vref on for differential
                                        measurements as well
-       ti,swap-xy                      swap x and y axis
        ti,settle-delay-usec            Settling time of the analog signals;
                                        a function of Vcc and the capacitance
                                        on the X/Y drivers.  If set to non-zero,
@@ -51,13 +50,6 @@ Optional properties:
                                        in Ohms (u16).
        ti,x-min                        Minimum value on the X axis (u16).
        ti,y-min                        Minimum value on the Y axis (u16).
-       ti,x-max                        Maximum value on the X axis (u16).
-       ti,y-max                        Minimum value on the Y axis (u16).
-       ti,pressure-min                 Minimum reported pressure value
-                                       (threshold) - u16.
-       ti,pressure-max                 Maximum reported pressure value (u16).
-       ti,debounce-max                 Max number of additional readings per
-                                       sample (u16).
        ti,debounce-tol                 Tolerance used for filtering (u16).
        ti,debounce-rep                 Additional consecutive good readings
                                        required after the first two (u16).
@@ -67,7 +59,28 @@ Optional properties:
                                        line is connected to.
        wakeup-source                   use any event on touchscreen as wakeup event.
                                        (Legacy property support: "linux,wakeup")
+       touchscreen-size-x              General touchscreen binding, see [1].
+       touchscreen-size-y              General touchscreen binding, see [1].
+       touchscreen-max-pressure        General touchscreen binding, see [1].
+       touchscreen-min-pressure        General touchscreen binding, see [1].
+       touchscreen-average-samples     General touchscreen binding, see [1].
+       touchscreen-inverted-x          General touchscreen binding, see [1].
+       touchscreen-inverted-y          General touchscreen binding, see [1].
+       touchscreen-swapped-x-y         General touchscreen binding, see [1].
+
+[1] All general touchscreen properties are described in
+    Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt.
 
+Deprecated properties:
+
+       ti,swap-xy                      swap x and y axis
+       ti,x-max                        Maximum value on the X axis (u16).
+       ti,y-max                        Maximum value on the Y axis (u16).
+       ti,pressure-min                 Minimum reported pressure value
+                                       (threshold) - u16.
+       ti,pressure-max                 Maximum reported pressure value (u16).
+       ti,debounce-max                 Max number of additional readings per
+                                       sample (u16).
 
 Example for a TSC2046 chip connected to an McSPI controller of an OMAP SoC::
 
index e81e60bd7c2646892e7eb90c14bcab6c5286ac85..4e21b8a49d24b4118fa704fe5cdebaafdf34eead 100644 (file)
@@ -12623,6 +12623,12 @@ S:     Maintained
 F:     Documentation/input/devices/pxrc.rst
 F:     drivers/input/joystick/pxrc.c
 
+FLYSKY FSIA6B RC RECEIVER
+M:     Markus Koch <markus@notsyncing.net>
+L:     linux-input@vger.kernel.org
+S:     Maintained
+F:     drivers/input/joystick/fsia6b.c
+
 PHONET PROTOCOL
 M:     Remi Denis-Courmont <courmisch@gmail.com>
 S:     Supported
index 867c2cfd003819dc7ce58a527c8ef806c5f327f7..d7dd6fcf2db05a8841e60a4089dd71212d15c476 100644 (file)
 #include <linux/cdev.h>
 #include "input-compat.h"
 
-enum evdev_clock_type {
-       EV_CLK_REAL = 0,
-       EV_CLK_MONO,
-       EV_CLK_BOOT,
-       EV_CLK_MAX
-};
-
 struct evdev {
        int open;
        struct input_handle handle;
@@ -53,7 +46,7 @@ struct evdev_client {
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
-       unsigned int clk_type;
+       enum input_clock_type clk_type;
        bool revoked;
        unsigned long *evmasks[EV_CNT];
        unsigned int bufsize;
@@ -149,17 +142,10 @@ static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
 
 static void __evdev_queue_syn_dropped(struct evdev_client *client)
 {
+       ktime_t *ev_time = input_get_timestamp(client->evdev->handle.dev);
+       struct timespec64 ts = ktime_to_timespec64(ev_time[client->clk_type]);
        struct input_event ev;
-       ktime_t time;
-       struct timespec64 ts;
 
-       time = client->clk_type == EV_CLK_REAL ?
-                       ktime_get_real() :
-                       client->clk_type == EV_CLK_MONO ?
-                               ktime_get() :
-                               ktime_get_boottime();
-
-       ts = ktime_to_timespec64(time);
        ev.input_event_sec = ts.tv_sec;
        ev.input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
        ev.type = EV_SYN;
@@ -188,18 +174,18 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
 static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
 {
        unsigned long flags;
-       unsigned int clk_type;
+       enum input_clock_type clk_type;
 
        switch (clkid) {
 
        case CLOCK_REALTIME:
-               clk_type = EV_CLK_REAL;
+               clk_type = INPUT_CLK_REAL;
                break;
        case CLOCK_MONOTONIC:
-               clk_type = EV_CLK_MONO;
+               clk_type = INPUT_CLK_MONO;
                break;
        case CLOCK_BOOTTIME:
-               clk_type = EV_CLK_BOOT;
+               clk_type = INPUT_CLK_BOOT;
                break;
        default:
                return -EINVAL;
@@ -307,12 +293,7 @@ static void evdev_events(struct input_handle *handle,
 {
        struct evdev *evdev = handle->private;
        struct evdev_client *client;
-       ktime_t ev_time[EV_CLK_MAX];
-
-       ev_time[EV_CLK_MONO] = ktime_get();
-       ev_time[EV_CLK_REAL] = ktime_mono_to_real(ev_time[EV_CLK_MONO]);
-       ev_time[EV_CLK_BOOT] = ktime_mono_to_any(ev_time[EV_CLK_MONO],
-                                                TK_OFFS_BOOT);
+       ktime_t *ev_time = input_get_timestamp(handle->dev);
 
        rcu_read_lock();
 
index 7f3c5fcb9ed6e6b4a618601dd41efa8b0dbdbe60..7494a0dede792237354e2c5027f8ab848fc5fa6f 100644 (file)
@@ -1894,6 +1894,46 @@ void input_free_device(struct input_dev *dev)
 }
 EXPORT_SYMBOL(input_free_device);
 
+/**
+ * input_set_timestamp - set timestamp for input events
+ * @dev: input device to set timestamp for
+ * @timestamp: the time at which the event has occurred
+ *   in CLOCK_MONOTONIC
+ *
+ * This function is intended to provide to the input system a more
+ * accurate time of when an event actually occurred. The driver should
+ * call this function as soon as a timestamp is acquired ensuring
+ * clock conversions in input_set_timestamp are done correctly.
+ *
+ * The system entering suspend state between timestamp acquisition and
+ * calling input_set_timestamp can result in inaccurate conversions.
+ */
+void input_set_timestamp(struct input_dev *dev, ktime_t timestamp)
+{
+       dev->timestamp[INPUT_CLK_MONO] = timestamp;
+       dev->timestamp[INPUT_CLK_REAL] = ktime_mono_to_real(timestamp);
+       dev->timestamp[INPUT_CLK_BOOT] = ktime_mono_to_any(timestamp,
+                                                          TK_OFFS_BOOT);
+}
+EXPORT_SYMBOL(input_set_timestamp);
+
+/**
+ * input_get_timestamp - get timestamp for input events
+ * @dev: input device to get timestamp from
+ *
+ * A valid timestamp is a timestamp of non-zero value.
+ */
+ktime_t *input_get_timestamp(struct input_dev *dev)
+{
+       const ktime_t invalid_timestamp = ktime_set(0, 0);
+
+       if (!ktime_compare(dev->timestamp[INPUT_CLK_MONO], invalid_timestamp))
+               input_set_timestamp(dev, ktime_get());
+
+       return dev->timestamp;
+}
+EXPORT_SYMBOL(input_get_timestamp);
+
 /**
  * input_set_capability - mark device as capable of a certain event
  * @dev: device that is capable of emitting or accepting event
index 72b932901d00f390dd58779ad6d8688407f84a36..312b854b5506f5be467ced59ac5be246f177845a 100644 (file)
@@ -362,4 +362,14 @@ config JOYSTICK_PXRC
          To compile this driver as a module, choose M here: the
          module will be called pxrc.
 
+config JOYSTICK_FSIA6B
+       tristate "FlySky FS-iA6B RC Receiver"
+       select SERIO
+       help
+         Say Y here if you use a FlySky FS-i6 RC remote control along with the
+         FS-iA6B RC receiver as a joystick input device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called fsia6b.
+
 endif
index dd0492ebbed79613374004decee6b87996336794..8656023f6ef531d0297ce3425c349c6b83186dc1 100644 (file)
@@ -12,6 +12,7 @@ obj-$(CONFIG_JOYSTICK_AS5011)         += as5011.o
 obj-$(CONFIG_JOYSTICK_ANALOG)          += analog.o
 obj-$(CONFIG_JOYSTICK_COBRA)           += cobra.o
 obj-$(CONFIG_JOYSTICK_DB9)             += db9.o
+obj-$(CONFIG_JOYSTICK_FSIA6B)          += fsia6b.o
 obj-$(CONFIG_JOYSTICK_GAMECON)         += gamecon.o
 obj-$(CONFIG_JOYSTICK_GF2K)            += gf2k.o
 obj-$(CONFIG_JOYSTICK_GRIP)            += grip.o
@@ -23,7 +24,7 @@ obj-$(CONFIG_JOYSTICK_JOYDUMP)                += joydump.o
 obj-$(CONFIG_JOYSTICK_MAGELLAN)                += magellan.o
 obj-$(CONFIG_JOYSTICK_MAPLE)           += maplecontrol.o
 obj-$(CONFIG_JOYSTICK_PSXPAD_SPI)      += psxpad-spi.o
-obj-$(CONFIG_JOYSTICK_PXRC)                    += pxrc.o
+obj-$(CONFIG_JOYSTICK_PXRC)            += pxrc.o
 obj-$(CONFIG_JOYSTICK_SIDEWINDER)      += sidewinder.o
 obj-$(CONFIG_JOYSTICK_SPACEBALL)       += spaceball.o
 obj-$(CONFIG_JOYSTICK_SPACEORB)                += spaceorb.o
@@ -32,7 +33,7 @@ obj-$(CONFIG_JOYSTICK_TMDC)           += tmdc.o
 obj-$(CONFIG_JOYSTICK_TURBOGRAFX)      += turbografx.o
 obj-$(CONFIG_JOYSTICK_TWIDJOY)         += twidjoy.o
 obj-$(CONFIG_JOYSTICK_WARRIOR)         += warrior.o
+obj-$(CONFIG_JOYSTICK_WALKERA0701)     += walkera0701.o
 obj-$(CONFIG_JOYSTICK_XPAD)            += xpad.o
 obj-$(CONFIG_JOYSTICK_ZHENHUA)         += zhenhua.o
-obj-$(CONFIG_JOYSTICK_WALKERA0701)     += walkera0701.o
 
diff --git a/drivers/input/joystick/fsia6b.c b/drivers/input/joystick/fsia6b.c
new file mode 100644 (file)
index 0000000..e78c4c7
--- /dev/null
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FS-iA6B iBus RC receiver driver
+ *
+ * This driver provides all 14 channels of the FlySky FS-ia6B RC receiver
+ * as analog values.
+ *
+ * Additionally, the channels can be converted to discrete switch values.
+ * By default, it is configured for the offical FS-i6 remote control.
+ * If you use a different hardware configuration, you can configure it
+ * using the `switch_config` parameter.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define DRIVER_DESC            "FS-iA6B iBus RC receiver"
+
+MODULE_AUTHOR("Markus Koch <markus@notsyncing.net>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+#define IBUS_SERVO_COUNT       14
+
+static char *switch_config = "00000022320000";
+module_param(switch_config, charp, 0444);
+MODULE_PARM_DESC(switch_config,
+                "Amount of switch positions per channel (14 characters, 0-3)");
+
+static int fsia6b_axes[IBUS_SERVO_COUNT] = {
+       ABS_X, ABS_Y,
+       ABS_Z, ABS_RX,
+       ABS_RY, ABS_RZ,
+       ABS_HAT0X, ABS_HAT0Y,
+       ABS_HAT1X, ABS_HAT1Y,
+       ABS_HAT2X, ABS_HAT2Y,
+       ABS_HAT3X, ABS_HAT3Y
+};
+
+enum ibus_state { SYNC, COLLECT, PROCESS };
+
+struct ibus_packet {
+       enum ibus_state state;
+
+       int offset;
+       u16 ibuf;
+       u16 channel[IBUS_SERVO_COUNT];
+};
+
+struct fsia6b {
+       struct input_dev *dev;
+       struct ibus_packet packet;
+
+       char phys[32];
+};
+
+static irqreturn_t fsia6b_serio_irq(struct serio *serio,
+                                   unsigned char data, unsigned int flags)
+{
+       struct fsia6b *fsia6b = serio_get_drvdata(serio);
+       int i;
+       int sw_state;
+       int sw_id = BTN_0;
+
+       fsia6b->packet.ibuf = (data << 8) | ((fsia6b->packet.ibuf >> 8) & 0xFF);
+
+       switch (fsia6b->packet.state) {
+       case SYNC:
+               if (fsia6b->packet.ibuf == 0x4020)
+                       fsia6b->packet.state = COLLECT;
+               break;
+
+       case COLLECT:
+               fsia6b->packet.state = PROCESS;
+               break;
+
+       case PROCESS:
+               fsia6b->packet.channel[fsia6b->packet.offset] =
+                               fsia6b->packet.ibuf;
+               fsia6b->packet.offset++;
+
+               if (fsia6b->packet.offset == IBUS_SERVO_COUNT) {
+                       fsia6b->packet.offset = 0;
+                       fsia6b->packet.state = SYNC;
+                       for (i = 0; i < IBUS_SERVO_COUNT; ++i) {
+                               input_report_abs(fsia6b->dev, fsia6b_axes[i],
+                                                fsia6b->packet.channel[i]);
+
+                               sw_state = 0;
+                               if (fsia6b->packet.channel[i] > 1900)
+                                       sw_state = 1;
+                               else if (fsia6b->packet.channel[i] < 1100)
+                                       sw_state = 2;
+
+                               switch (switch_config[i]) {
+                               case '3':
+                                       input_report_key(fsia6b->dev,
+                                                        sw_id++,
+                                                        sw_state == 0);
+                                       /* fall-through */
+                               case '2':
+                                       input_report_key(fsia6b->dev,
+                                                        sw_id++,
+                                                        sw_state == 1);
+                                       /* fall-through */
+                               case '1':
+                                       input_report_key(fsia6b->dev,
+                                                        sw_id++,
+                                                        sw_state == 2);
+                               }
+                       }
+                       input_sync(fsia6b->dev);
+               } else {
+                       fsia6b->packet.state = COLLECT;
+               }
+               break;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static int fsia6b_serio_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct fsia6b *fsia6b;
+       struct input_dev *input_dev;
+       int err;
+       int i, j;
+       int sw_id = 0;
+
+       fsia6b = kzalloc(sizeof(*fsia6b), GFP_KERNEL);
+       if (!fsia6b)
+               return -ENOMEM;
+
+       fsia6b->packet.ibuf = 0;
+       fsia6b->packet.offset = 0;
+       fsia6b->packet.state = SYNC;
+
+       serio_set_drvdata(serio, fsia6b);
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               err = -ENOMEM;
+               goto fail1;
+       }
+       fsia6b->dev = input_dev;
+
+       snprintf(fsia6b->phys, sizeof(fsia6b->phys), "%s/input0", serio->phys);
+
+       input_dev->name = DRIVER_DESC;
+       input_dev->phys = fsia6b->phys;
+       input_dev->id.bustype = BUS_RS232;
+       input_dev->id.vendor = SERIO_FSIA6B;
+       input_dev->id.product = serio->id.id;
+       input_dev->id.version = 0x0100;
+       input_dev->dev.parent = &serio->dev;
+
+       for (i = 0; i < IBUS_SERVO_COUNT; i++)
+               input_set_abs_params(input_dev, fsia6b_axes[i],
+                                    1000, 2000, 2, 2);
+
+       /* Register switch configuration */
+       for (i = 0; i < IBUS_SERVO_COUNT; i++) {
+               if (switch_config[i] < '0' || switch_config[i] > '3') {
+                       dev_err(&fsia6b->dev->dev,
+                               "Invalid switch configuration supplied for fsia6b.\n");
+                       err = -EINVAL;
+                       goto fail2;
+               }
+
+               for (j = '1'; j <= switch_config[i]; j++) {
+                       input_set_capability(input_dev, EV_KEY, BTN_0 + sw_id);
+                       sw_id++;
+               }
+       }
+
+       err = serio_open(serio, drv);
+       if (err)
+               goto fail2;
+
+       err = input_register_device(fsia6b->dev);
+       if (err)
+               goto fail3;
+
+       return 0;
+
+fail3: serio_close(serio);
+fail2: input_free_device(input_dev);
+fail1: serio_set_drvdata(serio, NULL);
+       kfree(fsia6b);
+       return err;
+}
+
+static void fsia6b_serio_disconnect(struct serio *serio)
+{
+       struct fsia6b *fsia6b = serio_get_drvdata(serio);
+
+       serio_close(serio);
+       serio_set_drvdata(serio, NULL);
+       input_unregister_device(fsia6b->dev);
+       kfree(fsia6b);
+}
+
+static const struct serio_device_id fsia6b_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_FSIA6B,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, fsia6b_serio_ids);
+
+static struct serio_driver fsia6b_serio_drv = {
+       .driver         = {
+               .name   = "fsia6b"
+       },
+       .description    = DRIVER_DESC,
+       .id_table       = fsia6b_serio_ids,
+       .interrupt      = fsia6b_serio_irq,
+       .connect        = fsia6b_serio_connect,
+       .disconnect     = fsia6b_serio_disconnect
+};
+
+module_serio_driver(fsia6b_serio_drv)
index 90e8a7f2f07c863196762633930bc46a5c659319..2e6d2887eec1f823f0ffab58afe3a902f63b2ad2 100644 (file)
@@ -733,17 +733,6 @@ config KEYBOARD_XTKBD
          To compile this driver as a module, choose M here: the
          module will be called xtkbd.
 
-config KEYBOARD_W90P910
-       tristate "W90P910 Matrix Keypad support"
-       depends on ARCH_W90X900
-       select INPUT_MATRIXKMAP
-       help
-         Say Y here to enable the matrix keypad on evaluation board
-         based on W90P910.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w90p910_keypad.
-
 config KEYBOARD_CROS_EC
        tristate "ChromeOS EC keyboard"
        select INPUT_MATRIXKMAP
index 06a0af6efeaea91fb2c9d112ff35885d9e4ff78f..9510325c0c5d666546b41126675282f34edeafa0 100644 (file)
@@ -68,4 +68,3 @@ obj-$(CONFIG_KEYBOARD_TEGRA)          += tegra-kbc.o
 obj-$(CONFIG_KEYBOARD_TM2_TOUCHKEY)    += tm2-touchkey.o
 obj-$(CONFIG_KEYBOARD_TWL4030)         += twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)           += xtkbd.o
-obj-$(CONFIG_KEYBOARD_W90P910)         += w90p910_keypad.o
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c
deleted file mode 100644 (file)
index c88d05d..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2008-2009 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/input.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-
-#include <linux/platform_data/keypad-w90p910.h>
-
-/* Keypad Interface Control Registers */
-#define KPI_CONF               0x00
-#define KPI_3KCONF             0x04
-#define KPI_LPCONF             0x08
-#define KPI_STATUS             0x0C
-
-#define IS1KEY                 (0x01 << 16)
-#define INTTR                  (0x01 << 21)
-#define KEY0R                  (0x0f << 3)
-#define KEY0C                  0x07
-#define DEBOUNCE_BIT           0x08
-#define KSIZE0                 (0x01 << 16)
-#define KSIZE1                 (0x01 << 17)
-#define KPSEL                  (0x01 << 19)
-#define ENKP                   (0x01 << 18)
-
-#define KGET_RAW(n)            (((n) & KEY0R) >> 3)
-#define KGET_COLUMN(n)         ((n) & KEY0C)
-
-#define W90P910_NUM_ROWS       8
-#define W90P910_NUM_COLS       8
-#define W90P910_ROW_SHIFT      3
-
-struct w90p910_keypad {
-       const struct w90p910_keypad_platform_data *pdata;
-       struct clk *clk;
-       struct input_dev *input_dev;
-       void __iomem *mmio_base;
-       int irq;
-       unsigned short keymap[W90P910_NUM_ROWS * W90P910_NUM_COLS];
-};
-
-static void w90p910_keypad_scan_matrix(struct w90p910_keypad *keypad,
-                                                       unsigned int status)
-{
-       struct input_dev *input_dev = keypad->input_dev;
-       unsigned int row = KGET_RAW(status);
-       unsigned int col = KGET_COLUMN(status);
-       unsigned int code = MATRIX_SCAN_CODE(row, col, W90P910_ROW_SHIFT);
-       unsigned int key = keypad->keymap[code];
-
-       input_event(input_dev, EV_MSC, MSC_SCAN, code);
-       input_report_key(input_dev, key, 1);
-       input_sync(input_dev);
-
-       input_event(input_dev, EV_MSC, MSC_SCAN, code);
-       input_report_key(input_dev, key, 0);
-       input_sync(input_dev);
-}
-
-static irqreturn_t w90p910_keypad_irq_handler(int irq, void *dev_id)
-{
-       struct w90p910_keypad *keypad = dev_id;
-       unsigned int  kstatus, val;
-
-       kstatus = __raw_readl(keypad->mmio_base + KPI_STATUS);
-
-       val = INTTR | IS1KEY;
-
-       if (kstatus & val)
-               w90p910_keypad_scan_matrix(keypad, kstatus);
-
-       return IRQ_HANDLED;
-}
-
-static int w90p910_keypad_open(struct input_dev *dev)
-{
-       struct w90p910_keypad *keypad = input_get_drvdata(dev);
-       const struct w90p910_keypad_platform_data *pdata = keypad->pdata;
-       unsigned int val, config;
-
-       /* Enable unit clock */
-       clk_enable(keypad->clk);
-
-       val = __raw_readl(keypad->mmio_base + KPI_CONF);
-       val |= (KPSEL | ENKP);
-       val &= ~(KSIZE0 | KSIZE1);
-
-       config = pdata->prescale | (pdata->debounce << DEBOUNCE_BIT);
-
-       val |= config;
-
-       __raw_writel(val, keypad->mmio_base + KPI_CONF);
-
-       return 0;
-}
-
-static void w90p910_keypad_close(struct input_dev *dev)
-{
-       struct w90p910_keypad *keypad = input_get_drvdata(dev);
-
-       /* Disable clock unit */
-       clk_disable(keypad->clk);
-}
-
-static int w90p910_keypad_probe(struct platform_device *pdev)
-{
-       const struct w90p910_keypad_platform_data *pdata =
-                                               dev_get_platdata(&pdev->dev);
-       const struct matrix_keymap_data *keymap_data;
-       struct w90p910_keypad *keypad;
-       struct input_dev *input_dev;
-       struct resource *res;
-       int irq;
-       int error;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "no platform data defined\n");
-               return -EINVAL;
-       }
-
-       keymap_data = pdata->keymap_data;
-
-       irq = platform_get_irq(pdev, 0);
-       if (irq < 0) {
-               dev_err(&pdev->dev, "failed to get keypad irq\n");
-               return -ENXIO;
-       }
-
-       keypad = kzalloc(sizeof(struct w90p910_keypad), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!keypad || !input_dev) {
-               dev_err(&pdev->dev, "failed to allocate driver data\n");
-               error = -ENOMEM;
-               goto failed_free;
-       }
-
-       keypad->pdata = pdata;
-       keypad->input_dev = input_dev;
-       keypad->irq = irq;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to get I/O memory\n");
-               error = -ENXIO;
-               goto failed_free;
-       }
-
-       res = request_mem_region(res->start, resource_size(res), pdev->name);
-       if (res == NULL) {
-               dev_err(&pdev->dev, "failed to request I/O memory\n");
-               error = -EBUSY;
-               goto failed_free;
-       }
-
-       keypad->mmio_base = ioremap(res->start, resource_size(res));
-       if (keypad->mmio_base == NULL) {
-               dev_err(&pdev->dev, "failed to remap I/O memory\n");
-               error = -ENXIO;
-               goto failed_free_res;
-       }
-
-       keypad->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(keypad->clk)) {
-               dev_err(&pdev->dev, "failed to get keypad clock\n");
-               error = PTR_ERR(keypad->clk);
-               goto failed_free_io;
-       }
-
-       /* set multi-function pin for w90p910 kpi. */
-       mfp_set_groupi(&pdev->dev);
-
-       input_dev->name = pdev->name;
-       input_dev->id.bustype = BUS_HOST;
-       input_dev->open = w90p910_keypad_open;
-       input_dev->close = w90p910_keypad_close;
-       input_dev->dev.parent = &pdev->dev;
-
-       error = matrix_keypad_build_keymap(keymap_data, NULL,
-                                          W90P910_NUM_ROWS, W90P910_NUM_COLS,
-                                          keypad->keymap, input_dev);
-       if (error) {
-               dev_err(&pdev->dev, "failed to build keymap\n");
-               goto failed_put_clk;
-       }
-
-       error = request_irq(keypad->irq, w90p910_keypad_irq_handler,
-                           0, pdev->name, keypad);
-       if (error) {
-               dev_err(&pdev->dev, "failed to request IRQ\n");
-               goto failed_put_clk;
-       }
-
-       __set_bit(EV_REP, input_dev->evbit);
-       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
-       input_set_drvdata(input_dev, keypad);
-
-       /* Register the input device */
-       error = input_register_device(input_dev);
-       if (error) {
-               dev_err(&pdev->dev, "failed to register input device\n");
-               goto failed_free_irq;
-       }
-
-       platform_set_drvdata(pdev, keypad);
-       return 0;
-
-failed_free_irq:
-       free_irq(irq, keypad);
-failed_put_clk:
-       clk_put(keypad->clk);
-failed_free_io:
-       iounmap(keypad->mmio_base);
-failed_free_res:
-       release_mem_region(res->start, resource_size(res));
-failed_free:
-       input_free_device(input_dev);
-       kfree(keypad);
-       return error;
-}
-
-static int w90p910_keypad_remove(struct platform_device *pdev)
-{
-       struct w90p910_keypad *keypad = platform_get_drvdata(pdev);
-       struct resource *res;
-
-       free_irq(keypad->irq, keypad);
-
-       clk_put(keypad->clk);
-
-       input_unregister_device(keypad->input_dev);
-
-       iounmap(keypad->mmio_base);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       kfree(keypad);
-
-       return 0;
-}
-
-static struct platform_driver w90p910_keypad_driver = {
-       .probe          = w90p910_keypad_probe,
-       .remove         = w90p910_keypad_remove,
-       .driver         = {
-               .name   = "nuc900-kpi",
-       },
-};
-module_platform_driver(w90p910_keypad_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 keypad driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-keypad");
index d07c1eb15aa677d7907a5752988d136b314f5374..7d9ae394e59786d3d6ed2289abb4eca454f8e74b 100644 (file)
@@ -813,10 +813,10 @@ config INPUT_IDEAPAD_SLIDEBAR
 
 config INPUT_SOC_BUTTON_ARRAY
        tristate "Windows-compatible SoC Button Array"
-       depends on KEYBOARD_GPIO
+       depends on KEYBOARD_GPIO && ACPI
        help
-         Say Y here if you have a SoC-based tablet that originally
-         runs Windows 8.
+         Say Y here if you have a SoC-based tablet that originally runs
+         Windows 8 or a Microsoft Surface Book 2, Pro 5, Laptop 1 or later.
 
          To compile this driver as a module, choose M here: the
          module will be called soc_button_array.
index 5e59f8e57f8e230abbe56808b9a4b37457b21b5c..6f0133fe1546f2d7e33c96da52a5a0767c9a3362 100644 (file)
@@ -25,6 +25,11 @@ struct soc_button_info {
        bool wakeup;
 };
 
+struct soc_device_data {
+       const struct soc_button_info *button_info;
+       int (*check)(struct device *dev);
+};
+
 /*
  * Some of the buttons like volume up/down are auto repeat, while others
  * are not. To support both, we register two platform devices, and put
@@ -87,8 +92,13 @@ soc_button_device_create(struct platform_device *pdev,
                        continue;
 
                gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
-               if (!gpio_is_valid(gpio))
+               if (gpio < 0 && gpio != -ENOENT) {
+                       error = gpio;
+                       goto err_free_mem;
+               } else if (!gpio_is_valid(gpio)) {
+                       /* Skip GPIO if not present */
                        continue;
+               }
 
                gpio_keys[n_buttons].type = info->event_type;
                gpio_keys[n_buttons].code = info->event_code;
@@ -309,23 +319,26 @@ static int soc_button_remove(struct platform_device *pdev)
 static int soc_button_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       const struct acpi_device_id *id;
-       struct soc_button_info *button_info;
+       const struct soc_device_data *device_data;
+       const struct soc_button_info *button_info;
        struct soc_button_data *priv;
        struct platform_device *pd;
        int i;
        int error;
 
-       id = acpi_match_device(dev->driver->acpi_match_table, dev);
-       if (!id)
-               return -ENODEV;
+       device_data = acpi_device_get_match_data(dev);
+       if (device_data && device_data->check) {
+               error = device_data->check(dev);
+               if (error)
+                       return error;
+       }
 
-       if (!id->driver_data) {
+       if (device_data && device_data->button_info) {
+               button_info = device_data->button_info;
+       } else {
                button_info = soc_button_get_button_info(dev);
                if (IS_ERR(button_info))
                        return PTR_ERR(button_info);
-       } else {
-               button_info = (struct soc_button_info *)id->driver_data;
        }
 
        error = gpiod_count(dev, NULL);
@@ -357,7 +370,7 @@ static int soc_button_probe(struct platform_device *pdev)
        if (!priv->children[0] && !priv->children[1])
                return -ENODEV;
 
-       if (!id->driver_data)
+       if (!device_data || !device_data->button_info)
                devm_kfree(dev, button_info);
 
        return 0;
@@ -368,7 +381,7 @@ static int soc_button_probe(struct platform_device *pdev)
  * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
  * Platforms"
  */
-static struct soc_button_info soc_button_PNP0C40[] = {
+static const struct soc_button_info soc_button_PNP0C40[] = {
        { "power", 0, EV_KEY, KEY_POWER, false, true },
        { "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
        { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
@@ -377,9 +390,77 @@ static struct soc_button_info soc_button_PNP0C40[] = {
        { }
 };
 
+static const struct soc_device_data soc_device_PNP0C40 = {
+       .button_info = soc_button_PNP0C40,
+};
+
+/*
+ * Special device check for Surface Book 2 and Surface Pro (2017).
+ * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
+ * devices use MSHW0040 for power and volume buttons, however the way they
+ * have to be addressed differs. Make sure that we only load this drivers
+ * for the correct devices by checking the OEM Platform Revision provided by
+ * the _DSM method.
+ */
+#define MSHW0040_DSM_REVISION          0x01
+#define MSHW0040_DSM_GET_OMPR          0x02    // get OEM Platform Revision
+static const guid_t MSHW0040_DSM_UUID =
+       GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
+                 0x49, 0x80, 0x35);
+
+static int soc_device_check_MSHW0040(struct device *dev)
+{
+       acpi_handle handle = ACPI_HANDLE(dev);
+       union acpi_object *result;
+       u64 oem_platform_rev = 0;       // valid revisions are nonzero
+
+       // get OEM platform revision
+       result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
+                                        MSHW0040_DSM_REVISION,
+                                        MSHW0040_DSM_GET_OMPR, NULL,
+                                        ACPI_TYPE_INTEGER);
+
+       if (result) {
+               oem_platform_rev = result->integer.value;
+               ACPI_FREE(result);
+       }
+
+       /*
+        * If the revision is zero here, the _DSM evaluation has failed. This
+        * indicates that we have a Pro 4 or Book 1 and this driver should not
+        * be used.
+        */
+       if (oem_platform_rev == 0)
+               return -ENODEV;
+
+       dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
+
+       return 0;
+}
+
+/*
+ * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
+ * Obtained from DSDT/testing.
+ */
+static const struct soc_button_info soc_button_MSHW0040[] = {
+       { "power", 0, EV_KEY, KEY_POWER, false, true },
+       { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
+       { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false },
+       { }
+};
+
+static const struct soc_device_data soc_device_MSHW0040 = {
+       .button_info = soc_button_MSHW0040,
+       .check = soc_device_check_MSHW0040,
+};
+
 static const struct acpi_device_id soc_button_acpi_match[] = {
-       { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
+       { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
        { "ACPI0011", 0 },
+
+       /* Microsoft Surface Devices (5th and 6th generation) */
+       { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
+
        { }
 };
 
index dfd3873513e4b5b635b492b83217b18f0ad96e01..c675f156948b5178ce9a7d3deb4f0ea4316d7b2a 100644 (file)
@@ -1238,13 +1238,6 @@ static const struct attribute_group cyapa_sysfs_group = {
        .attrs = cyapa_sysfs_entries,
 };
 
-static void cyapa_remove_sysfs_group(void *data)
-{
-       struct cyapa *cyapa = data;
-
-       sysfs_remove_group(&cyapa->client->dev.kobj, &cyapa_sysfs_group);
-}
-
 static void cyapa_disable_regulator(void *data)
 {
        struct cyapa *cyapa = data;
@@ -1312,19 +1305,12 @@ static int cyapa_probe(struct i2c_client *client,
                return error;
        }
 
-       error = sysfs_create_group(&dev->kobj, &cyapa_sysfs_group);
+       error = devm_device_add_group(dev, &cyapa_sysfs_group);
        if (error) {
                dev_err(dev, "failed to create sysfs entries: %d\n", error);
                return error;
        }
 
-       error = devm_add_action(dev, cyapa_remove_sysfs_group, cyapa);
-       if (error) {
-               cyapa_remove_sysfs_group(cyapa);
-               dev_err(dev, "failed to add sysfs cleanup action: %d\n", error);
-               return error;
-       }
-
        error = cyapa_prepare_wakeup_controls(cyapa);
        if (error) {
                dev_err(dev, "failed to prepare wakeup controls: %d\n", error);
index d9b103a81a798e4a22a224504c7f7b445d6e68a7..8719da54038346b0441f74cd72fc4af7c48ed1a7 100644 (file)
@@ -1138,13 +1138,6 @@ static void elan_disable_regulator(void *_data)
        regulator_disable(data->vcc);
 }
 
-static void elan_remove_sysfs_groups(void *_data)
-{
-       struct elan_tp_data *data = _data;
-
-       sysfs_remove_groups(&data->client->dev.kobj, elan_sysfs_groups);
-}
-
 static int elan_probe(struct i2c_client *client,
                      const struct i2c_device_id *dev_id)
 {
@@ -1194,9 +1187,8 @@ static int elan_probe(struct i2c_client *client,
                return error;
        }
 
-       error = devm_add_action(dev, elan_disable_regulator, data);
+       error = devm_add_action_or_reset(dev, elan_disable_regulator, data);
        if (error) {
-               regulator_disable(data->vcc);
                dev_err(dev, "Failed to add disable regulator action: %d\n",
                        error);
                return error;
@@ -1269,20 +1261,12 @@ static int elan_probe(struct i2c_client *client,
                return error;
        }
 
-       error = sysfs_create_groups(&dev->kobj, elan_sysfs_groups);
+       error = devm_device_add_groups(dev, elan_sysfs_groups);
        if (error) {
                dev_err(dev, "failed to create sysfs attributes: %d\n", error);
                return error;
        }
 
-       error = devm_add_action(dev, elan_remove_sysfs_groups, data);
-       if (error) {
-               elan_remove_sysfs_groups(data);
-               dev_err(dev, "Failed to add sysfs cleanup action: %d\n",
-                       error);
-               return error;
-       }
-
        error = input_register_device(data->input);
        if (error) {
                dev_err(dev, "failed to register input device: %d\n", error);
index 46bbe99d651135b093ba6b3de6473243103e5493..56fae34721146839ee7cbd608f6f821d0fc5518e 100644 (file)
@@ -193,7 +193,7 @@ static const char * const forcepad_pnp_ids[] = {
 };
 
 /*
- * Send a command to the synpatics touchpad by special commands
+ * Send a command to the synaptics touchpad by special commands
  */
 static int synaptics_send_cmd(struct psmouse *psmouse, u8 cmd, u8 *param)
 {
index ea549efe4bc40fa784c5ec1582c93146d0323ce7..b7fe6eb35a4ecd629f367bf49306a9fdcbd2c98a 100644 (file)
@@ -204,7 +204,6 @@ static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor)
        if (sensor->topbuttonpad)
                set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit);
 }
-EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params);
 
 int rmi_2d_sensor_configure_input(struct rmi_function *fn,
                                        struct rmi_2d_sensor *sensor)
index fb91f2d4049eff3a9c0cf4d6c530f8a1786300da..46ad9090493bb5f7f654cfa723a1d914cd7ea2dc 100644 (file)
@@ -1112,15 +1112,6 @@ config TOUCHSCREEN_TSC2007_IIO
          or ambient light monitoring), temperature and raw input
          values.
 
-config TOUCHSCREEN_W90X900
-       tristate "W90P910 touchscreen driver"
-       depends on ARCH_W90X900
-       help
-         Say Y here if you have a W90P910 based touchscreen.
-
-         To compile this driver as a module, choose M here: the
-         module will be called w90p910_ts.
-
 config TOUCHSCREEN_PCAP
        tristate "Motorola PCAP touchscreen"
        depends on EZX_PCAP
index 084a596a0c8bda9e064498c1c736d9868814bfff..94c6162409b379724bf0fffc5bfd19c79b0d0974 100644 (file)
@@ -102,7 +102,6 @@ wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)      += wm9712.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE)     += mainstone-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)      += zylonite-wm97xx.o
-obj-$(CONFIG_TOUCHSCREEN_W90X900)      += w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_SX8654)       += sx8654.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)     += tps6507x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ZET6223)      += zet6223.o
index accbbe8d2966680b8016716de879c5c14c68205d..51ddb204ca1badd3838890932e9b51f74d792339 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/input/touchscreen.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/pm.h>
@@ -129,6 +130,8 @@ struct ads7846 {
 
        u16                     penirq_recheck_delay_usecs;
 
+       struct touchscreen_properties core_prop;
+
        struct mutex            lock;
        bool                    stopped;        /* P: lock */
        bool                    disabled;       /* P: lock */
@@ -823,17 +826,13 @@ static void ads7846_report_state(struct ads7846 *ts)
        if (Rt) {
                struct input_dev *input = ts->input;
 
-               if (ts->swap_xy)
-                       swap(x, y);
-
                if (!ts->pendown) {
                        input_report_key(input, BTN_TOUCH, 1);
                        ts->pendown = true;
                        dev_vdbg(&ts->spi->dev, "DOWN\n");
                }
 
-               input_report_abs(input, ABS_X, x);
-               input_report_abs(input, ABS_Y, y);
+               touchscreen_report_pos(input, &ts->core_prop, x, y, false);
                input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
 
                input_sync(input);
@@ -1185,6 +1184,7 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
        struct ads7846_platform_data *pdata;
        struct device_node *node = dev->of_node;
        const struct of_device_id *match;
+       u32 value;
 
        if (!node) {
                dev_err(dev, "Device does not have associated DT data\n");
@@ -1223,10 +1223,18 @@ static const struct ads7846_platform_data *ads7846_probe_dt(struct device *dev)
        of_property_read_u16(node, "ti,x-max", &pdata->x_max);
        of_property_read_u16(node, "ti,y-max", &pdata->y_max);
 
+       /*
+        * touchscreen-max-pressure gets parsed during
+        * touchscreen_parse_properties()
+        */
        of_property_read_u16(node, "ti,pressure-min", &pdata->pressure_min);
+       if (!of_property_read_u32(node, "touchscreen-min-pressure", &value))
+               pdata->pressure_min = (u16) value;
        of_property_read_u16(node, "ti,pressure-max", &pdata->pressure_max);
 
        of_property_read_u16(node, "ti,debounce-max", &pdata->debounce_max);
+       if (!of_property_read_u32(node, "touchscreen-average-samples", &value))
+               pdata->debounce_max = (u16) value;
        of_property_read_u16(node, "ti,debounce-tol", &pdata->debounce_tol);
        of_property_read_u16(node, "ti,debounce-rep", &pdata->debounce_rep);
 
@@ -1309,10 +1317,7 @@ static int ads7846_probe(struct spi_device *spi)
        ts->model = pdata->model ? : 7846;
        ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
        ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
-       ts->pressure_max = pdata->pressure_max ? : ~0;
-
        ts->vref_mv = pdata->vref_mv;
-       ts->swap_xy = pdata->swap_xy;
 
        if (pdata->filter != NULL) {
                if (pdata->filter_init != NULL) {
@@ -1364,6 +1369,23 @@ static int ads7846_probe(struct spi_device *spi)
        input_set_abs_params(input_dev, ABS_PRESSURE,
                        pdata->pressure_min, pdata->pressure_max, 0, 0);
 
+       /*
+        * Parse common framework properties. Must be done here to ensure the
+        * correct behaviour in case of using the legacy vendor bindings. The
+        * general binding value overrides the vendor specific one.
+        */
+       touchscreen_parse_properties(ts->input, false, &ts->core_prop);
+       ts->pressure_max = input_abs_get_max(input_dev, ABS_PRESSURE) ? : ~0;
+
+       /*
+        * Check if legacy ti,swap-xy binding is used instead of
+        * touchscreen-swapped-x-y
+        */
+       if (!ts->core_prop.swap_x_y && pdata->swap_xy) {
+               swap(input_dev->absinfo[ABS_X], input_dev->absinfo[ABS_Y]);
+               ts->core_prop.swap_x_y = true;
+       }
+
        ads7846_setup_spi_msg(ts, pdata);
 
        ts->reg = regulator_get(&spi->dev, "vcc");
index 1d6c8f490b4082576ccabe20d8928d7b6485c94d..b66df8ab89f22d72cb2785831e48ec1831d9299a 100644 (file)
@@ -503,7 +503,6 @@ static int mx25_tcq_probe(struct platform_device *pdev)
        struct input_dev *idev;
        struct mx25_tcq_priv *priv;
        struct mx25_tsadc *tsadc = dev_get_drvdata(dev->parent);
-       struct resource *res;
        void __iomem *mem;
        int error;
 
@@ -512,8 +511,7 @@ static int mx25_tcq_probe(struct platform_device *pdev)
                return -ENOMEM;
        priv->dev = dev;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       mem = devm_ioremap_resource(dev, res);
+       mem = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(mem))
                return PTR_ERR(mem);
 
index 593b8d3e90b5fd2443b8284a6d4cd04b144bdf83..9e36fee38d612b1700e727d0ace40a4477bcc800 100644 (file)
@@ -606,7 +606,6 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
        struct device_node *node = dev->parent->of_node;
        struct mxs_lradc *lradc = dev_get_drvdata(dev->parent);
        struct mxs_lradc_ts *ts;
-       struct resource *iores;
        int ret, irq, virq, i;
        u32 ts_wires = 0, adapt;
 
@@ -620,12 +619,9 @@ static int mxs_lradc_ts_probe(struct platform_device *pdev)
        ts->dev = dev;
        spin_lock_init(&ts->lock);
 
-       iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!iores)
-               return -EINVAL;
-       ts->base = devm_ioremap(dev, iores->start, resource_size(iores));
-       if (!ts->base)
-               return -ENOMEM;
+       ts->base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(ts->base))
+               return PTR_ERR(ts->base);
 
        ret = of_property_read_u32(node, "fsl,lradc-touchscreen-wires",
                                   &ts_wires);
index f11ba7f2dca76aaa218b27dff7b2f5823c4db223..0af0fe8c40d7f19dae9c52e7e6dc1a20845f4ffe 100644 (file)
@@ -300,8 +300,7 @@ static int sun4i_ts_probe(struct platform_device *pdev)
                input_set_drvdata(ts->input, ts);
        }
 
-       ts->base = devm_ioremap_resource(dev,
-                             platform_get_resource(pdev, IORESOURCE_MEM, 0));
+       ts->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(ts->base))
                return PTR_ERR(ts->base);
 
index fed73eeb47b3c6e263ca2e0415d9b385cc2f4854..5b4f5362c67b4f79b21f518bd04cdf0a4da43fd1 100644 (file)
@@ -148,7 +148,6 @@ static int ts4800_ts_probe(struct platform_device *pdev)
 {
        struct input_polled_dev *poll_dev;
        struct ts4800_ts *ts;
-       struct resource *res;
        int error;
 
        ts = devm_kzalloc(&pdev->dev, sizeof(*ts), GFP_KERNEL);
@@ -159,8 +158,7 @@ static int ts4800_ts_probe(struct platform_device *pdev)
        if (error)
                return error;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       ts->base = devm_ioremap_resource(&pdev->dev, res);
+       ts->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(ts->base))
                return PTR_ERR(ts->base);
 
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c
deleted file mode 100644 (file)
index 7893d7f..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2008 Nuvoton technology corporation.
- *
- * Wan ZongShun <mcuos.com@gmail.com>
- */
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-/* ADC controller bit defines */
-#define ADC_DELAY      0xf00
-#define ADC_DOWN       0x01
-#define ADC_TSC_Y      (0x01 << 8)
-#define ADC_TSC_X      (0x00 << 8)
-#define TSC_FOURWIRE   (~(0x03 << 1))
-#define ADC_CLK_EN     (0x01 << 28)    /* ADC clock enable */
-#define ADC_READ_CON   (0x01 << 12)
-#define ADC_CONV       (0x01 << 13)
-#define ADC_SEMIAUTO   (0x01 << 14)
-#define ADC_WAITTRIG   (0x03 << 14)
-#define ADC_RST1       (0x01 << 16)
-#define ADC_RST0       (0x00 << 16)
-#define ADC_EN         (0x01 << 17)
-#define ADC_INT                (0x01 << 18)
-#define WT_INT         (0x01 << 20)
-#define ADC_INT_EN     (0x01 << 21)
-#define LVD_INT_EN     (0x01 << 22)
-#define WT_INT_EN      (0x01 << 23)
-#define ADC_DIV                (0x04 << 1)     /* div = 6 */
-
-enum ts_state {
-       TS_WAIT_NEW_PACKET,     /* We are waiting next touch report */
-       TS_WAIT_X_COORD,        /* We are waiting for ADC to report X coord */
-       TS_WAIT_Y_COORD,        /* We are waiting for ADC to report Y coord */
-       TS_IDLE,                /* Input device is closed, don't do anything */
-};
-
-struct w90p910_ts {
-       struct input_dev *input;
-       struct timer_list timer;
-       struct clk *clk;
-       int irq_num;
-       void __iomem *ts_reg;
-       spinlock_t lock;
-       enum ts_state state;
-};
-
-static void w90p910_report_event(struct w90p910_ts *w90p910_ts, bool down)
-{
-       struct input_dev *dev = w90p910_ts->input;
-
-       if (down) {
-               input_report_abs(dev, ABS_X,
-                                __raw_readl(w90p910_ts->ts_reg + 0x0c));
-               input_report_abs(dev, ABS_Y,
-                                __raw_readl(w90p910_ts->ts_reg + 0x10));
-       }
-
-       input_report_key(dev, BTN_TOUCH, down);
-       input_sync(dev);
-}
-
-static void w90p910_prepare_x_reading(struct w90p910_ts *w90p910_ts)
-{
-       unsigned long ctlreg;
-
-       __raw_writel(ADC_TSC_X, w90p910_ts->ts_reg + 0x04);
-       ctlreg = __raw_readl(w90p910_ts->ts_reg);
-       ctlreg &= ~(ADC_WAITTRIG | WT_INT | WT_INT_EN);
-       ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV;
-       __raw_writel(ctlreg, w90p910_ts->ts_reg);
-
-       w90p910_ts->state = TS_WAIT_X_COORD;
-}
-
-static void w90p910_prepare_y_reading(struct w90p910_ts *w90p910_ts)
-{
-       unsigned long ctlreg;
-
-       __raw_writel(ADC_TSC_Y, w90p910_ts->ts_reg + 0x04);
-       ctlreg = __raw_readl(w90p910_ts->ts_reg);
-       ctlreg &= ~(ADC_WAITTRIG | ADC_INT | WT_INT_EN);
-       ctlreg |= ADC_SEMIAUTO | ADC_INT_EN | ADC_CONV;
-       __raw_writel(ctlreg, w90p910_ts->ts_reg);
-
-       w90p910_ts->state = TS_WAIT_Y_COORD;
-}
-
-static void w90p910_prepare_next_packet(struct w90p910_ts *w90p910_ts)
-{
-       unsigned long ctlreg;
-
-       ctlreg = __raw_readl(w90p910_ts->ts_reg);
-       ctlreg &= ~(ADC_INT | ADC_INT_EN | ADC_SEMIAUTO | ADC_CONV);
-       ctlreg |= ADC_WAITTRIG | WT_INT_EN;
-       __raw_writel(ctlreg, w90p910_ts->ts_reg);
-
-       w90p910_ts->state = TS_WAIT_NEW_PACKET;
-}
-
-static irqreturn_t w90p910_ts_interrupt(int irq, void *dev_id)
-{
-       struct w90p910_ts *w90p910_ts = dev_id;
-       unsigned long flags;
-
-       spin_lock_irqsave(&w90p910_ts->lock, flags);
-
-       switch (w90p910_ts->state) {
-       case TS_WAIT_NEW_PACKET:
-               /*
-                * The controller only generates interrupts when pen
-                * is down.
-                */
-               del_timer(&w90p910_ts->timer);
-               w90p910_prepare_x_reading(w90p910_ts);
-               break;
-
-
-       case TS_WAIT_X_COORD:
-               w90p910_prepare_y_reading(w90p910_ts);
-               break;
-
-       case TS_WAIT_Y_COORD:
-               w90p910_report_event(w90p910_ts, true);
-               w90p910_prepare_next_packet(w90p910_ts);
-               mod_timer(&w90p910_ts->timer, jiffies + msecs_to_jiffies(100));
-               break;
-
-       case TS_IDLE:
-               break;
-       }
-
-       spin_unlock_irqrestore(&w90p910_ts->lock, flags);
-
-       return IRQ_HANDLED;
-}
-
-static void w90p910_check_pen_up(struct timer_list *t)
-{
-       struct w90p910_ts *w90p910_ts = from_timer(w90p910_ts, t, timer);
-       unsigned long flags;
-
-       spin_lock_irqsave(&w90p910_ts->lock, flags);
-
-       if (w90p910_ts->state == TS_WAIT_NEW_PACKET &&
-           !(__raw_readl(w90p910_ts->ts_reg + 0x04) & ADC_DOWN)) {
-
-               w90p910_report_event(w90p910_ts, false);
-       }
-
-       spin_unlock_irqrestore(&w90p910_ts->lock, flags);
-}
-
-static int w90p910_open(struct input_dev *dev)
-{
-       struct w90p910_ts *w90p910_ts = input_get_drvdata(dev);
-       unsigned long val;
-
-       /* enable the ADC clock */
-       clk_enable(w90p910_ts->clk);
-
-       __raw_writel(ADC_RST1, w90p910_ts->ts_reg);
-       msleep(1);
-       __raw_writel(ADC_RST0, w90p910_ts->ts_reg);
-       msleep(1);
-
-       /* set delay and screen type */
-       val = __raw_readl(w90p910_ts->ts_reg + 0x04);
-       __raw_writel(val & TSC_FOURWIRE, w90p910_ts->ts_reg + 0x04);
-       __raw_writel(ADC_DELAY, w90p910_ts->ts_reg + 0x08);
-
-       w90p910_ts->state = TS_WAIT_NEW_PACKET;
-       wmb();
-
-       /* set trigger mode */
-       val = __raw_readl(w90p910_ts->ts_reg);
-       val |= ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN;
-       __raw_writel(val, w90p910_ts->ts_reg);
-
-       return 0;
-}
-
-static void w90p910_close(struct input_dev *dev)
-{
-       struct w90p910_ts *w90p910_ts = input_get_drvdata(dev);
-       unsigned long val;
-
-       /* disable trigger mode */
-
-       spin_lock_irq(&w90p910_ts->lock);
-
-       w90p910_ts->state = TS_IDLE;
-
-       val = __raw_readl(w90p910_ts->ts_reg);
-       val &= ~(ADC_WAITTRIG | ADC_DIV | ADC_EN | WT_INT_EN | ADC_INT_EN);
-       __raw_writel(val, w90p910_ts->ts_reg);
-
-       spin_unlock_irq(&w90p910_ts->lock);
-
-       /* Now that interrupts are shut off we can safely delete timer */
-       del_timer_sync(&w90p910_ts->timer);
-
-       /* stop the ADC clock */
-       clk_disable(w90p910_ts->clk);
-}
-
-static int w90x900ts_probe(struct platform_device *pdev)
-{
-       struct w90p910_ts *w90p910_ts;
-       struct input_dev *input_dev;
-       struct resource *res;
-       int err;
-
-       w90p910_ts = kzalloc(sizeof(struct w90p910_ts), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!w90p910_ts || !input_dev) {
-               err = -ENOMEM;
-               goto fail1;
-       }
-
-       w90p910_ts->input = input_dev;
-       w90p910_ts->state = TS_IDLE;
-       spin_lock_init(&w90p910_ts->lock);
-       timer_setup(&w90p910_ts->timer, w90p910_check_pen_up, 0);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               err = -ENXIO;
-               goto fail1;
-       }
-
-       if (!request_mem_region(res->start, resource_size(res),
-                               pdev->name)) {
-               err = -EBUSY;
-               goto fail1;
-       }
-
-       w90p910_ts->ts_reg = ioremap(res->start, resource_size(res));
-       if (!w90p910_ts->ts_reg) {
-               err = -ENOMEM;
-               goto fail2;
-       }
-
-       w90p910_ts->clk = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(w90p910_ts->clk)) {
-               err = PTR_ERR(w90p910_ts->clk);
-               goto fail3;
-       }
-
-       input_dev->name = "W90P910 TouchScreen";
-       input_dev->phys = "w90p910ts/event0";
-       input_dev->id.bustype = BUS_HOST;
-       input_dev->id.vendor  = 0x0005;
-       input_dev->id.product = 0x0001;
-       input_dev->id.version = 0x0100;
-       input_dev->dev.parent = &pdev->dev;
-       input_dev->open = w90p910_open;
-       input_dev->close = w90p910_close;
-
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-       input_set_abs_params(input_dev, ABS_X, 0, 0x400, 0, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, 0x400, 0, 0);
-
-       input_set_drvdata(input_dev, w90p910_ts);
-
-       w90p910_ts->irq_num = platform_get_irq(pdev, 0);
-       if (request_irq(w90p910_ts->irq_num, w90p910_ts_interrupt,
-                       0, "w90p910ts", w90p910_ts)) {
-               err = -EBUSY;
-               goto fail4;
-       }
-
-       err = input_register_device(w90p910_ts->input);
-       if (err)
-               goto fail5;
-
-       platform_set_drvdata(pdev, w90p910_ts);
-
-       return 0;
-
-fail5: free_irq(w90p910_ts->irq_num, w90p910_ts);
-fail4: clk_put(w90p910_ts->clk);
-fail3: iounmap(w90p910_ts->ts_reg);
-fail2: release_mem_region(res->start, resource_size(res));
-fail1: input_free_device(input_dev);
-       kfree(w90p910_ts);
-       return err;
-}
-
-static int w90x900ts_remove(struct platform_device *pdev)
-{
-       struct w90p910_ts *w90p910_ts = platform_get_drvdata(pdev);
-       struct resource *res;
-
-       free_irq(w90p910_ts->irq_num, w90p910_ts);
-       del_timer_sync(&w90p910_ts->timer);
-       iounmap(w90p910_ts->ts_reg);
-
-       clk_put(w90p910_ts->clk);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(res->start, resource_size(res));
-
-       input_unregister_device(w90p910_ts->input);
-       kfree(w90p910_ts);
-
-       return 0;
-}
-
-static struct platform_driver w90x900ts_driver = {
-       .probe          = w90x900ts_probe,
-       .remove         = w90x900ts_remove,
-       .driver         = {
-               .name   = "nuc900-ts",
-       },
-};
-module_platform_driver(w90x900ts_driver);
-
-MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
-MODULE_DESCRIPTION("w90p910 touch screen driver!");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:nuc900-ts");
index 47c6d000465a72855922ef70ee96350b8f1a7031..ec515223f6549d8cbc8968d1f13780f21d65686a 100644 (file)
 #define SURFACE_BUTTON_OBJ_NAME                "VGBI"
 #define SURFACE_BUTTON_DEVICE_NAME     "Surface Pro 3/4 Buttons"
 
+#define MSHW0040_DSM_REVISION          0x01
+#define MSHW0040_DSM_GET_OMPR          0x02    // get OEM Platform Revision
+static const guid_t MSHW0040_DSM_UUID =
+       GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
+                 0x49, 0x80, 0x35);
+
 #define SURFACE_BUTTON_NOTIFY_TABLET_MODE      0xc8
 
 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER      0xc6
@@ -142,6 +148,44 @@ static int surface_button_resume(struct device *dev)
 }
 #endif
 
+/*
+ * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
+ * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
+ * device by checking for the _DSM method and OEM Platform Revision.
+ *
+ * Returns true if the driver should bind to this device, i.e. the device is
+ * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
+ */
+static bool surface_button_check_MSHW0040(struct acpi_device *dev)
+{
+       acpi_handle handle = dev->handle;
+       union acpi_object *result;
+       u64 oem_platform_rev = 0;       // valid revisions are nonzero
+
+       // get OEM platform revision
+       result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
+                                        MSHW0040_DSM_REVISION,
+                                        MSHW0040_DSM_GET_OMPR,
+                                        NULL, ACPI_TYPE_INTEGER);
+
+       /*
+        * If evaluating the _DSM fails, the method is not present. This means
+        * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
+        * should use this driver. We use revision 0 indicating it is
+        * unavailable.
+        */
+
+       if (result) {
+               oem_platform_rev = result->integer.value;
+               ACPI_FREE(result);
+       }
+
+       dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
+
+       return oem_platform_rev == 0;
+}
+
+
 static int surface_button_add(struct acpi_device *device)
 {
        struct surface_button *button;
@@ -154,6 +198,9 @@ static int surface_button_add(struct acpi_device *device)
            strlen(SURFACE_BUTTON_OBJ_NAME)))
                return -ENODEV;
 
+       if (!surface_button_check_MSHW0040(device))
+               return -ENODEV;
+
        button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
        if (!button)
                return -ENOMEM;
index 510e78558c106379368d6a90af5974260be43f72..e95a439d8bd5afdb6b73684d1014c3e4bbf56410 100644 (file)
@@ -33,6 +33,13 @@ struct input_value {
        __s32 value;
 };
 
+enum input_clock_type {
+       INPUT_CLK_REAL = 0,
+       INPUT_CLK_MONO,
+       INPUT_CLK_BOOT,
+       INPUT_CLK_MAX
+};
+
 /**
  * struct input_dev - represents an input device
  * @name: name of the device
@@ -114,6 +121,8 @@ struct input_value {
  * @vals: array of values queued in the current frame
  * @devres_managed: indicates that devices is managed with devres framework
  *     and needs not be explicitly unregistered or freed.
+ * @timestamp: storage for a timestamp set by input_set_timestamp called
+ *  by a driver
  */
 struct input_dev {
        const char *name;
@@ -184,6 +193,8 @@ struct input_dev {
        struct input_value *vals;
 
        bool devres_managed;
+
+       ktime_t timestamp[INPUT_CLK_MAX];
 };
 #define to_input_dev(d) container_of(d, struct input_dev, dev)
 
@@ -382,6 +393,9 @@ void input_close_device(struct input_handle *);
 
 int input_flush_device(struct input_handle *handle, struct file *file);
 
+void input_set_timestamp(struct input_dev *dev, ktime_t timestamp);
+ktime_t *input_get_timestamp(struct input_dev *dev);
+
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 
diff --git a/include/linux/platform_data/keypad-w90p910.h b/include/linux/platform_data/keypad-w90p910.h
deleted file mode 100644 (file)
index 206ca4e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __ASM_ARCH_W90P910_KEYPAD_H
-#define __ASM_ARCH_W90P910_KEYPAD_H
-
-#include <linux/input/matrix_keypad.h>
-
-extern void mfp_set_groupi(struct device *dev);
-
-struct w90p910_keypad_platform_data {
-       const struct matrix_keymap_data *keymap_data;
-
-       unsigned int    prescale;
-       unsigned int    debounce;
-};
-
-#endif /* __ASM_ARCH_W90P910_KEYPAD_H */
index a0cac1d8670d8a89320adba86688aee6ef8a63b7..50e991952c979e6ebf4cd15d29bae9c55db88112 100644 (file)
@@ -82,5 +82,6 @@
 #define SERIO_EGALAX   0x3f
 #define SERIO_PULSE8_CEC       0x40
 #define SERIO_RAINSHADOW_CEC   0x41
+#define SERIO_FSIA6B   0x42
 
 #endif /* _UAPI_SERIO_H */