[PATCH] platform/x86: Add GETAC MPMD programmable button driver

From: Zhan Chubukou

Date: Tue Jul 14 2026 - 20:42:21 EST


From: chubukou <chubukou@xxxxxxxxx>

GETAC rugged laptops (e.g. S410) expose vendor button events through an
ACPI device "MPMD" with hardware ID MTC0303. The Embedded Controller
raises query methods that issue Notify(MPMD, <code>) on programmable /
hotkey button activity. Because no Linux driver binds MTC0303, these
notifies are silently dropped and the buttons appear dead under Linux
(neither libinput nor acpid observe them: they are device notifies, not
generic ACPI events).

Add a minimal ACPI driver that binds MTC0303 and forwards the notifies
as input events through a sparse-keymap. On the S410 (BIOS R1.25) the
programmable P2 button generates Notify(MPMD, 0x97) and is mapped to
KEY_PROG1. Other buttons in the 0xC0..0xCB range (EC queries _Q81.._Q89,
_Q6A, _Q6B) remain unmapped until confirmed on a given model; enable
dynamic-debug to identify them.

Signed-off-by: chubukou <chubukou@xxxxxxxxx>
---
MAINTAINERS | 6 ++
drivers/platform/x86/Kconfig | 11 ++++
drivers/platform/x86/Makefile | 3 +
drivers/platform/x86/getac-mpmd.c | 96 +++++++++++++++++++++++++++++++
4 files changed, 116 insertions(+)
create mode 100644 drivers/platform/x86/getac-mpmd.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ce5c518..9bdabdf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11014,6 +11014,12 @@ F: Documentation/filesystems/gfs2/
F: fs/gfs2/
F: include/uapi/linux/gfs2_ondisk.h

+GETAC MPMD DRIVER
+M: chubukou <chubukou@xxxxxxxxx>
+L: platform-driver-x86@xxxxxxxxxxxxxxx
+S: Maintained
+F: drivers/platform/x86/getac-mpmd.c
+
GIGABYTE WATERFORCE SENSOR DRIVER
M: Aleksa Savic <savicaleksa83@xxxxxxxxx>
L: linux-hwmon@xxxxxxxxxxxxxxx
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index b54b521..2effb96 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -440,6 +440,17 @@ config FUJITSU_TABLET

If you have a Fujitsu convertible or slate, say Y or M here.

+config GETAC_MPMD
+ tristate "GETAC MPMD programmable button support"
+ depends on ACPI
+ help
+ Driver for the GETAC MPMD ACPI device (HID MTC0303) which forwards
+ Embedded Controller button events (e.g. the programmable P2 button)
+ as input key events. Without this driver the buttons are silently
+ dropped and appear dead under Linux.
+
+ Say Y or M if you have a GETAC rugged laptop (e.g. S410).
+
config GPD_POCKET_FAN
tristate "GPD Pocket Fan Controller support"
depends on ACPI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 872ac38..8896da3 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -57,6 +57,9 @@ obj-$(CONFIG_FUJITSU_TABLET) += fujitsu-tablet.o
# GPD
obj-$(CONFIG_GPD_POCKET_FAN) += gpd-pocket-fan.o

+# GETAC
+obj-$(CONFIG_GETAC_MPMD) += getac-mpmd.o
+
# Hewlett Packard
obj-$(CONFIG_X86_PLATFORM_DRIVERS_HP) += hp/

diff --git a/drivers/platform/x86/getac-mpmd.c b/drivers/platform/x86/getac-mpmd.c
new file mode 100644
index 0000000..0f1ec8b
--- /dev/null
+++ b/drivers/platform/x86/getac-mpmd.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * GETAC MPMD programmable button driver
+ *
+ * GETAC rugged laptops expose vendor events through an ACPI device named
+ * "MPMD" with hardware ID MTC0303. The Embedded Controller raises query
+ * methods that Notify(MPMD, <code>) on programmable / hotkey button
+ * activity. Without a driver bound to MTC0303 these notifies are silently
+ * dropped, so the buttons appear dead under Linux.
+ *
+ * This driver binds MTC0303 and forwards the notifies as input events.
+ *
+ * Observed on GETAC S410 (BIOS R1.25.070520):
+ * 0x97 P2 programmable button (repeats at ~3 Hz while held)
+ *
+ * The 0xC0..0xCB range is generated by EC query methods _Q81.._Q89, _Q6A
+ * and _Q6B and is left as KEY_UNKNOWN until a button is confirmed; enable
+ * module dynamic-debug to identify further buttons on a given model.
+ *
+ * Copyright (C) 2026 chubukou <chubukou@xxxxxxxxx>
+ */
+
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
+
+struct getac_mpmd_priv {
+ struct input_dev *input;
+};
+
+static const struct key_entry getac_mpmd_keymap[] = {
+ { KE_KEY, 0x97, { KEY_PROG1 } }, /* P2 programmable button */
+ { KE_END, 0 }
+};
+
+static void getac_mpmd_notify(struct acpi_device *adev, u32 event)
+{
+ struct getac_mpmd_priv *priv = acpi_driver_data(adev);
+
+ if (!sparse_keymap_report_event(priv->input, event, 1, true))
+ dev_dbg(&adev->dev, "unknown notify event 0x%02x\n", event);
+}
+
+static int getac_mpmd_add(struct acpi_device *adev)
+{
+ struct getac_mpmd_priv *priv;
+ struct input_dev *input;
+ int ret;
+
+ priv = devm_kzalloc(&adev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ input = devm_input_allocate_device(&adev->dev);
+ if (!input)
+ return -ENOMEM;
+
+ input->name = "GETAC MPMD programmable buttons";
+ input->phys = "getac-mpmd/input0";
+ input->id.bustype = BUS_HOST;
+
+ ret = sparse_keymap_setup(input, getac_mpmd_keymap, NULL);
+ if (ret)
+ return ret;
+
+ ret = input_register_device(input);
+ if (ret)
+ return ret;
+
+ priv->input = input;
+ adev->driver_data = priv;
+ return 0;
+}
+
+static const struct acpi_device_id getac_mpmd_ids[] = {
+ { "MTC0303" },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, getac_mpmd_ids);
+
+static struct acpi_driver getac_mpmd_driver = {
+ .name = "getac_mpmd",
+ .class = "getac",
+ .ids = getac_mpmd_ids,
+ .ops = {
+ .add = getac_mpmd_add,
+ .notify = getac_mpmd_notify,
+ },
+};
+
+module_acpi_driver(getac_mpmd_driver);
+
+MODULE_AUTHOR("chubukou <chubukou@xxxxxxxxx>");
+MODULE_DESCRIPTION("GETAC MPMD (MTC0303) programmable button driver");
+MODULE_LICENSE("GPL");
--
2.55.0