From: Armin Wolf <W_Armin@gmx.de>
To: "Miloš Vlku" <vlku.milos.fun@gmail.com>,
"Mingyou Chen" <qby140326@gmail.com>
Cc: foxido@foxido.dev, hansg@kernel.org,
ilpo.jarvinen@linux.intel.com, linux-kernel@vger.kernel.org,
nika@nikableh.moe, platform-driver-x86@vger.kernel.org,
i@rsplwe.com, wolf109909@outlook.com, rahulbheda131313@gmail.com
Subject: Re: [PATCH v5 6/6] platform/x86: bitland-mifs-wmi: Add Redmi laptop support
Date: Thu, 10 Sep 2026 00:48:56 +0200 [thread overview]
Message-ID: <6f14fa17-7206-41d2-b6e4-1711427ba91b@gmx.de> (raw)
In-Reply-To: <CAObHBTwjvBHX8o_W9S=B2VBzmMyfFrHdvjH7o1y99iwGEa7RhA@mail.gmail.com>
Am 06.09.26 um 20:16 schrieb Miloš Vlku:
> Hi,
>
> Following up on this - my Aug 18 report still applies: my board
> (XIAOMI / TM2307 / "Redmi Book Pro 14 2024") doesn't match either
> DMI_SYS_VENDOR "Redmi" or "TIMI", so it falls through to the generic
> bitland_ops table instead of redmi_book_ops, which means
> bitland_pp_check_capability() (barrel-jack/DC required) runs instead
> of redmi_pp_check_capability() (any AC source), and performance mode
> stays blocked on my USB-C-only machine.
>
> Proposed fix is still just adding a DMI_BOARD_NAME "TM2307" match (or
> possibly broadening to DMI_SYS_VENDOR "XIAOMI" if that covers the
> wider lineup) to bitland_mifs_dmi_table.
>
> Armin - since you mentioned your buffer-format series (Sep 5) should
> be the new base for outstanding patches, should this DMI fix be
> rebased on top of that, or is it independent enough to land
> separately?
>
> Thanks,
> Milos
I think that rebasing is the safest choice here.
Thanks,
Armin Wolf
>
> On Tue, Aug 18, 2026 at 1:17 AM Miloš Vlku <vlku.milos.fun@gmail.com> wrote:
>>> + {
>>> + /* Redmi Book series */
>>> + .matches = {
>>> + DMI_MATCH(DMI_SYS_VENDOR, "Redmi"),
>>> + },
>>> + .driver_data = (void *)&redmi_book_ops,
>>> + },
>>> + {
>>> + /* Xiaomi Book series */
>>> + .matches = {
>>> + DMI_MATCH(DMI_SYS_VENDOR, "TIMI"),
>>> + },
>>> + .driver_data = (void *)&redmi_book_ops,
>>> + },
>> Neither entry matches my machine. I have a Redmi Book Pro 14 2024, and
>> it reports:
>>
>> DMI_SYS_VENDOR XIAOMI
>> DMI_BOARD_NAME TM2307
>> DMI_PRODUCT_NAME Redmi Book Pro 14 2024
>>
>> Since DMI_MATCH() is a substring test, neither "Redmi" nor "TIMI"
>> matches "XIAOMI", so dmi_first_match() returns NULL and data->ops stays
>> at &bitland_ops. The series has no effect on this model.
>>
>> A board-name match would cover it:
>>
>> {
>> /* Redmi Book Pro 14 2024 */
>> .matches = {
>> DMI_MATCH(DMI_BOARD_NAME, "TM2307"),
>> },
>> .driver_data = (void *)&redmi_book_ops,
>> },
>>
>> I don't know how widely the "XIAOMI" vendor string is used across the
>> range, so matching DMI_SYS_VENDOR "XIAOMI" may cover more machines at
>> once if that encoding applies to all of them.
>>
>> Thanks,
>> Milos
>>
>> On Sun, Aug 16, 2026 at 12:08 PM Mingyou Chen <qby140326@gmail.com> wrote:
>>> Redmi laptops (Redmi Book and Redmi G series) use the same MIFS WMI
>>> interface but encode the performance mode values of
>>> WMI_FN_SYSTEM_PER_MODE differently, as reverse engineered from the
>>> Windows GCommandCenter application:
>>>
>>> 0 = performance, 1 = balanced, 2 = quiet, 4 = full speed
>>>
>>> Add "Redmi Book" and "Redmi G" ops entries selected via DMI:
>>> - Redmi G (board TM2135/TM2137): the full-speed mode is available
>>> - Redmi Book/Xiaomi Book: no full-speed mode
>>> - The performance modes only require AC power (any source); the
>>> barrel-jack requirement is Bitland-specific
>>>
>>> The GCommandCenter application further showed that:
>>> - the CPU power sensor (WMI_FN_CPU_POWER) is only available on Redmi
>>> machines, gate the hwmon power channel on the ops table
>>> - the refresh-rate-toggle quirk in the CPU fan speed event is
>>> Redmi-specific, gate it on the ops table instead of applying it
>>> unconditionally
>>>
>>> Also add Redmi support for Fn lock and touchpad lock control
>>> (WMI_FN_FN_LOCK / WMI_FN_TP_LOCK sysfs attributes), keyboard type
>>> detection (hide the RGB kb_mode attribute on white-only backlit
>>> keyboards) and hotkeys (airplane mode -> KEY_RFKILL, ignore the
>>> lock-state and keyboard mode indicator events).
>>>
>>> The sysfs attribute group is now registered in probe (instead of via
>>> dev_groups) so that the is_visible callback can access the probe
>>> populated driver data.
>>>
>>> Signed-off-by: Mingyou Chen <qby140326@gmail.com>
>>> ---
>>> drivers/platform/x86/bitland-mifs-wmi.c | 336 ++++++++++++++++++++++--
>>> 1 file changed, 318 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
>>> index 17792d8b7c29..1eb9f92740e0 100644
>>> --- a/drivers/platform/x86/bitland-mifs-wmi.c
>>> +++ b/drivers/platform/x86/bitland-mifs-wmi.c
>>> @@ -14,6 +14,7 @@
>>> #include <linux/dev_printk.h>
>>> #include <linux/device.h>
>>> #include <linux/device/devres.h>
>>> +#include <linux/dmi.h>
>>> #include <linux/err.h>
>>> #include <linux/hwmon.h>
>>> #include <linux/init.h>
>>> @@ -71,6 +72,11 @@ enum bitland_system_ac_mode {
>>> WMI_SYSTEM_AC_CIRCULARHOLE = 2,
>>> };
>>>
>>> +enum bitland_kbd_type {
>>> + WMI_KBD_TYPE_WHITE = 0,
>>> + WMI_KBD_TYPE_RGB = 1,
>>> +};
>>> +
>>> enum bitland_mifs_power_profile {
>>> WMI_PP_BALANCED = 0,
>>> WMI_PP_PERFORMANCE = 1,
>>> @@ -97,7 +103,15 @@ static const struct bitland_profile_mode_map bitland_mode_map = {
>>> .full_speed = WMI_PP_FULL_SPEED,
>>> };
>>>
>>> +static const struct bitland_profile_mode_map redmi_mode_map = {
>>> + .balanced = 1,
>>> + .performance = 0,
>>> + .quiet = 2,
>>> + .full_speed = 4,
>>> +};
>>> +
>>> static int bitland_pp_check_capability(struct bitland_mifs_wmi_data *data);
>>> +static int redmi_pp_check_capability(struct bitland_mifs_wmi_data *data);
>>>
>>> /*
>>> * Machine-specific operations. The MIFS WMI interface is shared by
>>> @@ -109,6 +123,8 @@ struct bitland_mifs_ops {
>>> const struct bitland_profile_mode_map *mode_map;
>>> int (*check_performance_capability)(struct bitland_mifs_wmi_data *data);
>>> bool has_full_speed;
>>> + bool has_cpu_power;
>>> + bool quirk_refresh_rate_toggle;
>>> };
>>>
>>> static const struct bitland_mifs_ops bitland_ops = {
>>> @@ -118,6 +134,54 @@ static const struct bitland_mifs_ops bitland_ops = {
>>> .has_full_speed = true,
>>> };
>>>
>>> +static const struct bitland_mifs_ops redmi_book_ops = {
>>> + .name = "Redmi Book",
>>> + .mode_map = &redmi_mode_map,
>>> + .check_performance_capability = redmi_pp_check_capability,
>>> + .has_cpu_power = true,
>>> + .quirk_refresh_rate_toggle = true,
>>> +};
>>> +
>>> +static const struct bitland_mifs_ops redmi_g_ops = {
>>> + .name = "Redmi G",
>>> + .mode_map = &redmi_mode_map,
>>> + .check_performance_capability = redmi_pp_check_capability,
>>> + .has_full_speed = true,
>>> + .has_cpu_power = true,
>>> + .quirk_refresh_rate_toggle = true,
>>> +};
>>> +
>>> +static const struct dmi_system_id bitland_mifs_dmi_table[] = {
>>> + {
>>> + /* Redmi G */
>>> + .matches = {
>>> + DMI_MATCH(DMI_BOARD_NAME, "TM2135"),
>>> + },
>>> + .driver_data = (void *)&redmi_g_ops,
>>> + },
>>> + {
>>> + .matches = {
>>> + DMI_MATCH(DMI_BOARD_NAME, "TM2137"),
>>> + },
>>> + .driver_data = (void *)&redmi_g_ops,
>>> + },
>>> + {
>>> + /* Redmi Book series */
>>> + .matches = {
>>> + DMI_MATCH(DMI_SYS_VENDOR, "Redmi"),
>>> + },
>>> + .driver_data = (void *)&redmi_book_ops,
>>> + },
>>> + {
>>> + /* Xiaomi Book series */
>>> + .matches = {
>>> + DMI_MATCH(DMI_SYS_VENDOR, "TIMI"),
>>> + },
>>> + .driver_data = (void *)&redmi_book_ops,
>>> + },
>>> + {}
>>> +};
>>> +
>>> enum bitland_mifs_event_id {
>>> WMI_EVENT_RESERVED_1 = 1,
>>> WMI_EVENT_RESERVED_2 = 2,
>>> @@ -203,6 +267,8 @@ struct bitland_mifs_wmi_data {
>>> struct input_dev *input_dev;
>>> struct device *hwmon_dev;
>>> struct device *pp_dev;
>>> + enum bitland_wmi_device_type dev_type;
>>> + u8 kbd_type;
>>> const struct bitland_mifs_ops *ops;
>>> enum platform_profile_option saved_profile;
>>> };
>>> @@ -255,8 +321,10 @@ static int laptop_profile_get(struct device *dev,
>>> else if (mode == map->balanced)
>>> *profile = PLATFORM_PROFILE_BALANCED;
>>> else if (mode == map->performance)
>>> - *profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
>>> - else if (mode == map->full_speed)
>>> + *profile = data->ops->has_full_speed ?
>>> + PLATFORM_PROFILE_BALANCED_PERFORMANCE :
>>> + PLATFORM_PROFILE_PERFORMANCE;
>>> + else if (data->ops->has_full_speed && mode == map->full_speed)
>>> *profile = PLATFORM_PROFILE_PERFORMANCE;
>>> else
>>> return -EINVAL;
>>> @@ -273,10 +341,11 @@ static int bitland_pp_check_capability(struct bitland_mifs_wmi_data *data)
>>> struct bitland_mifs_output output;
>>> int ret;
>>>
>>> - /* Full-speed/performance mode requires DC power (not USB-C) */
>>> + /* The performance modes require AC power */
>>> if (!power_supply_is_system_supplied())
>>> return -EOPNOTSUPP;
>>>
>>> + /* Additionally require the barrel-jack power supply (not USB-C) */
>>> ret = bitland_mifs_wmi_call(data, &input, &output);
>>> if (ret)
>>> return ret;
>>> @@ -287,6 +356,15 @@ static int bitland_pp_check_capability(struct bitland_mifs_wmi_data *data)
>>> return 0;
>>> }
>>>
>>> +static int redmi_pp_check_capability(struct bitland_mifs_wmi_data *data)
>>> +{
>>> + /* The performance modes require AC power (any source) */
>>> + if (!power_supply_is_system_supplied())
>>> + return -EOPNOTSUPP;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> static int laptop_profile_set(struct device *dev,
>>> enum platform_profile_option profile)
>>> {
>>> @@ -309,6 +387,8 @@ static int laptop_profile_set(struct device *dev,
>>> mode = map->balanced;
>>> break;
>>> case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
>>> + if (!data->ops->has_full_speed)
>>> + return -EOPNOTSUPP;
>>> ret = data->ops->check_performance_capability(data);
>>> if (ret)
>>> return ret;
>>> @@ -318,7 +398,7 @@ static int laptop_profile_set(struct device *dev,
>>> ret = data->ops->check_performance_capability(data);
>>> if (ret)
>>> return ret;
>>> - mode = map->full_speed;
>>> + mode = data->ops->has_full_speed ? map->full_speed : map->performance;
>>> break;
>>> default:
>>> return -EOPNOTSUPP;
>>> @@ -335,10 +415,10 @@ static int platform_profile_probe(void *drvdata, unsigned long *choices)
>>>
>>> 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);
>>> + set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
>>>
>>> return 0;
>>> }
>>> @@ -418,6 +498,13 @@ static int laptop_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
>>> default:
>>> return -EINVAL;
>>> }
>>> + case hwmon_power:
>>> + /* WMI_FN_CPU_POWER returns the CPU power draw in watts */
>>> + input.function = WMI_FN_CPU_POWER;
>>> + ret = bitland_mifs_wmi_call(data, &input, &res);
>>> + if (!ret)
>>> + *val = res.data[0] * MICROWATT_PER_WATT;
>>> + return ret;
>>> default:
>>> return -EINVAL;
>>> }
>>> @@ -444,6 +531,15 @@ static const struct hwmon_channel_info *laptop_hwmon_info[] = {
>>> NULL
>>> };
>>>
>>> +static const struct hwmon_channel_info *laptop_hwmon_info_power[] = {
>>> + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
>>> + HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_LABEL,
>>> + HWMON_F_INPUT | HWMON_F_LABEL,
>>> + HWMON_F_INPUT | HWMON_F_LABEL),
>>> + HWMON_CHANNEL_INFO(power, HWMON_P_INPUT),
>>> + NULL
>>> +};
>>> +
>>> static const struct hwmon_ops laptop_hwmon_ops = {
>>> .visible = 0444,
>>> .read = laptop_hwmon_read,
>>> @@ -455,6 +551,11 @@ static const struct hwmon_chip_info laptop_chip_info = {
>>> .info = laptop_hwmon_info,
>>> };
>>>
>>> +static const struct hwmon_chip_info laptop_chip_info_power = {
>>> + .ops = &laptop_hwmon_ops,
>>> + .info = laptop_hwmon_info_power,
>>> +};
>>> +
>>> static int laptop_kbd_led_set(struct led_classdev *led_cdev,
>>> enum led_brightness value)
>>> {
>>> @@ -498,6 +599,96 @@ static const char *const gpu_mode_strings[] = {
>>> "uma",
>>> };
>>>
>>> +static ssize_t fn_lock_show(struct device *dev, struct device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
>>> + struct bitland_mifs_input input = {
>>> + .reserved1 = 0,
>>> + .operation = WMI_METHOD_GET,
>>> + .reserved2 = 0,
>>> + .function = WMI_FN_FN_LOCK,
>>> + };
>>> + struct bitland_mifs_output res;
>>> + int ret;
>>> +
>>> + ret = bitland_mifs_wmi_call(data, &input, &res);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return sysfs_emit(buf, "%u\n", res.data[0]);
>>> +}
>>> +
>>> +static ssize_t fn_lock_store(struct device *dev, struct device_attribute *attr,
>>> + const char *buf, size_t count)
>>> +{
>>> + struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
>>> + struct bitland_mifs_input input = {
>>> + .reserved1 = 0,
>>> + .operation = WMI_METHOD_SET,
>>> + .reserved2 = 0,
>>> + .function = WMI_FN_FN_LOCK,
>>> + };
>>> + bool val;
>>> + int ret;
>>> +
>>> + if (kstrtobool(buf, &val))
>>> + return -EINVAL;
>>> +
>>> + input.payload[0] = val;
>>> +
>>> + ret = bitland_mifs_wmi_call(data, &input, NULL);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return count;
>>> +}
>>> +
>>> +static ssize_t touchpad_lock_show(struct device *dev, struct device_attribute *attr,
>>> + char *buf)
>>> +{
>>> + struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
>>> + struct bitland_mifs_input input = {
>>> + .reserved1 = 0,
>>> + .operation = WMI_METHOD_GET,
>>> + .reserved2 = 0,
>>> + .function = WMI_FN_TP_LOCK,
>>> + };
>>> + struct bitland_mifs_output res;
>>> + int ret;
>>> +
>>> + ret = bitland_mifs_wmi_call(data, &input, &res);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return sysfs_emit(buf, "%u\n", res.data[0]);
>>> +}
>>> +
>>> +static ssize_t touchpad_lock_store(struct device *dev, struct device_attribute *attr,
>>> + const char *buf, size_t count)
>>> +{
>>> + struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
>>> + struct bitland_mifs_input input = {
>>> + .reserved1 = 0,
>>> + .operation = WMI_METHOD_SET,
>>> + .reserved2 = 0,
>>> + .function = WMI_FN_TP_LOCK,
>>> + };
>>> + bool val;
>>> + int ret;
>>> +
>>> + if (kstrtobool(buf, &val))
>>> + return -EINVAL;
>>> +
>>> + input.payload[0] = val;
>>> +
>>> + ret = bitland_mifs_wmi_call(data, &input, NULL);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + return count;
>>> +}
>>> +
>>> /* GPU Mode: 0:Hybrid, 1:Discrete, 2:UMA */
>>> static ssize_t gpu_mode_show(struct device *dev, struct device_attribute *attr,
>>> char *buf)
>>> @@ -637,17 +828,46 @@ static ssize_t fan_boost_store(struct device *dev,
>>> return count;
>>> }
>>>
>>> -static const DEVICE_ATTR_RW(gpu_mode);
>>> -static const DEVICE_ATTR_RW(kb_mode);
>>> -static const DEVICE_ATTR_WO(fan_boost);
>>> +static DEVICE_ATTR_RW(gpu_mode);
>>> +static DEVICE_ATTR_RW(kb_mode);
>>> +static DEVICE_ATTR_WO(fan_boost);
>>> +static DEVICE_ATTR_RW(fn_lock);
>>> +static DEVICE_ATTR_RW(touchpad_lock);
>>>
>>> -static const struct attribute *const laptop_attrs[] = {
>>> +static struct attribute *laptop_attrs[] = {
>>> &dev_attr_gpu_mode.attr,
>>> &dev_attr_kb_mode.attr,
>>> &dev_attr_fan_boost.attr,
>>> + &dev_attr_fn_lock.attr,
>>> + &dev_attr_touchpad_lock.attr,
>>> NULL,
>>> };
>>> -ATTRIBUTE_GROUPS(laptop);
>>> +
>>> +static umode_t laptop_attr_is_visible(struct kobject *kobj,
>>> + struct attribute *attr, int idx)
>>> +{
>>> + struct device *dev = kobj_to_dev(kobj);
>>> + struct bitland_mifs_wmi_data *data = dev_get_drvdata(dev);
>>> +
>>> + /* The sysfs attributes are only supported on the control device */
>>> + if (data->dev_type != BITLAND_WMI_CONTROL)
>>> + return 0;
>>> +
>>> + /*
>>> + * White-only backlit keyboards (e.g. Redmi Book series) do not
>>> + * support the RGB backlight modes.
>>> + */
>>> + if (attr == &dev_attr_kb_mode.attr &&
>>> + data->kbd_type == WMI_KBD_TYPE_WHITE)
>>> + return 0;
>>> +
>>> + return attr->mode;
>>> +}
>>> +
>>> +static const struct attribute_group laptop_group = {
>>> + .attrs = laptop_attrs,
>>> + .is_visible = laptop_attr_is_visible,
>>> +};
>>>
>>> static const struct key_entry bitland_mifs_wmi_keymap[] = {
>>> { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_OPEN_APP, 1, 0), { KEY_PROG1 } },
>>> @@ -699,6 +919,34 @@ static const struct key_entry bitland_mifs_wmi_keymap[] = {
>>> { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FNLOCK_STATE, 0, 0), {} },
>>> { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_FNLOCK_STATE, 1, 0), {} },
>>>
>>> + /* Airplane mode toggle (Redmi) */
>>> + { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_AIRPLANE_MODE, 0, 0), { KEY_RFKILL } },
>>> + { KE_KEY, BI_HOTKEY_CODE(WMI_EVENT_AIRPLANE_MODE, 1, 0), { KEY_RFKILL } },
>>> +
>>> + /*
>>> + * Touchpad state change (Redmi Fn+F7). The EC performs the actual
>>> + * toggle itself; userspace can control the state via the
>>> + * touchpad_lock sysfs attribute.
>>> + */
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_TOUCHPAD_STATE, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_TOUCHPAD_STATE, 1, 0), {} },
>>> +
>>> + /* Keyboard backlight mode change */
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_MODE, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_KBD_MODE, 1, 0), {} },
>>> +
>>> + /* Lock-state indicator events */
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_CAPSLOCK_STATE, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_CAPSLOCK_STATE, 1, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_NUMLOCK_STATE, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_NUMLOCK_STATE, 1, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_SCROLLLOCK_STATE, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_SCROLLLOCK_STATE, 1, 0), {} },
>>> +
>>> + /* Win key lock (Redmi gaming mode) */
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_WIN_KEY_LOCK, 0, 0), {} },
>>> + { KE_IGNORE, BI_HOTKEY_CODE(WMI_EVENT_WIN_KEY_LOCK, 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 } },
>>> @@ -744,6 +992,36 @@ static int bitland_notifier_callback(struct notifier_block *nb,
>>> return NOTIFY_OK;
>>> }
>>>
>>> +static int bitland_detect_kbd_type(struct bitland_mifs_wmi_data *data)
>>> +{
>>> + struct bitland_mifs_input input = {
>>> + .reserved1 = 0,
>>> + .operation = WMI_METHOD_GET,
>>> + .reserved2 = 0,
>>> + .function = WMI_FN_KBD_TYPE,
>>> + };
>>> + struct bitland_mifs_output res;
>>> + int ret;
>>> +
>>> + ret = bitland_mifs_wmi_call(data, &input, &res);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + data->kbd_type = res.data[0];
>>> + return 0;
>>> +}
>>> +
>>> +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;
>>> +
>>> + 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;
>>> @@ -761,6 +1039,9 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
>>> return -ENOMEM;
>>>
>>> drv_data->wdev = wdev;
>>> + drv_data->dev_type = dev_type;
>>> + /* Default to RGB so the RGB attributes stay visible if detection fails */
>>> + drv_data->kbd_type = WMI_KBD_TYPE_RGB;
>>> drv_data->ops = &bitland_ops;
>>>
>>> ret = devm_mutex_init(&wdev->dev, &drv_data->lock);
>>> @@ -769,6 +1050,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);
>>> @@ -794,12 +1077,28 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
>>> if (IS_ERR(drv_data->pp_dev))
>>> return PTR_ERR(drv_data->pp_dev);
>>>
>>> + /* Detect the keyboard type */
>>> + ret = bitland_detect_kbd_type(drv_data);
>>> + if (ret)
>>> + dev_dbg(&wdev->dev, "Failed to detect keyboard type, assuming RGB: %d\n", ret);
>>> +
>>> + ret = devm_device_add_group(&wdev->dev, &laptop_group);
>>> + if (ret)
>>> + return ret;
>>> +
>>> /* Register hwmon */
>>> - drv_data->hwmon_dev = devm_hwmon_device_register_with_info(&wdev->dev,
>>> - "bitland_mifs",
>>> - drv_data,
>>> - &laptop_chip_info,
>>> - NULL);
>>> + if (drv_data->ops->has_cpu_power)
>>> + drv_data->hwmon_dev = devm_hwmon_device_register_with_info(&wdev->dev,
>>> + "bitland_mifs",
>>> + drv_data,
>>> + &laptop_chip_info_power,
>>> + NULL);
>>> + else
>>> + drv_data->hwmon_dev = devm_hwmon_device_register_with_info(&wdev->dev,
>>> + "bitland_mifs",
>>> + drv_data,
>>> + &laptop_chip_info,
>>> + NULL);
>>> if (IS_ERR(drv_data->hwmon_dev))
>>> return PTR_ERR(drv_data->hwmon_dev);
>>>
>>> @@ -851,6 +1150,7 @@ static void bitland_mifs_wmi_report_key(struct wmi_device *wdev, u32 payload)
>>> 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;
>>> @@ -885,7 +1185,8 @@ 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 &&
>>> + if (data->ops->quirk_refresh_rate_toggle &&
>>> + 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);
>>> @@ -923,7 +1224,6 @@ static struct wmi_driver bitland_mifs_wmi_driver = {
>>> .no_singleton = true,
>>> .driver = {
>>> .name = DRV_NAME,
>>> - .dev_groups = laptop_groups,
>>> .pm = pm_sleep_ptr(&bitland_mifs_wmi_pm_ops),
>>> },
>>> .id_table = bitland_mifs_wmi_id_table,
>>> --
>>> 2.55.0
>>>
next prev parent reply other threads:[~2026-09-09 22:49 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-16 10:08 [PATCH v5 0/6] Merge redmi-wmi into bitland-mifs-wmi Mingyou Chen
2026-08-16 10:08 ` [PATCH v5 1/6] MAINTAINERS: Add maintainer entry of bitland-mifs-wmi driver Mingyou Chen
2026-08-26 20:23 ` MAINTAINERS: Add maintainer entry for " Ilya Gladyshev
2026-08-16 10:08 ` [PATCH v5 2/6] platform/x86: bitland-mifs-wmi: Merge the function of redmi-wmi into the bitland driver Mingyou Chen
2026-08-26 20:45 ` Ilya Gladyshev
2026-08-16 10:08 ` [PATCH v5 3/6] platform/x86: bitland-mifs-wmi: Add Redmi mic-mute key entries Mingyou Chen
2026-08-16 10:08 ` [PATCH v5 4/6] platform/x86: redmi-wmi: Drop redmi-wmi driver Mingyou Chen
2026-08-26 20:50 ` Ilya Gladyshev
2026-09-29 8:48 ` Ilpo Järvinen
2026-08-16 10:08 ` [PATCH v5 5/6] platform/x86: bitland-mifs-wmi: Add per-machine ops table Mingyou Chen
2026-09-29 9:02 ` Ilpo Järvinen
2026-08-16 10:08 ` [PATCH v5 6/6] platform/x86: bitland-mifs-wmi: Add Redmi laptop support Mingyou Chen
2026-08-17 23:17 ` Miloš Vlku
2026-09-06 18:16 ` Miloš Vlku
2026-09-09 22:48 ` Armin Wolf [this message]
2026-08-26 13:26 ` [PATCH] platform/x86: bitland-mifs-wmi: add TM2424 ops and hotkeys KentoNion
2026-08-26 13:29 ` KentoNion
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6f14fa17-7206-41d2-b6e4-1711427ba91b@gmx.de \
--to=w_armin@gmx.de \
--cc=foxido@foxido.dev \
--cc=hansg@kernel.org \
--cc=i@rsplwe.com \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nika@nikableh.moe \
--cc=platform-driver-x86@vger.kernel.org \
--cc=qby140326@gmail.com \
--cc=rahulbheda131313@gmail.com \
--cc=vlku.milos.fun@gmail.com \
--cc=wolf109909@outlook.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®