asus-armoury.c 33 KB

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