Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: asus-armoury: move existing tunings to asus-armoury module

The fw_attributes_class provides a much cleaner interface to all of the
attributes introduced to asus-wmi. This patch moves all of these extra
attributes over to fw_attributes_class, and shifts the bulk of these
definitions to a new kernel module to reduce the clutter of asus-wmi
with the intention of deprecating the asus-wmi attributes in future.

The work applies only to WMI methods which don't have a clearly defined
place within the sysfs and as a result ended up lumped together in
/sys/devices/platform/asus-nb-wmi/ with no standard API.

Where possible the fw attrs now implement defaults, min, max, scalar,
choices, etc. As en example dgpu_disable becomes:

/sys/class/firmware-attributes/asus-armoury/attributes/dgpu_disable/
├── current_value
├── display_name
├── possible_values
└── type

as do other attributes.

Co-developed-by: Denis Benato <denis.benato@linux.dev>
Signed-off-by: Denis Benato <denis.benato@linux.dev>
Signed-off-by: Luke D. Jones <luke@ljones.dev>
Link: https://patch.msgid.link/20251102215319.3126879-3-denis.benato@linux.dev
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>

authored by

Luke D. Jones and committed by
Ilpo Järvinen
f99eb098 22ea7b9d

+1034 -47
+1
drivers/hid/hid-asus.c
··· 27 27 #include <linux/hid.h> 28 28 #include <linux/module.h> 29 29 #include <linux/platform_data/x86/asus-wmi.h> 30 + #include <linux/platform_data/x86/asus-wmi-leds-ids.h> 30 31 #include <linux/input/mt.h> 31 32 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */ 32 33 #include <linux/power_supply.h>
+12
drivers/platform/x86/Kconfig
··· 264 264 If you choose to compile this driver as a module the module will be 265 265 called asus-wireless. 266 266 267 + config ASUS_ARMOURY 268 + tristate "ASUS Armoury driver" 269 + depends on ASUS_WMI 270 + select FW_ATTR_CLASS 271 + help 272 + Say Y here if you have a WMI aware Asus machine and would like to use the 273 + firmware_attributes API to control various settings typically exposed in 274 + the ASUS Armoury Crate application available on Windows. 275 + 276 + To compile this driver as a module, choose M here: the module will 277 + be called asus-armoury. 278 + 267 279 config ASUS_WMI 268 280 tristate "ASUS WMI Driver" 269 281 depends on ACPI_WMI
+1
drivers/platform/x86/Makefile
··· 33 33 # ASUS 34 34 obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o 35 35 obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o 36 + obj-$(CONFIG_ASUS_ARMOURY) += asus-armoury.o 36 37 obj-$(CONFIG_ASUS_WMI) += asus-wmi.o 37 38 obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o 38 39 obj-$(CONFIG_ASUS_TF103C_DOCK) += asus-tf103c-dock.o
+763
drivers/platform/x86/asus-armoury.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Asus Armoury (WMI) attributes driver. 4 + * 5 + * This driver uses the fw_attributes class to expose various WMI functions 6 + * that are present in many gaming and some non-gaming ASUS laptops. 7 + * 8 + * These typically don't fit anywhere else in the sysfs such as under LED class, 9 + * hwmon or others, and are set in Windows using the ASUS Armoury Crate tool. 10 + * 11 + * Copyright(C) 2024 Luke Jones <luke@ljones.dev> 12 + */ 13 + 14 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 + 16 + #include <linux/acpi.h> 17 + #include <linux/array_size.h> 18 + #include <linux/bitfield.h> 19 + #include <linux/device.h> 20 + #include <linux/dmi.h> 21 + #include <linux/err.h> 22 + #include <linux/errno.h> 23 + #include <linux/fs.h> 24 + #include <linux/kernel.h> 25 + #include <linux/kmod.h> 26 + #include <linux/kobject.h> 27 + #include <linux/kstrtox.h> 28 + #include <linux/module.h> 29 + #include <linux/mutex.h> 30 + #include <linux/pci.h> 31 + #include <linux/platform_data/x86/asus-wmi.h> 32 + #include <linux/printk.h> 33 + #include <linux/sysfs.h> 34 + 35 + #include "asus-armoury.h" 36 + #include "firmware_attributes_class.h" 37 + 38 + #define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" 39 + 40 + #define ASUS_MINI_LED_MODE_MASK GENMASK(1, 0) 41 + /* Standard modes for devices with only on/off */ 42 + #define ASUS_MINI_LED_OFF 0x00 43 + #define ASUS_MINI_LED_ON 0x01 44 + /* Like "on" but the effect is more vibrant or brighter */ 45 + #define ASUS_MINI_LED_STRONG_MODE 0x02 46 + /* New modes for devices with 3 mini-led mode types */ 47 + #define ASUS_MINI_LED_2024_WEAK 0x00 48 + #define ASUS_MINI_LED_2024_STRONG 0x01 49 + #define ASUS_MINI_LED_2024_OFF 0x02 50 + 51 + struct asus_armoury_priv { 52 + struct device *fw_attr_dev; 53 + struct kset *fw_attr_kset; 54 + 55 + /* 56 + * Mutex to protect eGPU activation/deactivation 57 + * sequences and dGPU connection status: 58 + * do not allow concurrent changes or changes 59 + * before a reboot if dGPU got disabled. 60 + */ 61 + struct mutex egpu_mutex; 62 + 63 + u32 mini_led_dev_id; 64 + u32 gpu_mux_dev_id; 65 + }; 66 + 67 + static struct asus_armoury_priv asus_armoury = { 68 + .egpu_mutex = __MUTEX_INITIALIZER(asus_armoury.egpu_mutex), 69 + }; 70 + 71 + struct fw_attrs_group { 72 + bool pending_reboot; 73 + }; 74 + 75 + static struct fw_attrs_group fw_attrs = { 76 + .pending_reboot = false, 77 + }; 78 + 79 + struct asus_attr_group { 80 + const struct attribute_group *attr_group; 81 + u32 wmi_devid; 82 + }; 83 + 84 + static void asus_set_reboot_and_signal_event(void) 85 + { 86 + fw_attrs.pending_reboot = true; 87 + kobject_uevent(&asus_armoury.fw_attr_dev->kobj, KOBJ_CHANGE); 88 + } 89 + 90 + static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 91 + { 92 + return sysfs_emit(buf, "%d\n", fw_attrs.pending_reboot); 93 + } 94 + 95 + static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); 96 + 97 + static bool asus_bios_requires_reboot(struct kobj_attribute *attr) 98 + { 99 + return !strcmp(attr->attr.name, "gpu_mux_mode"); 100 + } 101 + 102 + /** 103 + * armoury_has_devstate() - Check presence of the WMI function state. 104 + * 105 + * @dev_id: The WMI method ID to check for presence. 106 + * 107 + * Returns: true iif method is supported. 108 + */ 109 + static bool armoury_has_devstate(u32 dev_id) 110 + { 111 + u32 retval; 112 + int status; 113 + 114 + status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 0, &retval); 115 + pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); 116 + 117 + return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); 118 + } 119 + 120 + /** 121 + * armoury_get_devstate() - Get the WMI function state. 122 + * @attr: NULL or the kobj_attribute associated to called WMI function. 123 + * @dev_id: The WMI method ID to call. 124 + * @retval: 125 + * * non-NULL pointer to where to store the value returned from WMI 126 + * * with the function presence bit cleared. 127 + * 128 + * Intended usage is from sysfs attribute checking associated WMI function. 129 + * 130 + * Returns: 131 + * * %-ENODEV - method ID is unsupported. 132 + * * %0 - successful and retval is filled. 133 + * * %other - error from WMI call. 134 + */ 135 + static int armoury_get_devstate(struct kobj_attribute *attr, u32 *retval, u32 dev_id) 136 + { 137 + int err; 138 + 139 + err = asus_wmi_get_devstate_dsts(dev_id, retval); 140 + if (err) { 141 + if (attr) 142 + pr_err("Failed to get %s: %d\n", attr->attr.name, err); 143 + else 144 + pr_err("Failed to get devstate for 0x%x: %d\n", dev_id, err); 145 + 146 + return err; 147 + } 148 + 149 + /* 150 + * asus_wmi_get_devstate_dsts will populate retval with WMI return, but 151 + * the true value is expressed when ASUS_WMI_DSTS_PRESENCE_BIT is clear. 152 + */ 153 + *retval &= ~ASUS_WMI_DSTS_PRESENCE_BIT; 154 + 155 + return 0; 156 + } 157 + 158 + /** 159 + * armoury_set_devstate() - Set the WMI function state. 160 + * @attr: The kobj_attribute associated to called WMI function. 161 + * @dev_id: The WMI method ID to call. 162 + * @value: The new value to be set. 163 + * @retval: Where to store the value returned from WMI or NULL. 164 + * 165 + * Intended usage is from sysfs attribute setting associated WMI function. 166 + * Before calling the presence of the function should be checked. 167 + * 168 + * Every WMI write MUST go through this function to enforce safety checks. 169 + * 170 + * Results !1 is usually considered a fail by ASUS, but some WMI methods 171 + * (like eGPU or CPU cores) do use > 1 to return a status code or similar: 172 + * in these cases caller is interested in the actual return value 173 + * and should perform relevant checks. 174 + * 175 + * Returns: 176 + * * %-EIO - WMI function returned an error. 177 + * * %0 - successful and retval is filled. 178 + * * %other - error from WMI call. 179 + */ 180 + static int armoury_set_devstate(struct kobj_attribute *attr, 181 + u32 value, u32 *retval, u32 dev_id) 182 + { 183 + u32 result; 184 + int err; 185 + 186 + err = asus_wmi_set_devstate(dev_id, value, retval ? retval : &result); 187 + if (err) { 188 + if (attr) 189 + pr_err("Failed to set %s: %d\n", attr->attr.name, err); 190 + else 191 + pr_err("Failed to set devstate for 0x%x: %d\n", dev_id, err); 192 + 193 + return err; 194 + } 195 + 196 + /* 197 + * If retval == NULL caller is uninterested in return value: 198 + * perform the most common result check here. 199 + */ 200 + if ((retval == NULL) && (result == 0)) { 201 + pr_err("Failed to set %s: (result): 0x%x\n", attr->attr.name, result); 202 + return -EIO; 203 + } 204 + 205 + return 0; 206 + } 207 + 208 + static int armoury_attr_enum_list(char *buf, size_t enum_values) 209 + { 210 + size_t i; 211 + int len = 0; 212 + 213 + for (i = 0; i < enum_values; i++) { 214 + if (i == 0) 215 + len += sysfs_emit_at(buf, len, "%zu", i); 216 + else 217 + len += sysfs_emit_at(buf, len, ";%zu", i); 218 + } 219 + len += sysfs_emit_at(buf, len, "\n"); 220 + 221 + return len; 222 + } 223 + 224 + ssize_t armoury_attr_uint_store(struct kobject *kobj, struct kobj_attribute *attr, 225 + const char *buf, size_t count, u32 min, u32 max, 226 + u32 *store_value, u32 wmi_dev) 227 + { 228 + u32 value; 229 + int err; 230 + 231 + err = kstrtou32(buf, 10, &value); 232 + if (err) 233 + return err; 234 + 235 + if (value < min || value > max) 236 + return -EINVAL; 237 + 238 + err = armoury_set_devstate(attr, value, NULL, wmi_dev); 239 + if (err) 240 + return err; 241 + 242 + if (store_value != NULL) 243 + *store_value = value; 244 + sysfs_notify(kobj, NULL, attr->attr.name); 245 + 246 + if (asus_bios_requires_reboot(attr)) 247 + asus_set_reboot_and_signal_event(); 248 + 249 + return count; 250 + } 251 + 252 + ssize_t armoury_attr_uint_show(struct kobject *kobj, struct kobj_attribute *attr, 253 + char *buf, u32 wmi_dev) 254 + { 255 + u32 result; 256 + int err; 257 + 258 + err = armoury_get_devstate(attr, &result, wmi_dev); 259 + if (err) 260 + return err; 261 + 262 + return sysfs_emit(buf, "%u\n", result); 263 + } 264 + 265 + static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, 266 + char *buf) 267 + { 268 + return sysfs_emit(buf, "enumeration\n"); 269 + } 270 + 271 + /* Mini-LED mode **************************************************************/ 272 + 273 + /* Values map for mini-led modes on 2023 and earlier models. */ 274 + static u32 mini_led_mode1_map[] = { 275 + [0] = ASUS_MINI_LED_OFF, 276 + [1] = ASUS_MINI_LED_ON, 277 + }; 278 + 279 + /* Values map for mini-led modes on 2024 and later models. */ 280 + static u32 mini_led_mode2_map[] = { 281 + [0] = ASUS_MINI_LED_2024_OFF, 282 + [1] = ASUS_MINI_LED_2024_WEAK, 283 + [2] = ASUS_MINI_LED_2024_STRONG, 284 + }; 285 + 286 + static ssize_t mini_led_mode_current_value_show(struct kobject *kobj, 287 + struct kobj_attribute *attr, char *buf) 288 + { 289 + u32 *mini_led_mode_map; 290 + size_t mini_led_mode_map_size; 291 + u32 i, mode; 292 + int err; 293 + 294 + switch (asus_armoury.mini_led_dev_id) { 295 + case ASUS_WMI_DEVID_MINI_LED_MODE: 296 + mini_led_mode_map = mini_led_mode1_map; 297 + mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode1_map); 298 + break; 299 + 300 + case ASUS_WMI_DEVID_MINI_LED_MODE2: 301 + mini_led_mode_map = mini_led_mode2_map; 302 + mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode2_map); 303 + break; 304 + 305 + default: 306 + pr_err("Unrecognized mini-LED device: %u\n", asus_armoury.mini_led_dev_id); 307 + return -ENODEV; 308 + } 309 + 310 + err = armoury_get_devstate(attr, &mode, asus_armoury.mini_led_dev_id); 311 + if (err) 312 + return err; 313 + 314 + mode = FIELD_GET(ASUS_MINI_LED_MODE_MASK, 0); 315 + 316 + for (i = 0; i < mini_led_mode_map_size; i++) 317 + return sysfs_emit(buf, "%u\n", mini_led_mode_map[i]); 318 + 319 + pr_warn("Unrecognized mini-LED mode: %u", mode); 320 + return -EINVAL; 321 + } 322 + 323 + static ssize_t mini_led_mode_current_value_store(struct kobject *kobj, 324 + struct kobj_attribute *attr, 325 + const char *buf, size_t count) 326 + { 327 + u32 *mini_led_mode_map; 328 + size_t mini_led_mode_map_size; 329 + u32 mode; 330 + int err; 331 + 332 + err = kstrtou32(buf, 10, &mode); 333 + if (err) 334 + return err; 335 + 336 + switch (asus_armoury.mini_led_dev_id) { 337 + case ASUS_WMI_DEVID_MINI_LED_MODE: 338 + mini_led_mode_map = mini_led_mode1_map; 339 + mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode1_map); 340 + break; 341 + 342 + case ASUS_WMI_DEVID_MINI_LED_MODE2: 343 + mini_led_mode_map = mini_led_mode2_map; 344 + mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode2_map); 345 + break; 346 + 347 + default: 348 + pr_err("Unrecognized mini-LED devid: %u\n", asus_armoury.mini_led_dev_id); 349 + return -EINVAL; 350 + } 351 + 352 + if (mode >= mini_led_mode_map_size) { 353 + return pr_warn("mini-LED mode unrecognized device: %u\n", mode); 354 + return -ENODEV; 355 + } 356 + 357 + return armoury_attr_uint_store(kobj, attr, buf, count, 358 + 0, mini_led_mode_map[mode], 359 + NULL, asus_armoury.mini_led_dev_id); 360 + } 361 + 362 + static ssize_t mini_led_mode_possible_values_show(struct kobject *kobj, 363 + struct kobj_attribute *attr, char *buf) 364 + { 365 + switch (asus_armoury.mini_led_dev_id) { 366 + case ASUS_WMI_DEVID_MINI_LED_MODE: 367 + return armoury_attr_enum_list(buf, ARRAY_SIZE(mini_led_mode1_map)); 368 + case ASUS_WMI_DEVID_MINI_LED_MODE2: 369 + return armoury_attr_enum_list(buf, ARRAY_SIZE(mini_led_mode2_map)); 370 + default: 371 + return -ENODEV; 372 + } 373 + } 374 + ASUS_ATTR_GROUP_ENUM(mini_led_mode, "mini_led_mode", "Set the mini-LED backlight mode"); 375 + 376 + static ssize_t gpu_mux_mode_current_value_store(struct kobject *kobj, 377 + struct kobj_attribute *attr, 378 + const char *buf, size_t count) 379 + { 380 + int result, err; 381 + bool optimus; 382 + 383 + err = kstrtobool(buf, &optimus); 384 + if (err) 385 + return err; 386 + 387 + if (armoury_has_devstate(ASUS_WMI_DEVID_DGPU)) { 388 + err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_DGPU); 389 + if (err) 390 + return err; 391 + if (result && !optimus) { 392 + pr_warn("Cannot switch MUX to dGPU mode when dGPU is disabled: %02X\n", 393 + result); 394 + return -ENODEV; 395 + } 396 + } 397 + 398 + if (armoury_has_devstate(ASUS_WMI_DEVID_EGPU)) { 399 + err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_EGPU); 400 + if (err) 401 + return err; 402 + if (result && !optimus) { 403 + pr_warn("Cannot switch MUX to dGPU mode when eGPU is enabled\n"); 404 + return -EBUSY; 405 + } 406 + } 407 + 408 + err = armoury_set_devstate(attr, optimus ? 1 : 0, NULL, asus_armoury.gpu_mux_dev_id); 409 + if (err) 410 + return err; 411 + 412 + sysfs_notify(kobj, NULL, attr->attr.name); 413 + asus_set_reboot_and_signal_event(); 414 + 415 + return count; 416 + } 417 + ASUS_WMI_SHOW_INT(gpu_mux_mode_current_value, asus_armoury.gpu_mux_dev_id); 418 + ASUS_ATTR_GROUP_BOOL(gpu_mux_mode, "gpu_mux_mode", "Set the GPU display MUX mode"); 419 + 420 + static ssize_t dgpu_disable_current_value_store(struct kobject *kobj, 421 + struct kobj_attribute *attr, const char *buf, 422 + size_t count) 423 + { 424 + int result, err; 425 + bool disable; 426 + 427 + err = kstrtobool(buf, &disable); 428 + if (err) 429 + return err; 430 + 431 + if (asus_armoury.gpu_mux_dev_id) { 432 + err = armoury_get_devstate(NULL, &result, asus_armoury.gpu_mux_dev_id); 433 + if (err) 434 + return err; 435 + if (!result && disable) { 436 + pr_warn("Cannot disable dGPU when the MUX is in dGPU mode\n"); 437 + return -EBUSY; 438 + } 439 + } 440 + 441 + scoped_guard(mutex, &asus_armoury.egpu_mutex) { 442 + err = armoury_set_devstate(attr, disable ? 1 : 0, NULL, ASUS_WMI_DEVID_DGPU); 443 + if (err) 444 + return err; 445 + } 446 + 447 + sysfs_notify(kobj, NULL, attr->attr.name); 448 + 449 + return count; 450 + } 451 + ASUS_WMI_SHOW_INT(dgpu_disable_current_value, ASUS_WMI_DEVID_DGPU); 452 + ASUS_ATTR_GROUP_BOOL(dgpu_disable, "dgpu_disable", "Disable the dGPU"); 453 + 454 + /* Values map for eGPU activation requests. */ 455 + static u32 egpu_status_map[] = { 456 + [0] = 0x00000000U, 457 + [1] = 0x00000001U, 458 + [2] = 0x00000101U, 459 + [3] = 0x00000201U, 460 + }; 461 + 462 + /* 463 + * armoury_pci_rescan() - Performs a PCI rescan 464 + * 465 + * Bring up any GPU that has been hotplugged in the system. 466 + */ 467 + static void armoury_pci_rescan(void) 468 + { 469 + struct pci_bus *b = NULL; 470 + 471 + pci_lock_rescan_remove(); 472 + while ((b = pci_find_next_bus(b)) != NULL) 473 + pci_rescan_bus(b); 474 + pci_unlock_rescan_remove(); 475 + } 476 + 477 + /* 478 + * The ACPI call to enable the eGPU might also disable the internal dGPU, 479 + * but this is not always the case and on certain models enabling the eGPU 480 + * when the dGPU is either still active or has been disabled without rebooting 481 + * will make both GPUs malfunction and the kernel will detect many 482 + * PCI AER unrecoverable errors. 483 + */ 484 + static ssize_t egpu_enable_current_value_store(struct kobject *kobj, struct kobj_attribute *attr, 485 + const char *buf, size_t count) 486 + { 487 + int err; 488 + u32 requested, enable, result; 489 + 490 + err = kstrtou32(buf, 10, &requested); 491 + if (err) 492 + return err; 493 + 494 + if (requested >= ARRAY_SIZE(egpu_status_map)) 495 + return -EINVAL; 496 + enable = egpu_status_map[requested]; 497 + 498 + scoped_guard(mutex, &asus_armoury.egpu_mutex) { 499 + /* Ensure the eGPU is connected before attempting to activate it. */ 500 + if (enable) { 501 + err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_EGPU_CONNECTED); 502 + if (err) { 503 + pr_warn("Failed to get eGPU connection status: %d\n", err); 504 + return err; 505 + } 506 + if (!result) { 507 + pr_warn("Cannot activate eGPU while undetected\n"); 508 + return -ENOENT; 509 + } 510 + } 511 + 512 + if (asus_armoury.gpu_mux_dev_id) { 513 + err = armoury_get_devstate(NULL, &result, asus_armoury.gpu_mux_dev_id); 514 + if (err) 515 + return err; 516 + 517 + if (!result && enable) { 518 + pr_warn("Cannot enable eGPU when the MUX is in dGPU mode\n"); 519 + return -ENODEV; 520 + } 521 + } 522 + 523 + err = armoury_set_devstate(attr, enable, &result, ASUS_WMI_DEVID_EGPU); 524 + if (err) { 525 + pr_err("Failed to set %s: %d\n", attr->attr.name, err); 526 + return err; 527 + } 528 + 529 + /* 530 + * ACPI returns value 0x01 on success and 0x02 on a partial activation: 531 + * performing a pci rescan will bring up the device in pci-e 3.0 speed, 532 + * after a reboot the device will work at full speed. 533 + */ 534 + switch (result) { 535 + case 0x01: 536 + /* 537 + * When a GPU is in use it does not get disconnected even if 538 + * the ACPI call returns a success. 539 + */ 540 + if (!enable) { 541 + err = armoury_get_devstate(attr, &result, ASUS_WMI_DEVID_EGPU); 542 + if (err) { 543 + pr_warn("Failed to ensure eGPU is deactivated: %d\n", err); 544 + return err; 545 + } 546 + 547 + if (result != 0) 548 + return -EBUSY; 549 + } 550 + 551 + pr_debug("Success changing the eGPU status\n"); 552 + break; 553 + case 0x02: 554 + pr_info("Success changing the eGPU status, a reboot is strongly advised\n"); 555 + asus_set_reboot_and_signal_event(); 556 + break; 557 + default: 558 + pr_err("Failed to change the eGPU status: wmi result is 0x%x\n", result); 559 + return -EIO; 560 + } 561 + } 562 + 563 + /* 564 + * Perform a PCI rescan: on every tested model this is necessary 565 + * to make the eGPU visible on the bus without rebooting. 566 + */ 567 + armoury_pci_rescan(); 568 + 569 + sysfs_notify(kobj, NULL, attr->attr.name); 570 + 571 + return count; 572 + } 573 + 574 + static ssize_t egpu_enable_current_value_show(struct kobject *kobj, struct kobj_attribute *attr, 575 + char *buf) 576 + { 577 + int i, err; 578 + u32 status; 579 + 580 + scoped_guard(mutex, &asus_armoury.egpu_mutex) { 581 + err = armoury_get_devstate(attr, &status, ASUS_WMI_DEVID_EGPU); 582 + if (err) 583 + return err; 584 + } 585 + 586 + for (i = 0; i < ARRAY_SIZE(egpu_status_map); i++) { 587 + if (egpu_status_map[i] == status) 588 + return sysfs_emit(buf, "%u\n", i); 589 + } 590 + 591 + return -EIO; 592 + } 593 + 594 + static ssize_t egpu_enable_possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, 595 + char *buf) 596 + { 597 + return armoury_attr_enum_list(buf, ARRAY_SIZE(egpu_status_map)); 598 + } 599 + ASUS_ATTR_GROUP_ENUM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); 600 + 601 + /* Simple attribute creation */ 602 + ASUS_ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, "0;1;2\n", 603 + "Show the current mode of charging"); 604 + ASUS_ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, 605 + "Set the boot POST sound"); 606 + ASUS_ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, 607 + "Set MCU powersaving mode"); 608 + ASUS_ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, 609 + "Set the panel refresh overdrive"); 610 + ASUS_ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, 611 + "Show the eGPU connection status"); 612 + 613 + /* If an attribute does not require any special case handling add it here */ 614 + static const struct asus_attr_group armoury_attr_groups[] = { 615 + { &egpu_connected_attr_group, ASUS_WMI_DEVID_EGPU_CONNECTED }, 616 + { &egpu_enable_attr_group, ASUS_WMI_DEVID_EGPU }, 617 + { &dgpu_disable_attr_group, ASUS_WMI_DEVID_DGPU }, 618 + 619 + { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, 620 + { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, 621 + { &mcu_powersave_attr_group, ASUS_WMI_DEVID_MCU_POWERSAVE }, 622 + { &panel_od_attr_group, ASUS_WMI_DEVID_PANEL_OD }, 623 + }; 624 + 625 + static int asus_fw_attr_add(void) 626 + { 627 + int err, i; 628 + 629 + asus_armoury.fw_attr_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 630 + NULL, "%s", DRIVER_NAME); 631 + if (IS_ERR(asus_armoury.fw_attr_dev)) { 632 + err = PTR_ERR(asus_armoury.fw_attr_dev); 633 + goto fail_class_get; 634 + } 635 + 636 + asus_armoury.fw_attr_kset = kset_create_and_add("attributes", NULL, 637 + &asus_armoury.fw_attr_dev->kobj); 638 + if (!asus_armoury.fw_attr_kset) { 639 + err = -ENOMEM; 640 + goto err_destroy_classdev; 641 + } 642 + 643 + err = sysfs_create_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 644 + if (err) { 645 + pr_err("Failed to create sysfs level attributes\n"); 646 + goto err_destroy_kset; 647 + } 648 + 649 + asus_armoury.mini_led_dev_id = 0; 650 + if (armoury_has_devstate(ASUS_WMI_DEVID_MINI_LED_MODE)) 651 + asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; 652 + else if (armoury_has_devstate(ASUS_WMI_DEVID_MINI_LED_MODE2)) 653 + asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; 654 + 655 + if (asus_armoury.mini_led_dev_id) { 656 + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 657 + &mini_led_mode_attr_group); 658 + if (err) { 659 + pr_err("Failed to create sysfs-group for mini_led\n"); 660 + goto err_remove_file; 661 + } 662 + } 663 + 664 + asus_armoury.gpu_mux_dev_id = 0; 665 + if (armoury_has_devstate(ASUS_WMI_DEVID_GPU_MUX)) 666 + asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX; 667 + else if (armoury_has_devstate(ASUS_WMI_DEVID_GPU_MUX_VIVO)) 668 + asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO; 669 + 670 + if (asus_armoury.gpu_mux_dev_id) { 671 + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 672 + &gpu_mux_mode_attr_group); 673 + if (err) { 674 + pr_err("Failed to create sysfs-group for gpu_mux\n"); 675 + goto err_remove_mini_led_group; 676 + } 677 + } 678 + 679 + for (i = 0; i < ARRAY_SIZE(armoury_attr_groups); i++) { 680 + if (!armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 681 + continue; 682 + 683 + err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 684 + armoury_attr_groups[i].attr_group); 685 + if (err) { 686 + pr_err("Failed to create sysfs-group for %s\n", 687 + armoury_attr_groups[i].attr_group->name); 688 + goto err_remove_groups; 689 + } 690 + } 691 + 692 + return 0; 693 + 694 + err_remove_groups: 695 + while (i--) { 696 + if (armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 697 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, 698 + armoury_attr_groups[i].attr_group); 699 + } 700 + if (asus_armoury.gpu_mux_dev_id) 701 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); 702 + err_remove_mini_led_group: 703 + if (asus_armoury.mini_led_dev_id) 704 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group); 705 + err_remove_file: 706 + sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 707 + err_destroy_kset: 708 + kset_unregister(asus_armoury.fw_attr_kset); 709 + err_destroy_classdev: 710 + fail_class_get: 711 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 712 + return err; 713 + } 714 + 715 + /* Init / exit ****************************************************************/ 716 + 717 + static int __init asus_fw_init(void) 718 + { 719 + char *wmi_uid; 720 + 721 + wmi_uid = wmi_get_acpi_device_uid(ASUS_WMI_MGMT_GUID); 722 + if (!wmi_uid) 723 + return -ENODEV; 724 + 725 + /* 726 + * if equal to "ASUSWMI" then it's DCTS that can't be used for this 727 + * driver, DSTS is required. 728 + */ 729 + if (!strcmp(wmi_uid, ASUS_ACPI_UID_ASUSWMI)) 730 + return -ENODEV; 731 + 732 + return asus_fw_attr_add(); 733 + } 734 + 735 + static void __exit asus_fw_exit(void) 736 + { 737 + int i; 738 + 739 + for (i = ARRAY_SIZE(armoury_attr_groups) - 1; i >= 0; i--) { 740 + if (armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 741 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, 742 + armoury_attr_groups[i].attr_group); 743 + } 744 + 745 + if (asus_armoury.gpu_mux_dev_id) 746 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); 747 + 748 + if (asus_armoury.mini_led_dev_id) 749 + sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group); 750 + 751 + sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 752 + kset_unregister(asus_armoury.fw_attr_kset); 753 + device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 754 + } 755 + 756 + module_init(asus_fw_init); 757 + module_exit(asus_fw_exit); 758 + 759 + MODULE_IMPORT_NS("ASUS_WMI"); 760 + MODULE_AUTHOR("Luke Jones <luke@ljones.dev>"); 761 + MODULE_DESCRIPTION("ASUS BIOS Configuration Driver"); 762 + MODULE_LICENSE("GPL"); 763 + MODULE_ALIAS("wmi:" ASUS_NB_WMI_EVENT_GUID);
+200
drivers/platform/x86/asus-armoury.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * 3 + * Definitions for kernel modules using asus-armoury driver 4 + * 5 + * Copyright (c) 2024 Luke Jones <luke@ljones.dev> 6 + */ 7 + 8 + #ifndef _ASUS_ARMOURY_H_ 9 + #define _ASUS_ARMOURY_H_ 10 + 11 + #include <linux/platform_device.h> 12 + #include <linux/sysfs.h> 13 + #include <linux/types.h> 14 + 15 + #define DRIVER_NAME "asus-armoury" 16 + 17 + /** 18 + * armoury_attr_uint_store() - Send an uint to WMI method if within min/max. 19 + * @kobj: Pointer to the driver object. 20 + * @attr: Pointer to the attribute calling this function. 21 + * @buf: The buffer to read from, this is parsed to `uint` type. 22 + * @count: Required by sysfs attribute macros, pass in from the callee attr. 23 + * @min: Minimum accepted value. Below this returns -EINVAL. 24 + * @max: Maximum accepted value. Above this returns -EINVAL. 25 + * @store_value: Pointer to where the parsed value should be stored. 26 + * @wmi_dev: The WMI function ID to use. 27 + * 28 + * This function is intended to be generic so it can be called from any "_store" 29 + * attribute which works only with integers. 30 + * 31 + * Integers to be sent to the WMI method is inclusive range checked and 32 + * an error returned if out of range. 33 + * 34 + * If the value is valid and WMI is success then the sysfs attribute is notified 35 + * and if asus_bios_requires_reboot() is true then reboot attribute 36 + * is also notified. 37 + * 38 + * Returns: Either count, or an error. 39 + */ 40 + ssize_t armoury_attr_uint_store(struct kobject *kobj, struct kobj_attribute *attr, 41 + const char *buf, size_t count, u32 min, u32 max, 42 + u32 *store_value, u32 wmi_dev); 43 + 44 + /** 45 + * armoury_attr_uint_show() - Receive an uint from a WMI method. 46 + * @kobj: Pointer to the driver object. 47 + * @attr: Pointer to the attribute calling this function. 48 + * @buf: The buffer to write to, as an `uint` type. 49 + * @wmi_dev: The WMI function ID to use. 50 + * 51 + * This function is intended to be generic so it can be called from any "_show" 52 + * attribute which works only with integers. 53 + * 54 + * Returns: Either count, or an error. 55 + */ 56 + ssize_t armoury_attr_uint_show(struct kobject *kobj, struct kobj_attribute *attr, 57 + char *buf, u32 wmi_dev); 58 + 59 + #define __ASUS_ATTR_RO(_func, _name) \ 60 + { \ 61 + .attr = { .name = __stringify(_name), .mode = 0444 }, \ 62 + .show = _func##_##_name##_show, \ 63 + } 64 + 65 + #define __ASUS_ATTR_RO_AS(_name, _show) \ 66 + { \ 67 + .attr = { .name = __stringify(_name), .mode = 0444 }, \ 68 + .show = _show, \ 69 + } 70 + 71 + #define __ASUS_ATTR_RW(_func, _name) \ 72 + __ATTR(_name, 0644, _func##_##_name##_show, _func##_##_name##_store) 73 + 74 + #define __WMI_STORE_INT(_attr, _min, _max, _wmi) \ 75 + static ssize_t _attr##_store(struct kobject *kobj, \ 76 + struct kobj_attribute *attr, \ 77 + const char *buf, size_t count) \ 78 + { \ 79 + return armoury_attr_uint_store(kobj, attr, buf, count, _min, \ 80 + _max, NULL, _wmi); \ 81 + } 82 + 83 + #define ASUS_WMI_SHOW_INT(_attr, _wmi) \ 84 + static ssize_t _attr##_show(struct kobject *kobj, \ 85 + struct kobj_attribute *attr, char *buf) \ 86 + { \ 87 + return armoury_attr_uint_show(kobj, attr, buf, _wmi); \ 88 + } 89 + 90 + /* Create functions and attributes for use in other macros or on their own */ 91 + 92 + /* Shows a formatted static variable */ 93 + #define __ATTR_SHOW_FMT(_prop, _attrname, _fmt, _val) \ 94 + static ssize_t _attrname##_##_prop##_show( \ 95 + struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ 96 + { \ 97 + return sysfs_emit(buf, _fmt, _val); \ 98 + } \ 99 + static struct kobj_attribute attr_##_attrname##_##_prop = \ 100 + __ASUS_ATTR_RO(_attrname, _prop) 101 + 102 + #define __ATTR_RO_INT_GROUP_ENUM(_attrname, _wmi, _fsname, _possible, _dispname)\ 103 + ASUS_WMI_SHOW_INT(_attrname##_current_value, _wmi); \ 104 + static struct kobj_attribute attr_##_attrname##_current_value = \ 105 + __ASUS_ATTR_RO(_attrname, current_value); \ 106 + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ 107 + __ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \ 108 + static struct kobj_attribute attr_##_attrname##_type = \ 109 + __ASUS_ATTR_RO_AS(type, enum_type_show); \ 110 + static struct attribute *_attrname##_attrs[] = { \ 111 + &attr_##_attrname##_current_value.attr, \ 112 + &attr_##_attrname##_display_name.attr, \ 113 + &attr_##_attrname##_possible_values.attr, \ 114 + &attr_##_attrname##_type.attr, \ 115 + NULL \ 116 + }; \ 117 + static const struct attribute_group _attrname##_attr_group = { \ 118 + .name = _fsname, .attrs = _attrname##_attrs \ 119 + } 120 + 121 + #define __ATTR_RW_INT_GROUP_ENUM(_attrname, _minv, _maxv, _wmi, _fsname,\ 122 + _possible, _dispname) \ 123 + __WMI_STORE_INT(_attrname##_current_value, _minv, _maxv, _wmi); \ 124 + ASUS_WMI_SHOW_INT(_attrname##_current_value, _wmi); \ 125 + static struct kobj_attribute attr_##_attrname##_current_value = \ 126 + __ASUS_ATTR_RW(_attrname, current_value); \ 127 + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ 128 + __ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \ 129 + static struct kobj_attribute attr_##_attrname##_type = \ 130 + __ASUS_ATTR_RO_AS(type, enum_type_show); \ 131 + static struct attribute *_attrname##_attrs[] = { \ 132 + &attr_##_attrname##_current_value.attr, \ 133 + &attr_##_attrname##_display_name.attr, \ 134 + &attr_##_attrname##_possible_values.attr, \ 135 + &attr_##_attrname##_type.attr, \ 136 + NULL \ 137 + }; \ 138 + static const struct attribute_group _attrname##_attr_group = { \ 139 + .name = _fsname, .attrs = _attrname##_attrs \ 140 + } 141 + 142 + /* Boolean style enumeration, base macro. Requires adding show/store */ 143 + #define __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) \ 144 + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ 145 + __ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \ 146 + static struct kobj_attribute attr_##_attrname##_type = \ 147 + __ASUS_ATTR_RO_AS(type, enum_type_show); \ 148 + static struct attribute *_attrname##_attrs[] = { \ 149 + &attr_##_attrname##_current_value.attr, \ 150 + &attr_##_attrname##_display_name.attr, \ 151 + &attr_##_attrname##_possible_values.attr, \ 152 + &attr_##_attrname##_type.attr, \ 153 + NULL \ 154 + }; \ 155 + static const struct attribute_group _attrname##_attr_group = { \ 156 + .name = _fsname, .attrs = _attrname##_attrs \ 157 + } 158 + 159 + #define ASUS_ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \ 160 + __ATTR_RO_INT_GROUP_ENUM(_attrname, _wmi, _fsname, "0;1", _dispname) 161 + 162 + 163 + #define ASUS_ATTR_GROUP_BOOL_RW(_attrname, _fsname, _wmi, _dispname) \ 164 + __ATTR_RW_INT_GROUP_ENUM(_attrname, 0, 1, _wmi, _fsname, "0;1", _dispname) 165 + 166 + #define ASUS_ATTR_GROUP_ENUM_INT_RO(_attrname, _fsname, _wmi, _possible, _dispname) \ 167 + __ATTR_RO_INT_GROUP_ENUM(_attrname, _wmi, _fsname, _possible, _dispname) 168 + 169 + /* 170 + * Requires <name>_current_value_show(), <name>_current_value_show() 171 + */ 172 + #define ASUS_ATTR_GROUP_BOOL(_attrname, _fsname, _dispname) \ 173 + static struct kobj_attribute attr_##_attrname##_current_value = \ 174 + __ASUS_ATTR_RW(_attrname, current_value); \ 175 + __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname) 176 + 177 + /* 178 + * Requires <name>_current_value_show(), <name>_current_value_show() 179 + * and <name>_possible_values_show() 180 + */ 181 + #define ASUS_ATTR_GROUP_ENUM(_attrname, _fsname, _dispname) \ 182 + __ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ 183 + static struct kobj_attribute attr_##_attrname##_current_value = \ 184 + __ASUS_ATTR_RW(_attrname, current_value); \ 185 + static struct kobj_attribute attr_##_attrname##_possible_values = \ 186 + __ASUS_ATTR_RO(_attrname, possible_values); \ 187 + static struct kobj_attribute attr_##_attrname##_type = \ 188 + __ASUS_ATTR_RO_AS(type, enum_type_show); \ 189 + static struct attribute *_attrname##_attrs[] = { \ 190 + &attr_##_attrname##_current_value.attr, \ 191 + &attr_##_attrname##_display_name.attr, \ 192 + &attr_##_attrname##_possible_values.attr, \ 193 + &attr_##_attrname##_type.attr, \ 194 + NULL \ 195 + }; \ 196 + static const struct attribute_group _attrname##_attr_group = { \ 197 + .name = _fsname, .attrs = _attrname##_attrs \ 198 + } 199 + 200 + #endif /* _ASUS_ARMOURY_H_ */
+4 -6
drivers/platform/x86/asus-wmi.c
··· 15 15 16 16 #include <linux/acpi.h> 17 17 #include <linux/backlight.h> 18 + #include <linux/bits.h> 18 19 #include <linux/debugfs.h> 19 20 #include <linux/delay.h> 20 21 #include <linux/dmi.h> ··· 31 30 #include <linux/pci.h> 32 31 #include <linux/pci_hotplug.h> 33 32 #include <linux/platform_data/x86/asus-wmi.h> 33 + #include <linux/platform_data/x86/asus-wmi-leds-ids.h> 34 34 #include <linux/platform_device.h> 35 35 #include <linux/platform_profile.h> 36 36 #include <linux/power_supply.h> ··· 56 54 57 55 #define to_asus_wmi_driver(pdrv) \ 58 56 (container_of((pdrv), struct asus_wmi_driver, platform_driver)) 59 - 60 - #define ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66" 61 57 62 58 #define NOTIFY_BRNUP_MIN 0x11 63 59 #define NOTIFY_BRNUP_MAX 0x1f ··· 104 104 105 105 #define USB_INTEL_XUSB2PR 0xD0 106 106 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 107 - 108 - #define ASUS_ACPI_UID_ASUSWMI "ASUSWMI" 109 107 110 108 #define WMI_EVENT_MASK 0xFFFF 111 109 ··· 559 561 * 560 562 * Returns: 561 563 * * %-ENODEV - method ID is unsupported. 562 - * * %0 - successful and retval is filled. 563 - * * %other - error from WMI call. 564 + * * %0 - successful and retval is filled. 565 + * * %other - error from WMI call. 564 566 */ 565 567 int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval) 566 568 {
+50
include/linux/platform_data/x86/asus-wmi-leds-ids.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H 3 + #define __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H 4 + 5 + #include <linux/dmi.h> 6 + #include <linux/types.h> 7 + 8 + /* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */ 9 + #if IS_REACHABLE(CONFIG_ASUS_WMI) || IS_REACHABLE(CONFIG_HID_ASUS) 10 + static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { 11 + { 12 + .matches = { 13 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"), 14 + }, 15 + }, 16 + { 17 + .matches = { 18 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"), 19 + }, 20 + }, 21 + { 22 + .matches = { 23 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), 24 + }, 25 + }, 26 + { 27 + .matches = { 28 + DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt P16"), 29 + }, 30 + }, 31 + { 32 + .matches = { 33 + DMI_MATCH(DMI_BOARD_NAME, "GA403U"), 34 + }, 35 + }, 36 + { 37 + .matches = { 38 + DMI_MATCH(DMI_BOARD_NAME, "GU605M"), 39 + }, 40 + }, 41 + { 42 + .matches = { 43 + DMI_MATCH(DMI_BOARD_NAME, "RC71L"), 44 + }, 45 + }, 46 + { }, 47 + }; 48 + #endif 49 + 50 + #endif /* __PLATFORM_DATA_X86_ASUS_WMI_LEDS_IDS_H */
+3 -41
include/linux/platform_data/x86/asus-wmi.h
··· 4 4 5 5 #include <linux/errno.h> 6 6 #include <linux/types.h> 7 - #include <linux/dmi.h> 7 + 8 + #define ASUS_WMI_MGMT_GUID "97845ED0-4E6D-11DE-8A39-0800200C9A66" 9 + #define ASUS_ACPI_UID_ASUSWMI "ASUSWMI" 8 10 9 11 /* WMI Methods */ 10 12 #define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ ··· 192 190 return -ENODEV; 193 191 } 194 192 #endif 195 - 196 - /* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */ 197 - static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { 198 - { 199 - .matches = { 200 - DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"), 201 - }, 202 - }, 203 - { 204 - .matches = { 205 - DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"), 206 - }, 207 - }, 208 - { 209 - .matches = { 210 - DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), 211 - }, 212 - }, 213 - { 214 - .matches = { 215 - DMI_MATCH(DMI_PRODUCT_FAMILY, "ProArt P16"), 216 - }, 217 - }, 218 - { 219 - .matches = { 220 - DMI_MATCH(DMI_BOARD_NAME, "GA403U"), 221 - }, 222 - }, 223 - { 224 - .matches = { 225 - DMI_MATCH(DMI_BOARD_NAME, "GU605M"), 226 - }, 227 - }, 228 - { 229 - .matches = { 230 - DMI_MATCH(DMI_BOARD_NAME, "RC71L"), 231 - }, 232 - }, 233 - { }, 234 - }; 235 193 236 194 #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */