mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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
>>>

  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®