* [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi
@ 2026-09-29 13:44 Mingyou Chen
2026-09-29 13:44 ` [PATCH v6 1/5] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver Mingyou Chen
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:44 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen
This patch series consolidates the standalone 'redmi-wmi' driver into the
'bitland-mifs-wmi' driver to eliminate code duplication and centralize
the maintenance of overlapping ACPI WMI event streams.
Bitland is the ODM manufacturer for various Xiaomi Redmibook models. Both
platforms share the exact same keyboard event stream WMI GUID
(46C93E13-EE9B-4262-8488-563BCA757FEF). While redmi-wmi previously parsed
the 4-byte payload as a bulk u32 scancode, bitland-mifs-wmi deconstructed
it into discrete type/id/value fields.
Redmi operations were not contained in this patch series, future reverse
engineering is required.
This series introduce a newly reported mic-mute hotkey definition for Redmibooks
and dropped the previous redmi-wmi driver.
I don't have a Redmi or other Bitland device. So I cannot work on the
real device.
Features are working properly on my device (Lecoo Bellator N176).
I leave the future reverse engineering work to the community.
I apologize for not participating in kernel development over the past month.
Sorry for the late reply.
v6:
Drop the wrong Redmi ops
v5:
Correct Xiaomi DMI vendor name
v4:
Map PLATFORM_PROFILE_PERFORMANCE to wmi performance mode if the device
doesn't support full-speed mode.
Mingyou Chen (5):
MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver
platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into
the bitland driver
platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries
platform/x86: redmi-wmi: Drop redmi-wmi driver
platform/x86: bitland-mifs-wmi: Add per-machine ops table
MAINTAINERS | 5 +-
drivers/platform/x86/Kconfig | 12 --
drivers/platform/x86/Makefile | 1 -
drivers/platform/x86/bitland-mifs-wmi.c | 251 ++++++++++++++++++------
drivers/platform/x86/redmi-wmi.c | 154 ---------------
5 files changed, 189 insertions(+), 234 deletions(-)
delete mode 100644 drivers/platform/x86/redmi-wmi.c
base-commit: fe5030c8cc7156223f48530e9b49aa87c0305bcd
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 1/5] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
@ 2026-09-29 13:44 ` Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver Mingyou Chen
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:44 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen
Add a new maintainer entry for the bitland-mifs-wmi platform driver.
Signed-off-by: Mingyou Chen <qby140326@gmail.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index d55b637c32e1..c0b657dfe11f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23042,6 +23042,13 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/redmi-wmi.c
+BITLAND LAPTOP DRIVER
+M: Mingyou Chen <qby140326@gmail.com>
+M: Gladyshev Ilya <foxido@foxido.dev>
+L: platform-driver-x86@vger.kernel.org
+S: Maintained
+F: drivers/platform/x86/bitland-mifs-wmi.c
+
REDPINE WIRELESS DRIVER
L: linux-wireless@vger.kernel.org
S: Orphan
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
2026-09-29 13:44 ` [PATCH v6 1/5] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver Mingyou Chen
@ 2026-09-29 13:45 ` Mingyou Chen
2026-09-30 1:58 ` Anton Karasev
2026-09-29 13:45 ` [PATCH v6 3/5] platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries Mingyou Chen
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:45 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen,
Nika Krasnova
The bitland-mifs-wmi and legacy redmi-wmi drivers both attempt to bind
to the same WMI GUID (46C93E13-EE9B-4262-8488-563BCA757FEF). This
overlap causes a device registration conflict, preventing one of the
drivers from loading properly depending on the module initialization
order.
Merge the event handling logic from redmi-wmi into bitland-mifs-wmi. By
handling both device layouts within a single driver, we eliminate the
GUID ownership conflict.
Tested-by: Nika Krasnova <nika@nikableh.moe>
Signed-off-by: Mingyou Chen <qby140326@gmail.com>
---
drivers/platform/x86/bitland-mifs-wmi.c | 139 ++++++++++++++++--------
1 file changed, 96 insertions(+), 43 deletions(-)
diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
index dd1648b7de77..e1a81e89856e 100644
--- a/drivers/platform/x86/bitland-mifs-wmi.c
+++ b/drivers/platform/x86/bitland-mifs-wmi.c
@@ -35,6 +35,11 @@
#include <linux/units.h>
#include <linux/wmi.h>
+#define BI_HOTKEY_CODE(id, low, high) \
+ (((u32)(high) << 24) | ((u32)(low) << 16) | ((u32)(id) << 8) | WMI_EVENT_TYPE_HOTKEY)
+
+#define AI_KEY_VALUE_MASK BIT(8)
+
#define DRV_NAME "bitland-mifs-wmi"
#define BITLAND_MIFS_GUID "B60BFB48-3E5B-49E4-A0E9-8CFFE1B3434B"
#define BITLAND_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF"
@@ -607,18 +612,59 @@ static const struct attribute *const laptop_attrs[] = {
ATTRIBUTE_GROUPS(laptop);
static const struct key_entry bitland_mifs_wmi_keymap[] = {
- { KE_KEY, WMI_EVENT_OPEN_APP, { KEY_PROG1 } },
- { KE_KEY, WMI_EVENT_CALCULATOR_START, { KEY_CALC } },
- { KE_KEY, WMI_EVENT_BROWSER_START, { KEY_WWW } },
- { KE_IGNORE, WMI_EVENT_FN_J, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_F, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_0, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_1, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_2, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_3, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_4, { KEY_RESERVED } },
- { KE_IGNORE, WMI_EVENT_FN_5, { KEY_RESERVED } },
- { KE_END, 0 }
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_OPEN_APP, 1, 0), { KEY_PROG1 } },
+
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_CALCULATOR_START, 1, 0), { KEY_CALC } },
+
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_BROWSER_START, 1, 0), { KEY_WWW } },
+
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_J, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_F, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_0, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_1, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_2, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_3, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_4, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FN_5, 0, 0), {} },
+
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_2, 0, 0), { KEY_SELECTIVE_SCREENSHOT } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_3, 0, 0), { KEY_ALL_APPLICATIONS } },
+ { KE_KEY, BI_HOTKEY_CODE(0x1b, 0, 0), { KEY_CONFIG } },
+ { KE_KEY, BI_HOTKEY_CODE(0x1b, 1, 0), { KEY_CONFIG } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_1, 1, 0), { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_REFRESH_RATE, 0, 0), { KEY_REFRESH_RATE_TOGGLE } },
+
+ /* AI button has code for each position */
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_5, 1, 0), { KEY_ASSISTANT } },
+
+ { KE_KEY, BI_HOTKEY_CODE(0x19, 1, 0), { KEY_ASSISTANT } },
+
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_BRIGHTNESS, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_BRIGHTNESS, 0, 0x80), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_BRIGHTNESS, 5, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_BRIGHTNESS, 0x0a, 0), {} },
+
+ /* Xiaomi G Command Center */
+ { KE_KEY, BI_HOTKEY_CODE(0x0a, 1, 0), { KEY_VENDOR } },
+
+ /* OEM preset power mode */
+ { KE_IGNORE, BI_HOTKEY_CODE(0x16, 1, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(0x16, 2, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(0x16, 3, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(0x16, 4, 0), {} },
+
+ /* Fn Lock state */
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FNLOCK_STATE, 0, 0), {} },
+ { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FNLOCK_STATE, 1, 0), {} },
+
+ /* Fn+`/1/2/3/4 */
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_F, 1, 0), { KEY_F13 } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_0, 1, 0), { KEY_F14 } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_1, 1, 0), { KEY_F15 } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_2, 1, 0), { KEY_F16 } },
+ { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_3, 1, 0), { KEY_F17 } },
+
+ { KE_END }
};
static void bitland_notifier_unregister(void *data)
@@ -736,12 +782,35 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
&drv_data->notifier);
}
+static void bitland_mifs_wmi_report_key(struct wmi_device *wdev, u32 payload)
+{
+ struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev);
+ struct key_entry *entry;
+ bool autorelease = true;
+ int value = 1;
+
+ entry = sparse_keymap_entry_from_scancode(data->input_dev, payload);
+ if (!entry) {
+ dev_dbg(&wdev->dev, "Unknown WMI hotkey with payload 0x%08x\n", payload);
+ return;
+ }
+
+ /* AI key quirk */
+ if (entry->keycode == KEY_ASSISTANT) {
+ value = !(payload & AI_KEY_VALUE_MASK);
+ autorelease = false;
+ }
+
+ guard(mutex)(&data->lock);
+ sparse_keymap_report_entry(data->input_dev, entry, value, autorelease);
+}
+
static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
const struct wmi_buffer *buffer)
{
- struct bitland_mifs_wmi_data *data = dev_get_drvdata(&wdev->dev);
const struct bitland_mifs_event *event = buffer->data;
struct bitland_fan_notify_data fan_data;
+ u32 payload;
u8 brightness;
/* Validate event type */
@@ -758,24 +827,13 @@ static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
blocking_notifier_call_chain(&bitland_notifier_list,
BITLAND_NOTIFY_KBD_BRIGHTNESS,
&brightness);
- break;
+ return;
case WMI_EVENT_PERFORMANCE_PLAN:
blocking_notifier_call_chain(&bitland_notifier_list,
BITLAND_NOTIFY_PLATFORM_PROFILE,
NULL);
- break;
-
- case WMI_EVENT_OPEN_APP:
- case WMI_EVENT_CALCULATOR_START:
- case WMI_EVENT_BROWSER_START: {
- guard(mutex)(&data->lock);
- if (!sparse_keymap_report_event(data->input_dev,
- event->event_id, 1, true))
- dev_warn(&wdev->dev, "Unknown key pressed: 0x%02x\n",
- event->event_id);
- break;
- }
+ return;
/*
* The device has 3 fans (CPU, GPU, SYS),
@@ -783,6 +841,14 @@ static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
*/
case WMI_EVENT_CPU_FAN_SPEED:
case WMI_EVENT_GPU_FAN_SPEED:
+ /* Redmi refresh rate toggle quirk */
+ if (event->event_id == WMI_EVENT_CPU_FAN_SPEED &&
+ event->value_low == 0 && event->value_high == 0) {
+ payload = BI_HOTKEY_CODE(WMI_EVENT_REFRESH_RATE, 0, 0);
+ bitland_mifs_wmi_report_key(wdev, payload);
+ return;
+ }
+
if (event->event_id == WMI_EVENT_CPU_FAN_SPEED)
fan_data.channel = 0;
else
@@ -793,27 +859,14 @@ static void bitland_mifs_wmi_notify(struct wmi_device *wdev,
blocking_notifier_call_chain(&bitland_notifier_list,
BITLAND_NOTIFY_HWMON,
&fan_data);
- break;
-
- case WMI_EVENT_AIRPLANE_MODE:
- case WMI_EVENT_TOUCHPAD_STATE:
- case WMI_EVENT_FNLOCK_STATE:
- case WMI_EVENT_KBD_MODE:
- case WMI_EVENT_CAPSLOCK_STATE:
- case WMI_EVENT_NUMLOCK_STATE:
- case WMI_EVENT_SCROLLLOCK_STATE:
- case WMI_EVENT_REFRESH_RATE:
- case WMI_EVENT_WIN_KEY_LOCK:
- /* These events are informational or handled by firmware */
- dev_dbg(&wdev->dev, "State change event: id=%d value=%d\n",
- event->event_id, event->value_low);
- break;
+ return;
default:
- dev_dbg(&wdev->dev, "Unknown event: id=0x%02x value=0x%02x\n",
- event->event_id, event->value_low);
break;
}
+
+ payload = get_unaligned_le32(buffer->data);
+ bitland_mifs_wmi_report_key(wdev, payload);
}
static const struct wmi_device_id bitland_mifs_wmi_id_table[] = {
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 3/5] platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
2026-09-29 13:44 ` [PATCH v6 1/5] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver Mingyou Chen
@ 2026-09-29 13:45 ` Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 4/5] platform/x86: redmi-wmi: Drop redmi-wmi driver Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table Mingyou Chen
4 siblings, 0 replies; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:45 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen,
Nika Krasnova
Add the missing Redmibook mic-mute hotkey definitions to the shared
sparse keymap table:
- 0x00002101 (Fn-lock disabled state)
- 0x00012101 (Fn-lock enabled state)
Reported-by: Nika Krasnova <nika@nikableh.moe>
Link:
https://lore.kernel.org/platform-driver-x86/20260531123345.237521-1-nika@nikableh.moe/
Signed-off-by: Mingyou Chen <qby140326@gmail.com>
---
drivers/platform/x86/bitland-mifs-wmi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
index e1a81e89856e..df317aa6f555 100644
--- a/drivers/platform/x86/bitland-mifs-wmi.c
+++ b/drivers/platform/x86/bitland-mifs-wmi.c
@@ -634,6 +634,10 @@ static const struct key_entry bitland_mifs_wmi_keymap[] = {
{ KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_1, 1, 0), { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_REFRESH_RATE, 0, 0), { KEY_REFRESH_RATE_TOGGLE } },
+ /* Mic-mute key */
+ { KE_KEY, BI_HOTKEY_CODE(0x21, 0, 0), { KEY_MICMUTE } },
+ { KE_KEY, BI_HOTKEY_CODE(0x21, 1, 0), { KEY_MICMUTE } },
+
/* AI button has code for each position */
{ KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_FN_5, 1, 0), { KEY_ASSISTANT } },
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 4/5] platform/x86: redmi-wmi: Drop redmi-wmi driver
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
` (2 preceding siblings ...)
2026-09-29 13:45 ` [PATCH v6 3/5] platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries Mingyou Chen
@ 2026-09-29 13:45 ` Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table Mingyou Chen
4 siblings, 0 replies; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:45 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen
The redmi-wmi driver is no longer needed because its functionality
has been superseded by the new generic bitland platform driver.
All supported Redmi laptop models are now handled properly via the
updated WMI interfaces in bitland-mifs-wmi.
Remove the obsolete code, Kconfig entries, and Makefile references
to clean up the platform directory.
Signed-off-by: Mingyou Chen <qby140326@gmail.com>
---
MAINTAINERS | 6 --
drivers/platform/x86/Kconfig | 12 ---
drivers/platform/x86/Makefile | 1 -
drivers/platform/x86/redmi-wmi.c | 154 -------------------------------
4 files changed, 173 deletions(-)
delete mode 100644 drivers/platform/x86/redmi-wmi.c
diff --git a/MAINTAINERS b/MAINTAINERS
index c0b657dfe11f..cb4bd4e6ee48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23036,12 +23036,6 @@ S: Maintained
T: git https://github.com/pkshih/rtw.git
F: drivers/net/wireless/realtek/rtw89/
-REDMIBOOK WMI DRIVERS
-M: Gladyshev Ilya <foxido@foxido.dev>
-L: platform-driver-x86@vger.kernel.org
-S: Maintained
-F: drivers/platform/x86/redmi-wmi.c
-
BITLAND LAPTOP DRIVER
M: Mingyou Chen <qby140326@gmail.com>
M: Gladyshev Ilya <foxido@foxido.dev>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 45f15f93afa7..02e7ac00ac4f 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -90,18 +90,6 @@ config XIAOMI_WMI
To compile this driver as a module, choose M here: the module will
be called xiaomi-wmi.
-config REDMI_WMI
- tristate "Redmibook WMI key driver"
- depends on ACPI_WMI
- depends on INPUT
- select INPUT_SPARSEKMAP
- help
- Say Y here if you want support for WMI-based hotkey events on
- Xiaomi Redmibook devices.
-
- To compile this driver as a module, choose M here: the module will
- be called redmi-wmi.
-
config GIGABYTE_WMI
tristate "Gigabyte WMI temperature driver"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index a877acd937cd..567aabdcb58a 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_HUAWEI_WMI) += huawei-wmi.o
obj-$(CONFIG_MXM_WMI) += mxm-wmi.o
obj-$(CONFIG_NVIDIA_WMI_EC_BACKLIGHT) += nvidia-wmi-ec-backlight.o
obj-$(CONFIG_XIAOMI_WMI) += xiaomi-wmi.o
-obj-$(CONFIG_REDMI_WMI) += redmi-wmi.o
obj-$(CONFIG_GIGABYTE_WMI) += gigabyte-wmi.o
obj-$(CONFIG_BITLAND_MIFS_WMI) += bitland-mifs-wmi.o
diff --git a/drivers/platform/x86/redmi-wmi.c b/drivers/platform/x86/redmi-wmi.c
deleted file mode 100644
index cc82ef502002..000000000000
--- a/drivers/platform/x86/redmi-wmi.c
+++ /dev/null
@@ -1,154 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* WMI driver for Xiaomi Redmibooks */
-
-#include <linux/acpi.h>
-#include <linux/bits.h>
-#include <linux/device.h>
-#include <linux/input.h>
-#include <linux/input/sparse-keymap.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/unaligned.h>
-#include <linux/wmi.h>
-
-#include <uapi/linux/input-event-codes.h>
-
-#define WMI_REDMIBOOK_KEYBOARD_EVENT_GUID "46C93E13-EE9B-4262-8488-563BCA757FEF"
-
-#define AI_KEY_VALUE_MASK BIT(8)
-
-static const struct key_entry redmi_wmi_keymap[] = {
- {KE_KEY, 0x00000201, {KEY_SELECTIVE_SCREENSHOT}},
- {KE_KEY, 0x00000301, {KEY_ALL_APPLICATIONS}},
- {KE_KEY, 0x00001b01, {KEY_CONFIG}},
- {KE_KEY, 0x00011b01, {KEY_CONFIG}},
- {KE_KEY, 0x00010101, {KEY_SWITCHVIDEOMODE}},
- {KE_KEY, 0x00001a01, {KEY_REFRESH_RATE_TOGGLE}},
-
- /* AI button has code for each position */
- {KE_KEY, 0x00011801, {KEY_ASSISTANT}},
- {KE_KEY, 0x00011901, {KEY_ASSISTANT}},
-
- /* Keyboard backlight: Off / Auto / Low / High (new state in byte 2) */
- {KE_KEY, 0x00000501, {KEY_KBDILLUMTOGGLE}},
- {KE_KEY, 0x00800501, {KEY_KBDILLUMTOGGLE}},
- {KE_KEY, 0x00050501, {KEY_KBDILLUMTOGGLE}},
- {KE_KEY, 0x000a0501, {KEY_KBDILLUMTOGGLE}},
-
- /* Xiaomi G Command Center */
- {KE_KEY, 0x00010a01, {KEY_VENDOR}},
-
- /* OEM preset power mode: 1=Balanced 2=Silent 3=Turbo 4=Full speed */
- {KE_KEY, 0x00011601, {KEY_PERFORMANCE}},
- {KE_KEY, 0x00021601, {KEY_PERFORMANCE}},
- {KE_KEY, 0x00031601, {KEY_PERFORMANCE}},
- {KE_KEY, 0x00041601, {KEY_PERFORMANCE}},
-
- /* Fn Lock state: 1=on 0=off */
- {KE_KEY, 0x00000701, {KEY_FN_ESC}},
- {KE_KEY, 0x00010701, {KEY_FN_ESC}},
-
- /* Fn+`/1/2/3/4 */
- {KE_KEY, 0x00011101, {KEY_F13}},
- {KE_KEY, 0x00011201, {KEY_F14}},
- {KE_KEY, 0x00011301, {KEY_F15}},
- {KE_KEY, 0x00011401, {KEY_F16}},
- {KE_KEY, 0x00011501, {KEY_F17}},
-
- {KE_END}
-};
-
-struct redmi_wmi {
- struct input_dev *input_dev;
- /* Protects the key event sequence */
- struct mutex key_lock;
-};
-
-static int redmi_wmi_probe(struct wmi_device *wdev, const void *context)
-{
- struct redmi_wmi *data;
- int err;
-
- /* Init dev */
- data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- dev_set_drvdata(&wdev->dev, data);
-
- err = devm_mutex_init(&wdev->dev, &data->key_lock);
- if (err)
- return err;
-
- data->input_dev = devm_input_allocate_device(&wdev->dev);
- if (!data->input_dev)
- return -ENOMEM;
-
- data->input_dev->name = "Redmibook WMI keys";
- data->input_dev->phys = "wmi/input0";
-
- err = sparse_keymap_setup(data->input_dev, redmi_wmi_keymap, NULL);
- if (err)
- return err;
-
- return input_register_device(data->input_dev);
-}
-
-static void redmi_wmi_notify(struct wmi_device *wdev, union acpi_object *obj)
-{
- struct key_entry *entry;
- struct redmi_wmi *data = dev_get_drvdata(&wdev->dev);
- bool autorelease = true;
- u32 payload;
- int value = 1;
-
- if (obj->type != ACPI_TYPE_BUFFER) {
- dev_err(&wdev->dev, "Bad response type %u\n", obj->type);
- return;
- }
-
- if (obj->buffer.length < 32) {
- dev_err(&wdev->dev, "Invalid buffer length %u\n", obj->buffer.length);
- return;
- }
-
- payload = get_unaligned_le32(obj->buffer.pointer);
- entry = sparse_keymap_entry_from_scancode(data->input_dev, payload);
-
- if (!entry) {
- dev_dbg(&wdev->dev, "Unknown WMI event with payload %u", payload);
- return;
- }
-
- /* AI key quirk */
- if (entry->keycode == KEY_ASSISTANT) {
- value = !(payload & AI_KEY_VALUE_MASK);
- autorelease = false;
- }
-
- guard(mutex)(&data->key_lock);
- sparse_keymap_report_entry(data->input_dev, entry, value, autorelease);
-}
-
-static const struct wmi_device_id redmi_wmi_id_table[] = {
- { WMI_REDMIBOOK_KEYBOARD_EVENT_GUID, NULL },
- { }
-};
-
-static struct wmi_driver redmi_wmi_driver = {
- .driver = {
- .name = "redmi-wmi",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- .id_table = redmi_wmi_id_table,
- .min_event_size = 32,
- .probe = redmi_wmi_probe,
- .notify = redmi_wmi_notify,
- .no_singleton = true,
-};
-module_wmi_driver(redmi_wmi_driver);
-
-MODULE_DEVICE_TABLE(wmi, redmi_wmi_id_table);
-MODULE_AUTHOR("Gladyshev Ilya <foxido@foxido.dev>");
-MODULE_DESCRIPTION("Redmibook WMI driver");
-MODULE_LICENSE("GPL");
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
` (3 preceding siblings ...)
2026-09-29 13:45 ` [PATCH v6 4/5] platform/x86: redmi-wmi: Drop redmi-wmi driver Mingyou Chen
@ 2026-09-29 13:45 ` Mingyou Chen
2026-09-30 1:50 ` Anton Karasev
4 siblings, 1 reply; 8+ messages in thread
From: Mingyou Chen @ 2026-09-29 13:45 UTC (permalink / raw)
To: Ilpo Järvinen, Hans de Goede
Cc: KentoNion, platform-driver-x86, ted eric, Armin Wolf,
linux-kernel, Chris Taraszka, Matias Civadda,
高 俊文, powerfullz, 孙 誉铭,
Miloš Vlku, Rsplwe, Bozhen Peng, Mingyou Chen
The MIFS WMI interface is shared by several Bitland ODM laptops which
differ in the layout of the performance mode values of
WMI_FN_SYSTEM_PER_MODE and in the capability checks.
Introduce a machine ops table to support multiple machine families
without sprinkling model checks over the driver:
struct bitland_mifs_ops {
const char *name;
const struct bitland_profile_mode_map *mode_map;
int (*check_performance_capability)(
struct bitland_mifs_wmi_data *data);
bool has_full_speed;
};
The default ops instance keeps the current Bitland behavior, so this
change is a pure refactor without any functional changes.
Signed-off-by: Mingyou Chen <qby140326@gmail.com>
---
drivers/platform/x86/bitland-mifs-wmi.c | 108 +++++++++++++++++++-----
1 file changed, 86 insertions(+), 22 deletions(-)
diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
index df317aa6f555..d092bf07b7f7 100644
--- a/drivers/platform/x86/bitland-mifs-wmi.c
+++ b/drivers/platform/x86/bitland-mifs-wmi.c
@@ -12,6 +12,7 @@
#include <linux/bits.h>
#include <linux/container_of.h>
#include <linux/dev_printk.h>
+#include <linux/dmi.h>
#include <linux/device.h>
#include <linux/device/devres.h>
#include <linux/err.h>
@@ -84,6 +85,50 @@ enum bitland_mifs_power_profile {
WMI_PP_FULL_SPEED = 3,
};
+struct bitland_mifs_wmi_data;
+
+/*
+ * Value layout of WMI_FN_SYSTEM_PER_MODE.
+ */
+struct bitland_profile_mode_map {
+ u8 balanced;
+ u8 performance;
+ u8 quiet;
+ u8 full_speed;
+};
+
+static const struct bitland_profile_mode_map bitland_mode_map = {
+ .balanced = WMI_PP_BALANCED,
+ .performance = WMI_PP_PERFORMANCE,
+ .quiet = WMI_PP_QUIET,
+ .full_speed = WMI_PP_FULL_SPEED,
+};
+
+static int bitland_pp_check_capability(struct bitland_mifs_wmi_data *data);
+
+/*
+ * Machine-specific operations. The MIFS WMI interface is shared by
+ * several Bitland ODM laptops which differ in the layout of the
+ * performance mode values and in the capability checks.
+ */
+struct bitland_mifs_ops {
+ const char *name;
+ const struct bitland_profile_mode_map *mode_map;
+ int (*check_performance_capability)(struct bitland_mifs_wmi_data *data);
+ bool has_full_speed;
+};
+
+static const struct bitland_mifs_ops bitland_ops = {
+ .name = "Bitland",
+ .mode_map = &bitland_mode_map,
+ .check_performance_capability = bitland_pp_check_capability,
+ .has_full_speed = true,
+};
+
+static const struct dmi_system_id bitland_mifs_dmi_table[] = {
+ {}
+};
+
enum bitland_mifs_event_id {
WMI_EVENT_RESERVED_1 = 1,
WMI_EVENT_RESERVED_2 = 2,
@@ -165,6 +210,7 @@ struct bitland_mifs_wmi_data {
struct input_dev *input_dev;
struct device *hwmon_dev;
struct device *pp_dev;
+ const struct bitland_mifs_ops *ops;
enum platform_profile_option saved_profile;
};
@@ -207,37 +253,35 @@ static int laptop_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ const struct bitland_profile_mode_map *map = data->ops->mode_map;
struct bitland_mifs_input input = {
.operation = cpu_to_le16(WMI_METHOD_GET),
.function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE),
};
struct bitland_mifs_output result;
+ u8 mode;
int ret;
ret = bitland_mifs_wmi_call(data, &input, &result);
if (ret)
return ret;
- switch (result.data[0]) {
- case WMI_PP_BALANCED:
+ mode = result.data[0];
+ if (mode == map->quiet)
+ *profile = PLATFORM_PROFILE_LOW_POWER;
+ else if (mode == map->balanced)
*profile = PLATFORM_PROFILE_BALANCED;
- break;
- case WMI_PP_PERFORMANCE:
+ else if (mode == map->performance)
*profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
- break;
- case WMI_PP_QUIET:
- *profile = PLATFORM_PROFILE_LOW_POWER;
- break;
- case WMI_PP_FULL_SPEED:
+ else if (mode == map->full_speed)
*profile = PLATFORM_PROFILE_PERFORMANCE;
- break;
- default:
+ else
return -EINVAL;
- }
+
return 0;
}
-static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *data)
+static int bitland_pp_check_capability(struct bitland_mifs_wmi_data *data)
{
struct bitland_mifs_input input = {
.operation = cpu_to_le16(WMI_METHOD_GET),
@@ -268,47 +312,52 @@ static int laptop_profile_set(struct device *dev,
enum platform_profile_option profile)
{
struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
+ const struct bitland_profile_mode_map *map = data->ops->mode_map;
struct bitland_mifs_input input = {
.operation = cpu_to_le16(WMI_METHOD_SET),
.function = cpu_to_le16(WMI_FN_SYSTEM_PER_MODE),
};
int ret;
- u8 val;
+ u8 mode;
switch (profile) {
case PLATFORM_PROFILE_LOW_POWER:
- val = WMI_PP_QUIET;
+ mode = map->quiet;
break;
case PLATFORM_PROFILE_BALANCED:
- val = WMI_PP_BALANCED;
+ mode = map->balanced;
break;
case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
- ret = bitland_check_performance_capability(data);
+ ret = data->ops->check_performance_capability(data);
if (ret)
return ret;
- val = WMI_PP_PERFORMANCE;
+ mode = map->performance;
break;
case PLATFORM_PROFILE_PERFORMANCE:
- ret = bitland_check_performance_capability(data);
+ ret = data->ops->check_performance_capability(data);
if (ret)
return ret;
- val = WMI_PP_FULL_SPEED;
+ mode = map->full_speed;
break;
default:
return -EOPNOTSUPP;
}
- input.payload[0] = val;
+ input.payload[0] = mode;
return bitland_mifs_wmi_call(data, &input, NULL);
}
static int platform_profile_probe(void *drvdata, unsigned long *choices)
{
+ struct bitland_mifs_wmi_data *data = drvdata;
+
set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
set_bit(PLATFORM_PROFILE_BALANCED, choices);
set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
- set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ if (data->ops->has_full_speed)
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
return 0;
}
@@ -706,6 +755,19 @@ static int bitland_notifier_callback(struct notifier_block *nb,
return NOTIFY_OK;
}
+static void bitland_detect_ops(struct bitland_mifs_wmi_data *data)
+{
+ const struct dmi_system_id *id;
+
+ id = dmi_first_match(bitland_mifs_dmi_table);
+ if (id)
+ data->ops = id->driver_data;
+ else
+ data->ops = &bitland_ops;
+
+ dev_dbg(&data->wdev->dev, "Detected machine ops: %s\n", data->ops->name);
+}
+
static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct bitland_mifs_wmi_data *drv_data;
@@ -730,6 +792,8 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
dev_set_drvdata(&wdev->dev, drv_data);
+ bitland_detect_ops(drv_data);
+
if (dev_type == BITLAND_WMI_EVENT) {
/* Register input device for hotkeys */
drv_data->input_dev = devm_input_allocate_device(&wdev->dev);
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table
2026-09-29 13:45 ` [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table Mingyou Chen
@ 2026-09-30 1:50 ` Anton Karasev
0 siblings, 0 replies; 8+ messages in thread
From: Anton Karasev @ 2026-09-30 1:50 UTC (permalink / raw)
To: qby140326
Cc: ilpo.jarvinen, hansg, platform-driver-x86, linux-kernel, W_Armin,
ilya.gladyshev, foxido, kento, ericted8810, chris,
matias.civadda2342001, btx342, wleizc7319, wolf109909,
vlku.milos.fun, i, bozhenpeng93, martiya.ar, aleksejirlik
Hi,
Data for the per-machine table from a Xiaomi Redmi Book Pro 16 2024
(DMI: sys_vendor "XIAOMI", board_name "TM2309"; BIOS RMAMT6B0P0B0B,
bios_release and ec_firmware_release 1.11), the same model as in
Martiya's report. RMAMT6B0P0B0B (August 2025) is the latest BIOS Xiaomi
publishes for this model, so this is what an entry would be written
against. Its values match neither the Bitland defaults nor the Redmi map
proposed in v5 6/6. The full acpidump is attached to bugzilla 222062:
https://bugzilla.kernel.org/attachment.cgi?id=310971
The WMI method is \_SB.PC00.WMID.WMAA in the SSDT with OEM Table ID
XMCC1806; QFAN and NTDP are in the DSDT.
Mode values
-----------
WMAA stores the value written with WMI_FN_SYSTEM_PER_MODE in the EC
register QFAN as is (5 and 7 go to a separate register, SMMD, instead),
and NTDP in the DSDT maps QFAN to the DPTF variable \_SB.ODV1 (odvp1 in
sysfs) that thermald --adaptive uses to pick the policy from the GDDV:
QFAN meaning ODV1
0, 1 balanced (Fn+K sets 1) 0
2 quiet 2
3 performance ("Turbo") 1
4 full speed ("Geek") 4
GET returns QFAN for 1..4 and 0 otherwise (so 0 after a SET of 0).
Fn+K on this model cycles 1 -> 3 -> 2.
I tested this with a local build that maps low-power/balanced/
performance to 2/1/3: power-profiles-daemon power-saver, balanced and
performance give odvp1 2, 0 and 1, and thermald loads the matching GDDV
targets (PL1 limits, TCC offset), both on AC and on battery.
On the DMI match: the v5 6/6 match on sys_vendor "Redmi"/"TIMI" would
not cover this machine, and performance = 0 from that map is balanced
here. The REDMI Book Pro 16 2025 in Aleksey's report also has
sys_vendor "XIAOMI" but uses different values, so an entry for this
model has to match board_name "TM2309". The Pro 14 2024 (TM2307) is
built on the same platform (Xiaomi's downloads for both, the BIOS
included, are filed under one platform name, N56N57) and may behave the
same; I cannot verify that.
Capability checks
-----------------
a) Performance on AC and on battery. WMI_FN_SYSTEM_AC_TYPE is not
implemented on this BIOS, so with Armin's "Treat
WMI_FN_SYSTEM_AC_TYPE as optional" the capability check passes on
AC. The write itself is still reported as failed here, though:
WMAA's SET branches set only the return code and leave the function
id at 0 (only the GET branches fill it in), so "Detect failed
function calls" (23cc56f6dea6 in for-next) returns -ENOMSG for every
SET on this BIOS, although the firmware applies it -- the same as
Chris reported for the Book Pro 14. I checked it with the for-next
version of the driver built for 7.2.7: every write of low-power,
balanced and performance failed with -ENOMSG while QFAN changed to
2, 0 and 3; with Chris's "Only check the function id of GET
responses" on top, all of them succeed.
On battery, power_supply_is_system_supplied() still refuses
performance, although the firmware supports Turbo on DC: Fn+K
reaches it on battery, the GDDV has a DC Turbo target, and writing 3
on battery works (odvp1 1, thermald applies the DC Turbo limits).
b) Full speed. The firmware does not validate the mode at all. Writing
4 was accepted and applied (odvp1 4, thermald loads the Geek targets;
on AC the PL1 ramped towards the 90 W Geek maximum) both on battery
and on a 100 W USB-C PD charger, while Fn+K never offers full speed
in either case. It is not a charger thing either: with the stock
140 W USB-C charger (the EC register ADPW then reads 140, and GET of
command 0x10, subcommand 3, would report the adapter as not below
140 W) Fn+K still cycles only 1 -> 3 -> 2. So on this model full
speed is never offered by the vendor's own key, and whether it is
exposed has to be decided by the driver; the firmware will not stop
it.
Commands that are not implemented, and one that is dangerous
------------------------------------------------------------
On this BIOS WMAA implements only command 0x08 (GET and SET), 0x0a
subcommand 5, and 0x10 (GET subcommands 1-3, SET subcommand 2 only).
Other command IDs answer 0xE000, among them everything else the driver
uses: 0x09 (gpu_mode), 0x0d (fan speeds), 0x12 (keyboard brightness),
0x13 (AC type), 0x14 (fan_boost) and 0x16 (CPU temperature).
Unhandled subcommands of 0x0a and 0x10 mostly return status 0, and a
GET of 0x0a answers 0x8000 whatever the subcommand. The hwmon device,
the kbd_backlight LED, gpu_mode and fan_boost therefore have nothing
behind them on this machine; probing support at probe time would avoid
exposing them.
kb_mode is worse than unsupported. kb_mode_store() sends command 0x10
(WMI_FN_RGB_KB_MODE) with the mode in the first payload byte. On this
firmware command 0x10 is the battery interface, and subcommand 2 is the
charge protection (bit 0 of the EC register LONL, 80 % limit; reportedly
what Xiaomi's Windows tools toggle): WMAA sets the bit only for the
value 1 and clears it for anything else. "echo fixed > kb_mode" is
therefore 0x10/2 with value 0. I verified on this machine that it
silently turns off charge protection -- LONL goes from 0x31 to 0x00, the
charge limit in the EC goes from 80 back to 100 and the battery, which
had been held at 80 %, starts charging again -- while the firmware
reports success (0x8000). That was on 7.2.7, whose driver does not check
the reply; with 23cc56f6dea6 the write returns -ENOMSG instead, but
protection is off all the same. I think kb_mode must not be exposed on
these machines.
Once the generic profile table has settled I can send a patch with the
entry for this model and the kb_mode fix on top of it, and I am happy to
test patches in the meantime.
Thanks,
Anton Karasev
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver
2026-09-29 13:45 ` [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver Mingyou Chen
@ 2026-09-30 1:58 ` Anton Karasev
0 siblings, 0 replies; 8+ messages in thread
From: Anton Karasev @ 2026-09-30 1:58 UTC (permalink / raw)
To: qby140326
Cc: ilpo.jarvinen, hansg, platform-driver-x86, linux-kernel,
ilya.gladyshev, foxido, W_Armin, kento, ericted8810, chris,
matias.civadda2342001, btx342, wleizc7319, wolf109909,
vlku.milos.fun, i, bozhenpeng93, nika
Hi,
On a Xiaomi Redmi Book Pro 16 2024 (DMI: XIAOMI / TM2309, BIOS
RMAMT6B0P0B0B) the display-switch key sends payload 0x00000101 -- the
short form. The merged keymap in this patch only carries the long one:
{ KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_1, 1, 0), { KEY_SWITCHVIDEOMODE } },
With WMI_EVENT_RESERVED_1 = 1 and WMI_EVENT_TYPE_HOTKEY = 1 that expands
to 0x00010101, so on this model the key produces no input event at all:
sparse_keymap_entry_from_scancode() finds nothing and the event is
dropped.
redmi-wmi has exactly the same gap; it is being fixed there by
https://lore.kernel.org/platform-driver-x86/20260928221417.37875-1-ilya.gladyshev@linux.dev/
which I tested on this machine: with that patch the key reports
KEY_SWITCHVIDEOMODE and the desktop reacts to it. If this series lands as
is, that fix is lost again for this model. The equivalent here would be
one more line:
{ KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_RESERVED_1, 0, 0), { KEY_SWITCHVIDEOMODE } },
Note that the keymap already carries both forms for the settings key
(0x1b with low 0 and low 1), so the two forms are already known to the
driver; the display-switch key is simply missing its short variant.
While tracing this firmware, two more payloads showed up that neither
driver handles: 0x00000901 and 0x00010901. They are not key presses. The
EC echoes back the Caps Lock LED state that the host itself has just set
-- the third byte carries the new state (1 = on, 0 = off), the same
scheme as the Fn Lock events at 0x00000701 / 0x00010701. Verified by
switching between windows with per-window keyboard layouts, which changes
the LED without anyone touching the key: the events still arrive,
200-500 ms after the LED change. On a system where Caps Lock switches the
keyboard layout, each of them ends up in the "Unknown WMI hotkey"
dev_dbg path. If you agree they are just an echo, KE_IGNORE would
silence them:
{ KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_CAPSLOCK_STATE, 0, 0), {} },
{ KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_CAPSLOCK_STATE, 1, 0), {} },
Two more things about how this patch treats events from this firmware.
The observations below were made on 7.2.7, with redmi-wmi owning the
event GUID and a local build of bitland-mifs-wmi bound only to the
method GUID, reading the EC registers while doing it; what this patch
would do is from reading it. The ACPI references are to the SSDT with
OEM Table ID XMCC1806 (\_SB.PC00.WMID) and to the DSDT.
1. Fn+K. This firmware never sends WMI_EVENT_PERFORMANCE_PLAN (0x0f);
QV20(1, 0x0f) is not called anywhere in its tables. A mode change is
reported as event 0x16 with the new EC mode (register QFAN) in
value_low: the Fn+K query handler in the DSDT (_Q24) calls
QV20(1, 0x16) and then NTDP(QFAN), and the MIFS SET of
WMI_FN_SYSTEM_PER_MODE in WMAA sends the same QV20(1, 0x16) after
writing QFAN. EV20 fills value_low only for QFAN 1..4, so after a SET
of 0 -- what the default Bitland map writes for balanced -- the event
is 0x00001601.
This patch maps 0x16 with value_low 1..4 to KE_IGNORE, has no entry
for 0x00001601, and calls platform_profile_notify() only for 0x0f.
So after Fn+K userspace is told nothing: the EC mode and the DPTF
policy applied by thermald --adaptive change, and so does the value
read back from platform_profile, but power-profiles-daemon keeps the
old profile. That is already the case today; in my test PPD stayed
on balanced while the EC ran in Turbo. But redmi-wmi at least reports
KEY_PERFORMANCE for these events, as it reports KEY_KBDILLUMTOGGLE
and KEY_FN_ESC for the backlight and Fn Lock events. With this patch
they all become KE_IGNORE, so userspace gets neither a key nor a
profile notification.
Treating 0x16 as a profile change -- value_low 0..4, including
0x00001601 -- and calling platform_profile_notify() for it would
close the gap. It would also fire after the driver's own writes,
because the SET sends the same event: when userspace writes the
profile through bitland-mifs-wmi right after Fn+K, two 0x16 events
arrive 0.2-1 s apart. That is harmless.
2. Keyboard backlight (F10). On this model the event's value_low
cycles 0x00 -> 0x05 -> 0x0a -> 0x80 -> 0x00: off, dim with the BIOS
idle timeout, bright with the idle timeout, bright and always on.
The EC keeps the same state as 1 / 2 / 4 / 8, and EV20 translates
it into value_low. In this patch
BI_HOTKEY_CODE(WMI_EVENT_KBD_BRIGHTNESS, 0, 0x80) is 0x80000501,
while the firmware (and redmi-wmi's 0x00800501) has 0x80 in
value_low. All four KBD_BRIGHTNESS entries are unreachable anyway:
notify() returns for WMI_EVENT_KBD_BRIGHTNESS before the keymap
lookup, so the KEY_KBDILLUMTOGGLE that redmi-wmi reports today is
gone. That early path passes value_low (0, 5, 10 or 128) to
led_classdev_notify_brightness_hw_changed() for an LED with
max_brightness 3, and on this BIOS the LED has nothing behind it,
because WMAA does not implement WMI_FN_RGB_KB_BRIGHTNESS (0x12) and
answers 0xE000.
The full acpidump of this machine is attached to the bug:
https://bugzilla.kernel.org/attachment.cgi?id=310971
Details, traces and the exact verification steps for the key events:
https://bugzilla.kernel.org/show_bug.cgi?id=222062
I am happy to test patches on this model.
Thanks,
Anton Karasev
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-30 1:58 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 13:44 [PATCH v6 0/5] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
2026-09-29 13:44 ` [PATCH v6 1/5] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 2/5] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver Mingyou Chen
2026-09-30 1:58 ` Anton Karasev
2026-09-29 13:45 ` [PATCH v6 3/5] platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 4/5] platform/x86: redmi-wmi: Drop redmi-wmi driver Mingyou Chen
2026-09-29 13:45 ` [PATCH v6 5/5] platform/x86: bitland-mifs-wmi: Add per-machine ops table Mingyou Chen
2026-09-30 1:50 ` Anton Karasev
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®