* [RFC PATCH 1/3] platform: lenovo: move the architecture independent WMI drivers out of x86
2026-11-13 22:27 [RFC PATCH 0/3] platform: lenovo: architecture independent home for the Lenovo WMI drivers David Cemin
@ 2026-11-13 22:27 ` David Cemin
2026-11-13 22:27 ` [RFC PATCH 2/3] platform: lenovo: add WMI hotkeys driver David Cemin
2026-11-13 22:27 ` [RFC PATCH 3/3] platform/x86: ideapad-laptop: do not bind the WMI event devices without the VPC David Cemin
2 siblings, 0 replies; 4+ messages in thread
From: David Cemin @ 2026-11-13 22:27 UTC (permalink / raw)
To: hansg, ilpo.jarvinen, W_Armin
Cc: mpearson-lenovo, derekjohn.clark, xy-jackie, ikepanhc,
platform-driver-x86, linux-kernel, ldemarchi
The Lenovo WMI drivers (events, helpers, capability data, GameZone,
Other Mode, hotkey utilities and camera button) contain no x86 specific
code: they talk to firmware through the ACPI-WMI core only. They live
under drivers/platform/x86 because that is where Lenovo drivers were
collected, and X86_PLATFORM_DEVICES keeps them off every other
architecture.
Lenovo now ships ACPI based arm64 laptops whose firmware exposes the
same WMI GUIDs (the Fn key events, the mic mute LED method, GameZone and
Other Mode). Give these drivers an architecture independent home,
drivers/platform/lenovo, following the layout of drivers/platform/surface
which exists for the same reason, so they can be built wherever the WMI
core is available. ideapad-laptop, thinkpad_acpi, think-lmi, yogabook and
the Yoga Tablet drivers stay under x86: they depend on i8042, port I/O or
x86 only ACPI devices.
Pure code motion: the files, their Kconfig entries and the module naming
scheme are unchanged. MAINTAINERS entries are updated for the new paths.
Signed-off-by: David Cemin <dcemin@nvidia.com>
---
MAINTAINERS | 3 +-
drivers/platform/Kconfig | 2 +
drivers/platform/Makefile | 1 +
drivers/platform/lenovo/Kconfig | 87 +++++++++++++++++++
drivers/platform/lenovo/Makefile | 22 +++++
.../platform/{x86 => }/lenovo/wmi-camera.c | 0
.../platform/{x86 => }/lenovo/wmi-capdata.c | 0
.../platform/{x86 => }/lenovo/wmi-capdata.h | 0
.../platform/{x86 => }/lenovo/wmi-events.c | 0
.../platform/{x86 => }/lenovo/wmi-events.h | 0
.../platform/{x86 => }/lenovo/wmi-gamezone.c | 0
.../platform/{x86 => }/lenovo/wmi-helpers.c | 0
.../platform/{x86 => }/lenovo/wmi-helpers.h | 0
.../{x86 => }/lenovo/wmi-hotkey-utilities.c | 0
drivers/platform/{x86 => }/lenovo/wmi-other.c | 0
drivers/platform/x86/lenovo/Kconfig | 67 --------------
drivers/platform/x86/lenovo/Makefile | 7 --
17 files changed, 114 insertions(+), 75 deletions(-)
create mode 100644 drivers/platform/lenovo/Kconfig
create mode 100644 drivers/platform/lenovo/Makefile
rename drivers/platform/{x86 => }/lenovo/wmi-camera.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-capdata.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-capdata.h (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-events.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-events.h (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-gamezone.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-helpers.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-helpers.h (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-hotkey-utilities.c (100%)
rename drivers/platform/{x86 => }/lenovo/wmi-other.c (100%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 056408bc086e..3b0ad5a3debe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15170,13 +15170,14 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: Documentation/wmi/devices/lenovo-wmi-gamezone.rst
F: Documentation/wmi/devices/lenovo-wmi-other.rst
+F: drivers/platform/lenovo/
F: drivers/platform/x86/lenovo/*
LENOVO WMI HOTKEY UTILITIES DRIVER
M: Jackie Dong <xy-jackie@139.com>
L: platform-driver-x86@vger.kernel.org
S: Maintained
-F: drivers/platform/x86/lenovo/wmi-hotkey-utilities.c
+F: drivers/platform/lenovo/wmi-hotkey-utilities.c
LENOVO HID drivers
M: Derek J. Clark <derekjohn.clark@gmail.com>
diff --git a/drivers/platform/Kconfig b/drivers/platform/Kconfig
index 312788f249c9..80b2b83b69e5 100644
--- a/drivers/platform/Kconfig
+++ b/drivers/platform/Kconfig
@@ -15,6 +15,8 @@ source "drivers/platform/olpc/Kconfig"
source "drivers/platform/surface/Kconfig"
+source "drivers/platform/lenovo/Kconfig"
+
source "drivers/platform/x86/Kconfig"
source "drivers/platform/arm64/Kconfig"
diff --git a/drivers/platform/Makefile b/drivers/platform/Makefile
index fa322e7f8716..0144f88ff6db 100644
--- a/drivers/platform/Makefile
+++ b/drivers/platform/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_GOLDFISH) += goldfish/
obj-$(CONFIG_CHROME_PLATFORMS) += chrome/
obj-$(CONFIG_CZNIC_PLATFORMS) += cznic/
obj-$(CONFIG_SURFACE_PLATFORMS) += surface/
+obj-$(CONFIG_LENOVO_PLATFORMS) += lenovo/
obj-$(CONFIG_ARM64_PLATFORM_DEVICES) += arm64/
obj-$(CONFIG_BCM2835_VCHIQ) += raspberrypi/
obj-$(CONFIG_ACPI_WMI) += wmi/
diff --git a/drivers/platform/lenovo/Kconfig b/drivers/platform/lenovo/Kconfig
new file mode 100644
index 000000000000..8222322ca671
--- /dev/null
+++ b/drivers/platform/lenovo/Kconfig
@@ -0,0 +1,87 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Lenovo Platform-Specific Drivers
+#
+
+menuconfig LENOVO_PLATFORMS
+ bool "Lenovo Platform-Specific Device Drivers"
+ depends on ARM64 || X86 || COMPILE_TEST
+ default y if ARM64 || X86
+ help
+ Say Y here to get to see options for platform-specific device drivers
+ for Lenovo devices that do not depend on the CPU architecture, such
+ as the ACPI-WMI based drivers used on both x86 and arm64 laptops.
+ This option alone does not add any kernel code.
+
+ If you say N, all options in this submenu will be skipped and disabled.
+
+if LENOVO_PLATFORMS
+
+config LENOVO_WMI_HELPERS
+ tristate
+ depends on ACPI_WMI
+
+config LENOVO_WMI_EVENTS
+ tristate
+ depends on ACPI_WMI
+
+config LENOVO_WMI_CAPDATA
+ tristate
+ depends on ACPI_WMI
+ depends on LENOVO_WMI_HELPERS
+
+config LENOVO_WMI_HOTKEY_UTILITIES
+ tristate "Lenovo Hotkey Utility WMI extras driver"
+ depends on ACPI_WMI
+ select NEW_LEDS
+ select LEDS_CLASS
+ imply IDEAPAD_LAPTOP
+ help
+ This driver provides WMI support for Lenovo customized hotkeys function,
+ such as LED control for audio/mic mute event for Ideapad, YOGA, XiaoXin,
+ Gaming, ThinkBook and so on.
+
+config LENOVO_WMI_CAMERA
+ tristate "Lenovo WMI Camera Button driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ help
+ This driver provides support for Lenovo camera button. The Camera
+ button is a GPIO device. This driver receives ACPI notifications when
+ the camera button is switched on/off.
+
+ To compile this driver as a module, choose M here: the module
+ will be called lenovo-wmi-camera.
+
+config LENOVO_WMI_GAMEZONE
+ tristate "Lenovo GameZone WMI Driver"
+ depends on ACPI_WMI
+ depends on DMI
+ select ACPI_PLATFORM_PROFILE
+ select LENOVO_WMI_EVENTS
+ select LENOVO_WMI_HELPERS
+ help
+ Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
+ platform-profile firmware interface to manage power usage.
+
+ To compile this driver as a module, choose M here: the module will
+ be called lenovo-wmi-gamezone.
+
+config LENOVO_WMI_TUNING
+ tristate "Lenovo Other Mode WMI Driver"
+ depends on ACPI_WMI
+ depends on ACPI_BATTERY
+ select HWMON
+ select FW_ATTR_CLASS
+ select LENOVO_WMI_CAPDATA
+ select LENOVO_WMI_EVENTS
+ select LENOVO_WMI_HELPERS
+ help
+ Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
+ firmware_attributes API to control various tunable settings typically exposed by
+ Lenovo software in Windows.
+
+ To compile this driver as a module, choose M here: the module will
+ be called lenovo-wmi-other.
+
+endif # LENOVO_PLATFORMS
diff --git a/drivers/platform/lenovo/Makefile b/drivers/platform/lenovo/Makefile
new file mode 100644
index 000000000000..1cac115dd735
--- /dev/null
+++ b/drivers/platform/lenovo/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for linux/drivers/platform/lenovo
+# Lenovo Platform Specific Drivers (architecture independent)
+#
+
+lenovo-target-$(CONFIG_LENOVO_WMI_HELPERS) += wmi-helpers.o
+lenovo-target-$(CONFIG_LENOVO_WMI_EVENTS) += wmi-events.o
+lenovo-target-$(CONFIG_LENOVO_WMI_CAPDATA) += wmi-capdata.o
+lenovo-target-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += wmi-hotkey-utilities.o
+lenovo-target-$(CONFIG_LENOVO_WMI_CAMERA) += wmi-camera.o
+lenovo-target-$(CONFIG_LENOVO_WMI_GAMEZONE) += wmi-gamezone.o
+lenovo-target-$(CONFIG_LENOVO_WMI_TUNING) += wmi-other.o
+
+# Add 'lenovo' prefix to each module listed in lenovo-target-*
+define LENOVO_OBJ_TARGET
+lenovo-$(1)-y := $(1).o
+obj-$(2) += lenovo-$(1).o
+endef
+
+$(foreach target, $(basename $(lenovo-target-y)), $(eval $(call LENOVO_OBJ_TARGET,$(target),y)))
+$(foreach target, $(basename $(lenovo-target-m)), $(eval $(call LENOVO_OBJ_TARGET,$(target),m)))
diff --git a/drivers/platform/x86/lenovo/wmi-camera.c b/drivers/platform/lenovo/wmi-camera.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-camera.c
rename to drivers/platform/lenovo/wmi-camera.c
diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/lenovo/wmi-capdata.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-capdata.c
rename to drivers/platform/lenovo/wmi-capdata.c
diff --git a/drivers/platform/x86/lenovo/wmi-capdata.h b/drivers/platform/lenovo/wmi-capdata.h
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-capdata.h
rename to drivers/platform/lenovo/wmi-capdata.h
diff --git a/drivers/platform/x86/lenovo/wmi-events.c b/drivers/platform/lenovo/wmi-events.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-events.c
rename to drivers/platform/lenovo/wmi-events.c
diff --git a/drivers/platform/x86/lenovo/wmi-events.h b/drivers/platform/lenovo/wmi-events.h
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-events.h
rename to drivers/platform/lenovo/wmi-events.h
diff --git a/drivers/platform/x86/lenovo/wmi-gamezone.c b/drivers/platform/lenovo/wmi-gamezone.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-gamezone.c
rename to drivers/platform/lenovo/wmi-gamezone.c
diff --git a/drivers/platform/x86/lenovo/wmi-helpers.c b/drivers/platform/lenovo/wmi-helpers.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-helpers.c
rename to drivers/platform/lenovo/wmi-helpers.c
diff --git a/drivers/platform/x86/lenovo/wmi-helpers.h b/drivers/platform/lenovo/wmi-helpers.h
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-helpers.h
rename to drivers/platform/lenovo/wmi-helpers.h
diff --git a/drivers/platform/x86/lenovo/wmi-hotkey-utilities.c b/drivers/platform/lenovo/wmi-hotkey-utilities.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-hotkey-utilities.c
rename to drivers/platform/lenovo/wmi-hotkey-utilities.c
diff --git a/drivers/platform/x86/lenovo/wmi-other.c b/drivers/platform/lenovo/wmi-other.c
similarity index 100%
rename from drivers/platform/x86/lenovo/wmi-other.c
rename to drivers/platform/lenovo/wmi-other.c
diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig
index 516594993073..36bcefb61805 100644
--- a/drivers/platform/x86/lenovo/Kconfig
+++ b/drivers/platform/x86/lenovo/Kconfig
@@ -20,29 +20,6 @@ config IDEAPAD_LAPTOP
This is a driver for Lenovo IdeaPad netbooks contains drivers for
rfkill switch, hotkey, fan control and backlight control.
-config LENOVO_WMI_HOTKEY_UTILITIES
- tristate "Lenovo Hotkey Utility WMI extras driver"
- depends on ACPI_WMI
- select NEW_LEDS
- select LEDS_CLASS
- imply IDEAPAD_LAPTOP
- help
- This driver provides WMI support for Lenovo customized hotkeys function,
- such as LED control for audio/mic mute event for Ideapad, YOGA, XiaoXin,
- Gaming, ThinkBook and so on.
-
-config LENOVO_WMI_CAMERA
- tristate "Lenovo WMI Camera Button driver"
- depends on ACPI_WMI
- depends on INPUT
- help
- This driver provides support for Lenovo camera button. The Camera
- button is a GPIO device. This driver receives ACPI notifications when
- the camera button is switched on/off.
-
- To compile this driver as a module, choose M here: the module
- will be called lenovo-wmi-camera.
-
config LENOVO_YB9_KBDOCK
tristate "Lenovo Yoga Book 9 keyboard dock detection"
depends on ACPI_WMI
@@ -246,47 +223,3 @@ config YT2_1380
To compile this driver as a module, choose M here: the module will
be called lenovo-yogabook.
-
-config LENOVO_WMI_CAPDATA
- tristate
- depends on ACPI_WMI
- depends on LENOVO_WMI_HELPERS
-
-config LENOVO_WMI_EVENTS
- tristate
- depends on ACPI_WMI
-
-config LENOVO_WMI_HELPERS
- tristate
- depends on ACPI_WMI
-
-config LENOVO_WMI_GAMEZONE
- tristate "Lenovo GameZone WMI Driver"
- depends on ACPI_WMI
- depends on DMI
- select ACPI_PLATFORM_PROFILE
- select LENOVO_WMI_EVENTS
- select LENOVO_WMI_HELPERS
- help
- Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
- platform-profile firmware interface to manage power usage.
-
- To compile this driver as a module, choose M here: the module will
- be called lenovo-wmi-gamezone.
-
-config LENOVO_WMI_TUNING
- tristate "Lenovo Other Mode WMI Driver"
- depends on ACPI_WMI
- depends on ACPI_BATTERY
- select HWMON
- select FW_ATTR_CLASS
- select LENOVO_WMI_CAPDATA
- select LENOVO_WMI_EVENTS
- select LENOVO_WMI_HELPERS
- help
- Say Y here if you have a WMI aware Lenovo Legion device and would like to use the
- firmware_attributes API to control various tunable settings typically exposed by
- Lenovo software in Windows.
-
- To compile this driver as a module, choose M here: the module will
- be called lenovo-wmi-other.
diff --git a/drivers/platform/x86/lenovo/Makefile b/drivers/platform/x86/lenovo/Makefile
index 12816d8d5e24..758c36cedee8 100644
--- a/drivers/platform/x86/lenovo/Makefile
+++ b/drivers/platform/x86/lenovo/Makefile
@@ -7,17 +7,10 @@ obj-$(CONFIG_IDEAPAD_LAPTOP) += ideapad-laptop.o
obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
-lenovo-target-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += wmi-hotkey-utilities.o
lenovo-target-$(CONFIG_LENOVO_YB9_KBDOCK) += yb9-kbdock.o
lenovo-target-$(CONFIG_LENOVO_YMC) += ymc.o
lenovo-target-$(CONFIG_YOGABOOK) += yogabook.o
lenovo-target-$(CONFIG_YT2_1380) += yoga-tab2-pro-1380-fastcharger.o
-lenovo-target-$(CONFIG_LENOVO_WMI_CAMERA) += wmi-camera.o
-lenovo-target-$(CONFIG_LENOVO_WMI_CAPDATA) += wmi-capdata.o
-lenovo-target-$(CONFIG_LENOVO_WMI_EVENTS) += wmi-events.o
-lenovo-target-$(CONFIG_LENOVO_WMI_HELPERS) += wmi-helpers.o
-lenovo-target-$(CONFIG_LENOVO_WMI_GAMEZONE) += wmi-gamezone.o
-lenovo-target-$(CONFIG_LENOVO_WMI_TUNING) += wmi-other.o
# Add 'lenovo' prefix to each module listed in lenovo-target-*
define LENOVO_OBJ_TARGET
--
2.56.1
^ permalink raw reply [flat|nested] 4+ messages in thread* [RFC PATCH 2/3] platform: lenovo: add WMI hotkeys driver
2026-11-13 22:27 [RFC PATCH 0/3] platform: lenovo: architecture independent home for the Lenovo WMI drivers David Cemin
2026-11-13 22:27 ` [RFC PATCH 1/3] platform: lenovo: move the architecture independent WMI drivers out of x86 David Cemin
@ 2026-11-13 22:27 ` David Cemin
2026-11-13 22:27 ` [RFC PATCH 3/3] platform/x86: ideapad-laptop: do not bind the WMI event devices without the VPC David Cemin
2 siblings, 0 replies; 4+ messages in thread
From: David Cemin @ 2026-11-13 22:27 UTC (permalink / raw)
To: hansg, ilpo.jarvinen, W_Armin
Cc: mpearson-lenovo, derekjohn.clark, xy-jackie, ikepanhc,
platform-driver-x86, linux-kernel, ldemarchi
Lenovo consumer laptops deliver their vendor specific Fn keys (microphone
mute, airplane mode, performance mode, the Smart Key and Smart Connect
keys) as WMI events on GUID 8FC0DE0C-B4E4-43FD-B0F3-8871711C1294 instead
of keyboard usages. On x86, ideapad-laptop consumes these events, but it
depends on i8042 and on the IdeaPad VPC ACPI device, neither of which
exist on the ACPI based arm64 models. Add a small WMI driver that reports
the same key codes through a sparse keymap, so desktops see the generic
input events.
The key map follows ideapad-laptop. One code seen on the Yoga 9 2-in-1
16 (arm64) is new: 0x48 for the Smart Connect key.
Both drivers match the same GUID. The probe declines when the IdeaPad
VPC device (VPC2004) is present, so machines handled by ideapad-laptop,
including its Fn lock LED and DYTC performance mode handling, keep that
driver.
Signed-off-by: David Cemin <dcemin@nvidia.com>
---
MAINTAINERS | 6 +
drivers/platform/lenovo/Kconfig | 14 +++
drivers/platform/lenovo/Makefile | 1 +
drivers/platform/lenovo/wmi-hotkeys.c | 151 ++++++++++++++++++++++++++
4 files changed, 172 insertions(+)
create mode 100644 drivers/platform/lenovo/wmi-hotkeys.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 3b0ad5a3debe..207684aeaf69 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15173,6 +15173,12 @@ F: Documentation/wmi/devices/lenovo-wmi-other.rst
F: drivers/platform/lenovo/
F: drivers/platform/x86/lenovo/*
+LENOVO WMI HOTKEYS DRIVER
+M: David Cemin <dcemin@nvidia.com>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/lenovo/wmi-hotkeys.c
+
LENOVO WMI HOTKEY UTILITIES DRIVER
M: Jackie Dong <xy-jackie@139.com>
L: platform-driver-x86@vger.kernel.org
diff --git a/drivers/platform/lenovo/Kconfig b/drivers/platform/lenovo/Kconfig
index 8222322ca671..ba4248d56e5f 100644
--- a/drivers/platform/lenovo/Kconfig
+++ b/drivers/platform/lenovo/Kconfig
@@ -41,6 +41,20 @@ config LENOVO_WMI_HOTKEY_UTILITIES
such as LED control for audio/mic mute event for Ideapad, YOGA, XiaoXin,
Gaming, ThinkBook and so on.
+config LENOVO_WMI_HOTKEYS
+ tristate "Lenovo WMI hotkeys driver"
+ depends on ACPI_WMI
+ depends on INPUT
+ select INPUT_SPARSEKMAP
+ help
+ Say Y or M here to enable the vendor specific Fn keys (microphone
+ mute, airplane mode, performance mode, star key) on Lenovo laptops
+ that deliver them as WMI events and are not handled by the
+ ideapad-laptop driver, such as the ACPI based arm64 models.
+
+ To compile this driver as a module, choose M here: the module will
+ be called lenovo-wmi-hotkeys.
+
config LENOVO_WMI_CAMERA
tristate "Lenovo WMI Camera Button driver"
depends on ACPI_WMI
diff --git a/drivers/platform/lenovo/Makefile b/drivers/platform/lenovo/Makefile
index 1cac115dd735..d3f5e3ac14c2 100644
--- a/drivers/platform/lenovo/Makefile
+++ b/drivers/platform/lenovo/Makefile
@@ -8,6 +8,7 @@ lenovo-target-$(CONFIG_LENOVO_WMI_HELPERS) += wmi-helpers.o
lenovo-target-$(CONFIG_LENOVO_WMI_EVENTS) += wmi-events.o
lenovo-target-$(CONFIG_LENOVO_WMI_CAPDATA) += wmi-capdata.o
lenovo-target-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += wmi-hotkey-utilities.o
+lenovo-target-$(CONFIG_LENOVO_WMI_HOTKEYS) += wmi-hotkeys.o
lenovo-target-$(CONFIG_LENOVO_WMI_CAMERA) += wmi-camera.o
lenovo-target-$(CONFIG_LENOVO_WMI_GAMEZONE) += wmi-gamezone.o
lenovo-target-$(CONFIG_LENOVO_WMI_TUNING) += wmi-other.o
diff --git a/drivers/platform/lenovo/wmi-hotkeys.c b/drivers/platform/lenovo/wmi-hotkeys.c
new file mode 100644
index 000000000000..fc18867d8144
--- /dev/null
+++ b/drivers/platform/lenovo/wmi-hotkeys.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Lenovo WMI hotkey driver
+ *
+ * Lenovo consumer laptops deliver their vendor specific Fn keys (microphone
+ * mute, airplane mode, performance mode, the star key and others) as WMI
+ * events on GUID 8FC0DE0C-B4E4-43FD-B0F3-8871711C1294 instead of keyboard
+ * usages. On x86 ideapad-laptop consumes these events; that driver depends
+ * on i8042 and the IdeaPad VPC device, neither of which exist on the arm64
+ * platforms. This driver consumes the same event and reports the keys the
+ * same way, so desktops see the usual generic key codes.
+ *
+ * The key codes follow the mapping used by ideapad-laptop.
+ */
+
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+
+#define LENOVO_FN_KEYS_WMI_GUID "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294"
+
+static const struct key_entry lenovo_wmi_hotkeys_keymap[] = {
+ /* Customizable Lenovo Hotkey ("star" with 'S' inside) */
+ { KE_KEY, 0x01, { KEY_FAVORITES } },
+ /* Fn lock toggled on / off, firmware handles the LED */
+ { KE_IGNORE, 0x02 },
+ { KE_IGNORE, 0x03 },
+ { KE_KEY, 0x04, { KEY_SELECTIVE_SCREENSHOT } },
+ /* Lenovo Support */
+ { KE_KEY, 0x07, { KEY_HELP } },
+ { KE_KEY, 0x0a, { KEY_REFRESH_RATE_TOGGLE } },
+ { KE_KEY, 0x0e, { KEY_PICKUP_PHONE } },
+ { KE_KEY, 0x0f, { KEY_HANGUP_PHONE } },
+ { KE_KEY, 0x10, { KEY_REFRESH_RATE_TOGGLE } },
+ /* Sound profile switch */
+ { KE_KEY, 0x12, { KEY_PROG2 } },
+ /* Dark mode toggle */
+ { KE_KEY, 0x13, { KEY_PROG1 } },
+ /* Lenovo Support */
+ { KE_KEY, 0x27, { KEY_HELP } },
+ /* Lenovo Virtual Background application */
+ { KE_KEY, 0x28, { KEY_PROG3 } },
+ { KE_KEY, 0x29, { KEY_TOUCHPAD_TOGGLE } },
+ { KE_KEY, 0x2a, { KEY_ROOT_MENU } },
+ /* Shift + PrtSc */
+ { KE_KEY, 0x2d, { KEY_SELECTIVE_SCREENSHOT } },
+ /* Performance mode, Fn+Q */
+ { KE_KEY, 0x3d, { KEY_PROG4 } },
+ { KE_KEY, 0x3e, { KEY_MICMUTE } },
+ { KE_KEY, 0x3f, { KEY_RFKILL } },
+ /*
+ * Keyboard backlight level after Fn+Space, handled by the firmware:
+ * 0x40 off, 0x41 low, 0x42 high, 0x43 also seen
+ */
+ { KE_IGNORE, 0x40 },
+ { KE_IGNORE, 0x41 },
+ { KE_IGNORE, 0x42 },
+ { KE_IGNORE, 0x43 },
+ /* Star, user assignable key */
+ { KE_KEY, 0x44, { KEY_PROG1 } },
+ /* Eye care */
+ { KE_KEY, 0x45, { KEY_PROG3 } },
+ /* Smart Connect, phone to PC link */
+ { KE_KEY, 0x48, { KEY_PROG2 } },
+ { KE_END },
+};
+
+struct lenovo_wmi_hotkeys {
+ struct input_dev *input;
+};
+
+static int lenovo_wmi_hotkeys_probe(struct wmi_device *wdev, const void *context)
+{
+ struct lenovo_wmi_hotkeys *priv;
+ int ret;
+
+ /*
+ * ideapad-laptop binds the same GUID and handles these events together
+ * with the IdeaPad VPC device (Fn lock LED, DYTC performance mode
+ * cycling). Leave those machines to it.
+ */
+ if (acpi_dev_found("VPC2004")) {
+ dev_dbg(&wdev->dev, "IdeaPad VPC present, deferring to ideapad-laptop\n");
+ return -ENODEV;
+ }
+
+ priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->input = devm_input_allocate_device(&wdev->dev);
+ if (!priv->input)
+ return -ENOMEM;
+
+ priv->input->name = "Lenovo WMI hotkeys";
+ priv->input->phys = "wmi/input0";
+ priv->input->id.bustype = BUS_HOST;
+ priv->input->dev.parent = &wdev->dev;
+
+ ret = sparse_keymap_setup(priv->input, lenovo_wmi_hotkeys_keymap, NULL);
+ if (ret)
+ return ret;
+
+ ret = input_register_device(priv->input);
+ if (ret)
+ return ret;
+
+ dev_set_drvdata(&wdev->dev, priv);
+
+ return 0;
+}
+
+static void lenovo_wmi_hotkeys_notify(struct wmi_device *wdev, union acpi_object *data)
+{
+ struct lenovo_wmi_hotkeys *priv = dev_get_drvdata(&wdev->dev);
+ u32 code;
+
+ if (!data || data->type != ACPI_TYPE_INTEGER) {
+ dev_dbg(&wdev->dev, "event data is not an integer\n");
+ return;
+ }
+
+ code = data->integer.value;
+ dev_dbg(&wdev->dev, "hotkey event 0x%x\n", code);
+
+ if (!sparse_keymap_report_event(priv->input, code, 1, true))
+ dev_info_ratelimited(&wdev->dev, "unknown hotkey event 0x%x\n", code);
+}
+
+static const struct wmi_device_id lenovo_wmi_hotkeys_id_table[] = {
+ { LENOVO_FN_KEYS_WMI_GUID, NULL },
+ { }
+};
+MODULE_DEVICE_TABLE(wmi, lenovo_wmi_hotkeys_id_table);
+
+static struct wmi_driver lenovo_wmi_hotkeys_driver = {
+ .driver = {
+ .name = "lenovo-wmi-hotkeys",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = lenovo_wmi_hotkeys_id_table,
+ .probe = lenovo_wmi_hotkeys_probe,
+ .notify = lenovo_wmi_hotkeys_notify,
+ .no_singleton = true,
+};
+module_wmi_driver(lenovo_wmi_hotkeys_driver);
+
+MODULE_DESCRIPTION("Lenovo WMI hotkey driver");
+MODULE_LICENSE("GPL");
--
2.56.1
^ permalink raw reply [flat|nested] 4+ messages in thread