|
@@ -1,13 +1,13 @@
|
|
|
-From caff9a677d61eee7429d9a30ed33224bd3b96a42 Mon Sep 17 00:00:00 2001
|
|
|
+From 16423edf1a61130f052c5f6035e5b20870151810 Mon Sep 17 00:00:00 2001
|
|
|
From: Maximilian Luz <luzmaximilian@gmail.com>
|
|
|
Date: Fri, 26 Jul 2019 03:42:15 +0200
|
|
|
Subject: [PATCH 03/12] buttons
|
|
|
|
|
|
---
|
|
|
drivers/input/misc/Kconfig | 6 +-
|
|
|
- drivers/input/misc/soc_button_array.c | 141 ++++++++++++++++++++--
|
|
|
- drivers/platform/x86/surfacepro3_button.c | 47 ++++++++
|
|
|
- 3 files changed, 178 insertions(+), 16 deletions(-)
|
|
|
+ drivers/input/misc/soc_button_array.c | 105 +++++++++++++++++++---
|
|
|
+ drivers/platform/x86/surfacepro3_button.c | 47 ++++++++++
|
|
|
+ 3 files changed, 143 insertions(+), 15 deletions(-)
|
|
|
|
|
|
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
|
|
|
index ca59a2be9bc5..ea69610370e8 100644
|
|
@@ -28,28 +28,22 @@ index ca59a2be9bc5..ea69610370e8 100644
|
|
|
To compile this driver as a module, choose M here: the
|
|
|
module will be called soc_button_array.
|
|
|
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
|
|
|
-index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
+index 55cd6e0b409c..8f21c062c85d 100644
|
|
|
--- a/drivers/input/misc/soc_button_array.c
|
|
|
+++ b/drivers/input/misc/soc_button_array.c
|
|
|
-@@ -29,6 +29,17 @@ struct soc_button_info {
|
|
|
+@@ -29,6 +29,11 @@ struct soc_button_info {
|
|
|
bool wakeup;
|
|
|
};
|
|
|
|
|
|
-+/**
|
|
|
-+ * struct soc_device_data - driver data for different device types
|
|
|
-+ * @button_info: specifications of buttons, if NULL specification is assumed to
|
|
|
-+ * be present in _DSD
|
|
|
-+ * @check: device-specific check (NULL means all will be accepted)
|
|
|
-+ */
|
|
|
+struct soc_device_data {
|
|
|
-+ struct soc_button_info *button_info;
|
|
|
++ 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
|
|
|
-@@ -91,8 +102,13 @@ soc_button_device_create(struct platform_device *pdev,
|
|
|
+@@ -91,8 +96,13 @@ soc_button_device_create(struct platform_device *pdev,
|
|
|
continue;
|
|
|
|
|
|
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
|
|
@@ -64,45 +58,42 @@ index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
|
|
|
gpio_keys[n_buttons].type = info->event_type;
|
|
|
gpio_keys[n_buttons].code = info->event_code;
|
|
|
-@@ -310,6 +326,7 @@ static int soc_button_probe(struct platform_device *pdev)
|
|
|
+@@ -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_device_data *device_data;
|
|
|
- struct soc_button_info *button_info;
|
|
|
+- 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;
|
|
|
-@@ -320,18 +337,20 @@ static int soc_button_probe(struct platform_device *pdev)
|
|
|
- if (!id)
|
|
|
- return -ENODEV;
|
|
|
+ int i;
|
|
|
+ int error;
|
|
|
|
|
|
-- if (!id->driver_data) {
|
|
|
-+ device_data = (struct soc_device_data *)id->driver_data;
|
|
|
+- 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 = (struct soc_button_info *)
|
|
|
-+ 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);
|
|
|
-- if (error < 0) {
|
|
|
-- dev_dbg(dev, "no GPIO attached, ignoring...\n");
|
|
|
-- return -ENODEV;
|
|
|
}
|
|
|
|
|
|
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
|
|
-@@ -357,12 +376,32 @@ static int soc_button_probe(struct platform_device *pdev)
|
|
|
+ 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;
|
|
|
|
|
@@ -111,41 +102,23 @@ index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
devm_kfree(dev, button_info);
|
|
|
|
|
|
return 0;
|
|
|
- }
|
|
|
-
|
|
|
-+
|
|
|
-+static int soc_device_check_generic(struct device *dev)
|
|
|
-+{
|
|
|
-+ int gpios;
|
|
|
-+
|
|
|
-+ gpios = gpiod_count(dev, NULL);
|
|
|
-+ if (gpios < 0) {
|
|
|
-+ dev_dbg(dev, "no GPIO attached, ignoring...\n");
|
|
|
-+ return -ENODEV;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ return 0;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static struct soc_device_data soc_device_ACPI0011 = {
|
|
|
-+ .button_info = NULL,
|
|
|
-+ .check = soc_device_check_generic,
|
|
|
-+};
|
|
|
-+
|
|
|
-+
|
|
|
- /*
|
|
|
- * Definition of buttons on the tablet. The ACPI index of each button
|
|
|
+@@ -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
|
|
|
-@@ -377,9 +416,85 @@ static struct soc_button_info soc_button_PNP0C40[] = {
|
|
|
+ * 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 struct soc_device_data soc_device_PNP0C40 = {
|
|
|
++static const struct soc_device_data soc_device_PNP0C40 = {
|
|
|
+ .button_info = soc_button_PNP0C40,
|
|
|
-+ .check = soc_device_check_generic,
|
|
|
+};
|
|
|
+
|
|
|
-+
|
|
|
+/*
|
|
|
+ * Special device check for Surface Book 2 and Surface Pro (2017).
|
|
|
+ * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
|
|
@@ -165,7 +138,6 @@ index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
+ acpi_handle handle = ACPI_HANDLE(dev);
|
|
|
+ union acpi_object *result;
|
|
|
+ u64 oem_platform_rev = 0; // valid revisions are nonzero
|
|
|
-+ int gpios;
|
|
|
+
|
|
|
+ // get OEM platform revision
|
|
|
+ result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
|
|
@@ -188,10 +160,6 @@ index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
+
|
|
|
+ dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
|
|
|
+
|
|
|
-+ gpios = gpiod_count(dev, NULL);
|
|
|
-+ if (gpios < 0)
|
|
|
-+ return -ENODEV;
|
|
|
-+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
@@ -199,24 +167,22 @@ index 55cd6e0b409c..8c94acbbf574 100644
|
|
|
+ * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
|
|
|
+ * Obtained from DSDT/testing.
|
|
|
+ */
|
|
|
-+static struct soc_button_info soc_button_MSHW0040[] = {
|
|
|
++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 struct soc_device_data soc_device_MSHW0040 = {
|
|
|
++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 },
|
|
|
-- { "ACPI0011", 0 },
|
|
|
+ { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
|
|
|
-+ { "ACPI0011", (unsigned long)&soc_device_ACPI0011 },
|
|
|
+ { "ACPI0011", 0 },
|
|
|
+
|
|
|
+ /* Microsoft Surface Devices (5th and 6th generation) */
|
|
|
+ { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
|