* [PATCH v8 01/14] platform/x86: alienware-wmi: Add a state container for LED control feature
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 02/14] platform/x86: alienware-wmi: Add WMI Drivers Kurt Borja
` (13 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Add a state container for the "alienware-wmi" platform device and
initialize it on the new alienfx_probe(). Migrate all LED control functions
to use this state container to support upcoming file split.
Additionally move the led_classdev registration to the platform driver
probe and make it device managed.
Drop alienware_zone_init() and alienware_zone_exit() because they are no
longer needed and mimic the `quirks->num_zone > 0` check by failing the
platform device probe.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 125 ++++++++++++----------
1 file changed, 68 insertions(+), 57 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index e252e0cf47ef..ab86deb1adb9 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -413,13 +413,18 @@ struct wmax_u32_args {
u8 arg3;
};
+struct alienfx_priv {
+ struct platform_device *pdev;
+ struct led_classdev global_led;
+ struct color_platform colors[4];
+ u8 global_brightness;
+ u8 lighting_control_state;
+};
+
static struct platform_device *platform_device;
-static struct color_platform colors[4];
static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
static u8 interface;
-static u8 lighting_control_state;
-static u8 global_brightness;
/*
* Helpers used for zone control
@@ -451,7 +456,7 @@ static int parse_rgb(const char *buf, struct color_platform *colors)
/*
* Individual RGB zone control
*/
-static int alienware_update_led(u8 location)
+static int alienware_update_led(struct alienfx_priv *priv, u8 location)
{
int method_id;
acpi_status status;
@@ -461,21 +466,21 @@ static int alienware_update_led(u8 location)
struct wmax_led_args wmax_basic_args;
if (interface == WMAX) {
wmax_basic_args.led_mask = 1 << location;
- wmax_basic_args.colors = colors[location];
- wmax_basic_args.state = lighting_control_state;
+ wmax_basic_args.colors = priv->colors[location];
+ wmax_basic_args.state = priv->lighting_control_state;
guid = WMAX_CONTROL_GUID;
method_id = WMAX_METHOD_ZONE_CONTROL;
input.length = sizeof(wmax_basic_args);
input.pointer = &wmax_basic_args;
} else {
- legacy_args.colors = colors[location];
- legacy_args.brightness = global_brightness;
+ legacy_args.colors = priv->colors[location];
+ legacy_args.brightness = priv->global_brightness;
legacy_args.state = 0;
- if (lighting_control_state == LEGACY_BOOTING ||
- lighting_control_state == LEGACY_SUSPEND) {
+ if (priv->lighting_control_state == LEGACY_BOOTING ||
+ priv->lighting_control_state == LEGACY_SUSPEND) {
guid = LEGACY_POWER_CONTROL_GUID;
- legacy_args.state = lighting_control_state;
+ legacy_args.state = priv->lighting_control_state;
} else
guid = LEGACY_CONTROL_GUID;
method_id = location + 1;
@@ -494,22 +499,26 @@ static int alienware_update_led(u8 location)
static ssize_t zone_show(struct device *dev, struct device_attribute *attr,
char *buf, u8 location)
{
+ struct alienfx_priv *priv = dev_get_drvdata(dev);
+ struct color_platform *colors = &priv->colors[location];
+
return sprintf(buf, "red: %d, green: %d, blue: %d\n",
- colors[location].red, colors[location].green,
- colors[location].blue);
+ colors->red, colors->green, colors->blue);
}
static ssize_t zone_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count, u8 location)
{
+ struct alienfx_priv *priv = dev_get_drvdata(dev);
+ struct color_platform *colors = &priv->colors[location];
int ret;
- ret = parse_rgb(buf, &colors[location]);
+ ret = parse_rgb(buf, colors);
if (ret)
return ret;
- ret = alienware_update_led(location);
+ ret = alienware_update_led(priv, location);
return ret ? ret : count;
}
@@ -577,9 +586,11 @@ static ssize_t lighting_control_state_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- if (lighting_control_state == LEGACY_BOOTING)
+ struct alienfx_priv *priv = dev_get_drvdata(dev);
+
+ if (priv->lighting_control_state == LEGACY_BOOTING)
return sysfs_emit(buf, "[booting] running suspend\n");
- else if (lighting_control_state == LEGACY_SUSPEND)
+ else if (priv->lighting_control_state == LEGACY_SUSPEND)
return sysfs_emit(buf, "booting running [suspend]\n");
return sysfs_emit(buf, "booting [running] suspend\n");
@@ -589,6 +600,7 @@ static ssize_t lighting_control_state_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct alienfx_priv *priv = dev_get_drvdata(dev);
u8 val;
if (strcmp(buf, "booting\n") == 0)
@@ -600,9 +612,9 @@ static ssize_t lighting_control_state_store(struct device *dev,
else
val = WMAX_RUNNING;
- lighting_control_state = val;
+ priv->lighting_control_state = val;
pr_debug("alienware-wmi: updated control state to %d\n",
- lighting_control_state);
+ priv->lighting_control_state);
return count;
}
@@ -662,46 +674,26 @@ static int wmax_brightness(int brightness)
static void global_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
+ struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv,
+ global_led);
int ret;
- global_brightness = brightness;
+
+ priv->global_brightness = brightness;
+
if (interface == WMAX)
ret = wmax_brightness(brightness);
else
- ret = alienware_update_led(0);
+ ret = alienware_update_led(priv, 0);
if (ret)
pr_err("LED brightness update failed\n");
}
static enum led_brightness global_led_get(struct led_classdev *led_cdev)
{
- return global_brightness;
-}
-
-static struct led_classdev global_led = {
- .brightness_set = global_led_set,
- .brightness_get = global_led_get,
- .name = "alienware::global_brightness",
-};
+ struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv,
+ global_led);
-static int alienware_zone_init(struct platform_device *dev)
-{
- if (interface == WMAX) {
- lighting_control_state = WMAX_RUNNING;
- } else if (interface == LEGACY) {
- lighting_control_state = LEGACY_RUNNING;
- }
- global_led.max_brightness = 0x0F;
- global_brightness = global_led.max_brightness;
-
- return led_classdev_register(&dev->dev, &global_led);
-}
-
-static void alienware_zone_exit(struct platform_device *dev)
-{
- if (!quirks->num_zones)
- return;
-
- led_classdev_unregister(&global_led);
+ return priv->global_brightness;
}
static acpi_status alienware_wmax_command(void *in_args, size_t in_size,
@@ -1157,6 +1149,33 @@ static int create_thermal_profile(struct platform_device *platform_device)
/*
* Platform Driver
*/
+static int alienfx_probe(struct platform_device *pdev)
+{
+ struct alienfx_priv *priv;
+
+ if (!quirks->num_zones)
+ return -ENODEV;
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ if (interface == WMAX)
+ priv->lighting_control_state = WMAX_RUNNING;
+ else
+ priv->lighting_control_state = LEGACY_RUNNING;
+
+ priv->pdev = pdev;
+ priv->global_led.name = "alienware::global_brightness";
+ priv->global_led.brightness_set = global_led_set;
+ priv->global_led.brightness_get = global_led_get;
+ priv->global_led.max_brightness = 0x0F;
+ priv->global_brightness = priv->global_led.max_brightness;
+ platform_set_drvdata(pdev, priv);
+
+ return devm_led_classdev_register(&pdev->dev, &priv->global_led);
+}
+
static const struct attribute_group *alienfx_groups[] = {
&zone_attribute_group,
&hdmi_attribute_group,
@@ -1170,6 +1189,7 @@ static struct platform_driver platform_driver = {
.name = "alienware-wmi",
.dev_groups = alienfx_groups,
},
+ .probe = alienfx_probe,
};
static int __init alienware_wmi_init(void)
@@ -1217,16 +1237,8 @@ static int __init alienware_wmi_init(void)
goto fail_prep_thermal_profile;
}
- if (quirks->num_zones > 0) {
- ret = alienware_zone_init(platform_device);
- if (ret)
- goto fail_prep_zones;
- }
-
return 0;
-fail_prep_zones:
- alienware_zone_exit(platform_device);
fail_prep_thermal_profile:
platform_device_del(platform_device);
fail_platform_device2:
@@ -1241,7 +1253,6 @@ module_init(alienware_wmi_init);
static void __exit alienware_wmi_exit(void)
{
- alienware_zone_exit(platform_device);
platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 02/14] platform/x86: alienware-wmi: Add WMI Drivers
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
2025-02-03 18:27 ` [PATCH v8 01/14] platform/x86: alienware-wmi: Add a state container for LED control feature Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 03/14] platform/x86: alienware-wmi: Add a state container for thermal control methods Kurt Borja
` (12 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Add WMI drivers for LEGACY and WMAX devices.
This involves moving the platform device registration to a helper
function that is now called from the driver's preferred WMI device
driver probe. In the case of the WMAX this is done only if
`!quirks->thermal` because the newer WMAX interface doesn't support any
of the LED features of this driver. This also eliminates the need to
check for `quirks->num_zones > 0` inside alienfx_probe().
Only one WMI driver is registered on module initialization to prevent
registering a duplicate platform device.
Additionally, create_thermal_profile() now takes wmi_device * instead of
platform_device *.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 177 ++++++++++++++++------
1 file changed, 134 insertions(+), 43 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index ab86deb1adb9..506c096553e8 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -15,6 +15,7 @@
#include <linux/platform_profile.h>
#include <linux/dmi.h>
#include <linux/leds.h>
+#include <linux/wmi.h>
#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
@@ -39,8 +40,6 @@
MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>");
MODULE_DESCRIPTION("Alienware special feature control");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("wmi:" LEGACY_CONTROL_GUID);
-MODULE_ALIAS("wmi:" WMAX_CONTROL_GUID);
static bool force_platform_profile;
module_param_unsafe(force_platform_profile, bool, 0);
@@ -421,7 +420,10 @@ struct alienfx_priv {
u8 lighting_control_state;
};
-static struct platform_device *platform_device;
+struct alienfx_platdata {
+ struct wmi_device *wdev;
+};
+
static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
static u8 interface;
@@ -801,7 +803,7 @@ static DEVICE_ATTR_RW(source);
static bool hdmi_group_visible(struct kobject *kobj)
{
- return quirks->hdmi_mux;
+ return interface == WMAX && quirks->hdmi_mux;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
@@ -848,7 +850,7 @@ static DEVICE_ATTR_RO(status);
static bool amplifier_group_visible(struct kobject *kobj)
{
- return quirks->amplifier;
+ return interface == WMAX && quirks->amplifier;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
@@ -917,7 +919,7 @@ static DEVICE_ATTR_RW(deepsleep);
static bool deepsleep_group_visible(struct kobject *kobj)
{
- return quirks->deepslp;
+ return interface == WMAX && quirks->deepslp;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
@@ -1136,11 +1138,11 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
.profile_set = thermal_profile_set,
};
-static int create_thermal_profile(struct platform_device *platform_device)
+static int create_thermal_profile(struct wmi_device *wdev)
{
struct device *ppdev;
- ppdev = devm_platform_profile_register(&platform_device->dev, "alienware-wmi",
+ ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
NULL, &awcc_platform_profile_ops);
return PTR_ERR_OR_ZERO(ppdev);
@@ -1153,9 +1155,6 @@ static int alienfx_probe(struct platform_device *pdev)
{
struct alienfx_priv *priv;
- if (!quirks->num_zones)
- return -ENODEV;
-
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
@@ -1192,18 +1191,118 @@ static struct platform_driver platform_driver = {
.probe = alienfx_probe,
};
-static int __init alienware_wmi_init(void)
+static void alienware_alienfx_remove(void *data)
{
+ struct platform_device *pdev = data;
+
+ platform_device_unregister(pdev);
+}
+
+static int alienware_alienfx_setup(struct alienfx_platdata *pdata)
+{
+ struct device *dev = &pdata->wdev->dev;
+ struct platform_device *pdev;
int ret;
- if (wmi_has_guid(LEGACY_CONTROL_GUID))
- interface = LEGACY;
- else if (wmi_has_guid(WMAX_CONTROL_GUID))
- interface = WMAX;
- else {
- pr_warn("alienware-wmi: No known WMI GUID found\n");
- return -ENODEV;
- }
+ pdev = platform_device_register_data(NULL, "alienware-wmi",
+ PLATFORM_DEVID_NONE, pdata,
+ sizeof(*pdata));
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ dev_set_drvdata(dev, pdev);
+ ret = devm_add_action_or_reset(dev, alienware_alienfx_remove, pdev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/*
+ * Legacy WMI driver
+ */
+static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct alienfx_platdata pdata = {
+ .wdev = wdev,
+ };
+
+ return alienware_alienfx_setup(&pdata);
+}
+
+static const struct wmi_device_id alienware_legacy_device_id_table[] = {
+ { LEGACY_CONTROL_GUID, NULL },
+ { },
+};
+MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table);
+
+static struct wmi_driver alienware_legacy_wmi_driver = {
+ .driver = {
+ .name = "alienware-wmi-alienfx",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = alienware_legacy_device_id_table,
+ .probe = legacy_wmi_probe,
+ .no_singleton = true,
+};
+
+static int __init alienware_legacy_wmi_init(void)
+{
+ return wmi_driver_register(&alienware_legacy_wmi_driver);
+}
+
+static void __exit alienware_legacy_wmi_exit(void)
+{
+ wmi_driver_unregister(&alienware_legacy_wmi_driver);
+}
+
+/*
+ * WMAX WMI driver
+ */
+static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct alienfx_platdata pdata = {
+ .wdev = wdev,
+ };
+ int ret;
+
+ if (quirks->thermal)
+ ret = create_thermal_profile(wdev);
+ else
+ ret = alienware_alienfx_setup(&pdata);
+
+ return ret;
+}
+
+static const struct wmi_device_id alienware_wmax_device_id_table[] = {
+ { WMAX_CONTROL_GUID, NULL },
+ { },
+};
+MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table);
+
+static struct wmi_driver alienware_wmax_wmi_driver = {
+ .driver = {
+ .name = "alienware-wmi-wmax",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = alienware_wmax_device_id_table,
+ .probe = wmax_wmi_probe,
+ .no_singleton = true,
+};
+
+static int __init alienware_wmax_wmi_init(void)
+{
+ return wmi_driver_register(&alienware_wmax_wmi_driver);
+}
+
+static void __exit alienware_wmax_wmi_exit(void)
+{
+ wmi_driver_unregister(&alienware_wmax_wmi_driver);
+}
+
+static int __init alienware_wmi_init(void)
+{
+ int ret;
dmi_check_system(alienware_quirks);
if (quirks == NULL)
@@ -1220,32 +1319,20 @@ static int __init alienware_wmi_init(void)
}
ret = platform_driver_register(&platform_driver);
- if (ret)
- goto fail_platform_driver;
- platform_device = platform_device_alloc("alienware-wmi", PLATFORM_DEVID_NONE);
- if (!platform_device) {
- ret = -ENOMEM;
- goto fail_platform_device1;
- }
- ret = platform_device_add(platform_device);
- if (ret)
- goto fail_platform_device2;
+ if (ret < 0)
+ return ret;
- if (quirks->thermal) {
- ret = create_thermal_profile(platform_device);
- if (ret)
- goto fail_prep_thermal_profile;
+ if (wmi_has_guid(WMAX_CONTROL_GUID)) {
+ interface = WMAX;
+ ret = alienware_wmax_wmi_init();
+ } else {
+ interface = LEGACY;
+ ret = alienware_legacy_wmi_init();
}
- return 0;
+ if (ret < 0)
+ platform_driver_unregister(&platform_driver);
-fail_prep_thermal_profile:
- platform_device_del(platform_device);
-fail_platform_device2:
- platform_device_put(platform_device);
-fail_platform_device1:
- platform_driver_unregister(&platform_driver);
-fail_platform_driver:
return ret;
}
@@ -1253,7 +1340,11 @@ module_init(alienware_wmi_init);
static void __exit alienware_wmi_exit(void)
{
- platform_device_unregister(platform_device);
+ if (interface == WMAX)
+ alienware_wmax_wmi_exit();
+ else
+ alienware_legacy_wmi_exit();
+
platform_driver_unregister(&platform_driver);
}
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 03/14] platform/x86: alienware-wmi: Add a state container for thermal control methods
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
2025-02-03 18:27 ` [PATCH v8 01/14] platform/x86: alienware-wmi: Add a state container for LED control feature Kurt Borja
2025-02-03 18:27 ` [PATCH v8 02/14] platform/x86: alienware-wmi: Add WMI Drivers Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 04/14] platform/x86: alienware-wmi: Refactor LED " Kurt Borja
` (11 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Refactor all thermal control methods to use the newly defined awcc_priv
state container instead of global variables. While at it, rename
create_thermal_profile() to awcc_platform_profile_init() and introduce
alienware_awcc_setup() to set up the "AWCC" WMI device driver data.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 50 ++++++++++++++++++-----
1 file changed, 39 insertions(+), 11 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 506c096553e8..9512143c82ec 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -412,6 +412,12 @@ struct wmax_u32_args {
u8 arg3;
};
+struct awcc_priv {
+ struct wmi_device *wdev;
+ struct device *ppdev;
+ enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
+};
+
struct alienfx_priv {
struct platform_device *pdev;
struct led_classdev global_led;
@@ -424,8 +430,6 @@ struct alienfx_platdata {
struct wmi_device *wdev;
};
-static enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
-
static u8 interface;
/*
@@ -1060,6 +1064,8 @@ static int thermal_profile_get(struct device *dev,
static int thermal_profile_set(struct device *dev,
enum platform_profile_option profile)
{
+ struct awcc_priv *priv = dev_get_drvdata(dev);
+
if (quirks->gmode) {
u32 gmode_status;
int ret;
@@ -1080,12 +1086,13 @@ static int thermal_profile_set(struct device *dev,
}
}
- return wmax_thermal_control(supported_thermal_profiles[profile]);
+ return wmax_thermal_control(priv->supported_thermal_profiles[profile]);
}
static int thermal_profile_probe(void *drvdata, unsigned long *choices)
{
enum platform_profile_option profile;
+ struct awcc_priv *priv = drvdata;
enum wmax_thermal_mode mode;
u8 sys_desc[4];
u32 first_mode;
@@ -1114,7 +1121,7 @@ static int thermal_profile_probe(void *drvdata, unsigned long *choices)
mode = out_data & WMAX_THERMAL_MODE_MASK;
profile = wmax_mode_to_platform_profile[mode];
- supported_thermal_profiles[profile] = out_data;
+ priv->supported_thermal_profiles[profile] = out_data;
set_bit(profile, choices);
}
@@ -1123,7 +1130,7 @@ static int thermal_profile_probe(void *drvdata, unsigned long *choices)
return -ENODEV;
if (quirks->gmode) {
- supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
+ priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
WMAX_THERMAL_MODE_GMODE;
set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
@@ -1138,14 +1145,35 @@ static const struct platform_profile_ops awcc_platform_profile_ops = {
.profile_set = thermal_profile_set,
};
-static int create_thermal_profile(struct wmi_device *wdev)
+static int awcc_platform_profile_init(struct wmi_device *wdev)
{
- struct device *ppdev;
+ struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
+
+ priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
+ priv, &awcc_platform_profile_ops);
+
+ return PTR_ERR_OR_ZERO(priv->ppdev);
+}
- ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
- NULL, &awcc_platform_profile_ops);
+static int alienware_awcc_setup(struct wmi_device *wdev)
+{
+ struct awcc_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
- return PTR_ERR_OR_ZERO(ppdev);
+ priv->wdev = wdev;
+ dev_set_drvdata(&wdev->dev, priv);
+
+ if (quirks->thermal) {
+ ret = awcc_platform_profile_init(wdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
}
/*
@@ -1267,7 +1295,7 @@ static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
int ret;
if (quirks->thermal)
- ret = create_thermal_profile(wdev);
+ ret = alienware_awcc_setup(wdev);
else
ret = alienware_alienfx_setup(&pdata);
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 04/14] platform/x86: alienware-wmi: Refactor LED control methods
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (2 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 03/14] platform/x86: alienware-wmi: Add a state container for thermal control methods Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 05/14] platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods Kurt Borja
` (10 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Both WMI devices handled by this module specify a distinct interface for
LED control. Previously this module handled this by dynamically adapting
arguments passed to wmi_evaluate_method() based on the `interface`
global variable.
To avoid the use of global variables, and enable the migration to
non-deprecated WMI methods, let the WMI drivers define upd_led and
upd_brightness operations, which completely replace
alienware_update_led() and wmax_brightness().
Also define alienware_wmi_command(), which serves as a wrapper for
wmidev_evaluate_method(). This new method is very similar to
alienware_wmax_command() but is WMI device agnostic.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 166 ++++++++++++++--------
1 file changed, 104 insertions(+), 62 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 9512143c82ec..525d25a1fa6c 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -10,6 +10,7 @@
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/platform_profile.h>
@@ -426,12 +427,43 @@ struct alienfx_priv {
u8 lighting_control_state;
};
+struct alienfx_ops {
+ int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev,
+ u8 location);
+ int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev,
+ u8 brightness);
+};
+
struct alienfx_platdata {
struct wmi_device *wdev;
+ struct alienfx_ops ops;
};
static u8 interface;
+static int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
+ void *in_args, size_t in_size, u32 *out_data)
+{
+ struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct acpi_buffer in = {in_size, in_args};
+ acpi_status ret;
+
+ ret = wmidev_evaluate_method(wdev, 0, method_id, &in, out_data ? &out : NULL);
+ if (ACPI_FAILURE(ret))
+ return -EIO;
+
+ union acpi_object *obj __free(kfree) = out.pointer;
+
+ if (out_data) {
+ if (obj && obj->type == ACPI_TYPE_INTEGER)
+ *out_data = (u32)obj->integer.value;
+ else
+ return -ENOMSG;
+ }
+
+ return 0;
+}
+
/*
* Helpers used for zone control
*/
@@ -462,46 +494,6 @@ static int parse_rgb(const char *buf, struct color_platform *colors)
/*
* Individual RGB zone control
*/
-static int alienware_update_led(struct alienfx_priv *priv, u8 location)
-{
- int method_id;
- acpi_status status;
- char *guid;
- struct acpi_buffer input;
- struct legacy_led_args legacy_args;
- struct wmax_led_args wmax_basic_args;
- if (interface == WMAX) {
- wmax_basic_args.led_mask = 1 << location;
- wmax_basic_args.colors = priv->colors[location];
- wmax_basic_args.state = priv->lighting_control_state;
- guid = WMAX_CONTROL_GUID;
- method_id = WMAX_METHOD_ZONE_CONTROL;
-
- input.length = sizeof(wmax_basic_args);
- input.pointer = &wmax_basic_args;
- } else {
- legacy_args.colors = priv->colors[location];
- legacy_args.brightness = priv->global_brightness;
- legacy_args.state = 0;
- if (priv->lighting_control_state == LEGACY_BOOTING ||
- priv->lighting_control_state == LEGACY_SUSPEND) {
- guid = LEGACY_POWER_CONTROL_GUID;
- legacy_args.state = priv->lighting_control_state;
- } else
- guid = LEGACY_CONTROL_GUID;
- method_id = location + 1;
-
- input.length = sizeof(legacy_args);
- input.pointer = &legacy_args;
- }
- pr_debug("alienware-wmi: guid %s method %d\n", guid, method_id);
-
- status = wmi_evaluate_method(guid, 0, method_id, &input, NULL);
- if (ACPI_FAILURE(status))
- pr_err("alienware-wmi: zone set failure: %u\n", status);
- return ACPI_FAILURE(status);
-}
-
static ssize_t zone_show(struct device *dev, struct device_attribute *attr,
char *buf, u8 location)
{
@@ -518,13 +510,14 @@ static ssize_t zone_store(struct device *dev, struct device_attribute *attr,
{
struct alienfx_priv *priv = dev_get_drvdata(dev);
struct color_platform *colors = &priv->colors[location];
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
int ret;
ret = parse_rgb(buf, colors);
if (ret)
return ret;
- ret = alienware_update_led(priv, location);
+ ret = pdata->ops.upd_led(priv, pdata->wdev, location);
return ret ? ret : count;
}
@@ -660,36 +653,17 @@ static struct attribute_group zone_attribute_group = {
/*
* LED Brightness (Global)
*/
-static int wmax_brightness(int brightness)
-{
- acpi_status status;
- struct acpi_buffer input;
- struct wmax_brightness_args args = {
- .led_mask = 0xFF,
- .percentage = brightness,
- };
- input.length = sizeof(args);
- input.pointer = &args;
- status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
- WMAX_METHOD_BRIGHTNESS, &input, NULL);
- if (ACPI_FAILURE(status))
- pr_err("alienware-wmi: brightness set failure: %u\n", status);
- return ACPI_FAILURE(status);
-}
-
static void global_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct alienfx_priv *priv = container_of(led_cdev, struct alienfx_priv,
global_led);
+ struct alienfx_platdata *pdata = dev_get_platdata(&priv->pdev->dev);
int ret;
priv->global_brightness = brightness;
- if (interface == WMAX)
- ret = wmax_brightness(brightness);
- else
- ret = alienware_update_led(priv, 0);
+ ret = pdata->ops.upd_brightness(priv, pdata->wdev, brightness);
if (ret)
pr_err("LED brightness update failed\n");
}
@@ -1249,10 +1223,49 @@ static int alienware_alienfx_setup(struct alienfx_platdata *pdata)
/*
* Legacy WMI driver
*/
+static int legacy_wmi_update_led(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 location)
+{
+ struct legacy_led_args legacy_args = {
+ .colors = priv->colors[location],
+ .brightness = priv->global_brightness,
+ .state = 0,
+ };
+ struct acpi_buffer input;
+ acpi_status status;
+
+ if (legacy_args.state != LEGACY_RUNNING) {
+ legacy_args.state = priv->lighting_control_state;
+
+ input.length = sizeof(legacy_args);
+ input.pointer = &legacy_args;
+
+ status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0,
+ location + 1, &input, NULL);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ return 0;
+ }
+
+ return alienware_wmi_command(wdev, location + 1, &legacy_args,
+ sizeof(legacy_args), NULL);
+}
+
+static int legacy_wmi_update_brightness(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 brightness)
+{
+ return legacy_wmi_update_led(priv, wdev, 0);
+}
+
static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct alienfx_platdata pdata = {
.wdev = wdev,
+ .ops = {
+ .upd_led = legacy_wmi_update_led,
+ .upd_brightness = legacy_wmi_update_brightness,
+ },
};
return alienware_alienfx_setup(&pdata);
@@ -1287,10 +1300,39 @@ static void __exit alienware_legacy_wmi_exit(void)
/*
* WMAX WMI driver
*/
+static int wmax_wmi_update_led(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 location)
+{
+ struct wmax_led_args in_args = {
+ .led_mask = 1 << location,
+ .colors = priv->colors[location],
+ .state = priv->lighting_control_state,
+ };
+
+ return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args,
+ sizeof(in_args), NULL);
+}
+
+static int wmax_wmi_update_brightness(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 brightness)
+{
+ struct wmax_brightness_args in_args = {
+ .led_mask = 0xFF,
+ .percentage = brightness,
+ };
+
+ return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args,
+ sizeof(in_args), NULL);
+}
+
static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
{
struct alienfx_platdata pdata = {
.wdev = wdev,
+ .ops = {
+ .upd_led = wmax_wmi_update_led,
+ .upd_brightness = wmax_wmi_update_brightness,
+ },
};
int ret;
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 05/14] platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (3 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 04/14] platform/x86: alienware-wmi: Refactor LED " Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-07 13:44 ` Ilpo Järvinen
2025-02-03 18:27 ` [PATCH v8 06/14] platform/x86: alienware-wmi: Refactor thermal control methods Kurt Borja
` (9 subsequent siblings)
14 siblings, 1 reply; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Refactor show/store methods for hdmi, amplifier, deepslp sysfs groups to
use alienware_wmi_command() instead of alienware_wmax_command() which
uses deprecated WMI methods.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 80 +++++++++++++----------
1 file changed, 45 insertions(+), 35 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 525d25a1fa6c..412caf0e3b84 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -711,53 +711,57 @@ static acpi_status alienware_wmax_command(void *in_args, size_t in_size,
static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args in_args = {
.arg = 0,
};
- acpi_status status;
u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
+ &in_args, sizeof(in_args), &out_data);
- status =
- alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_HDMI_CABLE, &out_data);
- if (ACPI_SUCCESS(status)) {
+ if (!ret) {
if (out_data == 0)
return sysfs_emit(buf, "[unconnected] connected unknown\n");
else if (out_data == 1)
return sysfs_emit(buf, "unconnected [connected] unknown\n");
}
- pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status);
+
+ pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
return sysfs_emit(buf, "unconnected connected [unknown]\n");
}
static ssize_t source_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args in_args = {
.arg = 0,
};
- acpi_status status;
u32 out_data;
+ int ret;
- status =
- alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_HDMI_STATUS, &out_data);
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
+ &in_args, sizeof(in_args), &out_data);
- if (ACPI_SUCCESS(status)) {
+ if (!ret) {
if (out_data == 1)
return sysfs_emit(buf, "[input] gpu unknown\n");
else if (out_data == 2)
return sysfs_emit(buf, "input [gpu] unknown\n");
}
- pr_err("alienware-wmi: unknown HDMI source status: %u\n", status);
+
+ pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
return sysfs_emit(buf, "input gpu [unknown]\n");
}
static ssize_t source_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args args;
- acpi_status status;
+ int ret;
if (strcmp(buf, "gpu\n") == 0)
args.arg = 1;
@@ -767,12 +771,12 @@ static ssize_t source_store(struct device *dev, struct device_attribute *attr,
args.arg = 3;
pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
- status = alienware_wmax_command(&args, sizeof(args),
- WMAX_METHOD_HDMI_SOURCE, NULL);
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
+ sizeof(args), NULL);
+
+ if (ret < 0)
+ pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
- if (ACPI_FAILURE(status))
- pr_err("alienware-wmi: HDMI toggle failed: results: %u\n",
- status);
return count;
}
@@ -805,22 +809,24 @@ static const struct attribute_group hdmi_attribute_group = {
static ssize_t status_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args in_args = {
.arg = 0,
};
- acpi_status status;
u32 out_data;
+ int ret;
- status =
- alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_AMPLIFIER_CABLE, &out_data);
- if (ACPI_SUCCESS(status)) {
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
if (out_data == 0)
return sysfs_emit(buf, "[unconnected] connected unknown\n");
else if (out_data == 1)
return sysfs_emit(buf, "unconnected [connected] unknown\n");
}
- pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status);
+
+ pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
return sysfs_emit(buf, "unconnected connected [unknown]\n");
}
@@ -850,15 +856,17 @@ static const struct attribute_group amplifier_attribute_group = {
static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args in_args = {
.arg = 0,
};
- acpi_status status;
u32 out_data;
+ int ret;
- status = alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_DEEP_SLEEP_STATUS, &out_data);
- if (ACPI_SUCCESS(status)) {
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
if (out_data == 0)
return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
else if (out_data == 1)
@@ -866,15 +874,17 @@ static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
else if (out_data == 2)
return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
}
- pr_err("alienware-wmi: unknown deep sleep status: %d\n", status);
+
+ pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
}
static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
struct wmax_basic_args args;
- acpi_status status;
+ int ret;
if (strcmp(buf, "disabled\n") == 0)
args.arg = 0;
@@ -884,12 +894,12 @@ static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr
args.arg = 2;
pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
- status = alienware_wmax_command(&args, sizeof(args),
- WMAX_METHOD_DEEP_SLEEP_CONTROL, NULL);
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
+ &args, sizeof(args), NULL);
+
+ if (!ret)
+ pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
- if (ACPI_FAILURE(status))
- pr_err("alienware-wmi: deep sleep control failed: results: %u\n",
- status);
return count;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v8 05/14] platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods
2025-02-03 18:27 ` [PATCH v8 05/14] platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods Kurt Borja
@ 2025-02-07 13:44 ` Ilpo Järvinen
0 siblings, 0 replies; 17+ messages in thread
From: Ilpo Järvinen @ 2025-02-07 13:44 UTC (permalink / raw)
To: Kurt Borja
Cc: platform-driver-x86, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, LKML
On Mon, 3 Feb 2025, Kurt Borja wrote:
> Refactor show/store methods for hdmi, amplifier, deepslp sysfs groups to
> use alienware_wmi_command() instead of alienware_wmax_command() which
> uses deprecated WMI methods.
>
> Reviewed-by: Armin Wolf <W_Armin@gmx.de>
> Signed-off-by: Kurt Borja <kuurtb@gmail.com>
> ---
> drivers/platform/x86/dell/alienware-wmi.c | 80 +++++++++++++----------
> 1 file changed, 45 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
> index 525d25a1fa6c..412caf0e3b84 100644
> --- a/drivers/platform/x86/dell/alienware-wmi.c
> +++ b/drivers/platform/x86/dell/alienware-wmi.c
> @@ -711,53 +711,57 @@ static acpi_status alienware_wmax_command(void *in_args, size_t in_size,
> static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args in_args = {
> .arg = 0,
> };
> - acpi_status status;
> u32 out_data;
> + int ret;
> +
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
> + &in_args, sizeof(in_args), &out_data);
>
> - status =
> - alienware_wmax_command(&in_args, sizeof(in_args),
> - WMAX_METHOD_HDMI_CABLE, &out_data);
> - if (ACPI_SUCCESS(status)) {
> + if (!ret) {
> if (out_data == 0)
> return sysfs_emit(buf, "[unconnected] connected unknown\n");
> else if (out_data == 1)
> return sysfs_emit(buf, "unconnected [connected] unknown\n");
> }
> - pr_err("alienware-wmi: unknown HDMI cable status: %d\n", status);
> +
> + pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
> return sysfs_emit(buf, "unconnected connected [unknown]\n");
> }
>
> static ssize_t source_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args in_args = {
> .arg = 0,
> };
> - acpi_status status;
> u32 out_data;
> + int ret;
>
> - status =
> - alienware_wmax_command(&in_args, sizeof(in_args),
> - WMAX_METHOD_HDMI_STATUS, &out_data);
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
> + &in_args, sizeof(in_args), &out_data);
>
> - if (ACPI_SUCCESS(status)) {
> + if (!ret) {
> if (out_data == 1)
> return sysfs_emit(buf, "[input] gpu unknown\n");
> else if (out_data == 2)
> return sysfs_emit(buf, "input [gpu] unknown\n");
> }
> - pr_err("alienware-wmi: unknown HDMI source status: %u\n", status);
> +
> + pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
> return sysfs_emit(buf, "input gpu [unknown]\n");
> }
>
> static ssize_t source_store(struct device *dev, struct device_attribute *attr,
> const char *buf, size_t count)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args args;
> - acpi_status status;
> + int ret;
>
> if (strcmp(buf, "gpu\n") == 0)
> args.arg = 1;
> @@ -767,12 +771,12 @@ static ssize_t source_store(struct device *dev, struct device_attribute *attr,
> args.arg = 3;
> pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
>
> - status = alienware_wmax_command(&args, sizeof(args),
> - WMAX_METHOD_HDMI_SOURCE, NULL);
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
> + sizeof(args), NULL);
> +
> + if (ret < 0)
> + pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
>
> - if (ACPI_FAILURE(status))
> - pr_err("alienware-wmi: HDMI toggle failed: results: %u\n",
> - status);
> return count;
> }
>
> @@ -805,22 +809,24 @@ static const struct attribute_group hdmi_attribute_group = {
> static ssize_t status_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args in_args = {
> .arg = 0,
> };
> - acpi_status status;
> u32 out_data;
> + int ret;
>
> - status =
> - alienware_wmax_command(&in_args, sizeof(in_args),
> - WMAX_METHOD_AMPLIFIER_CABLE, &out_data);
> - if (ACPI_SUCCESS(status)) {
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
> + &in_args, sizeof(in_args), &out_data);
> +
> + if (!ret) {
Hi, I noticed one minor style problem while trying to apply these I'd
like to get addressed before I take them.
Could you please remove the empty line in between the call and its error
handling for the calls you touch. There are a few such cases at least in
this patch.
Thanks in advance.
--
i.
> if (out_data == 0)
> return sysfs_emit(buf, "[unconnected] connected unknown\n");
> else if (out_data == 1)
> return sysfs_emit(buf, "unconnected [connected] unknown\n");
> }
> - pr_err("alienware-wmi: unknown amplifier cable status: %d\n", status);
> +
> + pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
> return sysfs_emit(buf, "unconnected connected [unknown]\n");
> }
>
> @@ -850,15 +856,17 @@ static const struct attribute_group amplifier_attribute_group = {
> static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
> char *buf)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args in_args = {
> .arg = 0,
> };
> - acpi_status status;
> u32 out_data;
> + int ret;
>
> - status = alienware_wmax_command(&in_args, sizeof(in_args),
> - WMAX_METHOD_DEEP_SLEEP_STATUS, &out_data);
> - if (ACPI_SUCCESS(status)) {
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
> + &in_args, sizeof(in_args), &out_data);
> +
> + if (!ret) {
> if (out_data == 0)
> return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
> else if (out_data == 1)
> @@ -866,15 +874,17 @@ static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
> else if (out_data == 2)
> return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
> }
> - pr_err("alienware-wmi: unknown deep sleep status: %d\n", status);
> +
> + pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
> return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
> }
>
> static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
> const char *buf, size_t count)
> {
> + struct alienfx_platdata *pdata = dev_get_platdata(dev);
> struct wmax_basic_args args;
> - acpi_status status;
> + int ret;
>
> if (strcmp(buf, "disabled\n") == 0)
> args.arg = 0;
> @@ -884,12 +894,12 @@ static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr
> args.arg = 2;
> pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
>
> - status = alienware_wmax_command(&args, sizeof(args),
> - WMAX_METHOD_DEEP_SLEEP_CONTROL, NULL);
> + ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
> + &args, sizeof(args), NULL);
> +
> + if (!ret)
> + pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
>
> - if (ACPI_FAILURE(status))
> - pr_err("alienware-wmi: deep sleep control failed: results: %u\n",
> - status);
> return count;
> }
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v8 06/14] platform/x86: alienware-wmi: Refactor thermal control methods
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (4 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 05/14] platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 07/14] platform/x86: alienware-wmi: Split DMI table Kurt Borja
` (8 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Refactor thermal control methods to use alienware_wmi_command() instead
of alienware_wmax_command().
Drop alienware_wmax_command() as there is no more users left.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 87 ++++++++---------------
1 file changed, 30 insertions(+), 57 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 412caf0e3b84..d94690e50ecb 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -676,34 +676,6 @@ static enum led_brightness global_led_get(struct led_classdev *led_cdev)
return priv->global_brightness;
}
-static acpi_status alienware_wmax_command(void *in_args, size_t in_size,
- u32 command, u32 *out_data)
-{
- acpi_status status;
- union acpi_object *obj;
- struct acpi_buffer input;
- struct acpi_buffer output;
-
- input.length = in_size;
- input.pointer = in_args;
- if (out_data) {
- output.length = ACPI_ALLOCATE_BUFFER;
- output.pointer = NULL;
- status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
- command, &input, &output);
- if (ACPI_SUCCESS(status)) {
- obj = (union acpi_object *)output.pointer;
- if (obj && obj->type == ACPI_TYPE_INTEGER)
- *out_data = (u32)obj->integer.value;
- }
- kfree(output.pointer);
- } else {
- status = wmi_evaluate_method(WMAX_CONTROL_GUID, 0,
- command, &input, NULL);
- }
- return status;
-}
-
/*
* The HDMI mux sysfs node indicates the status of the HDMI input mux.
* It can toggle between standard system GPU output and HDMI input.
@@ -949,7 +921,8 @@ static bool is_wmax_thermal_code(u32 code)
return false;
}
-static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data)
+static int wmax_thermal_information(struct wmi_device *wdev, u8 operation,
+ u8 arg, u32 *out_data)
{
struct wmax_u32_args in_args = {
.operation = operation,
@@ -957,14 +930,12 @@ static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data)
.arg2 = 0,
.arg3 = 0,
};
- acpi_status status;
-
- status = alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_THERMAL_INFORMATION,
- out_data);
+ int ret;
- if (ACPI_FAILURE(status))
- return -EIO;
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_INFORMATION,
+ &in_args, sizeof(in_args), out_data);
+ if (ret < 0)
+ return ret;
if (*out_data == WMAX_FAILURE_CODE)
return -EBADRQC;
@@ -972,7 +943,7 @@ static int wmax_thermal_information(u8 operation, u8 arg, u32 *out_data)
return 0;
}
-static int wmax_thermal_control(u8 profile)
+static int wmax_thermal_control(struct wmi_device *wdev, u8 profile)
{
struct wmax_u32_args in_args = {
.operation = WMAX_OPERATION_ACTIVATE_PROFILE,
@@ -980,15 +951,13 @@ static int wmax_thermal_control(u8 profile)
.arg2 = 0,
.arg3 = 0,
};
- acpi_status status;
u32 out_data;
+ int ret;
- status = alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_THERMAL_CONTROL,
- &out_data);
-
- if (ACPI_FAILURE(status))
- return -EIO;
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_CONTROL,
+ &in_args, sizeof(in_args), &out_data);
+ if (ret)
+ return ret;
if (out_data == WMAX_FAILURE_CODE)
return -EBADRQC;
@@ -996,7 +965,8 @@ static int wmax_thermal_control(u8 profile)
return 0;
}
-static int wmax_game_shift_status(u8 operation, u32 *out_data)
+static int wmax_game_shift_status(struct wmi_device *wdev, u8 operation,
+ u32 *out_data)
{
struct wmax_u32_args in_args = {
.operation = operation,
@@ -1004,14 +974,13 @@ static int wmax_game_shift_status(u8 operation, u32 *out_data)
.arg2 = 0,
.arg3 = 0,
};
- acpi_status status;
+ int ret;
- status = alienware_wmax_command(&in_args, sizeof(in_args),
- WMAX_METHOD_GAME_SHIFT_STATUS,
- out_data);
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_GAME_SHIFT_STATUS,
+ &in_args, sizeof(in_args), out_data);
- if (ACPI_FAILURE(status))
- return -EIO;
+ if (ret < 0)
+ return ret;
if (*out_data == WMAX_FAILURE_CODE)
return -EOPNOTSUPP;
@@ -1022,10 +991,11 @@ static int wmax_game_shift_status(u8 operation, u32 *out_data)
static int thermal_profile_get(struct device *dev,
enum platform_profile_option *profile)
{
+ struct awcc_priv *priv = dev_get_drvdata(dev);
u32 out_data;
int ret;
- ret = wmax_thermal_information(WMAX_OPERATION_CURRENT_PROFILE,
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_CURRENT_PROFILE,
0, &out_data);
if (ret < 0)
@@ -1054,7 +1024,8 @@ static int thermal_profile_set(struct device *dev,
u32 gmode_status;
int ret;
- ret = wmax_game_shift_status(WMAX_OPERATION_GET_GAME_SHIFT_STATUS,
+ ret = wmax_game_shift_status(priv->wdev,
+ WMAX_OPERATION_GET_GAME_SHIFT_STATUS,
&gmode_status);
if (ret < 0)
@@ -1062,7 +1033,8 @@ static int thermal_profile_set(struct device *dev,
if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) ||
(profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) {
- ret = wmax_game_shift_status(WMAX_OPERATION_TOGGLE_GAME_SHIFT,
+ ret = wmax_game_shift_status(priv->wdev,
+ WMAX_OPERATION_TOGGLE_GAME_SHIFT,
&gmode_status);
if (ret < 0)
@@ -1070,7 +1042,8 @@ static int thermal_profile_set(struct device *dev,
}
}
- return wmax_thermal_control(priv->supported_thermal_profiles[profile]);
+ return wmax_thermal_control(priv->wdev,
+ priv->supported_thermal_profiles[profile]);
}
static int thermal_profile_probe(void *drvdata, unsigned long *choices)
@@ -1083,7 +1056,7 @@ static int thermal_profile_probe(void *drvdata, unsigned long *choices)
u32 out_data;
int ret;
- ret = wmax_thermal_information(WMAX_OPERATION_SYS_DESCRIPTION,
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_SYS_DESCRIPTION,
0, (u32 *) &sys_desc);
if (ret < 0)
return ret;
@@ -1091,7 +1064,7 @@ static int thermal_profile_probe(void *drvdata, unsigned long *choices)
first_mode = sys_desc[0] + sys_desc[1];
for (u32 i = 0; i < sys_desc[3]; i++) {
- ret = wmax_thermal_information(WMAX_OPERATION_LIST_IDS,
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_LIST_IDS,
i + first_mode, &out_data);
if (ret == -EIO)
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 07/14] platform/x86: alienware-wmi: Split DMI table
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (5 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 06/14] platform/x86: alienware-wmi: Refactor thermal control methods Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 08/14] MAINTAINERS: Update ALIENWARE WMI DRIVER entry Kurt Borja
` (7 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Split thermal features into a new DMI table to support upcoming file
split. While at it:
Rename quirk_entry -> alienfx_quirks,
Rename quirks -> alienfx
and change hdmi_mux, amplifier and deepslp types to bool, because they are
already being implicitly used as bools.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi.c | 363 +++++++++++-----------
1 file changed, 175 insertions(+), 188 deletions(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index d94690e50ecb..7e0a74555e91 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -114,102 +114,68 @@ static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_
[THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
};
-struct quirk_entry {
+struct alienfx_quirks {
u8 num_zones;
- u8 hdmi_mux;
- u8 amplifier;
- u8 deepslp;
- bool thermal;
- bool gmode;
+ bool hdmi_mux;
+ bool amplifier;
+ bool deepslp;
};
-static struct quirk_entry *quirks;
+static struct alienfx_quirks *alienfx;
-static struct quirk_entry quirk_inspiron5675 = {
+static struct alienfx_quirks quirk_inspiron5675 = {
.num_zones = 2,
- .hdmi_mux = 0,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = false,
+ .amplifier = false,
+ .deepslp = false,
};
-static struct quirk_entry quirk_unknown = {
+static struct alienfx_quirks quirk_unknown = {
.num_zones = 2,
- .hdmi_mux = 0,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = false,
+ .amplifier = false,
+ .deepslp = false,
};
-static struct quirk_entry quirk_x51_r1_r2 = {
+static struct alienfx_quirks quirk_x51_r1_r2 = {
.num_zones = 3,
- .hdmi_mux = 0,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = false,
+ .amplifier = false,
+ .deepslp = false,
};
-static struct quirk_entry quirk_x51_r3 = {
+static struct alienfx_quirks quirk_x51_r3 = {
.num_zones = 4,
- .hdmi_mux = 0,
- .amplifier = 1,
- .deepslp = 0,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = false,
+ .amplifier = true,
+ .deepslp = false,
};
-static struct quirk_entry quirk_asm100 = {
+static struct alienfx_quirks quirk_asm100 = {
.num_zones = 2,
- .hdmi_mux = 1,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = true,
+ .amplifier = false,
+ .deepslp = false,
};
-static struct quirk_entry quirk_asm200 = {
+static struct alienfx_quirks quirk_asm200 = {
.num_zones = 2,
- .hdmi_mux = 1,
- .amplifier = 0,
- .deepslp = 1,
- .thermal = false,
- .gmode = false,
+ .hdmi_mux = true,
+ .amplifier = false,
+ .deepslp = true,
};
-static struct quirk_entry quirk_asm201 = {
+static struct alienfx_quirks quirk_asm201 = {
.num_zones = 2,
- .hdmi_mux = 1,
- .amplifier = 1,
- .deepslp = 1,
- .thermal = false,
- .gmode = false,
-};
-
-static struct quirk_entry quirk_g_series = {
- .num_zones = 0,
- .hdmi_mux = 0,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = true,
- .gmode = true,
-};
-
-static struct quirk_entry quirk_x_series = {
- .num_zones = 0,
- .hdmi_mux = 0,
- .amplifier = 0,
- .deepslp = 0,
- .thermal = true,
- .gmode = false,
+ .hdmi_mux = true,
+ .amplifier = true,
+ .deepslp = true,
};
static int __init dmi_matched(const struct dmi_system_id *dmi)
{
- quirks = dmi->driver_data;
+ alienfx = dmi->driver_data;
return 1;
}
@@ -241,51 +207,6 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
},
.driver_data = &quirk_asm201,
},
- {
- .callback = dmi_matched,
- .ident = "Alienware m16 R1 AMD",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
- },
- .driver_data = &quirk_x_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Alienware m17 R5",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
- },
- .driver_data = &quirk_x_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Alienware m18 R2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
- },
- .driver_data = &quirk_x_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Alienware x15 R1",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
- },
- .driver_data = &quirk_x_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Alienware x17 R2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
- },
- .driver_data = &quirk_x_series,
- },
{
.callback = dmi_matched,
.ident = "Alienware X51 R1",
@@ -313,60 +234,6 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
},
.driver_data = &quirk_x51_r3,
},
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G15 5510",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
- },
- .driver_data = &quirk_g_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G15 5511",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
- },
- .driver_data = &quirk_g_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G15 5515",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
- },
- .driver_data = &quirk_g_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G3 3500",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
- },
- .driver_data = &quirk_g_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G3 3590",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
- },
- .driver_data = &quirk_g_series,
- },
- {
- .callback = dmi_matched,
- .ident = "Dell Inc. G5 5500",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
- },
- .driver_data = &quirk_g_series,
- },
{
.callback = dmi_matched,
.ident = "Dell Inc. Inspiron 5675",
@@ -441,6 +308,116 @@ struct alienfx_platdata {
static u8 interface;
+struct awcc_quirks {
+ bool pprof;
+ bool gmode;
+};
+
+static struct awcc_quirks g_series_quirks = {
+ .pprof = true,
+ .gmode = true,
+};
+
+static struct awcc_quirks generic_quirks = {
+ .pprof = true,
+ .gmode = false,
+};
+
+static struct awcc_quirks empty_quirks;
+
+static const struct dmi_system_id awcc_dmi_table[] __initconst = {
+ {
+ .ident = "Alienware m16 R1 AMD",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware m17 R5",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware m18 R2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware x15 R1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware x17 R2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5511",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5515",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G3 3500",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G3 3590",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G5 5500",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+};
+
+static struct awcc_quirks *awcc;
+
static int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
void *in_args, size_t in_size, u32 *out_data)
{
@@ -623,7 +600,7 @@ static DEVICE_ATTR_RW(lighting_control_state);
static umode_t zone_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
- if (n < quirks->num_zones + 1)
+ if (n < alienfx->num_zones + 1)
return attr->mode;
return 0;
@@ -631,7 +608,7 @@ static umode_t zone_attr_visible(struct kobject *kobj,
static bool zone_group_visible(struct kobject *kobj)
{
- return quirks->num_zones > 0;
+ return alienfx->num_zones > 0;
}
DEFINE_SYSFS_GROUP_VISIBLE(zone);
@@ -757,7 +734,7 @@ static DEVICE_ATTR_RW(source);
static bool hdmi_group_visible(struct kobject *kobj)
{
- return interface == WMAX && quirks->hdmi_mux;
+ return interface == WMAX && alienfx->hdmi_mux;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
@@ -806,7 +783,7 @@ static DEVICE_ATTR_RO(status);
static bool amplifier_group_visible(struct kobject *kobj)
{
- return interface == WMAX && quirks->amplifier;
+ return interface == WMAX && alienfx->amplifier;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
@@ -879,7 +856,7 @@ static DEVICE_ATTR_RW(deepsleep);
static bool deepsleep_group_visible(struct kobject *kobj)
{
- return interface == WMAX && quirks->deepslp;
+ return interface == WMAX && alienfx->deepslp;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
@@ -1020,7 +997,7 @@ static int thermal_profile_set(struct device *dev,
{
struct awcc_priv *priv = dev_get_drvdata(dev);
- if (quirks->gmode) {
+ if (awcc->gmode) {
u32 gmode_status;
int ret;
@@ -1086,7 +1063,7 @@ static int thermal_profile_probe(void *drvdata, unsigned long *choices)
if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
return -ENODEV;
- if (quirks->gmode) {
+ if (awcc->gmode) {
priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
WMAX_THERMAL_MODE_GMODE;
@@ -1124,7 +1101,7 @@ static int alienware_awcc_setup(struct wmi_device *wdev)
priv->wdev = wdev;
dev_set_drvdata(&wdev->dev, priv);
- if (quirks->thermal) {
+ if (awcc->pprof) {
ret = awcc_platform_profile_init(wdev);
if (ret)
return ret;
@@ -1319,7 +1296,7 @@ static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
};
int ret;
- if (quirks->thermal)
+ if (awcc)
ret = alienware_awcc_setup(wdev);
else
ret = alienware_alienfx_setup(&pdata);
@@ -1345,6 +1322,26 @@ static struct wmi_driver alienware_wmax_wmi_driver = {
static int __init alienware_wmax_wmi_init(void)
{
+ const struct dmi_system_id *id;
+
+ id = dmi_first_match(awcc_dmi_table);
+ if (id)
+ awcc = id->driver_data;
+
+ if (force_platform_profile) {
+ if (!awcc)
+ awcc = &empty_quirks;
+
+ awcc->pprof = true;
+ }
+
+ if (force_gmode) {
+ if (awcc)
+ awcc->gmode = true;
+ else
+ pr_warn("force_gmode requires platform profile support\n");
+ }
+
return wmi_driver_register(&alienware_wmax_wmi_driver);
}
@@ -1358,18 +1355,8 @@ static int __init alienware_wmi_init(void)
int ret;
dmi_check_system(alienware_quirks);
- if (quirks == NULL)
- quirks = &quirk_unknown;
-
- if (force_platform_profile)
- quirks->thermal = true;
-
- if (force_gmode) {
- if (quirks->thermal)
- quirks->gmode = true;
- else
- pr_warn("force_gmode requires platform profile support\n");
- }
+ if (!alienfx)
+ alienfx = &quirk_unknown;
ret = platform_driver_register(&platform_driver);
if (ret < 0)
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 08/14] MAINTAINERS: Update ALIENWARE WMI DRIVER entry
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (6 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 07/14] platform/x86: alienware-wmi: Split DMI table Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 09/14] platform/x86: Rename alienware-wmi.c Kurt Borja
` (6 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Dell has been inactive in its maintainership role of this driver since
around 2021. Due to this, add myself as a maintainer and update path
to support upcoming changes.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
MAINTAINERS | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 896a307fa065..129df78d0298 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -792,10 +792,12 @@ F: Documentation/admin-guide/perf/alibaba_pmu.rst
F: drivers/perf/alibaba_uncore_drw_pmu.c
ALIENWARE WMI DRIVER
+M: Kurt Borja <kuurtb@gmail.com>
+L: platform-driver-x86@vger.kernel.org
L: Dell.Client.Kernel@dell.com
S: Maintained
F: Documentation/wmi/devices/alienware-wmi.rst
-F: drivers/platform/x86/dell/alienware-wmi.c
+F: drivers/platform/x86/dell/alienware-wmi*
ALLEGRO DVT VIDEO IP CORE DRIVER
M: Michael Tretter <m.tretter@pengutronix.de>
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 09/14] platform/x86: Rename alienware-wmi.c
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (7 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 08/14] MAINTAINERS: Update ALIENWARE WMI DRIVER entry Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 10/14] platform/x86: Add alienware-wmi.h Kurt Borja
` (5 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Rename alienware-wmi to support upcoming split.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/Makefile | 1 +
.../platform/x86/dell/{alienware-wmi.c => alienware-wmi-base.c} | 0
2 files changed, 1 insertion(+)
rename drivers/platform/x86/dell/{alienware-wmi.c => alienware-wmi-base.c} (100%)
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index bb3cbd470a46..f8aec8502c2f 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -5,6 +5,7 @@
#
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
+alienware-wmi-objs := alienware-wmi-base.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi-base.c
similarity index 100%
rename from drivers/platform/x86/dell/alienware-wmi.c
rename to drivers/platform/x86/dell/alienware-wmi-base.c
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 10/14] platform/x86: Add alienware-wmi.h
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (8 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 09/14] platform/x86: Rename alienware-wmi.c Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 11/14] platform/x86: Split the alienware-wmi driver Kurt Borja
` (4 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Add a header file for alienware-wmi with shared resources to support the
upcoming file split.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
.../platform/x86/dell/alienware-wmi-base.c | 100 ++++--------------
drivers/platform/x86/dell/alienware-wmi.h | 92 ++++++++++++++++
2 files changed, 114 insertions(+), 78 deletions(-)
create mode 100644 drivers/platform/x86/dell/alienware-wmi.h
diff --git a/drivers/platform/x86/dell/alienware-wmi-base.c b/drivers/platform/x86/dell/alienware-wmi-base.c
index 7e0a74555e91..3df1f1d763e2 100644
--- a/drivers/platform/x86/dell/alienware-wmi-base.c
+++ b/drivers/platform/x86/dell/alienware-wmi-base.c
@@ -17,10 +17,7 @@
#include <linux/dmi.h>
#include <linux/leds.h>
#include <linux/wmi.h>
-
-#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
-#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
-#define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492"
+#include "alienware-wmi.h"
#define WMAX_METHOD_HDMI_SOURCE 0x1
#define WMAX_METHOD_HDMI_STATUS 0x2
@@ -50,23 +47,6 @@ static bool force_gmode;
module_param_unsafe(force_gmode, bool, 0);
MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
-enum INTERFACE_FLAGS {
- LEGACY,
- WMAX,
-};
-
-enum LEGACY_CONTROL_STATES {
- LEGACY_RUNNING = 1,
- LEGACY_BOOTING = 0,
- LEGACY_SUSPEND = 3,
-};
-
-enum WMAX_CONTROL_STATES {
- WMAX_RUNNING = 0xFF,
- WMAX_BOOTING = 0,
- WMAX_SUSPEND = 3,
-};
-
enum WMAX_THERMAL_INFORMATION_OPERATIONS {
WMAX_OPERATION_SYS_DESCRIPTION = 0x02,
WMAX_OPERATION_LIST_IDS = 0x03,
@@ -114,15 +94,7 @@ static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_
[THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
};
-struct alienfx_quirks {
- u8 num_zones;
- bool hdmi_mux;
- bool amplifier;
- bool deepslp;
-};
-
-static struct alienfx_quirks *alienfx;
-
+struct alienfx_quirks *alienfx;
static struct alienfx_quirks quirk_inspiron5675 = {
.num_zones = 2,
@@ -246,12 +218,6 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
{}
};
-struct color_platform {
- u8 blue;
- u8 green;
- u8 red;
-} __packed;
-
struct wmax_brightness_args {
u32 led_mask;
u32 percentage;
@@ -286,27 +252,7 @@ struct awcc_priv {
enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
};
-struct alienfx_priv {
- struct platform_device *pdev;
- struct led_classdev global_led;
- struct color_platform colors[4];
- u8 global_brightness;
- u8 lighting_control_state;
-};
-
-struct alienfx_ops {
- int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev,
- u8 location);
- int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev,
- u8 brightness);
-};
-
-struct alienfx_platdata {
- struct wmi_device *wdev;
- struct alienfx_ops ops;
-};
-
-static u8 interface;
+u8 alienware_interface;
struct awcc_quirks {
bool pprof;
@@ -418,8 +364,8 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = {
static struct awcc_quirks *awcc;
-static int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
- void *in_args, size_t in_size, u32 *out_data)
+int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
+ void *in_args, size_t in_size, u32 *out_data)
{
struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
struct acpi_buffer in = {in_size, in_args};
@@ -583,7 +529,7 @@ static ssize_t lighting_control_state_store(struct device *dev,
val = LEGACY_BOOTING;
else if (strcmp(buf, "suspend\n") == 0)
val = LEGACY_SUSPEND;
- else if (interface == LEGACY)
+ else if (alienware_interface == LEGACY)
val = LEGACY_RUNNING;
else
val = WMAX_RUNNING;
@@ -734,7 +680,7 @@ static DEVICE_ATTR_RW(source);
static bool hdmi_group_visible(struct kobject *kobj)
{
- return interface == WMAX && alienfx->hdmi_mux;
+ return alienware_interface == WMAX && alienfx->hdmi_mux;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
@@ -744,7 +690,7 @@ static struct attribute *hdmi_attrs[] = {
NULL,
};
-static const struct attribute_group hdmi_attribute_group = {
+const struct attribute_group wmax_hdmi_attribute_group = {
.name = "hdmi",
.is_visible = SYSFS_GROUP_VISIBLE(hdmi),
.attrs = hdmi_attrs,
@@ -783,7 +729,7 @@ static DEVICE_ATTR_RO(status);
static bool amplifier_group_visible(struct kobject *kobj)
{
- return interface == WMAX && alienfx->amplifier;
+ return alienware_interface == WMAX && alienfx->amplifier;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
@@ -792,7 +738,7 @@ static struct attribute *amplifier_attrs[] = {
NULL,
};
-static const struct attribute_group amplifier_attribute_group = {
+const struct attribute_group wmax_amplifier_attribute_group = {
.name = "amplifier",
.is_visible = SYSFS_GROUP_VISIBLE(amplifier),
.attrs = amplifier_attrs,
@@ -856,7 +802,7 @@ static DEVICE_ATTR_RW(deepsleep);
static bool deepsleep_group_visible(struct kobject *kobj)
{
- return interface == WMAX && alienfx->deepslp;
+ return alienware_interface == WMAX && alienfx->deepslp;
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
@@ -865,7 +811,7 @@ static struct attribute *deepsleep_attrs[] = {
NULL,
};
-static const struct attribute_group deepsleep_attribute_group = {
+const struct attribute_group wmax_deepsleep_attribute_group = {
.name = "deepsleep",
.is_visible = SYSFS_GROUP_VISIBLE(deepsleep),
.attrs = deepsleep_attrs,
@@ -1121,7 +1067,7 @@ static int alienfx_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- if (interface == WMAX)
+ if (alienware_interface == WMAX)
priv->lighting_control_state = WMAX_RUNNING;
else
priv->lighting_control_state = LEGACY_RUNNING;
@@ -1139,9 +1085,7 @@ static int alienfx_probe(struct platform_device *pdev)
static const struct attribute_group *alienfx_groups[] = {
&zone_attribute_group,
- &hdmi_attribute_group,
- &lifier_attribute_group,
- &deepsleep_attribute_group,
+ WMAX_DEV_GROUPS
NULL
};
@@ -1160,7 +1104,7 @@ static void alienware_alienfx_remove(void *data)
platform_device_unregister(pdev);
}
-static int alienware_alienfx_setup(struct alienfx_platdata *pdata)
+int alienware_alienfx_setup(struct alienfx_platdata *pdata)
{
struct device *dev = &pdata->wdev->dev;
struct platform_device *pdev;
@@ -1247,12 +1191,12 @@ static struct wmi_driver alienware_legacy_wmi_driver = {
.no_singleton = true,
};
-static int __init alienware_legacy_wmi_init(void)
+int __init alienware_legacy_wmi_init(void)
{
return wmi_driver_register(&alienware_legacy_wmi_driver);
}
-static void __exit alienware_legacy_wmi_exit(void)
+void __exit alienware_legacy_wmi_exit(void)
{
wmi_driver_unregister(&alienware_legacy_wmi_driver);
}
@@ -1320,7 +1264,7 @@ static struct wmi_driver alienware_wmax_wmi_driver = {
.no_singleton = true,
};
-static int __init alienware_wmax_wmi_init(void)
+int __init alienware_wmax_wmi_init(void)
{
const struct dmi_system_id *id;
@@ -1345,7 +1289,7 @@ static int __init alienware_wmax_wmi_init(void)
return wmi_driver_register(&alienware_wmax_wmi_driver);
}
-static void __exit alienware_wmax_wmi_exit(void)
+void __exit alienware_wmax_wmi_exit(void)
{
wmi_driver_unregister(&alienware_wmax_wmi_driver);
}
@@ -1363,10 +1307,10 @@ static int __init alienware_wmi_init(void)
return ret;
if (wmi_has_guid(WMAX_CONTROL_GUID)) {
- interface = WMAX;
+ alienware_interface = WMAX;
ret = alienware_wmax_wmi_init();
} else {
- interface = LEGACY;
+ alienware_interface = LEGACY;
ret = alienware_legacy_wmi_init();
}
@@ -1380,7 +1324,7 @@ module_init(alienware_wmi_init);
static void __exit alienware_wmi_exit(void)
{
- if (interface == WMAX)
+ if (alienware_interface == WMAX)
alienware_wmax_wmi_exit();
else
alienware_legacy_wmi_exit();
diff --git a/drivers/platform/x86/dell/alienware-wmi.h b/drivers/platform/x86/dell/alienware-wmi.h
new file mode 100644
index 000000000000..b950c91e1979
--- /dev/null
+++ b/drivers/platform/x86/dell/alienware-wmi.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Alienware WMI special features driver
+ *
+ * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
+ * Copyright (C) 2024 Kurt Borja <kuurtb@gmail.com>
+ */
+
+#ifndef _ALIENWARE_WMI_H_
+#define _ALIENWARE_WMI_H_
+
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/wmi.h>
+
+#define LEGACY_CONTROL_GUID "A90597CE-A997-11DA-B012-B622A1EF5492"
+#define LEGACY_POWER_CONTROL_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
+#define WMAX_CONTROL_GUID "A70591CE-A997-11DA-B012-B622A1EF5492"
+
+enum INTERFACE_FLAGS {
+ LEGACY,
+ WMAX,
+};
+
+enum LEGACY_CONTROL_STATES {
+ LEGACY_RUNNING = 1,
+ LEGACY_BOOTING = 0,
+ LEGACY_SUSPEND = 3,
+};
+
+enum WMAX_CONTROL_STATES {
+ WMAX_RUNNING = 0xFF,
+ WMAX_BOOTING = 0,
+ WMAX_SUSPEND = 3,
+};
+
+struct alienfx_quirks {
+ u8 num_zones;
+ bool hdmi_mux;
+ bool amplifier;
+ bool deepslp;
+};
+
+struct color_platform {
+ u8 blue;
+ u8 green;
+ u8 red;
+} __packed;
+
+struct alienfx_priv {
+ struct platform_device *pdev;
+ struct led_classdev global_led;
+ struct color_platform colors[4];
+ u8 global_brightness;
+ u8 lighting_control_state;
+};
+
+struct alienfx_ops {
+ int (*upd_led)(struct alienfx_priv *priv, struct wmi_device *wdev,
+ u8 location);
+ int (*upd_brightness)(struct alienfx_priv *priv, struct wmi_device *wdev,
+ u8 brightness);
+};
+
+struct alienfx_platdata {
+ struct wmi_device *wdev;
+ struct alienfx_ops ops;
+};
+
+extern u8 alienware_interface;
+extern struct alienfx_quirks *alienfx;
+
+int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
+ void *in_args, size_t in_size, u32 *out_data);
+
+int alienware_alienfx_setup(struct alienfx_platdata *pdata);
+
+int __init alienware_legacy_wmi_init(void);
+void __exit alienware_legacy_wmi_exit(void);
+
+extern const struct attribute_group wmax_hdmi_attribute_group;
+extern const struct attribute_group wmax_amplifier_attribute_group;
+extern const struct attribute_group wmax_deepsleep_attribute_group;
+
+#define WMAX_DEV_GROUPS &wmax_hdmi_attribute_group, \
+ &wmax_amplifier_attribute_group, \
+ &wmax_deepsleep_attribute_group,
+
+int __init alienware_wmax_wmi_init(void);
+void __exit alienware_wmax_wmi_exit(void);
+
+#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 11/14] platform/x86: Split the alienware-wmi driver
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (9 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 10/14] platform/x86: Add alienware-wmi.h Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 12/14] platform/x86: dell: Modify Makefile alignment Kurt Borja
` (3 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Split alienware-wmi WMI drivers into different files. This is done
seamlessly by copying and pasting, however some blocks are reordered.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/Makefile | 2 +
.../platform/x86/dell/alienware-wmi-base.c | 846 ------------------
.../platform/x86/dell/alienware-wmi-legacy.c | 95 ++
.../platform/x86/dell/alienware-wmi-wmax.c | 775 ++++++++++++++++
4 files changed, 872 insertions(+), 846 deletions(-)
create mode 100644 drivers/platform/x86/dell/alienware-wmi-legacy.c
create mode 100644 drivers/platform/x86/dell/alienware-wmi-wmax.c
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index f8aec8502c2f..03ba459f3d31 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -6,6 +6,8 @@
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
alienware-wmi-objs := alienware-wmi-base.o
+alienware-wmi-y += alienware-wmi-legacy.o
+alienware-wmi-y += alienware-wmi-wmax.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
diff --git a/drivers/platform/x86/dell/alienware-wmi-base.c b/drivers/platform/x86/dell/alienware-wmi-base.c
index 3df1f1d763e2..7bad9717183d 100644
--- a/drivers/platform/x86/dell/alienware-wmi-base.c
+++ b/drivers/platform/x86/dell/alienware-wmi-base.c
@@ -8,92 +8,17 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
-#include <linux/bitfield.h>
-#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/platform_profile.h>
#include <linux/dmi.h>
#include <linux/leds.h>
-#include <linux/wmi.h>
#include "alienware-wmi.h"
-#define WMAX_METHOD_HDMI_SOURCE 0x1
-#define WMAX_METHOD_HDMI_STATUS 0x2
-#define WMAX_METHOD_BRIGHTNESS 0x3
-#define WMAX_METHOD_ZONE_CONTROL 0x4
-#define WMAX_METHOD_HDMI_CABLE 0x5
-#define WMAX_METHOD_AMPLIFIER_CABLE 0x6
-#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
-#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
-#define WMAX_METHOD_THERMAL_INFORMATION 0x14
-#define WMAX_METHOD_THERMAL_CONTROL 0x15
-#define WMAX_METHOD_GAME_SHIFT_STATUS 0x25
-
-#define WMAX_THERMAL_MODE_GMODE 0xAB
-
-#define WMAX_FAILURE_CODE 0xFFFFFFFF
-
MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>");
MODULE_DESCRIPTION("Alienware special feature control");
MODULE_LICENSE("GPL");
-static bool force_platform_profile;
-module_param_unsafe(force_platform_profile, bool, 0);
-MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available");
-
-static bool force_gmode;
-module_param_unsafe(force_gmode, bool, 0);
-MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
-
-enum WMAX_THERMAL_INFORMATION_OPERATIONS {
- WMAX_OPERATION_SYS_DESCRIPTION = 0x02,
- WMAX_OPERATION_LIST_IDS = 0x03,
- WMAX_OPERATION_CURRENT_PROFILE = 0x0B,
-};
-
-enum WMAX_THERMAL_CONTROL_OPERATIONS {
- WMAX_OPERATION_ACTIVATE_PROFILE = 0x01,
-};
-
-enum WMAX_GAME_SHIFT_STATUS_OPERATIONS {
- WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01,
- WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02,
-};
-
-enum WMAX_THERMAL_TABLES {
- WMAX_THERMAL_TABLE_BASIC = 0x90,
- WMAX_THERMAL_TABLE_USTT = 0xA0,
-};
-
-enum wmax_thermal_mode {
- THERMAL_MODE_USTT_BALANCED,
- THERMAL_MODE_USTT_BALANCED_PERFORMANCE,
- THERMAL_MODE_USTT_COOL,
- THERMAL_MODE_USTT_QUIET,
- THERMAL_MODE_USTT_PERFORMANCE,
- THERMAL_MODE_USTT_LOW_POWER,
- THERMAL_MODE_BASIC_QUIET,
- THERMAL_MODE_BASIC_BALANCED,
- THERMAL_MODE_BASIC_BALANCED_PERFORMANCE,
- THERMAL_MODE_BASIC_PERFORMANCE,
- THERMAL_MODE_LAST,
-};
-
-static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = {
- [THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED,
- [THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
- [THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL,
- [THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET,
- [THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
- [THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER,
- [THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET,
- [THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED,
- [THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
- [THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
-};
-
struct alienfx_quirks *alienfx;
static struct alienfx_quirks quirk_inspiron5675 = {
@@ -218,152 +143,8 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
{}
};
-struct wmax_brightness_args {
- u32 led_mask;
- u32 percentage;
-};
-
-struct wmax_basic_args {
- u8 arg;
-};
-
-struct legacy_led_args {
- struct color_platform colors;
- u8 brightness;
- u8 state;
-} __packed;
-
-struct wmax_led_args {
- u32 led_mask;
- struct color_platform colors;
- u8 state;
-} __packed;
-
-struct wmax_u32_args {
- u8 operation;
- u8 arg1;
- u8 arg2;
- u8 arg3;
-};
-
-struct awcc_priv {
- struct wmi_device *wdev;
- struct device *ppdev;
- enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
-};
-
u8 alienware_interface;
-struct awcc_quirks {
- bool pprof;
- bool gmode;
-};
-
-static struct awcc_quirks g_series_quirks = {
- .pprof = true,
- .gmode = true,
-};
-
-static struct awcc_quirks generic_quirks = {
- .pprof = true,
- .gmode = false,
-};
-
-static struct awcc_quirks empty_quirks;
-
-static const struct dmi_system_id awcc_dmi_table[] __initconst = {
- {
- .ident = "Alienware m16 R1 AMD",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
- },
- .driver_data = &generic_quirks,
- },
- {
- .ident = "Alienware m17 R5",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
- },
- .driver_data = &generic_quirks,
- },
- {
- .ident = "Alienware m18 R2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
- },
- .driver_data = &generic_quirks,
- },
- {
- .ident = "Alienware x15 R1",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
- },
- .driver_data = &generic_quirks,
- },
- {
- .ident = "Alienware x17 R2",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
- },
- .driver_data = &generic_quirks,
- },
- {
- .ident = "Dell Inc. G15 5510",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
- },
- .driver_data = &g_series_quirks,
- },
- {
- .ident = "Dell Inc. G15 5511",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
- },
- .driver_data = &g_series_quirks,
- },
- {
- .ident = "Dell Inc. G15 5515",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
- },
- .driver_data = &g_series_quirks,
- },
- {
- .ident = "Dell Inc. G3 3500",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
- },
- .driver_data = &g_series_quirks,
- },
- {
- .ident = "Dell Inc. G3 3590",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
- },
- .driver_data = &g_series_quirks,
- },
- {
- .ident = "Dell Inc. G5 5500",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
- },
- .driver_data = &g_series_quirks,
- },
-};
-
-static struct awcc_quirks *awcc;
-
int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
void *in_args, size_t in_size, u32 *out_data)
{
@@ -599,463 +380,6 @@ static enum led_brightness global_led_get(struct led_classdev *led_cdev)
return priv->global_brightness;
}
-/*
- * The HDMI mux sysfs node indicates the status of the HDMI input mux.
- * It can toggle between standard system GPU output and HDMI input.
- */
-static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args in_args = {
- .arg = 0,
- };
- u32 out_data;
- int ret;
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
- &in_args, sizeof(in_args), &out_data);
-
- if (!ret) {
- if (out_data == 0)
- return sysfs_emit(buf, "[unconnected] connected unknown\n");
- else if (out_data == 1)
- return sysfs_emit(buf, "unconnected [connected] unknown\n");
- }
-
- pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
- return sysfs_emit(buf, "unconnected connected [unknown]\n");
-}
-
-static ssize_t source_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args in_args = {
- .arg = 0,
- };
- u32 out_data;
- int ret;
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
- &in_args, sizeof(in_args), &out_data);
-
- if (!ret) {
- if (out_data == 1)
- return sysfs_emit(buf, "[input] gpu unknown\n");
- else if (out_data == 2)
- return sysfs_emit(buf, "input [gpu] unknown\n");
- }
-
- pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
- return sysfs_emit(buf, "input gpu [unknown]\n");
-}
-
-static ssize_t source_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args args;
- int ret;
-
- if (strcmp(buf, "gpu\n") == 0)
- args.arg = 1;
- else if (strcmp(buf, "input\n") == 0)
- args.arg = 2;
- else
- args.arg = 3;
- pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
- sizeof(args), NULL);
-
- if (ret < 0)
- pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
-
- return count;
-}
-
-static DEVICE_ATTR_RO(cable);
-static DEVICE_ATTR_RW(source);
-
-static bool hdmi_group_visible(struct kobject *kobj)
-{
- return alienware_interface == WMAX && alienfx->hdmi_mux;
-}
-DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
-
-static struct attribute *hdmi_attrs[] = {
- &dev_attr_cable.attr,
- &dev_attr_source.attr,
- NULL,
-};
-
-const struct attribute_group wmax_hdmi_attribute_group = {
- .name = "hdmi",
- .is_visible = SYSFS_GROUP_VISIBLE(hdmi),
- .attrs = hdmi_attrs,
-};
-
-/*
- * Alienware GFX amplifier support
- * - Currently supports reading cable status
- * - Leaving expansion room to possibly support dock/undock events later
- */
-static ssize_t status_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args in_args = {
- .arg = 0,
- };
- u32 out_data;
- int ret;
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
- &in_args, sizeof(in_args), &out_data);
-
- if (!ret) {
- if (out_data == 0)
- return sysfs_emit(buf, "[unconnected] connected unknown\n");
- else if (out_data == 1)
- return sysfs_emit(buf, "unconnected [connected] unknown\n");
- }
-
- pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
- return sysfs_emit(buf, "unconnected connected [unknown]\n");
-}
-
-static DEVICE_ATTR_RO(status);
-
-static bool amplifier_group_visible(struct kobject *kobj)
-{
- return alienware_interface == WMAX && alienfx->amplifier;
-}
-DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
-
-static struct attribute *amplifier_attrs[] = {
- &dev_attr_status.attr,
- NULL,
-};
-
-const struct attribute_group wmax_amplifier_attribute_group = {
- .name = "amplifier",
- .is_visible = SYSFS_GROUP_VISIBLE(amplifier),
- .attrs = amplifier_attrs,
-};
-
-/*
- * Deep Sleep Control support
- * - Modifies BIOS setting for deep sleep control allowing extra wakeup events
- */
-static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args in_args = {
- .arg = 0,
- };
- u32 out_data;
- int ret;
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
- &in_args, sizeof(in_args), &out_data);
-
- if (!ret) {
- if (out_data == 0)
- return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
- else if (out_data == 1)
- return sysfs_emit(buf, "disabled [s5] s5_s4\n");
- else if (out_data == 2)
- return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
- }
-
- pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
- return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
-}
-
-static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct alienfx_platdata *pdata = dev_get_platdata(dev);
- struct wmax_basic_args args;
- int ret;
-
- if (strcmp(buf, "disabled\n") == 0)
- args.arg = 0;
- else if (strcmp(buf, "s5\n") == 0)
- args.arg = 1;
- else
- args.arg = 2;
- pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
-
- ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
- &args, sizeof(args), NULL);
-
- if (!ret)
- pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
-
- return count;
-}
-
-static DEVICE_ATTR_RW(deepsleep);
-
-static bool deepsleep_group_visible(struct kobject *kobj)
-{
- return alienware_interface == WMAX && alienfx->deepslp;
-}
-DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
-
-static struct attribute *deepsleep_attrs[] = {
- &dev_attr_deepsleep.attr,
- NULL,
-};
-
-const struct attribute_group wmax_deepsleep_attribute_group = {
- .name = "deepsleep",
- .is_visible = SYSFS_GROUP_VISIBLE(deepsleep),
- .attrs = deepsleep_attrs,
-};
-
-/*
- * Thermal Profile control
- * - Provides thermal profile control through the Platform Profile API
- */
-#define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4)
-#define WMAX_THERMAL_MODE_MASK GENMASK(3, 0)
-#define WMAX_SENSOR_ID_MASK BIT(8)
-
-static bool is_wmax_thermal_code(u32 code)
-{
- if (code & WMAX_SENSOR_ID_MASK)
- return false;
-
- if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST)
- return false;
-
- if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC &&
- (code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET)
- return true;
-
- if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT &&
- (code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER)
- return true;
-
- return false;
-}
-
-static int wmax_thermal_information(struct wmi_device *wdev, u8 operation,
- u8 arg, u32 *out_data)
-{
- struct wmax_u32_args in_args = {
- .operation = operation,
- .arg1 = arg,
- .arg2 = 0,
- .arg3 = 0,
- };
- int ret;
-
- ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_INFORMATION,
- &in_args, sizeof(in_args), out_data);
- if (ret < 0)
- return ret;
-
- if (*out_data == WMAX_FAILURE_CODE)
- return -EBADRQC;
-
- return 0;
-}
-
-static int wmax_thermal_control(struct wmi_device *wdev, u8 profile)
-{
- struct wmax_u32_args in_args = {
- .operation = WMAX_OPERATION_ACTIVATE_PROFILE,
- .arg1 = profile,
- .arg2 = 0,
- .arg3 = 0,
- };
- u32 out_data;
- int ret;
-
- ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_CONTROL,
- &in_args, sizeof(in_args), &out_data);
- if (ret)
- return ret;
-
- if (out_data == WMAX_FAILURE_CODE)
- return -EBADRQC;
-
- return 0;
-}
-
-static int wmax_game_shift_status(struct wmi_device *wdev, u8 operation,
- u32 *out_data)
-{
- struct wmax_u32_args in_args = {
- .operation = operation,
- .arg1 = 0,
- .arg2 = 0,
- .arg3 = 0,
- };
- int ret;
-
- ret = alienware_wmi_command(wdev, WMAX_METHOD_GAME_SHIFT_STATUS,
- &in_args, sizeof(in_args), out_data);
-
- if (ret < 0)
- return ret;
-
- if (*out_data == WMAX_FAILURE_CODE)
- return -EOPNOTSUPP;
-
- return 0;
-}
-
-static int thermal_profile_get(struct device *dev,
- enum platform_profile_option *profile)
-{
- struct awcc_priv *priv = dev_get_drvdata(dev);
- u32 out_data;
- int ret;
-
- ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_CURRENT_PROFILE,
- 0, &out_data);
-
- if (ret < 0)
- return ret;
-
- if (out_data == WMAX_THERMAL_MODE_GMODE) {
- *profile = PLATFORM_PROFILE_PERFORMANCE;
- return 0;
- }
-
- if (!is_wmax_thermal_code(out_data))
- return -ENODATA;
-
- out_data &= WMAX_THERMAL_MODE_MASK;
- *profile = wmax_mode_to_platform_profile[out_data];
-
- return 0;
-}
-
-static int thermal_profile_set(struct device *dev,
- enum platform_profile_option profile)
-{
- struct awcc_priv *priv = dev_get_drvdata(dev);
-
- if (awcc->gmode) {
- u32 gmode_status;
- int ret;
-
- ret = wmax_game_shift_status(priv->wdev,
- WMAX_OPERATION_GET_GAME_SHIFT_STATUS,
- &gmode_status);
-
- if (ret < 0)
- return ret;
-
- if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) ||
- (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) {
- ret = wmax_game_shift_status(priv->wdev,
- WMAX_OPERATION_TOGGLE_GAME_SHIFT,
- &gmode_status);
-
- if (ret < 0)
- return ret;
- }
- }
-
- return wmax_thermal_control(priv->wdev,
- priv->supported_thermal_profiles[profile]);
-}
-
-static int thermal_profile_probe(void *drvdata, unsigned long *choices)
-{
- enum platform_profile_option profile;
- struct awcc_priv *priv = drvdata;
- enum wmax_thermal_mode mode;
- u8 sys_desc[4];
- u32 first_mode;
- u32 out_data;
- int ret;
-
- ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_SYS_DESCRIPTION,
- 0, (u32 *) &sys_desc);
- if (ret < 0)
- return ret;
-
- first_mode = sys_desc[0] + sys_desc[1];
-
- for (u32 i = 0; i < sys_desc[3]; i++) {
- ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_LIST_IDS,
- i + first_mode, &out_data);
-
- if (ret == -EIO)
- return ret;
-
- if (ret == -EBADRQC)
- break;
-
- if (!is_wmax_thermal_code(out_data))
- continue;
-
- mode = out_data & WMAX_THERMAL_MODE_MASK;
- profile = wmax_mode_to_platform_profile[mode];
- priv->supported_thermal_profiles[profile] = out_data;
-
- set_bit(profile, choices);
- }
-
- if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
- return -ENODEV;
-
- if (awcc->gmode) {
- priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
- WMAX_THERMAL_MODE_GMODE;
-
- set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
- }
-
- return 0;
-}
-
-static const struct platform_profile_ops awcc_platform_profile_ops = {
- .probe = thermal_profile_probe,
- .profile_get = thermal_profile_get,
- .profile_set = thermal_profile_set,
-};
-
-static int awcc_platform_profile_init(struct wmi_device *wdev)
-{
- struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
-
- priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
- priv, &awcc_platform_profile_ops);
-
- return PTR_ERR_OR_ZERO(priv->ppdev);
-}
-
-static int alienware_awcc_setup(struct wmi_device *wdev)
-{
- struct awcc_priv *priv;
- int ret;
-
- priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->wdev = wdev;
- dev_set_drvdata(&wdev->dev, priv);
-
- if (awcc->pprof) {
- ret = awcc_platform_profile_init(wdev);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
/*
* Platform Driver
*/
@@ -1124,176 +448,6 @@ int alienware_alienfx_setup(struct alienfx_platdata *pdata)
return 0;
}
-/*
- * Legacy WMI driver
- */
-static int legacy_wmi_update_led(struct alienfx_priv *priv,
- struct wmi_device *wdev, u8 location)
-{
- struct legacy_led_args legacy_args = {
- .colors = priv->colors[location],
- .brightness = priv->global_brightness,
- .state = 0,
- };
- struct acpi_buffer input;
- acpi_status status;
-
- if (legacy_args.state != LEGACY_RUNNING) {
- legacy_args.state = priv->lighting_control_state;
-
- input.length = sizeof(legacy_args);
- input.pointer = &legacy_args;
-
- status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0,
- location + 1, &input, NULL);
- if (ACPI_FAILURE(status))
- return -EIO;
-
- return 0;
- }
-
- return alienware_wmi_command(wdev, location + 1, &legacy_args,
- sizeof(legacy_args), NULL);
-}
-
-static int legacy_wmi_update_brightness(struct alienfx_priv *priv,
- struct wmi_device *wdev, u8 brightness)
-{
- return legacy_wmi_update_led(priv, wdev, 0);
-}
-
-static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
-{
- struct alienfx_platdata pdata = {
- .wdev = wdev,
- .ops = {
- .upd_led = legacy_wmi_update_led,
- .upd_brightness = legacy_wmi_update_brightness,
- },
- };
-
- return alienware_alienfx_setup(&pdata);
-}
-
-static const struct wmi_device_id alienware_legacy_device_id_table[] = {
- { LEGACY_CONTROL_GUID, NULL },
- { },
-};
-MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table);
-
-static struct wmi_driver alienware_legacy_wmi_driver = {
- .driver = {
- .name = "alienware-wmi-alienfx",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- .id_table = alienware_legacy_device_id_table,
- .probe = legacy_wmi_probe,
- .no_singleton = true,
-};
-
-int __init alienware_legacy_wmi_init(void)
-{
- return wmi_driver_register(&alienware_legacy_wmi_driver);
-}
-
-void __exit alienware_legacy_wmi_exit(void)
-{
- wmi_driver_unregister(&alienware_legacy_wmi_driver);
-}
-
-/*
- * WMAX WMI driver
- */
-static int wmax_wmi_update_led(struct alienfx_priv *priv,
- struct wmi_device *wdev, u8 location)
-{
- struct wmax_led_args in_args = {
- .led_mask = 1 << location,
- .colors = priv->colors[location],
- .state = priv->lighting_control_state,
- };
-
- return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args,
- sizeof(in_args), NULL);
-}
-
-static int wmax_wmi_update_brightness(struct alienfx_priv *priv,
- struct wmi_device *wdev, u8 brightness)
-{
- struct wmax_brightness_args in_args = {
- .led_mask = 0xFF,
- .percentage = brightness,
- };
-
- return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args,
- sizeof(in_args), NULL);
-}
-
-static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
-{
- struct alienfx_platdata pdata = {
- .wdev = wdev,
- .ops = {
- .upd_led = wmax_wmi_update_led,
- .upd_brightness = wmax_wmi_update_brightness,
- },
- };
- int ret;
-
- if (awcc)
- ret = alienware_awcc_setup(wdev);
- else
- ret = alienware_alienfx_setup(&pdata);
-
- return ret;
-}
-
-static const struct wmi_device_id alienware_wmax_device_id_table[] = {
- { WMAX_CONTROL_GUID, NULL },
- { },
-};
-MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table);
-
-static struct wmi_driver alienware_wmax_wmi_driver = {
- .driver = {
- .name = "alienware-wmi-wmax",
- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
- },
- .id_table = alienware_wmax_device_id_table,
- .probe = wmax_wmi_probe,
- .no_singleton = true,
-};
-
-int __init alienware_wmax_wmi_init(void)
-{
- const struct dmi_system_id *id;
-
- id = dmi_first_match(awcc_dmi_table);
- if (id)
- awcc = id->driver_data;
-
- if (force_platform_profile) {
- if (!awcc)
- awcc = &empty_quirks;
-
- awcc->pprof = true;
- }
-
- if (force_gmode) {
- if (awcc)
- awcc->gmode = true;
- else
- pr_warn("force_gmode requires platform profile support\n");
- }
-
- return wmi_driver_register(&alienware_wmax_wmi_driver);
-}
-
-void __exit alienware_wmax_wmi_exit(void)
-{
- wmi_driver_unregister(&alienware_wmax_wmi_driver);
-}
-
static int __init alienware_wmi_init(void)
{
int ret;
diff --git a/drivers/platform/x86/dell/alienware-wmi-legacy.c b/drivers/platform/x86/dell/alienware-wmi-legacy.c
new file mode 100644
index 000000000000..4a84a2fe918b
--- /dev/null
+++ b/drivers/platform/x86/dell/alienware-wmi-legacy.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Alienware LEGACY WMI device driver
+ *
+ * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/wmi.h>
+#include "alienware-wmi.h"
+
+struct legacy_led_args {
+ struct color_platform colors;
+ u8 brightness;
+ u8 state;
+} __packed;
+
+
+/*
+ * Legacy WMI driver
+ */
+static int legacy_wmi_update_led(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 location)
+{
+ struct legacy_led_args legacy_args = {
+ .colors = priv->colors[location],
+ .brightness = priv->global_brightness,
+ .state = 0,
+ };
+ struct acpi_buffer input;
+ acpi_status status;
+
+ if (legacy_args.state != LEGACY_RUNNING) {
+ legacy_args.state = priv->lighting_control_state;
+
+ input.length = sizeof(legacy_args);
+ input.pointer = &legacy_args;
+
+ status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0,
+ location + 1, &input, NULL);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ return 0;
+ }
+
+ return alienware_wmi_command(wdev, location + 1, &legacy_args,
+ sizeof(legacy_args), NULL);
+}
+
+static int legacy_wmi_update_brightness(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 brightness)
+{
+ return legacy_wmi_update_led(priv, wdev, 0);
+}
+
+static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct alienfx_platdata pdata = {
+ .wdev = wdev,
+ .ops = {
+ .upd_led = legacy_wmi_update_led,
+ .upd_brightness = legacy_wmi_update_brightness,
+ },
+ };
+
+ return alienware_alienfx_setup(&pdata);
+}
+
+static const struct wmi_device_id alienware_legacy_device_id_table[] = {
+ { LEGACY_CONTROL_GUID, NULL },
+ { },
+};
+MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table);
+
+static struct wmi_driver alienware_legacy_wmi_driver = {
+ .driver = {
+ .name = "alienware-wmi-alienfx",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = alienware_legacy_device_id_table,
+ .probe = legacy_wmi_probe,
+ .no_singleton = true,
+};
+
+int __init alienware_legacy_wmi_init(void)
+{
+ return wmi_driver_register(&alienware_legacy_wmi_driver);
+}
+
+void __exit alienware_legacy_wmi_exit(void)
+{
+ wmi_driver_unregister(&alienware_legacy_wmi_driver);
+}
diff --git a/drivers/platform/x86/dell/alienware-wmi-wmax.c b/drivers/platform/x86/dell/alienware-wmi-wmax.c
new file mode 100644
index 000000000000..eb8818832abd
--- /dev/null
+++ b/drivers/platform/x86/dell/alienware-wmi-wmax.c
@@ -0,0 +1,775 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Alienware WMAX WMI device driver
+ *
+ * Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
+ * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/dmi.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_profile.h>
+#include <linux/wmi.h>
+#include "alienware-wmi.h"
+
+#define WMAX_METHOD_HDMI_SOURCE 0x1
+#define WMAX_METHOD_HDMI_STATUS 0x2
+#define WMAX_METHOD_HDMI_CABLE 0x5
+#define WMAX_METHOD_AMPLIFIER_CABLE 0x6
+#define WMAX_METHOD_DEEP_SLEEP_CONTROL 0x0B
+#define WMAX_METHOD_DEEP_SLEEP_STATUS 0x0C
+#define WMAX_METHOD_BRIGHTNESS 0x3
+#define WMAX_METHOD_ZONE_CONTROL 0x4
+#define WMAX_METHOD_THERMAL_INFORMATION 0x14
+#define WMAX_METHOD_THERMAL_CONTROL 0x15
+#define WMAX_METHOD_GAME_SHIFT_STATUS 0x25
+
+#define WMAX_THERMAL_MODE_GMODE 0xAB
+
+#define WMAX_FAILURE_CODE 0xFFFFFFFF
+#define WMAX_THERMAL_TABLE_MASK GENMASK(7, 4)
+#define WMAX_THERMAL_MODE_MASK GENMASK(3, 0)
+#define WMAX_SENSOR_ID_MASK BIT(8)
+
+static bool force_platform_profile;
+module_param_unsafe(force_platform_profile, bool, 0);
+MODULE_PARM_DESC(force_platform_profile, "Forces auto-detecting thermal profiles without checking if WMI thermal backend is available");
+
+static bool force_gmode;
+module_param_unsafe(force_gmode, bool, 0);
+MODULE_PARM_DESC(force_gmode, "Forces G-Mode when performance profile is selected");
+
+struct awcc_quirks {
+ bool pprof;
+ bool gmode;
+};
+
+static struct awcc_quirks g_series_quirks = {
+ .pprof = true,
+ .gmode = true,
+};
+
+static struct awcc_quirks generic_quirks = {
+ .pprof = true,
+ .gmode = false,
+};
+
+static struct awcc_quirks empty_quirks;
+
+static const struct dmi_system_id awcc_dmi_table[] __initconst = {
+ {
+ .ident = "Alienware m16 R1 AMD",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Alienware m17 R5",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware m18 R2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m18 R2"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware x15 R1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x15 R1"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Alienware x17 R2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware x17 R2"),
+ },
+ .driver_data = &generic_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5510",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5510"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5511",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5511"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G15 5515",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5515"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G3 3500",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G3 3500"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G3 3590",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G3 3590"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+ {
+ .ident = "Dell Inc. G5 5500",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G5 5500"),
+ },
+ .driver_data = &g_series_quirks,
+ },
+};
+
+enum WMAX_THERMAL_INFORMATION_OPERATIONS {
+ WMAX_OPERATION_SYS_DESCRIPTION = 0x02,
+ WMAX_OPERATION_LIST_IDS = 0x03,
+ WMAX_OPERATION_CURRENT_PROFILE = 0x0B,
+};
+
+enum WMAX_THERMAL_CONTROL_OPERATIONS {
+ WMAX_OPERATION_ACTIVATE_PROFILE = 0x01,
+};
+
+enum WMAX_GAME_SHIFT_STATUS_OPERATIONS {
+ WMAX_OPERATION_TOGGLE_GAME_SHIFT = 0x01,
+ WMAX_OPERATION_GET_GAME_SHIFT_STATUS = 0x02,
+};
+
+enum WMAX_THERMAL_TABLES {
+ WMAX_THERMAL_TABLE_BASIC = 0x90,
+ WMAX_THERMAL_TABLE_USTT = 0xA0,
+};
+
+enum wmax_thermal_mode {
+ THERMAL_MODE_USTT_BALANCED,
+ THERMAL_MODE_USTT_BALANCED_PERFORMANCE,
+ THERMAL_MODE_USTT_COOL,
+ THERMAL_MODE_USTT_QUIET,
+ THERMAL_MODE_USTT_PERFORMANCE,
+ THERMAL_MODE_USTT_LOW_POWER,
+ THERMAL_MODE_BASIC_QUIET,
+ THERMAL_MODE_BASIC_BALANCED,
+ THERMAL_MODE_BASIC_BALANCED_PERFORMANCE,
+ THERMAL_MODE_BASIC_PERFORMANCE,
+ THERMAL_MODE_LAST,
+};
+
+struct wmax_led_args {
+ u32 led_mask;
+ struct color_platform colors;
+ u8 state;
+} __packed;
+
+struct wmax_brightness_args {
+ u32 led_mask;
+ u32 percentage;
+};
+
+struct wmax_basic_args {
+ u8 arg;
+};
+
+struct wmax_u32_args {
+ u8 operation;
+ u8 arg1;
+ u8 arg2;
+ u8 arg3;
+};
+
+struct awcc_priv {
+ struct wmi_device *wdev;
+ struct device *ppdev;
+ enum wmax_thermal_mode supported_thermal_profiles[PLATFORM_PROFILE_LAST];
+};
+
+static const enum platform_profile_option wmax_mode_to_platform_profile[THERMAL_MODE_LAST] = {
+ [THERMAL_MODE_USTT_BALANCED] = PLATFORM_PROFILE_BALANCED,
+ [THERMAL_MODE_USTT_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
+ [THERMAL_MODE_USTT_COOL] = PLATFORM_PROFILE_COOL,
+ [THERMAL_MODE_USTT_QUIET] = PLATFORM_PROFILE_QUIET,
+ [THERMAL_MODE_USTT_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
+ [THERMAL_MODE_USTT_LOW_POWER] = PLATFORM_PROFILE_LOW_POWER,
+ [THERMAL_MODE_BASIC_QUIET] = PLATFORM_PROFILE_QUIET,
+ [THERMAL_MODE_BASIC_BALANCED] = PLATFORM_PROFILE_BALANCED,
+ [THERMAL_MODE_BASIC_BALANCED_PERFORMANCE] = PLATFORM_PROFILE_BALANCED_PERFORMANCE,
+ [THERMAL_MODE_BASIC_PERFORMANCE] = PLATFORM_PROFILE_PERFORMANCE,
+};
+
+static struct awcc_quirks *awcc;
+
+/*
+ * The HDMI mux sysfs node indicates the status of the HDMI input mux.
+ * It can toggle between standard system GPU output and HDMI input.
+ */
+static ssize_t cable_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args in_args = {
+ .arg = 0,
+ };
+ u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_CABLE,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
+ if (out_data == 0)
+ return sysfs_emit(buf, "[unconnected] connected unknown\n");
+ else if (out_data == 1)
+ return sysfs_emit(buf, "unconnected [connected] unknown\n");
+ }
+
+ pr_err("alienware-wmi: unknown HDMI cable status: %d\n", ret);
+ return sysfs_emit(buf, "unconnected connected [unknown]\n");
+}
+
+static ssize_t source_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args in_args = {
+ .arg = 0,
+ };
+ u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_STATUS,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
+ if (out_data == 1)
+ return sysfs_emit(buf, "[input] gpu unknown\n");
+ else if (out_data == 2)
+ return sysfs_emit(buf, "input [gpu] unknown\n");
+ }
+
+ pr_err("alienware-wmi: unknown HDMI source status: %u\n", ret);
+ return sysfs_emit(buf, "input gpu [unknown]\n");
+}
+
+static ssize_t source_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args args;
+ int ret;
+
+ if (strcmp(buf, "gpu\n") == 0)
+ args.arg = 1;
+ else if (strcmp(buf, "input\n") == 0)
+ args.arg = 2;
+ else
+ args.arg = 3;
+ pr_debug("alienware-wmi: setting hdmi to %d : %s", args.arg, buf);
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_HDMI_SOURCE, &args,
+ sizeof(args), NULL);
+
+ if (ret < 0)
+ pr_err("alienware-wmi: HDMI toggle failed: results: %u\n", ret);
+
+ return count;
+}
+
+static DEVICE_ATTR_RO(cable);
+static DEVICE_ATTR_RW(source);
+
+static bool hdmi_group_visible(struct kobject *kobj)
+{
+ return alienware_interface == WMAX && alienfx->hdmi_mux;
+}
+DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(hdmi);
+
+static struct attribute *hdmi_attrs[] = {
+ &dev_attr_cable.attr,
+ &dev_attr_source.attr,
+ NULL,
+};
+
+const struct attribute_group wmax_hdmi_attribute_group = {
+ .name = "hdmi",
+ .is_visible = SYSFS_GROUP_VISIBLE(hdmi),
+ .attrs = hdmi_attrs,
+};
+
+/*
+ * Alienware GFX amplifier support
+ * - Currently supports reading cable status
+ * - Leaving expansion room to possibly support dock/undock events later
+ */
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args in_args = {
+ .arg = 0,
+ };
+ u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_AMPLIFIER_CABLE,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
+ if (out_data == 0)
+ return sysfs_emit(buf, "[unconnected] connected unknown\n");
+ else if (out_data == 1)
+ return sysfs_emit(buf, "unconnected [connected] unknown\n");
+ }
+
+ pr_err("alienware-wmi: unknown amplifier cable status: %d\n", ret);
+ return sysfs_emit(buf, "unconnected connected [unknown]\n");
+}
+
+static DEVICE_ATTR_RO(status);
+
+static bool amplifier_group_visible(struct kobject *kobj)
+{
+ return alienware_interface == WMAX && alienfx->amplifier;
+}
+DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(amplifier);
+
+static struct attribute *amplifier_attrs[] = {
+ &dev_attr_status.attr,
+ NULL,
+};
+
+const struct attribute_group wmax_amplifier_attribute_group = {
+ .name = "amplifier",
+ .is_visible = SYSFS_GROUP_VISIBLE(amplifier),
+ .attrs = amplifier_attrs,
+};
+
+/*
+ * Deep Sleep Control support
+ * - Modifies BIOS setting for deep sleep control allowing extra wakeup events
+ */
+static ssize_t deepsleep_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args in_args = {
+ .arg = 0,
+ };
+ u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_STATUS,
+ &in_args, sizeof(in_args), &out_data);
+
+ if (!ret) {
+ if (out_data == 0)
+ return sysfs_emit(buf, "[disabled] s5 s5_s4\n");
+ else if (out_data == 1)
+ return sysfs_emit(buf, "disabled [s5] s5_s4\n");
+ else if (out_data == 2)
+ return sysfs_emit(buf, "disabled s5 [s5_s4]\n");
+ }
+
+ pr_err("alienware-wmi: unknown deep sleep status: %d\n", ret);
+ return sysfs_emit(buf, "disabled s5 s5_s4 [unknown]\n");
+}
+
+static ssize_t deepsleep_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct alienfx_platdata *pdata = dev_get_platdata(dev);
+ struct wmax_basic_args args;
+ int ret;
+
+ if (strcmp(buf, "disabled\n") == 0)
+ args.arg = 0;
+ else if (strcmp(buf, "s5\n") == 0)
+ args.arg = 1;
+ else
+ args.arg = 2;
+ pr_debug("alienware-wmi: setting deep sleep to %d : %s", args.arg, buf);
+
+ ret = alienware_wmi_command(pdata->wdev, WMAX_METHOD_DEEP_SLEEP_CONTROL,
+ &args, sizeof(args), NULL);
+
+ if (!ret)
+ pr_err("alienware-wmi: deep sleep control failed: results: %u\n", ret);
+
+ return count;
+}
+
+static DEVICE_ATTR_RW(deepsleep);
+
+static bool deepsleep_group_visible(struct kobject *kobj)
+{
+ return alienware_interface == WMAX && alienfx->deepslp;
+}
+DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(deepsleep);
+
+static struct attribute *deepsleep_attrs[] = {
+ &dev_attr_deepsleep.attr,
+ NULL,
+};
+
+const struct attribute_group wmax_deepsleep_attribute_group = {
+ .name = "deepsleep",
+ .is_visible = SYSFS_GROUP_VISIBLE(deepsleep),
+ .attrs = deepsleep_attrs,
+};
+
+/*
+ * Thermal Profile control
+ * - Provides thermal profile control through the Platform Profile API
+ */
+static bool is_wmax_thermal_code(u32 code)
+{
+ if (code & WMAX_SENSOR_ID_MASK)
+ return false;
+
+ if ((code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_LAST)
+ return false;
+
+ if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_BASIC &&
+ (code & WMAX_THERMAL_MODE_MASK) >= THERMAL_MODE_BASIC_QUIET)
+ return true;
+
+ if ((code & WMAX_THERMAL_TABLE_MASK) == WMAX_THERMAL_TABLE_USTT &&
+ (code & WMAX_THERMAL_MODE_MASK) <= THERMAL_MODE_USTT_LOW_POWER)
+ return true;
+
+ return false;
+}
+
+static int wmax_thermal_information(struct wmi_device *wdev, u8 operation,
+ u8 arg, u32 *out_data)
+{
+ struct wmax_u32_args in_args = {
+ .operation = operation,
+ .arg1 = arg,
+ .arg2 = 0,
+ .arg3 = 0,
+ };
+ int ret;
+
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_INFORMATION,
+ &in_args, sizeof(in_args), out_data);
+ if (ret < 0)
+ return ret;
+
+ if (*out_data == WMAX_FAILURE_CODE)
+ return -EBADRQC;
+
+ return 0;
+}
+
+static int wmax_thermal_control(struct wmi_device *wdev, u8 profile)
+{
+ struct wmax_u32_args in_args = {
+ .operation = WMAX_OPERATION_ACTIVATE_PROFILE,
+ .arg1 = profile,
+ .arg2 = 0,
+ .arg3 = 0,
+ };
+ u32 out_data;
+ int ret;
+
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_THERMAL_CONTROL,
+ &in_args, sizeof(in_args), &out_data);
+ if (ret)
+ return ret;
+
+ if (out_data == WMAX_FAILURE_CODE)
+ return -EBADRQC;
+
+ return 0;
+}
+
+static int wmax_game_shift_status(struct wmi_device *wdev, u8 operation,
+ u32 *out_data)
+{
+ struct wmax_u32_args in_args = {
+ .operation = operation,
+ .arg1 = 0,
+ .arg2 = 0,
+ .arg3 = 0,
+ };
+ int ret;
+
+ ret = alienware_wmi_command(wdev, WMAX_METHOD_GAME_SHIFT_STATUS,
+ &in_args, sizeof(in_args), out_data);
+
+ if (ret < 0)
+ return ret;
+
+ if (*out_data == WMAX_FAILURE_CODE)
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
+static int thermal_profile_get(struct device *dev,
+ enum platform_profile_option *profile)
+{
+ struct awcc_priv *priv = dev_get_drvdata(dev);
+ u32 out_data;
+ int ret;
+
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_CURRENT_PROFILE,
+ 0, &out_data);
+
+ if (ret < 0)
+ return ret;
+
+ if (out_data == WMAX_THERMAL_MODE_GMODE) {
+ *profile = PLATFORM_PROFILE_PERFORMANCE;
+ return 0;
+ }
+
+ if (!is_wmax_thermal_code(out_data))
+ return -ENODATA;
+
+ out_data &= WMAX_THERMAL_MODE_MASK;
+ *profile = wmax_mode_to_platform_profile[out_data];
+
+ return 0;
+}
+
+static int thermal_profile_set(struct device *dev,
+ enum platform_profile_option profile)
+{
+ struct awcc_priv *priv = dev_get_drvdata(dev);
+
+ if (awcc->gmode) {
+ u32 gmode_status;
+ int ret;
+
+ ret = wmax_game_shift_status(priv->wdev,
+ WMAX_OPERATION_GET_GAME_SHIFT_STATUS,
+ &gmode_status);
+
+ if (ret < 0)
+ return ret;
+
+ if ((profile == PLATFORM_PROFILE_PERFORMANCE && !gmode_status) ||
+ (profile != PLATFORM_PROFILE_PERFORMANCE && gmode_status)) {
+ ret = wmax_game_shift_status(priv->wdev,
+ WMAX_OPERATION_TOGGLE_GAME_SHIFT,
+ &gmode_status);
+
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return wmax_thermal_control(priv->wdev,
+ priv->supported_thermal_profiles[profile]);
+}
+
+static int thermal_profile_probe(void *drvdata, unsigned long *choices)
+{
+ enum platform_profile_option profile;
+ struct awcc_priv *priv = drvdata;
+ enum wmax_thermal_mode mode;
+ u8 sys_desc[4];
+ u32 first_mode;
+ u32 out_data;
+ int ret;
+
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_SYS_DESCRIPTION,
+ 0, (u32 *) &sys_desc);
+ if (ret < 0)
+ return ret;
+
+ first_mode = sys_desc[0] + sys_desc[1];
+
+ for (u32 i = 0; i < sys_desc[3]; i++) {
+ ret = wmax_thermal_information(priv->wdev, WMAX_OPERATION_LIST_IDS,
+ i + first_mode, &out_data);
+
+ if (ret == -EIO)
+ return ret;
+
+ if (ret == -EBADRQC)
+ break;
+
+ if (!is_wmax_thermal_code(out_data))
+ continue;
+
+ mode = out_data & WMAX_THERMAL_MODE_MASK;
+ profile = wmax_mode_to_platform_profile[mode];
+ priv->supported_thermal_profiles[profile] = out_data;
+
+ set_bit(profile, choices);
+ }
+
+ if (bitmap_empty(choices, PLATFORM_PROFILE_LAST))
+ return -ENODEV;
+
+ if (awcc->gmode) {
+ priv->supported_thermal_profiles[PLATFORM_PROFILE_PERFORMANCE] =
+ WMAX_THERMAL_MODE_GMODE;
+
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+ }
+
+ return 0;
+}
+
+static const struct platform_profile_ops awcc_platform_profile_ops = {
+ .probe = thermal_profile_probe,
+ .profile_get = thermal_profile_get,
+ .profile_set = thermal_profile_set,
+};
+
+static int awcc_platform_profile_init(struct wmi_device *wdev)
+{
+ struct awcc_priv *priv = dev_get_drvdata(&wdev->dev);
+
+ priv->ppdev = devm_platform_profile_register(&wdev->dev, "alienware-wmi",
+ priv, &awcc_platform_profile_ops);
+
+ return PTR_ERR_OR_ZERO(priv->ppdev);
+}
+
+static int alienware_awcc_setup(struct wmi_device *wdev)
+{
+ struct awcc_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->wdev = wdev;
+ dev_set_drvdata(&wdev->dev, priv);
+
+ if (awcc->pprof) {
+ ret = awcc_platform_profile_init(wdev);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
+ * WMAX WMI driver
+ */
+static int wmax_wmi_update_led(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 location)
+{
+ struct wmax_led_args in_args = {
+ .led_mask = 1 << location,
+ .colors = priv->colors[location],
+ .state = priv->lighting_control_state,
+ };
+
+ return alienware_wmi_command(wdev, WMAX_METHOD_ZONE_CONTROL, &in_args,
+ sizeof(in_args), NULL);
+}
+
+static int wmax_wmi_update_brightness(struct alienfx_priv *priv,
+ struct wmi_device *wdev, u8 brightness)
+{
+ struct wmax_brightness_args in_args = {
+ .led_mask = 0xFF,
+ .percentage = brightness,
+ };
+
+ return alienware_wmi_command(wdev, WMAX_METHOD_BRIGHTNESS, &in_args,
+ sizeof(in_args), NULL);
+}
+
+static int wmax_wmi_probe(struct wmi_device *wdev, const void *context)
+{
+ struct alienfx_platdata pdata = {
+ .wdev = wdev,
+ .ops = {
+ .upd_led = wmax_wmi_update_led,
+ .upd_brightness = wmax_wmi_update_brightness,
+ },
+ };
+ int ret;
+
+ if (awcc)
+ ret = alienware_awcc_setup(wdev);
+ else
+ ret = alienware_alienfx_setup(&pdata);
+
+ return ret;
+}
+
+static const struct wmi_device_id alienware_wmax_device_id_table[] = {
+ { WMAX_CONTROL_GUID, NULL },
+ { },
+};
+MODULE_DEVICE_TABLE(wmi, alienware_wmax_device_id_table);
+
+static struct wmi_driver alienware_wmax_wmi_driver = {
+ .driver = {
+ .name = "alienware-wmi-wmax",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ .id_table = alienware_wmax_device_id_table,
+ .probe = wmax_wmi_probe,
+ .no_singleton = true,
+};
+
+int __init alienware_wmax_wmi_init(void)
+{
+ const struct dmi_system_id *id;
+
+ id = dmi_first_match(awcc_dmi_table);
+ if (id)
+ awcc = id->driver_data;
+
+ if (force_platform_profile) {
+ if (!awcc)
+ awcc = &empty_quirks;
+
+ awcc->pprof = true;
+ }
+
+ if (force_gmode) {
+ if (awcc)
+ awcc->gmode = true;
+ else
+ pr_warn("force_gmode requires platform profile support\n");
+ }
+
+ return wmi_driver_register(&alienware_wmax_wmi_driver);
+}
+
+void __exit alienware_wmax_wmi_exit(void)
+{
+ wmi_driver_unregister(&alienware_wmax_wmi_driver);
+}
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 12/14] platform/x86: dell: Modify Makefile alignment
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (10 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 11/14] platform/x86: Split the alienware-wmi driver Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 13/14] platform/x86: Update alienware-wmi config entries Kurt Borja
` (2 subsequent siblings)
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Add one more TAB to each line to support upcoming changes.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/Makefile | 48 +++++++++++++++---------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index 03ba459f3d31..d5718ef34c48 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -4,27 +4,27 @@
# Dell x86 Platform-Specific Drivers
#
-obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
-alienware-wmi-objs := alienware-wmi-base.o
-alienware-wmi-y += alienware-wmi-legacy.o
-alienware-wmi-y += alienware-wmi-wmax.o
-obj-$(CONFIG_DCDBAS) += dcdbas.o
-obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
-obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
-obj-$(CONFIG_DELL_RBU) += dell_rbu.o
-obj-$(CONFIG_DELL_PC) += dell-pc.o
-obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
-dell-smbios-objs := dell-smbios-base.o
-dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
-dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
-obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
-obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o
-obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o
-obj-$(CONFIG_DELL_WMI) += dell-wmi.o
-dell-wmi-objs := dell-wmi-base.o
-dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o
-obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
-obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
-obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o
-obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
-obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
+obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
+alienware-wmi-objs := alienware-wmi-base.o
+alienware-wmi-y += alienware-wmi-legacy.o
+alienware-wmi-y += alienware-wmi-wmax.o
+obj-$(CONFIG_DCDBAS) += dcdbas.o
+obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
+obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
+obj-$(CONFIG_DELL_RBU) += dell_rbu.o
+obj-$(CONFIG_DELL_PC) += dell-pc.o
+obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
+dell-smbios-objs := dell-smbios-base.o
+dell-smbios-$(CONFIG_DELL_SMBIOS_WMI) += dell-smbios-wmi.o
+dell-smbios-$(CONFIG_DELL_SMBIOS_SMM) += dell-smbios-smm.o
+obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
+obj-$(CONFIG_DELL_SMO8800) += dell-lis3lv02d.o
+obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o
+obj-$(CONFIG_DELL_WMI) += dell-wmi.o
+dell-wmi-objs := dell-wmi-base.o
+dell-wmi-$(CONFIG_DELL_WMI_PRIVACY) += dell-wmi-privacy.o
+obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
+obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
+obj-$(CONFIG_DELL_WMI_DDV) += dell-wmi-ddv.o
+obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
+obj-$(CONFIG_DELL_WMI_SYSMAN) += dell-wmi-sysman/
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 13/14] platform/x86: Update alienware-wmi config entries
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (11 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 12/14] platform/x86: dell: Modify Makefile alignment Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-03 18:27 ` [PATCH v8 14/14] platform/x86: alienware-wmi: Update header and module information Kurt Borja
2025-02-06 5:23 ` [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Armin Wolf
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Add config entries for each WMI driver managed by the alienware-wmi
module to be able to conditionally compile them.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/Kconfig | 30 +++++++++++++++++++----
drivers/platform/x86/dell/Makefile | 4 +--
drivers/platform/x86/dell/alienware-wmi.h | 25 +++++++++++++++++++
3 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/x86/dell/Kconfig b/drivers/platform/x86/dell/Kconfig
index d09060aedd3f..f8a0dffcaab7 100644
--- a/drivers/platform/x86/dell/Kconfig
+++ b/drivers/platform/x86/dell/Kconfig
@@ -18,15 +18,35 @@ config ALIENWARE_WMI
tristate "Alienware Special feature control"
default m
depends on ACPI
+ depends on ACPI_WMI
+ depends on DMI
depends on LEDS_CLASS
depends on NEW_LEDS
- depends on ACPI_WMI
+ help
+ This is a driver for controlling Alienware WMI driven features.
+
+ On legacy devices, it exposes an interface for controlling the AlienFX
+ zones on Alienware machines that don't contain a dedicated
+ AlienFX USB MCU such as the X51 and X51-R2.
+
+ On newer devices, it exposes the AWCC thermal control interface through
+ known Kernel APIs.
+
+config ALIENWARE_WMI_LEGACY
+ bool "Alienware Legacy WMI device driver"
+ default y
+ depends on ALIENWARE_WMI
+ help
+ Legacy Alienware WMI driver with AlienFX LED control capabilities.
+
+config ALIENWARE_WMI_WMAX
+ bool "Alienware WMAX WMI device driver"
+ default y
+ depends on ALIENWARE_WMI
select ACPI_PLATFORM_PROFILE
help
- This is a driver for controlling Alienware BIOS driven
- features. It exposes an interface for controlling the AlienFX
- zones on Alienware machines that don't contain a dedicated AlienFX
- USB MCU such as the X51 and X51-R2.
+ Alienware WMI driver with AlienFX LED, HDMI, amplifier, deep sleep and
+ AWCC thermal control capabilities.
config DCDBAS
tristate "Dell Systems Management Base Driver"
diff --git a/drivers/platform/x86/dell/Makefile b/drivers/platform/x86/dell/Makefile
index d5718ef34c48..8ac9a933c770 100644
--- a/drivers/platform/x86/dell/Makefile
+++ b/drivers/platform/x86/dell/Makefile
@@ -6,8 +6,8 @@
obj-$(CONFIG_ALIENWARE_WMI) += alienware-wmi.o
alienware-wmi-objs := alienware-wmi-base.o
-alienware-wmi-y += alienware-wmi-legacy.o
-alienware-wmi-y += alienware-wmi-wmax.o
+alienware-wmi-$(CONFIG_ALIENWARE_WMI_LEGACY) += alienware-wmi-legacy.o
+alienware-wmi-$(CONFIG_ALIENWARE_WMI_WMAX) += alienware-wmi-wmax.o
obj-$(CONFIG_DCDBAS) += dcdbas.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_RBTN) += dell-rbtn.o
diff --git a/drivers/platform/x86/dell/alienware-wmi.h b/drivers/platform/x86/dell/alienware-wmi.h
index b950c91e1979..68d4242211ae 100644
--- a/drivers/platform/x86/dell/alienware-wmi.h
+++ b/drivers/platform/x86/dell/alienware-wmi.h
@@ -75,9 +75,21 @@ int alienware_wmi_command(struct wmi_device *wdev, u32 method_id,
int alienware_alienfx_setup(struct alienfx_platdata *pdata);
+#if IS_ENABLED(CONFIG_ALIENWARE_WMI_LEGACY)
int __init alienware_legacy_wmi_init(void);
void __exit alienware_legacy_wmi_exit(void);
+#else
+static inline int alienware_legacy_wmi_init(void)
+{
+ return -ENODEV;
+}
+
+static inline void alienware_legacy_wmi_exit(void)
+{
+}
+#endif
+#if IS_ENABLED(CONFIG_ALIENWARE_WMI_WMAX)
extern const struct attribute_group wmax_hdmi_attribute_group;
extern const struct attribute_group wmax_amplifier_attribute_group;
extern const struct attribute_group wmax_deepsleep_attribute_group;
@@ -88,5 +100,18 @@ extern const struct attribute_group wmax_deepsleep_attribute_group;
int __init alienware_wmax_wmi_init(void);
void __exit alienware_wmax_wmi_exit(void);
+#else
+#define WMAX_DEV_GROUPS
+
+static inline int alienware_wmax_wmi_init(void)
+{
+ return -ENODEV;
+}
+
+
+static inline void alienware_wmax_wmi_exit(void)
+{
+}
+#endif
#endif
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH v8 14/14] platform/x86: alienware-wmi: Update header and module information
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (12 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 13/14] platform/x86: Update alienware-wmi config entries Kurt Borja
@ 2025-02-03 18:27 ` Kurt Borja
2025-02-06 5:23 ` [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Armin Wolf
14 siblings, 0 replies; 17+ messages in thread
From: Kurt Borja @ 2025-02-03 18:27 UTC (permalink / raw)
To: platform-driver-x86
Cc: Ilpo Järvinen, Armin Wolf, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel, Kurt Borja
Update module header and description. Additionally add myself as a module
author.
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Kurt Borja <kuurtb@gmail.com>
---
drivers/platform/x86/dell/alienware-wmi-base.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/dell/alienware-wmi-base.c b/drivers/platform/x86/dell/alienware-wmi-base.c
index 7bad9717183d..64562b92314f 100644
--- a/drivers/platform/x86/dell/alienware-wmi-base.c
+++ b/drivers/platform/x86/dell/alienware-wmi-base.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Alienware AlienFX control
+ * Alienware special feature control
*
* Copyright (C) 2014 Dell Inc <Dell.Client.Kernel@dell.com>
+ * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -16,6 +17,7 @@
#include "alienware-wmi.h"
MODULE_AUTHOR("Mario Limonciello <mario.limonciello@outlook.com>");
+MODULE_AUTHOR("Kurt Borja <kuurtb@gmail.com>");
MODULE_DESCRIPTION("Alienware special feature control");
MODULE_LICENSE("GPL");
--
2.48.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH v8 00/14] platform/x86: alienware-wmi driver rework
2025-02-03 18:26 [PATCH v8 00/14] platform/x86: alienware-wmi driver rework Kurt Borja
` (13 preceding siblings ...)
2025-02-03 18:27 ` [PATCH v8 14/14] platform/x86: alienware-wmi: Update header and module information Kurt Borja
@ 2025-02-06 5:23 ` Armin Wolf
14 siblings, 0 replies; 17+ messages in thread
From: Armin Wolf @ 2025-02-06 5:23 UTC (permalink / raw)
To: Kurt Borja, platform-driver-x86
Cc: Ilpo Järvinen, Mario Limonciello, Hans de Goede,
Dell.Client.Kernel, linux-kernel
Am 03.02.25 um 19:26 schrieb Kurt Borja:
> Hello!
Reviewed-by: Armin Wolf <W_Armin@gmx.de>
>
> ---
> [02/14]
> - Dropped device_add_groups from wmax_wmi_probe
> - Added `interface == WMAX` condition to WMAX's groups visibility
>
> [10/14]
> - Add prefix to WMAX groups variable names
> - Exported WMAX groups as extern variables in header file
> - Exported `interface` as `alienware_interface` in header file
> - Added WMAX_DEV_GROUPS macro to add WMAX groups to the platform
> driver .dev_groups
>
> [13/14]
> - Define empty WMAX_DEV_GROUPS in case CONFIG_ALIENWARE_WMI_WMAX is
> not enabled
>
> v7: https://lore.kernel.org/platform-driver-x86/20250203062055.2915-1-kuurtb@gmail.com/
>
> Kurt Borja (14):
> platform/x86: alienware-wmi: Add a state container for LED control
> feature
> platform/x86: alienware-wmi: Add WMI Drivers
> platform/x86: alienware-wmi: Add a state container for thermal control
> methods
> platform/x86: alienware-wmi: Refactor LED control methods
> platform/x86: alienware-wmi: Refactor hdmi, amplifier, deepslp methods
> platform/x86: alienware-wmi: Refactor thermal control methods
> platform/x86: alienware-wmi: Split DMI table
> MAINTAINERS: Update ALIENWARE WMI DRIVER entry
> platform/x86: Rename alienware-wmi.c
> platform/x86: Add alienware-wmi.h
> platform/x86: Split the alienware-wmi driver
> platform/x86: dell: Modify Makefile alignment
> platform/x86: Update alienware-wmi config entries
> platform/x86: alienware-wmi: Update header and module information
>
> MAINTAINERS | 4 +-
> drivers/platform/x86/dell/Kconfig | 30 +-
> drivers/platform/x86/dell/Makefile | 45 +-
> .../platform/x86/dell/alienware-wmi-base.c | 491 +++++++
> .../platform/x86/dell/alienware-wmi-legacy.c | 95 ++
> .../platform/x86/dell/alienware-wmi-wmax.c | 775 ++++++++++
> drivers/platform/x86/dell/alienware-wmi.c | 1249 -----------------
> drivers/platform/x86/dell/alienware-wmi.h | 117 ++
> 8 files changed, 1530 insertions(+), 1276 deletions(-)
> create mode 100644 drivers/platform/x86/dell/alienware-wmi-base.c
> create mode 100644 drivers/platform/x86/dell/alienware-wmi-legacy.c
> create mode 100644 drivers/platform/x86/dell/alienware-wmi-wmax.c
> delete mode 100644 drivers/platform/x86/dell/alienware-wmi.c
> create mode 100644 drivers/platform/x86/dell/alienware-wmi.h
>
>
> base-commit: 2014c95afecee3e76ca4a56956a936e23283f05b
^ permalink raw reply [flat|nested] 17+ messages in thread