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/cleanup.h> 20 #include <linux/device.h> 21 #include <linux/dmi.h> 22 #include <linux/err.h> 23 #include <linux/errno.h> 24 #include <linux/fs.h> 25 #include <linux/kernel.h> 26 #include <linux/kmod.h> 27 #include <linux/kobject.h> 28 #include <linux/kstrtox.h> 29 #include <linux/module.h> 30 #include <linux/mutex.h> 31 #include <linux/pci.h> 32 #include <linux/platform_data/x86/asus-wmi.h> 33 #include <linux/printk.h> 34 #include <linux/power_supply.h> 35 #include <linux/sysfs.h> 36 37 #include "asus-armoury.h" 38 #include "firmware_attributes_class.h" 39 40 #define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" 41 42 #define ASUS_MINI_LED_MODE_MASK GENMASK(1, 0) 43 /* Standard modes for devices with only on/off */ 44 #define ASUS_MINI_LED_OFF 0x00 45 #define ASUS_MINI_LED_ON 0x01 46 /* Like "on" but the effect is more vibrant or brighter */ 47 #define ASUS_MINI_LED_STRONG_MODE 0x02 48 /* New modes for devices with 3 mini-led mode types */ 49 #define ASUS_MINI_LED_2024_WEAK 0x00 50 #define ASUS_MINI_LED_2024_STRONG 0x01 51 #define ASUS_MINI_LED_2024_OFF 0x02 52 53 /* Power tunable attribute name defines */ 54 #define ATTR_PPT_PL1_SPL "ppt_pl1_spl" 55 #define ATTR_PPT_PL2_SPPT "ppt_pl2_sppt" 56 #define ATTR_PPT_PL3_FPPT "ppt_pl3_fppt" 57 #define ATTR_PPT_APU_SPPT "ppt_apu_sppt" 58 #define ATTR_PPT_PLATFORM_SPPT "ppt_platform_sppt" 59 #define ATTR_NV_DYNAMIC_BOOST "nv_dynamic_boost" 60 #define ATTR_NV_TEMP_TARGET "nv_temp_target" 61 #define ATTR_NV_BASE_TGP "nv_base_tgp" 62 #define ATTR_NV_TGP "nv_tgp" 63 64 #define ASUS_ROG_TUNABLE_DC 0 65 #define ASUS_ROG_TUNABLE_AC 1 66 67 struct rog_tunables { 68 const struct power_limits *power_limits; 69 u32 ppt_pl1_spl; // cpu 70 u32 ppt_pl2_sppt; // cpu 71 u32 ppt_pl3_fppt; // cpu 72 u32 ppt_apu_sppt; // plat 73 u32 ppt_platform_sppt; // plat 74 75 u32 nv_dynamic_boost; 76 u32 nv_temp_target; 77 u32 nv_tgp; 78 }; 79 80 struct asus_armoury_priv { 81 struct device *fw_attr_dev; 82 struct kset *fw_attr_kset; 83 84 /* 85 * Mutex to protect eGPU activation/deactivation 86 * sequences and dGPU connection status: 87 * do not allow concurrent changes or changes 88 * before a reboot if dGPU got disabled. 89 */ 90 struct mutex egpu_mutex; 91 92 /* Index 0 for DC, 1 for AC */ 93 struct rog_tunables *rog_tunables[2]; 94 95 u32 mini_led_dev_id; 96 u32 gpu_mux_dev_id; 97 98 bool requires_fan_curve; 99 }; 100 101 static struct asus_armoury_priv asus_armoury = { 102 .egpu_mutex = __MUTEX_INITIALIZER(asus_armoury.egpu_mutex), 103 }; 104 105 struct fw_attrs_group { 106 bool pending_reboot; 107 }; 108 109 static struct fw_attrs_group fw_attrs = { 110 .pending_reboot = false, 111 }; 112 113 struct asus_attr_group { 114 const struct attribute_group *attr_group; 115 u32 wmi_devid; 116 }; 117 118 static void asus_set_reboot_and_signal_event(void) 119 { 120 fw_attrs.pending_reboot = true; 121 kobject_uevent(&asus_armoury.fw_attr_dev->kobj, KOBJ_CHANGE); 122 } 123 124 static ssize_t pending_reboot_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) 125 { 126 return sysfs_emit(buf, "%d\n", fw_attrs.pending_reboot); 127 } 128 129 static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); 130 131 static bool asus_bios_requires_reboot(struct kobj_attribute *attr) 132 { 133 return !strcmp(attr->attr.name, "gpu_mux_mode") || 134 !strcmp(attr->attr.name, "panel_hd_mode"); 135 } 136 137 /** 138 * armoury_has_devstate() - Check presence of the WMI function state. 139 * 140 * @dev_id: The WMI method ID to check for presence. 141 * 142 * Returns: true iif method is supported. 143 */ 144 static bool armoury_has_devstate(u32 dev_id) 145 { 146 u32 retval; 147 int status; 148 149 status = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 0, &retval); 150 pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); 151 152 return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); 153 } 154 155 /** 156 * armoury_get_devstate() - Get the WMI function state. 157 * @attr: NULL or the kobj_attribute associated to called WMI function. 158 * @dev_id: The WMI method ID to call. 159 * @retval: 160 * * non-NULL pointer to where to store the value returned from WMI 161 * * with the function presence bit cleared. 162 * 163 * Intended usage is from sysfs attribute checking associated WMI function. 164 * 165 * Returns: 166 * * %-ENODEV - method ID is unsupported. 167 * * %0 - successful and retval is filled. 168 * * %other - error from WMI call. 169 */ 170 static int armoury_get_devstate(struct kobj_attribute *attr, u32 *retval, u32 dev_id) 171 { 172 int err; 173 174 err = asus_wmi_get_devstate_dsts(dev_id, retval); 175 if (err) { 176 if (attr) 177 pr_err("Failed to get %s: %d\n", attr->attr.name, err); 178 else 179 pr_err("Failed to get devstate for 0x%x: %d\n", dev_id, err); 180 181 return err; 182 } 183 184 /* 185 * asus_wmi_get_devstate_dsts will populate retval with WMI return, but 186 * the true value is expressed when ASUS_WMI_DSTS_PRESENCE_BIT is clear. 187 */ 188 *retval &= ~ASUS_WMI_DSTS_PRESENCE_BIT; 189 190 return 0; 191 } 192 193 /** 194 * armoury_set_devstate() - Set the WMI function state. 195 * @attr: The kobj_attribute associated to called WMI function. 196 * @dev_id: The WMI method ID to call. 197 * @value: The new value to be set. 198 * @retval: Where to store the value returned from WMI or NULL. 199 * 200 * Intended usage is from sysfs attribute setting associated WMI function. 201 * Before calling the presence of the function should be checked. 202 * 203 * Every WMI write MUST go through this function to enforce safety checks. 204 * 205 * Results !1 is usually considered a fail by ASUS, but some WMI methods 206 * (like eGPU or CPU cores) do use > 1 to return a status code or similar: 207 * in these cases caller is interested in the actual return value 208 * and should perform relevant checks. 209 * 210 * Returns: 211 * * %-EINVAL - attempt to set a dangerous or unsupported value. 212 * * %-EIO - WMI function returned an error. 213 * * %0 - successful and retval is filled. 214 * * %other - error from WMI call. 215 */ 216 static int armoury_set_devstate(struct kobj_attribute *attr, 217 u32 value, u32 *retval, u32 dev_id) 218 { 219 u32 result; 220 int err; 221 222 /* On some models, PPT changes require an active fan curve */ 223 if (asus_armoury.requires_fan_curve) { 224 switch (dev_id) { 225 case ASUS_WMI_DEVID_PPT_PL1_SPL: 226 case ASUS_WMI_DEVID_PPT_PL2_SPPT: 227 case ASUS_WMI_DEVID_PPT_PL3_FPPT: 228 case ASUS_WMI_DEVID_PPT_APU_SPPT: 229 case ASUS_WMI_DEVID_PPT_PLAT_SPPT: 230 if (!asus_wmi_custom_fan_curve_is_enabled()) { 231 pr_warn_once("PPT change requires an active fan curve on this model. Enable a custom fan curve first.\n"); 232 return -EBUSY; 233 } 234 break; 235 } 236 } 237 238 /* 239 * Prevent developers from bricking devices or issuing dangerous 240 * commands that can be difficult or impossible to recover from. 241 */ 242 switch (dev_id) { 243 case ASUS_WMI_DEVID_APU_MEM: 244 /* 245 * A hard reset might suffice to save the device, 246 * but there is no value in sending these commands. 247 */ 248 if (value == 0x100 || value == 0x101) { 249 pr_err("Refusing to set APU memory to unsafe value: 0x%x\n", value); 250 return -EINVAL; 251 } 252 break; 253 default: 254 /* No problems are known for this dev_id */ 255 break; 256 } 257 258 err = asus_wmi_set_devstate(dev_id, value, retval ? retval : &result); 259 if (err) { 260 if (attr) 261 pr_err("Failed to set %s: %d\n", attr->attr.name, err); 262 else 263 pr_err("Failed to set devstate for 0x%x: %d\n", dev_id, err); 264 265 return err; 266 } 267 268 /* 269 * If retval == NULL caller is uninterested in return value: 270 * perform the most common result check here. 271 */ 272 if ((retval == NULL) && (result == 0)) { 273 pr_err("Failed to set %s: (result): 0x%x\n", attr->attr.name, result); 274 return -EIO; 275 } 276 277 return 0; 278 } 279 280 static int armoury_attr_enum_list(char *buf, size_t enum_values) 281 { 282 size_t i; 283 int len = 0; 284 285 for (i = 0; i < enum_values; i++) { 286 if (i == 0) 287 len += sysfs_emit_at(buf, len, "%zu", i); 288 else 289 len += sysfs_emit_at(buf, len, ";%zu", i); 290 } 291 len += sysfs_emit_at(buf, len, "\n"); 292 293 return len; 294 } 295 296 ssize_t armoury_attr_uint_store(struct kobject *kobj, struct kobj_attribute *attr, 297 const char *buf, size_t count, u32 min, u32 max, 298 u32 *store_value, u32 wmi_dev) 299 { 300 u32 value; 301 int err; 302 303 err = kstrtou32(buf, 10, &value); 304 if (err) 305 return err; 306 307 if (value < min || value > max) 308 return -EINVAL; 309 310 err = armoury_set_devstate(attr, value, NULL, wmi_dev); 311 if (err) 312 return err; 313 314 if (store_value != NULL) 315 *store_value = value; 316 sysfs_notify(kobj, NULL, attr->attr.name); 317 318 if (asus_bios_requires_reboot(attr)) 319 asus_set_reboot_and_signal_event(); 320 321 return count; 322 } 323 324 ssize_t armoury_attr_uint_show(struct kobject *kobj, struct kobj_attribute *attr, 325 char *buf, u32 wmi_dev) 326 { 327 u32 result; 328 int err; 329 330 err = armoury_get_devstate(attr, &result, wmi_dev); 331 if (err) 332 return err; 333 334 return sysfs_emit(buf, "%u\n", result); 335 } 336 337 static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, 338 char *buf) 339 { 340 return sysfs_emit(buf, "enumeration\n"); 341 } 342 343 static ssize_t int_type_show(struct kobject *kobj, struct kobj_attribute *attr, 344 char *buf) 345 { 346 return sysfs_emit(buf, "integer\n"); 347 } 348 349 /* Mini-LED mode **************************************************************/ 350 351 /* Values map for mini-led modes on 2023 and earlier models. */ 352 static u32 mini_led_mode1_map[] = { 353 [0] = ASUS_MINI_LED_OFF, 354 [1] = ASUS_MINI_LED_ON, 355 }; 356 357 /* Values map for mini-led modes on 2024 and later models. */ 358 static u32 mini_led_mode2_map[] = { 359 [0] = ASUS_MINI_LED_2024_OFF, 360 [1] = ASUS_MINI_LED_2024_WEAK, 361 [2] = ASUS_MINI_LED_2024_STRONG, 362 }; 363 364 static ssize_t mini_led_mode_current_value_show(struct kobject *kobj, 365 struct kobj_attribute *attr, char *buf) 366 { 367 u32 *mini_led_mode_map; 368 size_t mini_led_mode_map_size; 369 u32 i, mode; 370 int err; 371 372 switch (asus_armoury.mini_led_dev_id) { 373 case ASUS_WMI_DEVID_MINI_LED_MODE: 374 mini_led_mode_map = mini_led_mode1_map; 375 mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode1_map); 376 break; 377 378 case ASUS_WMI_DEVID_MINI_LED_MODE2: 379 mini_led_mode_map = mini_led_mode2_map; 380 mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode2_map); 381 break; 382 383 default: 384 pr_err("Unrecognized mini-LED device: %u\n", asus_armoury.mini_led_dev_id); 385 return -ENODEV; 386 } 387 388 err = armoury_get_devstate(attr, &mode, asus_armoury.mini_led_dev_id); 389 if (err) 390 return err; 391 392 mode = FIELD_GET(ASUS_MINI_LED_MODE_MASK, mode); 393 394 for (i = 0; i < mini_led_mode_map_size; i++) 395 if (mode == mini_led_mode_map[i]) 396 return sysfs_emit(buf, "%u\n", i); 397 398 pr_warn("Unrecognized mini-LED mode: %u", mode); 399 return -EINVAL; 400 } 401 402 static ssize_t mini_led_mode_current_value_store(struct kobject *kobj, 403 struct kobj_attribute *attr, 404 const char *buf, size_t count) 405 { 406 u32 *mini_led_mode_map; 407 size_t mini_led_mode_map_size; 408 char mapped_value[12]; 409 u32 mode; 410 int err; 411 412 err = kstrtou32(buf, 10, &mode); 413 if (err) 414 return err; 415 416 switch (asus_armoury.mini_led_dev_id) { 417 case ASUS_WMI_DEVID_MINI_LED_MODE: 418 mini_led_mode_map = mini_led_mode1_map; 419 mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode1_map); 420 break; 421 422 case ASUS_WMI_DEVID_MINI_LED_MODE2: 423 mini_led_mode_map = mini_led_mode2_map; 424 mini_led_mode_map_size = ARRAY_SIZE(mini_led_mode2_map); 425 break; 426 427 default: 428 pr_err("Unrecognized mini-LED devid: %u\n", asus_armoury.mini_led_dev_id); 429 return -EINVAL; 430 } 431 432 if (mode >= mini_led_mode_map_size) { 433 pr_warn("mini-LED mode unrecognized device: %u\n", mode); 434 return -ENODEV; 435 } 436 437 /* 438 * armoury_attr_uint_store() parses and sends the value from the 439 * passed buffer; hand it the mapped firmware value so the device 440 * receives the translated mode instead of the raw index. 441 */ 442 snprintf(mapped_value, sizeof(mapped_value), "%u", mini_led_mode_map[mode]); 443 444 return armoury_attr_uint_store(kobj, attr, mapped_value, count, 0, 445 mini_led_mode_map[mode], NULL, 446 asus_armoury.mini_led_dev_id); 447 } 448 449 static ssize_t mini_led_mode_possible_values_show(struct kobject *kobj, 450 struct kobj_attribute *attr, char *buf) 451 { 452 switch (asus_armoury.mini_led_dev_id) { 453 case ASUS_WMI_DEVID_MINI_LED_MODE: 454 return armoury_attr_enum_list(buf, ARRAY_SIZE(mini_led_mode1_map)); 455 case ASUS_WMI_DEVID_MINI_LED_MODE2: 456 return armoury_attr_enum_list(buf, ARRAY_SIZE(mini_led_mode2_map)); 457 default: 458 return -ENODEV; 459 } 460 } 461 ASUS_ATTR_GROUP_ENUM(mini_led_mode, "mini_led_mode", "Set the mini-LED backlight mode"); 462 463 static ssize_t gpu_mux_mode_current_value_store(struct kobject *kobj, 464 struct kobj_attribute *attr, 465 const char *buf, size_t count) 466 { 467 int result, err; 468 bool optimus; 469 470 err = kstrtobool(buf, &optimus); 471 if (err) 472 return err; 473 474 if (armoury_has_devstate(ASUS_WMI_DEVID_DGPU)) { 475 err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_DGPU); 476 if (err) 477 return err; 478 if (result && !optimus) { 479 pr_warn("Cannot switch MUX to dGPU mode when dGPU is disabled: %02X\n", 480 result); 481 return -ENODEV; 482 } 483 } 484 485 if (armoury_has_devstate(ASUS_WMI_DEVID_EGPU)) { 486 err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_EGPU); 487 if (err) 488 return err; 489 if (result && !optimus) { 490 pr_warn("Cannot switch MUX to dGPU mode when eGPU is enabled\n"); 491 return -EBUSY; 492 } 493 } 494 495 err = armoury_set_devstate(attr, optimus ? 1 : 0, NULL, asus_armoury.gpu_mux_dev_id); 496 if (err) 497 return err; 498 499 sysfs_notify(kobj, NULL, attr->attr.name); 500 asus_set_reboot_and_signal_event(); 501 502 return count; 503 } 504 ASUS_WMI_SHOW_INT(gpu_mux_mode_current_value, asus_armoury.gpu_mux_dev_id); 505 ASUS_ATTR_GROUP_BOOL(gpu_mux_mode, "gpu_mux_mode", "Set the GPU display MUX mode"); 506 507 static ssize_t dgpu_disable_current_value_store(struct kobject *kobj, 508 struct kobj_attribute *attr, const char *buf, 509 size_t count) 510 { 511 int result, err; 512 bool disable; 513 514 err = kstrtobool(buf, &disable); 515 if (err) 516 return err; 517 518 if (asus_armoury.gpu_mux_dev_id) { 519 err = armoury_get_devstate(NULL, &result, asus_armoury.gpu_mux_dev_id); 520 if (err) 521 return err; 522 if (!result && disable) { 523 pr_warn("Cannot disable dGPU when the MUX is in dGPU mode\n"); 524 return -EBUSY; 525 } 526 } 527 528 scoped_guard(mutex, &asus_armoury.egpu_mutex) { 529 err = armoury_set_devstate(attr, disable ? 1 : 0, NULL, ASUS_WMI_DEVID_DGPU); 530 if (err) 531 return err; 532 } 533 534 sysfs_notify(kobj, NULL, attr->attr.name); 535 536 return count; 537 } 538 ASUS_WMI_SHOW_INT(dgpu_disable_current_value, ASUS_WMI_DEVID_DGPU); 539 ASUS_ATTR_GROUP_BOOL(dgpu_disable, "dgpu_disable", "Disable the dGPU"); 540 541 /* Values map for eGPU activation requests. */ 542 static u32 egpu_status_map[] = { 543 [0] = 0x00000000U, 544 [1] = 0x00000001U, 545 [2] = 0x00000101U, 546 [3] = 0x00000201U, 547 }; 548 549 /* 550 * armoury_pci_rescan() - Performs a PCI rescan 551 * 552 * Bring up any GPU that has been hotplugged in the system. 553 */ 554 static void armoury_pci_rescan(void) 555 { 556 struct pci_bus *b = NULL; 557 558 pci_lock_rescan_remove(); 559 while ((b = pci_find_next_bus(b)) != NULL) 560 pci_rescan_bus(b); 561 pci_unlock_rescan_remove(); 562 } 563 564 /* 565 * The ACPI call to enable the eGPU might also disable the internal dGPU, 566 * but this is not always the case and on certain models enabling the eGPU 567 * when the dGPU is either still active or has been disabled without rebooting 568 * will make both GPUs malfunction and the kernel will detect many 569 * PCI AER unrecoverable errors. 570 */ 571 static ssize_t egpu_enable_current_value_store(struct kobject *kobj, struct kobj_attribute *attr, 572 const char *buf, size_t count) 573 { 574 int err; 575 u32 requested, enable, result; 576 577 err = kstrtou32(buf, 10, &requested); 578 if (err) 579 return err; 580 581 if (requested >= ARRAY_SIZE(egpu_status_map)) 582 return -EINVAL; 583 enable = egpu_status_map[requested]; 584 585 scoped_guard(mutex, &asus_armoury.egpu_mutex) { 586 /* Ensure the eGPU is connected before attempting to activate it. */ 587 if (enable) { 588 err = armoury_get_devstate(NULL, &result, ASUS_WMI_DEVID_EGPU_CONNECTED); 589 if (err) { 590 pr_warn("Failed to get eGPU connection status: %d\n", err); 591 return err; 592 } 593 if (!result) { 594 pr_warn("Cannot activate eGPU while undetected\n"); 595 return -ENOENT; 596 } 597 } 598 599 if (asus_armoury.gpu_mux_dev_id) { 600 err = armoury_get_devstate(NULL, &result, asus_armoury.gpu_mux_dev_id); 601 if (err) 602 return err; 603 604 if (!result && enable) { 605 pr_warn("Cannot enable eGPU when the MUX is in dGPU mode\n"); 606 return -ENODEV; 607 } 608 } 609 610 err = armoury_set_devstate(attr, enable, &result, ASUS_WMI_DEVID_EGPU); 611 if (err) { 612 pr_err("Failed to set %s: %d\n", attr->attr.name, err); 613 return err; 614 } 615 616 /* 617 * ACPI returns value 0x01 on success and 0x02 on a partial activation: 618 * performing a pci rescan will bring up the device in pci-e 3.0 speed, 619 * after a reboot the device will work at full speed. 620 */ 621 switch (result) { 622 case 0x01: 623 /* 624 * When a GPU is in use it does not get disconnected even if 625 * the ACPI call returns a success. 626 */ 627 if (!enable) { 628 err = armoury_get_devstate(attr, &result, ASUS_WMI_DEVID_EGPU); 629 if (err) { 630 pr_warn("Failed to ensure eGPU is deactivated: %d\n", err); 631 return err; 632 } 633 634 if (result != 0) 635 return -EBUSY; 636 } 637 638 pr_debug("Success changing the eGPU status\n"); 639 break; 640 case 0x02: 641 pr_info("Success changing the eGPU status, a reboot is strongly advised\n"); 642 asus_set_reboot_and_signal_event(); 643 break; 644 default: 645 pr_err("Failed to change the eGPU status: wmi result is 0x%x\n", result); 646 return -EIO; 647 } 648 } 649 650 /* 651 * Perform a PCI rescan: on every tested model this is necessary 652 * to make the eGPU visible on the bus without rebooting. 653 */ 654 armoury_pci_rescan(); 655 656 sysfs_notify(kobj, NULL, attr->attr.name); 657 658 return count; 659 } 660 661 static ssize_t egpu_enable_current_value_show(struct kobject *kobj, struct kobj_attribute *attr, 662 char *buf) 663 { 664 int i, err; 665 u32 status; 666 667 scoped_guard(mutex, &asus_armoury.egpu_mutex) { 668 err = armoury_get_devstate(attr, &status, ASUS_WMI_DEVID_EGPU); 669 if (err) 670 return err; 671 } 672 673 for (i = 0; i < ARRAY_SIZE(egpu_status_map); i++) { 674 if (egpu_status_map[i] == status) 675 return sysfs_emit(buf, "%u\n", i); 676 } 677 678 return -EIO; 679 } 680 681 static ssize_t egpu_enable_possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, 682 char *buf) 683 { 684 return armoury_attr_enum_list(buf, ARRAY_SIZE(egpu_status_map)); 685 } 686 ASUS_ATTR_GROUP_ENUM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); 687 688 /* Device memory available to APU */ 689 690 /* 691 * Values map for APU reserved memory (index + 1 number of GB). 692 * Some looks out of order, but are actually correct. 693 */ 694 static u32 apu_mem_map[] = { 695 [0] = 0x000, /* called "AUTO" on the BIOS, is the minimum available */ 696 [1] = 0x102, 697 [2] = 0x103, 698 [3] = 0x104, 699 [4] = 0x105, 700 [5] = 0x107, 701 [6] = 0x108, 702 [7] = 0x109, 703 [8] = 0x106, 704 }; 705 706 static ssize_t apu_mem_current_value_show(struct kobject *kobj, struct kobj_attribute *attr, 707 char *buf) 708 { 709 int err; 710 u32 mem; 711 712 err = armoury_get_devstate(attr, &mem, ASUS_WMI_DEVID_APU_MEM); 713 if (err) 714 return err; 715 716 /* After 0x000 is set, a read will return 0x100 */ 717 if (mem == 0x100) 718 return sysfs_emit(buf, "0\n"); 719 720 for (unsigned int i = 0; i < ARRAY_SIZE(apu_mem_map); i++) { 721 if (apu_mem_map[i] == mem) 722 return sysfs_emit(buf, "%u\n", i); 723 } 724 725 pr_warn("Unrecognised value for APU mem 0x%08x\n", mem); 726 return -EIO; 727 } 728 729 static ssize_t apu_mem_current_value_store(struct kobject *kobj, struct kobj_attribute *attr, 730 const char *buf, size_t count) 731 { 732 int result, err; 733 u32 requested, mem; 734 735 result = kstrtou32(buf, 10, &requested); 736 if (result) 737 return result; 738 739 if (requested >= ARRAY_SIZE(apu_mem_map)) 740 return -EINVAL; 741 mem = apu_mem_map[requested]; 742 743 err = armoury_set_devstate(attr, mem, NULL, ASUS_WMI_DEVID_APU_MEM); 744 if (err) { 745 pr_warn("Failed to set apu_mem 0x%x: %d\n", mem, err); 746 return err; 747 } 748 749 pr_info("APU memory changed to %uGB, reboot required\n", requested + 1); 750 sysfs_notify(kobj, NULL, attr->attr.name); 751 752 asus_set_reboot_and_signal_event(); 753 754 return count; 755 } 756 757 static ssize_t apu_mem_possible_values_show(struct kobject *kobj, struct kobj_attribute *attr, 758 char *buf) 759 { 760 return armoury_attr_enum_list(buf, ARRAY_SIZE(apu_mem_map)); 761 } 762 ASUS_ATTR_GROUP_ENUM(apu_mem, "apu_mem", "Set available system RAM (in GB) for the APU to use"); 763 764 /* Define helper to access the current power mode tunable values */ 765 static inline struct rog_tunables *get_current_tunables(void) 766 { 767 if (power_supply_is_system_supplied()) 768 return asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]; 769 770 return asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC]; 771 } 772 773 /* Simple attribute creation */ 774 ASUS_ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, "0;1;2\n", 775 "Show the current mode of charging"); 776 ASUS_ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, 777 "Set the boot POST sound"); 778 ASUS_ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, 779 "Set MCU powersaving mode"); 780 ASUS_ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, 781 "Set the panel refresh overdrive"); 782 ASUS_ATTR_GROUP_BOOL_RW(panel_hd_mode, "panel_hd_mode", ASUS_WMI_DEVID_PANEL_HD, 783 "Set the panel HD mode to UHD<0> or FHD<1>"); 784 ASUS_ATTR_GROUP_BOOL_RW(screen_auto_brightness, "screen_auto_brightness", 785 ASUS_WMI_DEVID_SCREEN_AUTO_BRIGHTNESS, 786 "Set the panel brightness to Off<0> or On<1>"); 787 ASUS_ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, 788 "Show the eGPU connection status"); 789 ASUS_ATTR_GROUP_ROG_TUNABLE(ppt_pl1_spl, ATTR_PPT_PL1_SPL, ASUS_WMI_DEVID_PPT_PL1_SPL, 790 "Set the CPU slow package limit"); 791 ASUS_ATTR_GROUP_ROG_TUNABLE(ppt_pl2_sppt, ATTR_PPT_PL2_SPPT, ASUS_WMI_DEVID_PPT_PL2_SPPT, 792 "Set the CPU fast package limit"); 793 ASUS_ATTR_GROUP_ROG_TUNABLE(ppt_pl3_fppt, ATTR_PPT_PL3_FPPT, ASUS_WMI_DEVID_PPT_PL3_FPPT, 794 "Set the CPU fastest package limit"); 795 ASUS_ATTR_GROUP_ROG_TUNABLE(ppt_apu_sppt, ATTR_PPT_APU_SPPT, ASUS_WMI_DEVID_PPT_APU_SPPT, 796 "Set the APU package limit"); 797 ASUS_ATTR_GROUP_ROG_TUNABLE(ppt_platform_sppt, ATTR_PPT_PLATFORM_SPPT, ASUS_WMI_DEVID_PPT_PLAT_SPPT, 798 "Set the platform package limit"); 799 ASUS_ATTR_GROUP_ROG_TUNABLE(nv_dynamic_boost, ATTR_NV_DYNAMIC_BOOST, ASUS_WMI_DEVID_NV_DYN_BOOST, 800 "Set the Nvidia dynamic boost limit"); 801 ASUS_ATTR_GROUP_ROG_TUNABLE(nv_temp_target, ATTR_NV_TEMP_TARGET, ASUS_WMI_DEVID_NV_THERM_TARGET, 802 "Set the Nvidia max thermal limit"); 803 ASUS_ATTR_GROUP_ROG_TUNABLE(nv_tgp, "nv_tgp", ASUS_WMI_DEVID_DGPU_SET_TGP, 804 "Set the additional TGP on top of the base TGP"); 805 ASUS_ATTR_GROUP_INT_VALUE_ONLY_RO(nv_base_tgp, ATTR_NV_BASE_TGP, ASUS_WMI_DEVID_DGPU_BASE_TGP, 806 "Read the base TGP value"); 807 808 /* If an attribute does not require any special case handling add it here */ 809 static const struct asus_attr_group armoury_attr_groups[] = { 810 { &egpu_connected_attr_group, ASUS_WMI_DEVID_EGPU_CONNECTED }, 811 { &egpu_enable_attr_group, ASUS_WMI_DEVID_EGPU }, 812 { &dgpu_disable_attr_group, ASUS_WMI_DEVID_DGPU }, 813 { &apu_mem_attr_group, ASUS_WMI_DEVID_APU_MEM }, 814 815 { &ppt_pl1_spl_attr_group, ASUS_WMI_DEVID_PPT_PL1_SPL }, 816 { &ppt_pl2_sppt_attr_group, ASUS_WMI_DEVID_PPT_PL2_SPPT }, 817 { &ppt_pl3_fppt_attr_group, ASUS_WMI_DEVID_PPT_PL3_FPPT }, 818 { &ppt_apu_sppt_attr_group, ASUS_WMI_DEVID_PPT_APU_SPPT }, 819 { &ppt_platform_sppt_attr_group, ASUS_WMI_DEVID_PPT_PLAT_SPPT }, 820 { &nv_dynamic_boost_attr_group, ASUS_WMI_DEVID_NV_DYN_BOOST }, 821 { &nv_temp_target_attr_group, ASUS_WMI_DEVID_NV_THERM_TARGET }, 822 { &nv_base_tgp_attr_group, ASUS_WMI_DEVID_DGPU_BASE_TGP }, 823 { &nv_tgp_attr_group, ASUS_WMI_DEVID_DGPU_SET_TGP }, 824 825 { &charge_mode_attr_group, ASUS_WMI_DEVID_CHARGE_MODE }, 826 { &boot_sound_attr_group, ASUS_WMI_DEVID_BOOT_SOUND }, 827 { &mcu_powersave_attr_group, ASUS_WMI_DEVID_MCU_POWERSAVE }, 828 { &panel_od_attr_group, ASUS_WMI_DEVID_PANEL_OD }, 829 { &panel_hd_mode_attr_group, ASUS_WMI_DEVID_PANEL_HD }, 830 { &screen_auto_brightness_attr_group, ASUS_WMI_DEVID_SCREEN_AUTO_BRIGHTNESS }, 831 }; 832 833 /** 834 * is_power_tunable_attr - Determines if an attribute is a power-related tunable 835 * @name: The name of the attribute to check 836 * 837 * This function checks if the given attribute name is related to power tuning. 838 * 839 * Return: true if the attribute is a power-related tunable, false otherwise 840 */ 841 static bool is_power_tunable_attr(const char *name) 842 { 843 static const char * const power_tunable_attrs[] = { 844 ATTR_PPT_PL1_SPL, ATTR_PPT_PL2_SPPT, 845 ATTR_PPT_PL3_FPPT, ATTR_PPT_APU_SPPT, 846 ATTR_PPT_PLATFORM_SPPT, ATTR_NV_DYNAMIC_BOOST, 847 ATTR_NV_TEMP_TARGET, ATTR_NV_BASE_TGP, 848 ATTR_NV_TGP 849 }; 850 851 for (unsigned int i = 0; i < ARRAY_SIZE(power_tunable_attrs); i++) { 852 if (!strcmp(name, power_tunable_attrs[i])) 853 return true; 854 } 855 856 return false; 857 } 858 859 /** 860 * has_valid_limit - Checks if a power-related attribute has a valid limit value 861 * @name: The name of the attribute to check 862 * @limits: Pointer to the power_limits structure containing limit values 863 * 864 * This function checks if a power-related attribute has a valid limit value. 865 * It returns false if limits is NULL or if the corresponding limit value is zero. 866 * 867 * Return: true if the attribute has a valid limit value, false otherwise 868 */ 869 static bool has_valid_limit(const char *name, const struct power_limits *limits) 870 { 871 u32 limit_value = 0; 872 873 if (!limits) 874 return false; 875 876 if (!strcmp(name, ATTR_PPT_PL1_SPL)) 877 limit_value = limits->ppt_pl1_spl_max; 878 else if (!strcmp(name, ATTR_PPT_PL2_SPPT)) 879 limit_value = limits->ppt_pl2_sppt_max; 880 else if (!strcmp(name, ATTR_PPT_PL3_FPPT)) 881 limit_value = limits->ppt_pl3_fppt_max; 882 else if (!strcmp(name, ATTR_PPT_APU_SPPT)) 883 limit_value = limits->ppt_apu_sppt_max; 884 else if (!strcmp(name, ATTR_PPT_PLATFORM_SPPT)) 885 limit_value = limits->ppt_platform_sppt_max; 886 else if (!strcmp(name, ATTR_NV_DYNAMIC_BOOST)) 887 limit_value = limits->nv_dynamic_boost_max; 888 else if (!strcmp(name, ATTR_NV_TEMP_TARGET)) 889 limit_value = limits->nv_temp_target_max; 890 else if (!strcmp(name, ATTR_NV_BASE_TGP) || 891 !strcmp(name, ATTR_NV_TGP)) 892 limit_value = limits->nv_tgp_max; 893 894 return limit_value > 0; 895 } 896 897 static int asus_fw_attr_add(void) 898 { 899 const struct rog_tunables *const ac_rog_tunables = 900 asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]; 901 const struct power_limits *limits; 902 bool should_create; 903 const char *name; 904 int err, i; 905 906 asus_armoury.fw_attr_dev = device_create(&firmware_attributes_class, NULL, MKDEV(0, 0), 907 NULL, "%s", DRIVER_NAME); 908 if (IS_ERR(asus_armoury.fw_attr_dev)) { 909 err = PTR_ERR(asus_armoury.fw_attr_dev); 910 goto fail_class_get; 911 } 912 913 asus_armoury.fw_attr_kset = kset_create_and_add("attributes", NULL, 914 &asus_armoury.fw_attr_dev->kobj); 915 if (!asus_armoury.fw_attr_kset) { 916 err = -ENOMEM; 917 goto err_destroy_classdev; 918 } 919 920 err = sysfs_create_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 921 if (err) { 922 pr_err("Failed to create sysfs level attributes\n"); 923 goto err_destroy_kset; 924 } 925 926 asus_armoury.mini_led_dev_id = 0; 927 if (armoury_has_devstate(ASUS_WMI_DEVID_MINI_LED_MODE)) 928 asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; 929 else if (armoury_has_devstate(ASUS_WMI_DEVID_MINI_LED_MODE2)) 930 asus_armoury.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; 931 932 if (asus_armoury.mini_led_dev_id) { 933 err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 934 &mini_led_mode_attr_group); 935 if (err) { 936 pr_err("Failed to create sysfs-group for mini_led\n"); 937 goto err_remove_file; 938 } 939 } 940 941 asus_armoury.gpu_mux_dev_id = 0; 942 if (armoury_has_devstate(ASUS_WMI_DEVID_GPU_MUX)) 943 asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX; 944 else if (armoury_has_devstate(ASUS_WMI_DEVID_GPU_MUX_VIVO)) 945 asus_armoury.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO; 946 947 if (asus_armoury.gpu_mux_dev_id) { 948 err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 949 &gpu_mux_mode_attr_group); 950 if (err) { 951 pr_err("Failed to create sysfs-group for gpu_mux\n"); 952 goto err_remove_mini_led_group; 953 } 954 } 955 956 for (i = 0; i < ARRAY_SIZE(armoury_attr_groups); i++) { 957 if (!armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 958 continue; 959 960 /* Always create by default, unless PPT is not present */ 961 should_create = true; 962 name = armoury_attr_groups[i].attr_group->name; 963 964 /* Check if this is a power-related tunable requiring limits */ 965 if (ac_rog_tunables && ac_rog_tunables->power_limits && 966 is_power_tunable_attr(name)) { 967 limits = ac_rog_tunables->power_limits; 968 /* Check only AC: if not present then DC won't be either */ 969 should_create = has_valid_limit(name, limits); 970 if (!should_create) 971 pr_debug("Missing max value for tunable %s\n", name); 972 } 973 974 if (should_create) { 975 err = sysfs_create_group(&asus_armoury.fw_attr_kset->kobj, 976 armoury_attr_groups[i].attr_group); 977 if (err) { 978 pr_err("Failed to create sysfs-group for %s\n", 979 armoury_attr_groups[i].attr_group->name); 980 goto err_remove_groups; 981 } 982 } 983 } 984 985 return 0; 986 987 err_remove_groups: 988 while (i--) { 989 if (armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 990 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, 991 armoury_attr_groups[i].attr_group); 992 } 993 if (asus_armoury.gpu_mux_dev_id) 994 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); 995 err_remove_mini_led_group: 996 if (asus_armoury.mini_led_dev_id) 997 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group); 998 err_remove_file: 999 sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 1000 err_destroy_kset: 1001 kset_unregister(asus_armoury.fw_attr_kset); 1002 err_destroy_classdev: 1003 fail_class_get: 1004 device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1005 return err; 1006 } 1007 1008 /* Init / exit ****************************************************************/ 1009 1010 /* Set up the min/max and defaults for ROG tunables */ 1011 static int init_rog_tunables(void) 1012 { 1013 const struct power_limits *ac_limits, *dc_limits; 1014 struct rog_tunables *ac_rog_tunables __free(kfree) = NULL; 1015 struct rog_tunables *dc_rog_tunables __free(kfree) = NULL; 1016 const struct power_data *power_data; 1017 const struct dmi_system_id *dmi_id; 1018 1019 /* Match the system against the power_limits table */ 1020 dmi_id = dmi_first_match(power_limits); 1021 if (!dmi_id) { 1022 pr_warn("No matching power limits found for this system\n"); 1023 return 0; 1024 } 1025 1026 /* Get the power data for this system */ 1027 power_data = dmi_id->driver_data; 1028 if (!power_data) { 1029 pr_info("No power data available for this system\n"); 1030 return 0; 1031 } 1032 1033 asus_armoury.requires_fan_curve = power_data->requires_fan_curve; 1034 1035 /* Initialize AC power tunables */ 1036 ac_limits = power_data->ac_data; 1037 if (ac_limits) { 1038 ac_rog_tunables = kzalloc_obj(*ac_rog_tunables); 1039 if (!ac_rog_tunables) 1040 return -ENOMEM; 1041 1042 ac_rog_tunables->power_limits = ac_limits; 1043 1044 /* Set initial AC values */ 1045 ac_rog_tunables->ppt_pl1_spl = 1046 ac_limits->ppt_pl1_spl_def ? 1047 ac_limits->ppt_pl1_spl_def : 1048 ac_limits->ppt_pl1_spl_max; 1049 1050 ac_rog_tunables->ppt_pl2_sppt = 1051 ac_limits->ppt_pl2_sppt_def ? 1052 ac_limits->ppt_pl2_sppt_def : 1053 ac_limits->ppt_pl2_sppt_max; 1054 1055 ac_rog_tunables->ppt_pl3_fppt = 1056 ac_limits->ppt_pl3_fppt_def ? 1057 ac_limits->ppt_pl3_fppt_def : 1058 ac_limits->ppt_pl3_fppt_max; 1059 1060 ac_rog_tunables->ppt_apu_sppt = 1061 ac_limits->ppt_apu_sppt_def ? 1062 ac_limits->ppt_apu_sppt_def : 1063 ac_limits->ppt_apu_sppt_max; 1064 1065 ac_rog_tunables->ppt_platform_sppt = 1066 ac_limits->ppt_platform_sppt_def ? 1067 ac_limits->ppt_platform_sppt_def : 1068 ac_limits->ppt_platform_sppt_max; 1069 1070 ac_rog_tunables->nv_dynamic_boost = 1071 ac_limits->nv_dynamic_boost_max; 1072 ac_rog_tunables->nv_temp_target = 1073 ac_limits->nv_temp_target_max; 1074 ac_rog_tunables->nv_tgp = ac_limits->nv_tgp_max; 1075 1076 pr_debug("AC power limits initialized for %s\n", dmi_id->matches[0].substr); 1077 } else { 1078 pr_debug("No AC PPT limits defined\n"); 1079 } 1080 1081 /* Initialize DC power tunables */ 1082 dc_limits = power_data->dc_data; 1083 if (dc_limits) { 1084 dc_rog_tunables = kzalloc_obj(*dc_rog_tunables); 1085 if (!dc_rog_tunables) 1086 return -ENOMEM; 1087 1088 dc_rog_tunables->power_limits = dc_limits; 1089 1090 /* Set initial DC values */ 1091 dc_rog_tunables->ppt_pl1_spl = 1092 dc_limits->ppt_pl1_spl_def ? 1093 dc_limits->ppt_pl1_spl_def : 1094 dc_limits->ppt_pl1_spl_max; 1095 1096 dc_rog_tunables->ppt_pl2_sppt = 1097 dc_limits->ppt_pl2_sppt_def ? 1098 dc_limits->ppt_pl2_sppt_def : 1099 dc_limits->ppt_pl2_sppt_max; 1100 1101 dc_rog_tunables->ppt_pl3_fppt = 1102 dc_limits->ppt_pl3_fppt_def ? 1103 dc_limits->ppt_pl3_fppt_def : 1104 dc_limits->ppt_pl3_fppt_max; 1105 1106 dc_rog_tunables->ppt_apu_sppt = 1107 dc_limits->ppt_apu_sppt_def ? 1108 dc_limits->ppt_apu_sppt_def : 1109 dc_limits->ppt_apu_sppt_max; 1110 1111 dc_rog_tunables->ppt_platform_sppt = 1112 dc_limits->ppt_platform_sppt_def ? 1113 dc_limits->ppt_platform_sppt_def : 1114 dc_limits->ppt_platform_sppt_max; 1115 1116 dc_rog_tunables->nv_dynamic_boost = 1117 dc_limits->nv_dynamic_boost_max; 1118 dc_rog_tunables->nv_temp_target = 1119 dc_limits->nv_temp_target_max; 1120 dc_rog_tunables->nv_tgp = dc_limits->nv_tgp_max; 1121 1122 pr_debug("DC power limits initialized for %s\n", dmi_id->matches[0].substr); 1123 } else { 1124 pr_debug("No DC PPT limits defined\n"); 1125 } 1126 1127 asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC] = no_free_ptr(ac_rog_tunables); 1128 asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC] = no_free_ptr(dc_rog_tunables); 1129 1130 return 0; 1131 } 1132 1133 static int __init asus_fw_init(void) 1134 { 1135 char *wmi_uid; 1136 int err; 1137 1138 wmi_uid = wmi_get_acpi_device_uid(ASUS_WMI_MGMT_GUID); 1139 if (!wmi_uid) 1140 return -ENODEV; 1141 1142 /* 1143 * if equal to "ASUSWMI" then it's DCTS that can't be used for this 1144 * driver, DSTS is required. 1145 */ 1146 if (!strcmp(wmi_uid, ASUS_ACPI_UID_ASUSWMI)) 1147 return -ENODEV; 1148 1149 err = init_rog_tunables(); 1150 if (err) 1151 return err; 1152 1153 /* Must always be last step to ensure data is available */ 1154 err = asus_fw_attr_add(); 1155 if (err) 1156 goto err_free_tunables; 1157 1158 return 0; 1159 1160 err_free_tunables: 1161 kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]); 1162 kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC]); 1163 return err; 1164 } 1165 1166 static void __exit asus_fw_exit(void) 1167 { 1168 int i; 1169 1170 for (i = ARRAY_SIZE(armoury_attr_groups) - 1; i >= 0; i--) { 1171 if (armoury_has_devstate(armoury_attr_groups[i].wmi_devid)) 1172 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, 1173 armoury_attr_groups[i].attr_group); 1174 } 1175 1176 if (asus_armoury.gpu_mux_dev_id) 1177 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); 1178 1179 if (asus_armoury.mini_led_dev_id) 1180 sysfs_remove_group(&asus_armoury.fw_attr_kset->kobj, &mini_led_mode_attr_group); 1181 1182 sysfs_remove_file(&asus_armoury.fw_attr_kset->kobj, &pending_reboot.attr); 1183 kset_unregister(asus_armoury.fw_attr_kset); 1184 device_destroy(&firmware_attributes_class, MKDEV(0, 0)); 1185 1186 kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]); 1187 kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC]); 1188 } 1189 1190 module_init(asus_fw_init); 1191 module_exit(asus_fw_exit); 1192 1193 MODULE_IMPORT_NS("ASUS_WMI"); 1194 MODULE_AUTHOR("Luke Jones <luke@ljones.dev>"); 1195 MODULE_DESCRIPTION("ASUS BIOS Configuration Driver"); 1196 MODULE_LICENSE("GPL"); 1197 MODULE_ALIAS("wmi:" ASUS_NB_WMI_EVENT_GUID); 1198