1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Alienware LEGACY WMI device driver
4  *
5  * Copyright (C) 2025 Kurt Borja <kuurtb@gmail.com>
6  */
7 
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 
10 #include <linux/wmi.h>
11 #include "alienware-wmi.h"
12 
13 struct legacy_led_args {
14 	struct color_platform colors;
15 	u8 brightness;
16 	u8 state;
17 } __packed;
18 
19 
20 /*
21  * Legacy WMI driver
22  */
legacy_wmi_update_led(struct alienfx_priv * priv,struct wmi_device * wdev,u8 location)23 static int legacy_wmi_update_led(struct alienfx_priv *priv,
24 				 struct wmi_device *wdev, u8 location)
25 {
26 	struct legacy_led_args legacy_args = {
27 		.colors = priv->colors[location],
28 		.brightness = priv->global_brightness,
29 		.state = 0,
30 	};
31 	struct acpi_buffer input;
32 	acpi_status status;
33 
34 	if (legacy_args.state != LEGACY_RUNNING) {
35 		legacy_args.state = priv->lighting_control_state;
36 
37 		input.length = sizeof(legacy_args);
38 		input.pointer = &legacy_args;
39 
40 		status = wmi_evaluate_method(LEGACY_POWER_CONTROL_GUID, 0,
41 					     location + 1, &input, NULL);
42 		if (ACPI_FAILURE(status))
43 			return -EIO;
44 
45 		return 0;
46 	}
47 
48 	return alienware_wmi_command(wdev, location + 1, &legacy_args,
49 				     sizeof(legacy_args), NULL);
50 }
51 
legacy_wmi_update_brightness(struct alienfx_priv * priv,struct wmi_device * wdev,u8 brightness)52 static int legacy_wmi_update_brightness(struct alienfx_priv *priv,
53 					struct wmi_device *wdev, u8 brightness)
54 {
55 	return legacy_wmi_update_led(priv, wdev, 0);
56 }
57 
legacy_wmi_probe(struct wmi_device * wdev,const void * context)58 static int legacy_wmi_probe(struct wmi_device *wdev, const void *context)
59 {
60 	struct alienfx_platdata pdata = {
61 		.wdev = wdev,
62 		.ops = {
63 			.upd_led = legacy_wmi_update_led,
64 			.upd_brightness = legacy_wmi_update_brightness,
65 		},
66 	};
67 
68 	return alienware_alienfx_setup(&pdata);
69 }
70 
71 static const struct wmi_device_id alienware_legacy_device_id_table[] = {
72 	{ LEGACY_CONTROL_GUID, NULL },
73 	{ },
74 };
75 MODULE_DEVICE_TABLE(wmi, alienware_legacy_device_id_table);
76 
77 static struct wmi_driver alienware_legacy_wmi_driver = {
78 	.driver = {
79 		.name = "alienware-wmi-alienfx",
80 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
81 	},
82 	.id_table = alienware_legacy_device_id_table,
83 	.probe = legacy_wmi_probe,
84 	.no_singleton = true,
85 };
86 
alienware_legacy_wmi_init(void)87 int __init alienware_legacy_wmi_init(void)
88 {
89 	return wmi_driver_register(&alienware_legacy_wmi_driver);
90 }
91 
alienware_legacy_wmi_exit(void)92 void __exit alienware_legacy_wmi_exit(void)
93 {
94 	wmi_driver_unregister(&alienware_legacy_wmi_driver);
95 }
96