Add support for the hardware buttons

Volume Up/Down, Windows key and power button.
This commit is contained in:
Bastien Nocera 2016-07-19 13:49:26 +02:00
parent d884e8fd12
commit 6526ccbb68
8 changed files with 616 additions and 0 deletions

View File

@ -0,0 +1,37 @@
From 7e990a7b8f8bd62a806c4804608d00640352841f Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Thu, 12 May 2016 11:21:13 +0200
Subject: [PATCH 1/6] Input - soc_button_array: use gpio_is_valid()
gpio_keys will later use gpio_is_valid(). To match the actual
behavior, we should use it here too.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/soc_button_array.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index c14b827..bbd433c 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -17,6 +17,7 @@
#include <linux/acpi.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
#include <linux/platform_device.h>
/*
@@ -92,7 +93,7 @@ soc_button_device_create(struct platform_device *pdev,
continue;
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
- if (gpio < 0)
+ if (!gpio_is_valid(gpio))
continue;
gpio_keys[n_buttons].type = info->event_type;
--
2.7.4

View File

@ -0,0 +1,34 @@
From dc16436c048a734bffabefb79508c39795f2a8bb Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Fri, 13 May 2016 15:52:20 +0200
Subject: [PATCH 2/6] Input - soc_button_array: bail out earlier if gpiod_count
is null
The PNP0C40 device of the Surface 3 doesn't have any GPIO attached to it.
Instead of trying to access the GPIO, request the count beforehand and
bail out if it is null or if an error is returned.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/soc_button_array.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index bbd433c..5467d04 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -167,6 +167,11 @@ static int soc_button_probe(struct platform_device *pdev)
button_info = (struct soc_button_info *)id->driver_data;
+ if (gpiod_count(&pdev->dev, KBUILD_MODNAME) <= 0) {
+ dev_info(&pdev->dev, "no GPIO attached, ignoring...\n");
+ return -ENODEV;
+ }
+
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
--
2.7.4

View File

@ -0,0 +1,47 @@
From 3a6162d1b35218b4fc684a0c95e103ce68105bb5 Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Mon, 9 May 2016 14:28:25 +0200
Subject: [PATCH 3/6] Input - soc_button_array: make sure one GPIO is not
assigned twice
The Surface 3 declares twice the GPIO as GpioInt and GpioIo in its
ACPI table. Given that we do not keep the gpiod around, but the actual
number associated to, there is a chance while enumerating the GPIOs that
one gets assigned twice. Make sure a previous button has not been mapped
already to the current button to prevent such failure.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/soc_button_array.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 5467d04..cb5cce3 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -77,7 +77,7 @@ soc_button_device_create(struct platform_device *pdev,
struct gpio_keys_platform_data *gpio_keys_pdata;
int n_buttons = 0;
int gpio;
- int error;
+ int i, error;
gpio_keys_pdata = devm_kzalloc(&pdev->dev,
sizeof(*gpio_keys_pdata) +
@@ -96,6 +96,13 @@ soc_button_device_create(struct platform_device *pdev,
if (!gpio_is_valid(gpio))
continue;
+ for (i = 0; i < n_buttons; i++) {
+ if (gpio_keys[i].gpio == gpio)
+ break;
+ }
+ if (i < n_buttons)
+ continue; /* the GPIO has already been assigned */
+
gpio_keys[n_buttons].type = info->event_type;
gpio_keys[n_buttons].code = info->event_code;
gpio_keys[n_buttons].gpio = gpio;
--
2.7.4

View File

@ -0,0 +1,54 @@
From de9a764d3063d5c1743eab8b1a994b02119767a0 Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Fri, 13 May 2016 15:54:15 +0200
Subject: [PATCH 4/6] Input - soc_button_array: allow to specify active_low
The Surface 3 has the "Windows" key active high, and not low. We need
a way to specify it in the description.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/soc_button_array.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index cb5cce3..077e06e4 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -34,6 +34,7 @@ struct soc_button_info {
unsigned int event_code;
bool autorepeat;
bool wakeup;
+ bool active_low;
};
/*
@@ -106,7 +107,7 @@ soc_button_device_create(struct platform_device *pdev,
gpio_keys[n_buttons].type = info->event_type;
gpio_keys[n_buttons].code = info->event_code;
gpio_keys[n_buttons].gpio = gpio;
- gpio_keys[n_buttons].active_low = 1;
+ gpio_keys[n_buttons].active_low = info->active_low;
gpio_keys[n_buttons].desc = info->name;
gpio_keys[n_buttons].wakeup = info->wakeup;
n_buttons++;
@@ -206,11 +207,11 @@ static int soc_button_probe(struct platform_device *pdev)
}
static 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 },
- { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false },
- { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false },
+ { "power", 0, EV_KEY, KEY_POWER, false, true, true },
+ { "home", 1, EV_KEY, KEY_LEFTMETA, false, true, true },
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
+ { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
+ { "rotation_lock", 4, EV_SW, SW_ROTATE_LOCK, false, false, true },
{ }
};
--
2.7.4

View File

@ -0,0 +1,255 @@
From 7423522630722f7aad88afb097776e41b52d1b22 Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Fri, 13 May 2016 15:56:56 +0200
Subject: [PATCH 5/6] Input - soc_button_array: export part of the internals
The MS Surfaces are not directly using the PNP0C40 device for the buttons
but instead a MSHW0028. This one is bound on a I2C bus and so we need to
use a separate driver for it.
One noticeable change is that the original soc_button_array fails
to rmmod and then modprobe when using KBUILD_MODNAME as the gpiod con_id
with the Surface 3. Add this as a parameter of the new API.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/soc_button_array.c | 108 +++++++++++++++++++--------------
include/linux/input/soc_button_array.h | 37 +++++++++++
2 files changed, 98 insertions(+), 47 deletions(-)
create mode 100644 include/linux/input/soc_button_array.h
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
index 077e06e4..96012f9 100644
--- a/drivers/input/misc/soc_button_array.c
+++ b/drivers/input/misc/soc_button_array.c
@@ -19,23 +19,7 @@
#include <linux/gpio_keys.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
-
-/*
- * Definition of buttons on the tablet. The ACPI index of each button
- * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
- * Platforms"
- */
-#define MAX_NBUTTONS 5
-
-struct soc_button_info {
- const char *name;
- int acpi_index;
- unsigned int event_type;
- unsigned int event_code;
- bool autorepeat;
- bool wakeup;
- bool active_low;
-};
+#include <linux/input/soc_button_array.h>
/*
* Some of the buttons like volume up/down are auto repeat, while others
@@ -51,12 +35,13 @@ struct soc_button_data {
/*
* Get the Nth GPIO number from the ACPI object.
*/
-static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
+static int soc_button_lookup_gpio(struct device *dev, const char *con_id,
+ int acpi_index)
{
struct gpio_desc *desc;
int gpio;
- desc = gpiod_get_index(dev, KBUILD_MODNAME, acpi_index, GPIOD_ASIS);
+ desc = gpiod_get_index(dev, con_id, acpi_index, GPIOD_ASIS);
if (IS_ERR(desc))
return PTR_ERR(desc);
@@ -68,7 +53,8 @@ static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
}
static struct platform_device *
-soc_button_device_create(struct platform_device *pdev,
+soc_button_device_create(struct device *dev,
+ const char *gpiod_con_id,
const struct soc_button_info *button_info,
bool autorepeat)
{
@@ -80,7 +66,7 @@ soc_button_device_create(struct platform_device *pdev,
int gpio;
int i, error;
- gpio_keys_pdata = devm_kzalloc(&pdev->dev,
+ gpio_keys_pdata = devm_kzalloc(dev,
sizeof(*gpio_keys_pdata) +
sizeof(*gpio_keys) * MAX_NBUTTONS,
GFP_KERNEL);
@@ -93,7 +79,9 @@ soc_button_device_create(struct platform_device *pdev,
if (info->autorepeat != autorepeat)
continue;
- gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
+ gpio = soc_button_lookup_gpio(dev,
+ gpiod_con_id,
+ info->acpi_index);
if (!gpio_is_valid(gpio))
continue;
@@ -142,14 +130,12 @@ soc_button_device_create(struct platform_device *pdev,
err_free_pdev:
platform_device_put(pd);
err_free_mem:
- devm_kfree(&pdev->dev, gpio_keys_pdata);
+ devm_kfree(dev, gpio_keys_pdata);
return ERR_PTR(error);
}
-static int soc_button_remove(struct platform_device *pdev)
+int soc_dev_button_remove(struct soc_button_data *priv)
{
- struct soc_button_data *priv = platform_get_drvdata(pdev);
-
int i;
for (i = 0; i < BUTTON_TYPES; i++)
@@ -158,40 +144,28 @@ static int soc_button_remove(struct platform_device *pdev)
return 0;
}
+EXPORT_SYMBOL_GPL(soc_dev_button_remove);
-static int soc_button_probe(struct platform_device *pdev)
+int soc_dev_button_enumerate(struct device *dev, struct soc_button_data *priv,
+ const char *gpiod_con_id,
+ struct soc_button_info *button_info)
{
- struct device *dev = &pdev->dev;
- const struct acpi_device_id *id;
- 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;
-
- button_info = (struct soc_button_info *)id->driver_data;
-
- if (gpiod_count(&pdev->dev, KBUILD_MODNAME) <= 0) {
- dev_info(&pdev->dev, "no GPIO attached, ignoring...\n");
+ if (gpiod_count(dev, gpiod_con_id) <= 0) {
+ dev_info(dev, "no GPIO attached, ignoring...\n");
return -ENODEV;
}
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, priv);
-
for (i = 0; i < BUTTON_TYPES; i++) {
- pd = soc_button_device_create(pdev, button_info, i == 0);
+ pd = soc_button_device_create(dev, gpiod_con_id, button_info,
+ i == 0);
if (IS_ERR(pd)) {
error = PTR_ERR(pd);
if (error != -ENODEV) {
- soc_button_remove(pdev);
+ soc_dev_button_remove(priv);
return error;
}
continue;
@@ -205,6 +179,46 @@ static int soc_button_probe(struct platform_device *pdev)
return 0;
}
+EXPORT_SYMBOL_GPL(soc_dev_button_enumerate);
+
+struct soc_button_data *soc_dev_button_data_allocate(struct device *dev)
+{
+ return devm_kzalloc(dev, sizeof(struct soc_button_data), GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(soc_dev_button_data_allocate);
+
+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;
+ struct soc_button_data *priv;
+ int error;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return -ENODEV;
+
+ button_info = (struct soc_button_info *)id->driver_data;
+
+ priv = soc_dev_button_data_allocate(dev);
+ if (!priv)
+ return -ENOMEM;
+
+ error = soc_dev_button_enumerate(dev, priv, KBUILD_MODNAME,
+ button_info);
+ if (error)
+ return error;
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+}
+
+static int soc_button_remove(struct platform_device *pdev)
+{
+ return soc_dev_button_remove(platform_get_drvdata(pdev));
+}
static struct soc_button_info soc_button_PNP0C40[] = {
{ "power", 0, EV_KEY, KEY_POWER, false, true, true },
diff --git a/include/linux/input/soc_button_array.h b/include/linux/input/soc_button_array.h
new file mode 100644
index 0000000..634ce90
--- /dev/null
+++ b/include/linux/input/soc_button_array.h
@@ -0,0 +1,37 @@
+/*
+ * Supports for the button array on SoC tablets originally running
+ * Windows 8.
+ *
+ * (C) Copyright 2014 Intel Corporation
+ * (C) Copyright 2016 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+/*
+ * Definition of buttons on the tablet. The ACPI index of each button
+ * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
+ * Platforms"
+ */
+#define MAX_NBUTTONS 5
+
+struct soc_button_info {
+ const char *name;
+ int acpi_index;
+ unsigned int event_type;
+ unsigned int event_code;
+ bool autorepeat;
+ bool wakeup;
+ bool active_low;
+};
+
+struct soc_button_data;
+
+struct soc_button_data *soc_dev_button_data_allocate(struct device *dev);
+int soc_dev_button_remove(struct soc_button_data *priv);
+int soc_dev_button_enumerate(struct device *dev, struct soc_button_data *priv,
+ const char *gpiod_con_id,
+ struct soc_button_info *button_info);
--
2.7.4

View File

@ -0,0 +1,181 @@
From d25373cf47d005fbab3b363a32fa9d890ead1a51 Mon Sep 17 00:00:00 2001
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Date: Fri, 13 May 2016 17:54:09 +0200
Subject: [PATCH 6/6] Input - surface3_button_array: Introduce button support
for the Surface 3
The Surface 3 is not following the ACPI spec for PNP0C40, but nearly.
The device is connected to a I2C device that might have some magic
but we don't know about.
Just create the device after the enumeration and use the declared GPIOs
to provide button support.
The Surface Pro 3 is using an ACPI driver and matches against the bid
of the device ("VGBI") but I think it also could use this. To prevent
this driver to be used on the Surface Pro, we add a match on the
Surface 3 bid "TEV2".
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
drivers/input/misc/Kconfig | 9 +++
drivers/input/misc/Makefile | 1 +
drivers/input/misc/surface3_button_array.c | 115 +++++++++++++++++++++++++++++
3 files changed, 125 insertions(+)
create mode 100644 drivers/input/misc/surface3_button_array.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index efb0ca8..6f99d3b 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -776,6 +776,15 @@ config INPUT_SOC_BUTTON_ARRAY
To compile this driver as a module, choose M here: the
module will be called soc_button_array.
+config INPUT_SURFACE3_BUTTON_ARRAY
+ tristate "Microsoft Surface 3 SoC Button Array"
+ depends on INPUT_SOC_BUTTON_ARRAY
+ help
+ Say Y here if you have a MS Surface tablet.
+
+ To compile this driver as a module, choose M here: the
+ module will be called surface3_button_array.
+
config INPUT_DRV260X_HAPTICS
tristate "TI DRV260X haptics support"
depends on INPUT && I2C
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 6a1e5e2..020b24a 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
obj-$(CONFIG_INPUT_SIRFSOC_ONKEY) += sirfsoc-onkey.o
obj-$(CONFIG_INPUT_SOC_BUTTON_ARRAY) += soc_button_array.o
obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o
+obj-$(CONFIG_INPUT_SURFACE3_BUTTON_ARRAY) += surface3_button_array.o
obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON) += tps65218-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o
obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o
diff --git a/drivers/input/misc/surface3_button_array.c b/drivers/input/misc/surface3_button_array.c
new file mode 100644
index 0000000..b48307c
--- /dev/null
+++ b/drivers/input/misc/surface3_button_array.c
@@ -0,0 +1,115 @@
+/*
+ * Supports for the button array on the Surface tablets.
+ *
+ * (C) Copyright 2016 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/acpi.h>
+#include <linux/input/soc_button_array.h>
+#include <uapi/linux/input-event-codes.h>
+
+struct soc_device_info {
+ const char * const *obj_names;
+ struct soc_button_info *buttons;
+};
+
+static int surface3_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ const char *bid, *obj_name;
+ struct soc_device_info *device_info;
+ struct soc_button_data *priv;
+ int error;
+ int i;
+
+ if (!id->driver_data)
+ return -EINVAL;
+
+ device_info = (struct soc_device_info *)id->driver_data;
+
+ if (device_info->obj_names) {
+ bid = acpi_device_bid(ACPI_COMPANION(&client->dev));
+ i = 0;
+ do {
+ obj_name = device_info->obj_names[i++];
+ if (obj_name && !strcmp(bid, obj_name))
+ break;
+ } while (obj_name);
+ /* no acpi_device_bid match, bail out */
+ if (!obj_name)
+ return -ENODEV;
+ }
+
+ priv = soc_dev_button_data_allocate(&client->dev);
+ if (!priv)
+ return -ENOMEM;
+
+ error = soc_dev_button_enumerate(&client->dev, priv, NULL,
+ device_info->buttons);
+ if (error)
+ return error;
+
+ i2c_set_clientdata(client, priv);
+
+ return 0;
+}
+
+static int surface3_remove(struct i2c_client *client)
+{
+ return soc_dev_button_remove(i2c_get_clientdata(client));
+}
+
+static struct soc_button_info soc_button_surface3[] = {
+ { "power", 0, EV_KEY, KEY_POWER, false, true, true },
+ { "home", 1, EV_KEY, KEY_LEFTMETA, false, true, false },
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false, true },
+ { "volume_down", 3, EV_KEY, KEY_VOLUMEDOWN, true, false, true },
+ { }
+};
+
+static const char * const soc_device_obj_names_surface3[] = {
+ "TEV2",
+ 0,
+};
+
+static const struct soc_device_info soc_device_surface3 = {
+ .obj_names = soc_device_obj_names_surface3,
+ .buttons = soc_button_surface3,
+};
+
+static const struct i2c_device_id surface3_id[] = {
+ { "MSHW0028:00", (unsigned long)&soc_device_surface3 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, surface3_id);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id surface3_acpi_match[] = {
+ { "MSHW0028", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, surface3_acpi_match);
+#endif
+
+static struct i2c_driver surface3_driver = {
+ .probe = surface3_probe,
+ .remove = surface3_remove,
+ .id_table = surface3_id,
+ .driver = {
+ .name = "surface3",
+ .acpi_match_table = ACPI_PTR(surface3_acpi_match),
+ },
+};
+module_i2c_driver(surface3_driver);
+
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
+MODULE_DESCRIPTION("surface3 button array driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4

View File

@ -2563,6 +2563,7 @@ CONFIG_INPUT_RETU_PWRBUTTON=m
CONFIG_INPUT_UINPUT=m
CONFIG_INPUT_WISTRON_BTNS=m
CONFIG_INPUT_ATLAS_BTNS=m
CONFIG_INPUT_SURFACE3_BUTTON_ARRAY=m
CONFIG_INPUT_ATI_REMOTE2=m
CONFIG_INPUT_KEYSPAN_REMOTE=m

View File

@ -639,6 +639,13 @@ Patch903: 0001-HID-input-rework-HID_QUIRK_MULTI_INPUT.patch
Patch904: 0002-HID-multitouch-enable-the-Surface-3-Type-Cover-to-re.patch
Patch905: 0003-HID-multitouch-set-correct-class-for-Surface-Type-Co.patch
Patch906: 0001-Input-soc_button_array-use-gpio_is_valid.patch
Patch907: 0002-Input-soc_button_array-bail-out-earlier-if-gpiod_cou.patch
Patch908: 0003-Input-soc_button_array-make-sure-one-GPIO-is-not-ass.patch
Patch909: 0004-Input-soc_button_array-allow-to-specify-active_low.patch
Patch910: 0005-Input-soc_button_array-export-part-of-the-internals.patch
Patch911: 0006-Input-surface3_button_array-Introduce-button-support.patch
# END OF PATCH DEFINITIONS
%endif