[PATCH 2/2] platform/x86: bitland-mifs-wmi: Add quirk support for MECHREVO MRID6

Rsplwe <[email protected]>
Newsgroups org.kernel.vger.platform-driver-x86,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Add DMI-based quirks for MECHREVO MRID6 laptops.

The MRID6 firmware does not implement the WMI_PP_FULL_SPEED profile
and its WMI_FN_SYSTEM_AC_TYPE method always returns 0, making the AC
adapter type check unreliable.

Use machine-specific quirks to:
- map WMI_PP_PERFORMANCE as the highest performance profile
- skip the AC type validation for performance modes
- hide unsupported balanced-performance/full-speed distinctions

This allows platform profile switching to work correctly on affected
systems.

Signed-off-by: Rsplwe <[email protected]>
---
 drivers/platform/x86/bitland-mifs-wmi.c | 62 +++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/bitland-mifs-wmi.c b/drivers/platform/x86/bitland-mifs-wmi.c
index e2652d1a1bf7..5dff4f4d923b 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>
@@ -153,6 +154,11 @@ struct bitland_fan_notify_data {
 	u16 speed;
 };
 
+struct bitland_mifs_quirk {
+	bool no_full_speed;
+	bool skip_ac_type;	/* EC always returns 0 for AC type */
+};
+
 struct bitland_mifs_wmi_data {
 	struct wmi_device *wdev;
 	struct mutex lock;		/* Protects WMI calls */
@@ -162,6 +168,28 @@ struct bitland_mifs_wmi_data {
 	struct device *hwmon_dev;
 	struct device *pp_dev;
 	enum platform_profile_option saved_profile;
+	struct bitland_mifs_quirk *quirk;
+};
+
+static struct bitland_mifs_quirk bitland_quirk_mrid6 = {
+	.no_full_speed = true,
+	.skip_ac_type = true,
+};
+
+static const struct dmi_system_id bitland_quirks[] = {
+	{
+		/*
+		 * MECHREVO MRID6: does not implement WMI_PP_FULL_SPEED,
+		 * its top profile is WMI_PP_PERFORMANCE; WMI_FN_SYSTEM_AC_TYPE
+		 * always returns 0, so the adapter type check is meaningless.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "MECHREVO"),
+			DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
+		},
+		.driver_data = (void *)&bitland_quirk_mrid6,
+	},
+	{}
 };
 
 static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
@@ -209,7 +237,10 @@ static int laptop_profile_get(struct device *dev,
 		*profile = PLATFORM_PROFILE_BALANCED;
 		break;
 	case WMI_PP_PERFORMANCE:
-		*profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
+		if (data->quirk && data->quirk->no_full_speed)
+			*profile = PLATFORM_PROFILE_PERFORMANCE;
+		else
+			*profile = PLATFORM_PROFILE_BALANCED_PERFORMANCE;
 		break;
 	case WMI_PP_QUIET:
 		*profile = PLATFORM_PROFILE_LOW_POWER;
@@ -236,6 +267,10 @@ static int bitland_check_performance_capability(struct bitland_mifs_wmi_data *da
 	if (!power_supply_is_system_supplied())
 		return -EOPNOTSUPP;
 
+	/* Some ECs never report a meaningful AC type (always 0), skip it */
+	if (data->quirk && data->quirk->skip_ac_type)
+		return 0;
+
 	ret = bitland_mifs_wmi_call(data, &input, &output);
 	if (ret)
 		return ret;
@@ -267,6 +302,8 @@ static int laptop_profile_set(struct device *dev,
 		val = WMI_PP_BALANCED;
 		break;
 	case PLATFORM_PROFILE_BALANCED_PERFORMANCE:
+		if (data->quirk && data->quirk->no_full_speed)
+			return -EOPNOTSUPP;
 		ret = bitland_check_performance_capability(data);
 		if (ret)
 			return ret;
@@ -276,7 +313,10 @@ static int laptop_profile_set(struct device *dev,
 		ret = bitland_check_performance_capability(data);
 		if (ret)
 			return ret;
-		val = WMI_PP_FULL_SPEED;
+		if (data->quirk && data->quirk->no_full_speed)
+			val = WMI_PP_PERFORMANCE;
+		else
+			val = WMI_PP_FULL_SPEED;
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -289,11 +329,17 @@ static int laptop_profile_set(struct device *dev,
 
 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->quirk && data->quirk->no_full_speed) {
+		/* No separate balanced-performance tier; performance is the top mode */
+		set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+	} else {
+		set_bit(PLATFORM_PROFILE_BALANCED_PERFORMANCE, choices);
+		set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+	}
 	return 0;
 }
 
@@ -815,6 +861,7 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
 		.default_label = ":" LED_FUNCTION_KBD_BACKLIGHT,
 		.devname_mandatory = true,
 	};
+	const struct dmi_system_id *match;
 	int ret;
 
 	drv_data = devm_kzalloc(&wdev->dev, sizeof(*drv_data), GFP_KERNEL);
@@ -829,6 +876,11 @@ static int bitland_mifs_wmi_probe(struct wmi_device *wdev, const void *context)
 
 	dev_set_drvdata(&wdev->dev, drv_data);
 
+	/* Apply machine-specific quirks */
+	match = dmi_first_match(bitland_quirks);
+	if (match && match->driver_data)
+		drv_data->quirk = match->driver_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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.