diff options
-rw-r--r-- | .SRCINFO | 83 | ||||
-rw-r--r-- | 0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch | 165 | ||||
-rw-r--r-- | 0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch | 170 | ||||
-rw-r--r-- | 0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch | 48 | ||||
-rw-r--r-- | 0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch | 1022 | ||||
-rw-r--r-- | 0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch | 778 | ||||
-rw-r--r-- | 0004-asus-bios-add-panel-hd-control.patch | 57 | ||||
-rw-r--r-- | 0005-asus-bios-add-dgpu-tgp-control.patch | 105 | ||||
-rw-r--r-- | 0006-asus-bios-add-apu-mem.patch | 160 | ||||
-rw-r--r-- | 0007-asus-bios-add-core-count-control.patch | 305 | ||||
-rw-r--r-- | 0008-asus-wmi-deprecate-bios-features.patch | 592 | ||||
-rw-r--r-- | PKGBUILD | 106 | ||||
-rw-r--r-- | v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch | 119 |
13 files changed, 3556 insertions, 154 deletions
@@ -1,6 +1,6 @@ pkgbase = linux-g14 pkgdesc = Linux-g14 - pkgver = 6.9.5.arch1 + pkgver = 6.9.6.arch1 pkgrel = 1 url = https://gitlab.com/dragonn/linux-g14.git arch = x86_64 @@ -17,29 +17,14 @@ pkgbase = linux-g14 makedepends = xz options = !strip options = !debug - source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.5.tar.xz - source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.5.tar.sign - source = https://github.com/archlinux/linux/releases/download/v6.9.5-arch1/linux-v6.9.5-arch1.patch.zst - source = https://github.com/archlinux/linux/releases/download/v6.9.5-arch1/linux-v6.9.5-arch1.patch.zst.sig + source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.6.tar.xz + source = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.6.tar.sign + source = https://github.com/archlinux/linux/releases/download/v6.9.6-arch1/linux-v6.9.6-arch1.patch.zst + source = https://github.com/archlinux/linux/releases/download/v6.9.6-arch1/linux-v6.9.6-arch1.patch.zst.sig source = config source = choose-gcc-optimization.sh source = sys-kernel_arch-sources-g14-6.8+--more-uarches-for-kernel.patch::https://raw.githubusercontent.com/graysky2/kernel_compiler_patch/master/more-uarches-for-kernel-6.8-rc4%2B.patch source = 0001-acpi-proc-idle-skip-dummy-wait.patch - source = 0027-mt76_-mt7921_-Disable-powersave-features-by-default.patch - source = 0032-Bluetooth-btusb-Add-a-new-PID-VID-0489-e0f6-for-MT7922.patch - source = 0035-Add_quirk_for_polling_the_KBD_port.patch - source = 0001-sched-ext.patch::https://raw.githubusercontent.com/cachyos/kernel-patches/master/6.9/sched/0001-sched-ext.patch - source = 0002-hid-asus-use-hid-for-brightness-control-on-keyboard.patch - source = 0003-Debugging.patch - source = 0004-asus-wmi-don-t-error-out-if-platform_profile-already.patch - source = 0005-hid-asus-add-USB_DEVICE_ID_ASUSTEK_DUO_KEYBOARD.patch - source = 0001-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch - source = 0002-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch - source = v2-0005-platform-x86-asus-wmi-don-t-allow-eGPU-switching-.patch - source = 0038-mediatek-pci-reset.patch - source = 0040-workaround_hardware_decoding_amdgpu.patch - source = 0001-platform-x86-asus-wmi-Support-2023-ROG-X16-tablet-mo.patch - source = amd-tablet-sfh.patch source = 0001-v4-platform-x86-asus-wmi-add-support-for-2024-ROG-Mini-LED.patch source = 0002-v4-platform-x86-asus-wmi-add-support-for-Vivobook-GPU-MUX.patch source = 0003-v4-platform-x86-asus-wmi-add-support-variant-of-TUF-RGB.patch @@ -54,35 +39,36 @@ pkgbase = linux-g14 source = 0002-HID-asus-make-asus_kbd_init-generic-remove-rog_nkey_.patch source = 0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch source = 0004-HID-asus-add-ROG-Z13-lightbar.patch + source = 0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch + source = 0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch + source = 0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch + source = 0004-asus-bios-add-panel-hd-control.patch + source = 0005-asus-bios-add-dgpu-tgp-control.patch + source = 0006-asus-bios-add-apu-mem.patch + source = 0007-asus-bios-add-core-count-control.patch + source = v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch + source = 0027-mt76_-mt7921_-Disable-powersave-features-by-default.patch + source = 0032-Bluetooth-btusb-Add-a-new-PID-VID-0489-e0f6-for-MT7922.patch + source = 0035-Add_quirk_for_polling_the_KBD_port.patch + source = 0001-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch + source = 0002-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch + source = 0038-mediatek-pci-reset.patch + source = 0040-workaround_hardware_decoding_amdgpu.patch + source = amd-tablet-sfh.patch + source = 0001-sched-ext.patch::https://raw.githubusercontent.com/cachyos/kernel-patches/master/6.9/sched/0001-sched-ext.patch source = sys-kernel_arch-sources-g14_files-0047-asus-nb-wmi-Add-tablet_mode_sw-lid-flip.patch source = sys-kernel_arch-sources-g14_files-0048-asus-nb-wmi-fix-tablet_mode_sw_int.patch validpgpkeys = ABAF11C65A2970B130ABE3C479BE3E4300411886 validpgpkeys = 647F28654894E3BD457199BE38DBBDC86092693E validpgpkeys = 83BC8889351B5DEBBB68416EB8AC08600F108CDF - sha256sums = c321c46401368774fc236f57095b205a5da57415f9a6008018902f9fd5eddfae + sha256sums = 5d4366e2b89998f274abe03557ef3bc78b58e47fc62c102d51e6f49e5ed96b4b sha256sums = SKIP - sha256sums = cf11fe18d60f2bf85fa0dd61a2fb1d59bf40f98db48dfae2244c5839c1281919 + sha256sums = f11095f47da518ce4074be587438d30f424d98bcc5c59f7a1a8c00c58ddf5aa4 sha256sums = SKIP - sha256sums = ccb010f9cf043f07dd2a2aba56cf2b7a82654dc7ee0b12a4984fcfed05d3e8ec + sha256sums = d6c1352567ed50b9a24062f93d575dfb6b744995d7ea029beb897480c992f706 sha256sums = 278118011d7a2eeca9971ac97b31bf0c55ab55e99c662ab9ae4717b55819c9a2 sha256sums = f4e7fcd011f2691840d2c8c2361dca850a78ea33cc5c24d2e27c3e0294fd1dc5 sha256sums = 0a7ea482fe20c403788d290826cec42fe395e5a6eab07b88845f8b9a9829998d - sha256sums = ed242f4be3f8eaade2a1d42157c5c6c86281917a08ae43221b088fafdc775ee7 - sha256sums = a8e1e11a4ab1995cc4975c9b134a43ddfe7054ef0c965e52a7d8f9223e15c3e0 - sha256sums = 315d1839630b37894a626bbc2aea012618b2e1ccb6f9d8aa27c0a3ce5e90e99c - sha256sums = ecbd4fc71f04d391d6e3ec1d90ee84b04a026ae89c901257915e304aa4b3dd57 - sha256sums = 9152af5811a61dd196c520ac39792aebee325fda093ecf9acd19f80819cf8d7c - sha256sums = 567efcbb400bf2dc7327a790839d2a441bd7ca9fb7f5b2b07591c4abc63554bf - sha256sums = 6ab14523be3cadf4d495dd13b0ed12a1241118d93d8313f47a8dea6b1bf16df6 - sha256sums = c9835e39798d97ba0ca48c0d2353d1182715d4bfc99964051993dacc8f59ba83 - sha256sums = 423380be1902da29e695cb201516751759050fc0a50914a0459f05e1f4614087 - sha256sums = a00b952d53df9d3617d93e8fba4146a4d6169ebe79f029b3a55cca68f738d8ea - sha256sums = 4912b1319e46ddd6670147f5e878b4aca8bcfbd7b5c852fe11e434e424666365 - sha256sums = 9f98765b43f5f31b33ed05f3611508113b02518e680ee82b251de80dae2e141d - sha256sums = d673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1 - sha256sums = e41198b29cee4de7a5132d8df606f48c2d0f9c9076fe4230b00a33c7e0b22c71 - sha256sums = 1edb362a762c8858374027e30ff58ae0014e117fdc05cc7db6da50f80e7aab87 - sha256sums = 508f90cbe81a9a145cc540703470f1e6b5d21c7a7b9166d2ce6e56b401262b04 sha256sums = feaf5f5fb62e25e2369f92f77e8327dcd4cb4cf4bc6d0c91d9c7bc40c0f4de46 sha256sums = b9866121c69ce22b4651b3ef2a1956e6d0547e40a14d1224e2f367a4f716ca1a sha256sums = 6f2f248a5ac9b1a37324cbce8d29a65b22a2b20d4b3564c0dc6063789ae733ba @@ -93,10 +79,27 @@ pkgbase = linux-g14 sha256sums = f5b560d988c47033c44307da0b584599d1f59cc0028a594f4df87affffc219d5 sha256sums = de85da760f6692b284e39aa78479904d6ee78b349f1e98d1d210777f9ef17581 sha256sums = 3be072ed798becd91bae66a75d09235c9cb5e84547b1f4eb7768e954ba109e92 - sha256sums = 93c9a77f6c25494cecbe6b236bd2179065d5f5db5589dabaa425134c1a8c3481 + sha256sums = 9c8679f5995b69b6778539f48f30142e5a357213cf9a04ee0877f50f859d1233 sha256sums = c1d96328d96964c2ce3ef7609fb7c07e97eb136dfab9f6d4efcce072a5739838 sha256sums = 2414dc71174c90b92f975a7d16cabc99ba509397d843132764ea9ee91b643dc0 sha256sums = 107a08aa610d3ba3c7ecec301df2ea8f345bc74107fcf4dac96fe9e89a23dcf1 + sha256sums = 0ac28bb000cf2eb56f36d028588fd898dd8afa63ba247fcf326496570c2fe87e + sha256sums = f45f61b9e023bf0224d70f76c73c0f667193a9915ba6ae9586046a9c4d73b8a0 + sha256sums = 9de67962522d07b9babe7c97e4240bb267939c2c6c97bb91d64ed14123f81e3f + sha256sums = 9884ce2c34d9520e343dbaf33ef1d053deeb752c12bd595ec5c96a17859131d4 + sha256sums = cc7d6594d152b95d3edc82f4a01317881f94dd365b28264805840e33a523b4c6 + sha256sums = 5b6a2f1ac22c55f43cd7e7b8b79b7ee8a76d58acd74abecc3102b2c32ed15576 + sha256sums = 6f5325bf096668d25a9bcf7fdd9fc574fc1c16640f2d163c54b87527ed961d83 + sha256sums = b7422349428f0476477167f81d9cd9e3692f7ca7345eb6e1f861a0994f9a366e + sha256sums = ed242f4be3f8eaade2a1d42157c5c6c86281917a08ae43221b088fafdc775ee7 + sha256sums = a8e1e11a4ab1995cc4975c9b134a43ddfe7054ef0c965e52a7d8f9223e15c3e0 + sha256sums = 315d1839630b37894a626bbc2aea012618b2e1ccb6f9d8aa27c0a3ce5e90e99c + sha256sums = a00b952d53df9d3617d93e8fba4146a4d6169ebe79f029b3a55cca68f738d8ea + sha256sums = 4912b1319e46ddd6670147f5e878b4aca8bcfbd7b5c852fe11e434e424666365 + sha256sums = d673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1 + sha256sums = e41198b29cee4de7a5132d8df606f48c2d0f9c9076fe4230b00a33c7e0b22c71 + sha256sums = 508f90cbe81a9a145cc540703470f1e6b5d21c7a7b9166d2ce6e56b401262b04 + sha256sums = b6e59b42ae96d69430aa78e5f7c5212e2092e7a17a9cd67575c76d79a68f28e1 sha256sums = 15e912a66e4bbce1cf0450f1dc6610653df29df8dd6d5426f9c1b039490436c8 sha256sums = 444f2d86de8c2177655b01596f939f99c2e7abfa8efad8a509e0a334f42dfa85 diff --git a/0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch b/0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch new file mode 100644 index 000000000000..2406ee91ade9 --- /dev/null +++ b/0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch @@ -0,0 +1,165 @@ +From f6690cfd476029bc67f3161705587497dabb6b8e Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Tue, 21 May 2024 18:17:17 +1200 +Subject: [PATCH 1/8] platform/x86: asus-wmi: add debug print in more key + places + +Add more verbose debug print in the WMI method calls. This helps a lot +with debugging various issues working with regular users as the WMI +methods can be traced now. + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-wmi.c | 58 +++++++++++++++++++++++++++------ + 1 file changed, 48 insertions(+), 10 deletions(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 799d928c7d3d..4c129881ce28 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -334,20 +334,29 @@ static int asus_wmi_evaluate_method3(u32 method_id, + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, + &input, &output); + +- if (ACPI_FAILURE(status)) ++ pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x\n", ++ __func__, method_id, arg0, arg1, arg2); ++ if (ACPI_FAILURE(status)) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, -EIO); + return -EIO; ++ } + + obj = (union acpi_object *)output.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + tmp = (u32) obj->integer.value; + ++ pr_debug("Result: 0x%08x\n", tmp); + if (retval) + *retval = tmp; + + kfree(obj); + +- if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) ++ if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, -ENODEV); + return -ENODEV; ++ } + + return 0; + } +@@ -377,20 +386,29 @@ static int asus_wmi_evaluate_method5(u32 method_id, + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, + &input, &output); + +- if (ACPI_FAILURE(status)) ++ pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", ++ __func__, method_id, arg0, arg1, arg2, arg3, arg4); ++ if (ACPI_FAILURE(status)) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, -EIO); + return -EIO; ++ } + + obj = (union acpi_object *)output.pointer; + if (obj && obj->type == ACPI_TYPE_INTEGER) + tmp = (u32) obj->integer.value; + ++ pr_debug("Result: %x\n", tmp); + if (retval) + *retval = tmp; + + kfree(obj); + +- if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) ++ if (tmp == ASUS_WMI_UNSUPPORTED_METHOD) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, -ENODEV); + return -ENODEV; ++ } + + return 0; + } +@@ -416,8 +434,13 @@ static int asus_wmi_evaluate_method_buf(u32 method_id, + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, + &input, &output); + +- if (ACPI_FAILURE(status)) ++ pr_debug("%s called (0x%08x) with args: 0x%08x, 0x%08x\n", ++ __func__, method_id, arg0, arg1); ++ if (ACPI_FAILURE(status)) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, -EIO); + return -EIO; ++ } + + obj = (union acpi_object *)output.pointer; + +@@ -453,8 +476,11 @@ static int asus_wmi_evaluate_method_buf(u32 method_id, + + kfree(obj); + +- if (err) ++ if (err) { ++ pr_debug("%s, (0x%08x), arg 0x%08x failed: %d\n", ++ __func__, method_id, arg0, err); + return err; ++ } + + return 0; + } +@@ -542,6 +568,7 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) + { + u32 retval; + int status = asus_wmi_get_devstate(asus, dev_id, &retval); ++ pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); + + return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); + } +@@ -3559,18 +3586,27 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) + + err = fan_curve_check_present(asus, &asus->cpu_fan_curve_available, + ASUS_WMI_DEVID_CPU_FAN_CURVE); +- if (err) ++ if (err) { ++ pr_err("%s, checked 0x%08x, failed: %d\n", ++ __func__, ASUS_WMI_DEVID_CPU_FAN_CURVE, err); + return err; ++ } + + err = fan_curve_check_present(asus, &asus->gpu_fan_curve_available, + ASUS_WMI_DEVID_GPU_FAN_CURVE); +- if (err) ++ if (err) { ++ pr_err("%s, checked 0x%08x, failed: %d\n", ++ __func__, ASUS_WMI_DEVID_GPU_FAN_CURVE, err); + return err; ++ } + + err = fan_curve_check_present(asus, &asus->mid_fan_curve_available, + ASUS_WMI_DEVID_MID_FAN_CURVE); +- if (err) ++ if (err) { ++ pr_err("%s, checked 0x%08x, failed: %d\n", ++ __func__, ASUS_WMI_DEVID_MID_FAN_CURVE, err); + return err; ++ } + + if (!asus->cpu_fan_curve_available + && !asus->gpu_fan_curve_available +@@ -4398,8 +4434,10 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + else if (attr == &dev_attr_available_mini_led_mode.attr) + ok = asus->mini_led_dev_id != 0; + +- if (devid != -1) ++ if (devid != -1) { + ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); ++ pr_debug("%s called 0x%08x, ok: %x\n", __func__, devid, ok); ++ } + + return ok ? attr->mode : 0; + } +-- +2.45.1 + diff --git a/0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch b/0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch index e4e3bf170841..8c96126fa539 100644 --- a/0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch +++ b/0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch @@ -1,14 +1,8 @@ -From 8cab59d3fb33f17e3b3fa4937c5d4bf0b59e6b12 Mon Sep 17 00:00:00 2001 -From: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn> -Date: Fri, 12 Apr 2024 00:56:39 +0100 -Subject: [PATCH] platform/x86: asus-wmi: add support for vivobook fan profiles - Add support for vivobook fan profiles wmi call on the ASUS VIVOBOOK to adjust power limits. -These fan profiles have a different device id than the ROG series. -and different order. This reorders the existing modes and adds a new -full speed mode available on these laptops. +These fan profiles have a different device id than the ROG series +and different order. This reorders the existing modes. As part of keeping the patch clean the throttle_thermal_policy_available boolean stored in the driver struct is removed and @@ -18,27 +12,28 @@ Signed-off-by: Mohamed Ghanmi <mohamed.ghanmi@supcom.tn> Co-developed-by: Luke D. Jones <luke@ljones.dev> Signed-off-by: Luke D. Jones <luke@ljones.dev> --- - drivers/platform/x86/asus-wmi.c | 100 +++++++++++---------- + drivers/platform/x86/asus-wmi.c | 125 ++++++++++++--------- include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 55 insertions(+), 46 deletions(-) + 2 files changed, 76 insertions(+), 50 deletions(-) diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 2d2b4eca7fd8..439d330fb80b 100644 +index 3c61d75a3..2e3d8d8fb 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c -@@ -97,6 +97,11 @@ module_param(fnlock_default, bool, 0444); +@@ -97,6 +97,12 @@ module_param(fnlock_default, bool, 0444); #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1 #define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2 +#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0 ++#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 +#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2 -+#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 -+#define ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED 3 ++ ++#define PLATFORM_PROFILE_MAX 2 + #define USB_INTEL_XUSB2PR 0xD0 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 -@@ -285,8 +290,8 @@ struct asus_wmi { +@@ -293,8 +299,8 @@ struct asus_wmi { u32 kbd_rgb_dev; bool kbd_rgb_state_available; @@ -48,7 +43,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 bool cpu_fan_curve_available; bool gpu_fan_curve_available; -@@ -3153,7 +3158,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) +@@ -3152,7 +3158,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) int err, fan_idx; u8 mode = 0; @@ -57,7 +52,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 mode = asus->throttle_thermal_policy_mode; /* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */ if (mode == 2) -@@ -3360,7 +3365,7 @@ static ssize_t fan_curve_enable_store(struct device *dev, +@@ -3359,7 +3365,7 @@ static ssize_t fan_curve_enable_store(struct device *dev, * For machines with throttle this is the only way to reset fans * to default mode of operation (does not erase curve data). */ @@ -66,7 +61,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 err = throttle_thermal_policy_write(asus); if (err) return err; -@@ -3577,8 +3582,8 @@ static const struct attribute_group asus_fan_curve_attr_group = { +@@ -3576,8 +3582,8 @@ static const struct attribute_group asus_fan_curve_attr_group = { __ATTRIBUTE_GROUPS(asus_fan_curve_attr); /* @@ -77,7 +72,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 */ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) { -@@ -3619,38 +3624,31 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) +@@ -3618,38 +3624,13 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) } /* Throttle thermal policy ****************************************************/ @@ -110,33 +105,16 @@ index 2d2b4eca7fd8..439d330fb80b 100644 - u8 value; + u8 value = asus->throttle_thermal_policy_mode; u32 retval; -+ bool vivo; + int err; - value = asus->throttle_thermal_policy_mode; -+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; -+ if (vivo) { -+ switch (value) { -+ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: -+ value = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; -+ break; -+ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: -+ value = ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; -+ break; -+ case ASUS_THROTTLE_THERMAL_POLICY_SILENT: -+ value = ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; -+ break; -+ default: -+ break; -+ } -+ } - +- - err = asus_wmi_set_devstate(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, + err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, value, &retval); sysfs_notify(&asus->platform_device->dev.kobj, NULL, -@@ -3680,7 +3678,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus) +@@ -3679,7 +3660,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus) static int throttle_thermal_policy_set_default(struct asus_wmi *asus) { @@ -145,54 +123,112 @@ index 2d2b4eca7fd8..439d330fb80b 100644 return 0; asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; -@@ -3690,9 +3688,14 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus) - static int throttle_thermal_policy_switch_next(struct asus_wmi *asus) - { +@@ -3691,7 +3672,7 @@ static int throttle_thermal_policy_switch_next(struct asus_wmi *asus) u8 new_mode = asus->throttle_thermal_policy_mode + 1; -+ bool vivo; int err; - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) -+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; -+ if (!vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) -+ new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; -+ -+ if (vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED) ++ if (new_mode > PLATFORM_PROFILE_MAX) new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; asus->throttle_thermal_policy_mode = new_mode; -@@ -3725,13 +3728,17 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, - struct asus_wmi *asus = dev_get_drvdata(dev); - u8 new_mode; - int result; -+ bool vivo; - int err; - - result = kstrtou8(buf, 10, &new_mode); +@@ -3730,7 +3711,7 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, if (result < 0) return result; - if (new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) -+ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; -+ if (vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED) -+ return -EINVAL; -+ else if (!vivo && new_mode > ASUS_THROTTLE_THERMAL_POLICY_SILENT) ++ if (new_mode > PLATFORM_PROFILE_MAX) return -EINVAL; asus->throttle_thermal_policy_mode = new_mode; -@@ -3748,7 +3755,10 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, +@@ -3747,10 +3728,56 @@ static ssize_t throttle_thermal_policy_store(struct device *dev, return count; } -// Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent +/* + * Throttle thermal policy: 0 - default, 1 - overboost, 2 - silent -+ * VIVOBOOK: 3 - fans full speed + */ static DEVICE_ATTR_RW(throttle_thermal_policy); /* Platform profile ***********************************************************/ -@@ -3814,7 +3824,7 @@ static int platform_profile_setup(struct asus_wmi *asus) ++static int asus_wmi_platform_profile_to_vivo(struct asus_wmi *asus, ++ int mode) ++{ ++ bool vivo; ++ ++ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; ++ ++ if (vivo) { ++ switch (mode) { ++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: ++ return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO; ++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST: ++ return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO; ++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT: ++ return ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO; ++ } ++ } ++ ++ return mode; ++ ++} ++ ++static int asus_wmi_platform_profile_mode_from_vivo(struct asus_wmi *asus, ++ int mode) ++{ ++ bool vivo; ++ ++ vivo = asus->throttle_thermal_policy_dev == ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; ++ ++ if (vivo) { ++ switch (mode) { ++ case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO: ++ return ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; ++ case ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO: ++ return ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST; ++ case ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO: ++ return ASUS_THROTTLE_THERMAL_POLICY_SILENT; ++ } ++ } ++ ++ return mode; ++ ++} ++ + static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, + enum platform_profile_option *profile) + { +@@ -3758,10 +3785,9 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, + int tp; + + asus = container_of(pprof, struct asus_wmi, platform_profile_handler); +- + tp = asus->throttle_thermal_policy_mode; + +- switch (tp) { ++ switch (asus_wmi_platform_profile_mode_from_vivo(asus, tp)) { + case ASUS_THROTTLE_THERMAL_POLICY_DEFAULT: + *profile = PLATFORM_PROFILE_BALANCED; + break; +@@ -3775,6 +3801,7 @@ static int asus_wmi_platform_profile_get(struct platform_profile_handler *pprof, + return -EINVAL; + } + ++ + return 0; + } + +@@ -3800,7 +3827,7 @@ static int asus_wmi_platform_profile_set(struct platform_profile_handler *pprof, + return -EOPNOTSUPP; + } + +- asus->throttle_thermal_policy_mode = tp; ++ asus->throttle_thermal_policy_mode = asus_wmi_platform_profile_to_vivo(asus, tp); + return throttle_thermal_policy_write(asus); + } + +@@ -3813,7 +3840,7 @@ static int platform_profile_setup(struct asus_wmi *asus) * Not an error if a component platform_profile relies on is unavailable * so early return, skipping the setup of platform_profile. */ @@ -201,7 +237,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 return 0; dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); -@@ -4229,7 +4239,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) +@@ -4228,7 +4255,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) { if (asus->fan_boost_mode_available) fan_boost_mode_switch_next(asus); @@ -210,7 +246,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 throttle_thermal_policy_switch_next(asus); return; -@@ -4401,7 +4411,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, +@@ -4436,7 +4463,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, else if (attr == &dev_attr_fan_boost_mode.attr) ok = asus->fan_boost_mode_available; else if (attr == &dev_attr_throttle_thermal_policy.attr) @@ -219,7 +255,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 else if (attr == &dev_attr_ppt_pl2_sppt.attr) devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; else if (attr == &dev_attr_ppt_pl1_spl.attr) -@@ -4693,16 +4703,15 @@ static int asus_wmi_add(struct platform_device *pdev) +@@ -4745,16 +4772,15 @@ static int asus_wmi_add(struct platform_device *pdev) else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; @@ -241,7 +277,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 err = platform_profile_setup(asus); if (err) goto fail_platform_profile_setup; -@@ -4797,7 +4806,6 @@ static int asus_wmi_add(struct platform_device *pdev) +@@ -4849,7 +4875,6 @@ static int asus_wmi_add(struct platform_device *pdev) fail_input: asus_wmi_sysfs_exit(asus->platform_device); fail_sysfs: @@ -250,7 +286,7 @@ index 2d2b4eca7fd8..439d330fb80b 100644 fail_platform_profile_setup: if (asus->platform_profile_support) diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 3eb5cd6773ad..982a637744ec 100644 +index 3eb5cd677..982a63774 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -64,6 +64,7 @@ diff --git a/0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch b/0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch new file mode 100644 index 000000000000..94213c0bcf47 --- /dev/null +++ b/0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch @@ -0,0 +1,48 @@ +From 7a08b0a6a1b47ad7c3e84a14f433c5909ec13679 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Fri, 24 May 2024 10:54:36 +1200 +Subject: [PATCH 2/8] platform/x86: asus-wmi: don't fail if platform_profile + already registered + +On some newer laptops it appears that an AMD driver can register a +platform_profile handler. If this happens then the asus_wmi driver would +error with -EEXIST when trying to register its own handler. + +We can safely continue loading the driver instead of bombing out. + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-wmi.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 4c129881ce28..7d87ff68f418 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -3836,8 +3836,13 @@ static int platform_profile_setup(struct asus_wmi *asus) + asus->platform_profile_handler.choices); + + err = platform_profile_register(&asus->platform_profile_handler); +- if (err) ++ if (err == -EEXIST) { ++ pr_warn("%s, a platform_profile handler is already registered\n", __func__); ++ return 0; ++ } else if (err) { ++ pr_err("%s, failed at platform_profile_register: %d\n", __func__, err); + return err; ++ } + + asus->platform_profile_support = true; + return 0; +@@ -4713,7 +4718,7 @@ static int asus_wmi_add(struct platform_device *pdev) + throttle_thermal_policy_set_default(asus); + + err = platform_profile_setup(asus); +- if (err) ++ if (err && err != -EEXIST) + goto fail_platform_profile_setup; + + err = asus_wmi_sysfs_init(asus->platform_device); +-- +2.45.1 + diff --git a/0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch b/0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch new file mode 100644 index 000000000000..278e6d126007 --- /dev/null +++ b/0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch @@ -0,0 +1,1022 @@ +From 2ebd194c3d390abdb67e61941f3b71fe149620eb Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Thu, 30 May 2024 13:20:11 +1200 +Subject: [PATCH 3/8] asus-bios: refactor existing tunings in to asus-bios + module + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/Kconfig | 14 + + drivers/platform/x86/Makefile | 1 + + drivers/platform/x86/asus-bios.c | 654 +++++++++++++++++++++ + drivers/platform/x86/asus-bios.h | 234 ++++++++ + drivers/platform/x86/asus-wmi.c | 18 +- + include/linux/platform_data/x86/asus-wmi.h | 10 + + 6 files changed, 930 insertions(+), 1 deletion(-) + create mode 100644 drivers/platform/x86/asus-bios.c + create mode 100644 drivers/platform/x86/asus-bios.h + +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 0ec952b5d03e..296b5c9bfbb0 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -264,6 +264,18 @@ config ASUS_WIRELESS + If you choose to compile this driver as a module the module will be + called asus-wireless. + ++config ASUS_BIOS ++ tristate "ASUS BIOS Driver" ++ depends on ACPI_WMI ++ depends on ASUS_WMI ++ select FW_ATTR_CLASS ++ help ++ Say Y here if you have a WMI aware Asus laptop and would like to use the ++ firmware_attributes API. ++ ++ To compile this driver as a module, choose M here: the module will ++ be called asus-bios. ++ + config ASUS_WMI + tristate "ASUS WMI Driver" + depends on ACPI_WMI +@@ -275,6 +287,8 @@ config ASUS_WMI + depends on HOTPLUG_PCI + depends on ACPI_VIDEO || ACPI_VIDEO = n + depends on SERIO_I8042 || SERIO_I8042 = n ++ select ASUS_BIOS ++ select ASUS_WMI_BIOS + select INPUT_SPARSEKMAP + select LEDS_CLASS + select NEW_LEDS +diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile +index e1b142947067..d9b5b3f3b241 100644 +--- a/drivers/platform/x86/Makefile ++++ b/drivers/platform/x86/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o + # ASUS + obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o + obj-$(CONFIG_ASUS_WIRELESS) += asus-wireless.o ++obj-$(CONFIG_ASUS_BIOS) += asus-bios.o + obj-$(CONFIG_ASUS_WMI) += asus-wmi.o + obj-$(CONFIG_ASUS_NB_WMI) += asus-nb-wmi.o + obj-$(CONFIG_ASUS_TF103C_DOCK) += asus-tf103c-dock.o +diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c +new file mode 100644 +index 000000000000..c245a48c4072 +--- /dev/null ++++ b/drivers/platform/x86/asus-bios.c +@@ -0,0 +1,654 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Asus BIOS attributes driver ++ * ++ * Copyright(C) 2010 Intel Corporation. ++ * Copyright(C) 2024-2024 Luke Jones <luke@ljones.dev> ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/platform_data/x86/asus-wmi.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/types.h> ++#include <linux/dmi.h> ++#include <linux/device.h> ++#include <linux/kmod.h> ++#include <linux/kobject.h> ++#include <linux/module.h> ++#include <linux/mutex.h> ++#include <linux/kernel.h> ++#include "asus-bios.h" ++#include "asus-wmi.h" ++#include "firmware_attributes_class.h" ++ ++MODULE_AUTHOR("Luke Jones <luke@ljones.dev>"); ++MODULE_DESCRIPTION("ASUS BIOS Configuration Driver"); ++MODULE_LICENSE("GPL"); ++ ++#define ASUS_NB_WMI_EVENT_GUID "0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C" ++ ++MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); ++ ++#define ASUS_MINI_LED_MODE_MASK 0x03 ++/* Standard modes for devices with only on/off */ ++#define ASUS_MINI_LED_OFF 0x00 ++#define ASUS_MINI_LED_ON 0x01 ++/* New mode on some devices, define here to clarify remapping later */ ++#define ASUS_MINI_LED_STRONG_MODE 0x02 ++/* New modes for devices with 3 mini-led mode types */ ++#define ASUS_MINI_LED_2024_WEAK 0x00 ++#define ASUS_MINI_LED_2024_STRONG 0x01 ++#define ASUS_MINI_LED_2024_OFF 0x02 ++ ++/* Default limits for tunables available on ASUS ROG laptops */ ++#define PPT_CPU_LIMIT_MIN 5 ++#define PPT_CPU_LIMIT_MAX 150 ++#define PPT_CPU_LIMIT_DEFAULT 80 ++#define PPT_PLATFORM_MIN 5 ++#define PPT_PLATFORM_MAX 100 ++#define PPT_PLATFORM_DEFAULT 80 ++#define NVIDIA_BOOST_MIN 5 ++#define NVIDIA_BOOST_MAX 25 ++#define NVIDIA_TEMP_MIN 75 ++#define NVIDIA_TEMP_MAX 87 ++ ++/* Tunables provided by ASUS for gaming laptops */ ++struct rog_tunables { ++ u32 cpu_default; ++ u32 cpu_max; ++ ++ u32 platform_default; ++ u32 platform_max; ++ ++ u32 ppt_pl1_spl; // cpu ++ u32 ppt_pl2_sppt; // cpu ++ u32 ppt_apu_sppt; // plat ++ u32 ppt_platform_sppt; // plat ++ u32 ppt_fppt; // cpu ++ ++ u32 nv_boost_default; ++ u32 nv_boost_max; ++ u32 nv_dynamic_boost; ++ ++ u32 nv_temp_default; ++ u32 nv_temp_max; ++ u32 nv_temp_target; ++}; ++ ++static const struct class *fw_attr_class; ++ ++struct asus_bios_priv { ++ struct device *fw_attr_dev; ++ struct kset *fw_attr_kset; ++ ++ struct rog_tunables *rog_tunables; ++ u32 mini_led_dev_id; ++ u32 gpu_mux_dev_id; ++ bool dgpu_disable_available; ++ bool egpu_enable_available; ++ ++ struct mutex mutex; ++} asus_bios = { ++ .mutex = __MUTEX_INITIALIZER(asus_bios.mutex), ++}; ++ ++static struct fw_attrs_group { ++ u32 pending_reboot; ++} fw_attrs = { ++ .pending_reboot = 0, ++}; ++ ++/* WMI helper methods */ ++static bool asus_wmi_is_present(u32 dev_id) ++{ ++ u32 retval; ++ int status = asus_wmi_get_devstate_dsts(dev_id, &retval); ++ pr_debug("%s called (0x%08x), retval: 0x%08x\n", __func__, dev_id, retval); ++ ++ return status == 0 && (retval & ASUS_WMI_DSTS_PRESENCE_BIT); ++} ++ ++static void asus_set_reboot_and_signal_event(void) ++{ ++ fw_attrs.pending_reboot = 1; ++ kobject_uevent(&asus_bios.fw_attr_dev->kobj, KOBJ_CHANGE); ++} ++ ++static ssize_t pending_reboot_show(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "%d\n", fw_attrs.pending_reboot); ++} ++ ++static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); ++ ++static bool asus_bios_requires_reboot(struct kobj_attribute *attr) { ++ return !strcmp(attr->attr.name, "gpu_mux_mode"); ++} ++ ++/* ++ * Generic store function for use with many ROG tunables ++ */ ++static ssize_t attr_int_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count, ++ u32 min, u32 max, u32 *store_value, u32 wmi_dev) ++{ ++ int result, value; ++ ++ result = kstrtoint(buf, 10, &value); ++ if (result) ++ return result; ++ ++ if (value < min || value > max) ++ return -EINVAL; ++ ++ asus_wmi_set_devstate(wmi_dev, value, &result); ++ if (result) { ++ pr_err("Failed to set %s: %d\n", attr->attr.name, result); ++ return result; ++ } ++ ++ if (result > 1) { ++ pr_err("Failed to set %s (result): 0x%x\n", attr->attr.name, result); ++ return -EIO; ++ } ++ ++ if (store_value != NULL) ++ *store_value = value; ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ if (asus_bios_requires_reboot(attr)) ++ asus_set_reboot_and_signal_event(); ++ ++ return count; ++} ++ ++/* Mini-LED mode **************************************************************/ ++static ssize_t mini_led_mode_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ u32 value; ++ int err; ++ ++ err = asus_wmi_get_devstate_dsts(asus_bios.mini_led_dev_id, &value); ++ if (err) ++ return err; ++ ++ value = value & ASUS_MINI_LED_MODE_MASK; ++ ++ /* ++ * Remap the mode values to match previous generation mini-led. The last gen ++ * WMI 0 == off, while on this version WMI 2 ==off (flipped). ++ */ ++ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { ++ switch (value) { ++ case ASUS_MINI_LED_2024_WEAK: ++ value = ASUS_MINI_LED_ON; ++ break; ++ case ASUS_MINI_LED_2024_STRONG: ++ value = ASUS_MINI_LED_STRONG_MODE; ++ break; ++ case ASUS_MINI_LED_2024_OFF: ++ value = ASUS_MINI_LED_OFF; ++ break; ++ } ++ } ++ ++ return sysfs_emit(buf, "%d\n", value); ++} ++ ++static ssize_t mini_led_mode_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int result, err; ++ u32 mode; ++ ++ result = kstrtou32(buf, 10, &mode); ++ if (result) ++ return result; ++ ++ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE && ++ mode > ASUS_MINI_LED_ON) ++ return -EINVAL; ++ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 && ++ mode > ASUS_MINI_LED_STRONG_MODE) ++ return -EINVAL; ++ ++ /* ++ * Remap the mode values so expected behaviour is the same as the last ++ * generation of mini-LED with 0 == off, 1 == on. ++ */ ++ if (asus_bios.mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2) { ++ switch (mode) { ++ case ASUS_MINI_LED_OFF: ++ mode = ASUS_MINI_LED_2024_OFF; ++ break; ++ case ASUS_MINI_LED_ON: ++ mode = ASUS_MINI_LED_2024_WEAK; ++ break; ++ case ASUS_MINI_LED_STRONG_MODE: ++ mode = ASUS_MINI_LED_2024_STRONG; ++ break; ++ } ++ } ++ ++ err = asus_wmi_set_devstate(asus_bios.mini_led_dev_id, mode, &result); ++ if (err) { ++ pr_warn("Failed to set mini-LED: %d\n", err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_warn("Failed to set mini-LED mode (result): 0x%x\n", result); ++ return -EIO; ++ } ++ ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ return count; ++} ++ ++static ssize_t mini_led_mode_possible_values_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ switch (asus_bios.mini_led_dev_id) { ++ case ASUS_WMI_DEVID_MINI_LED_MODE: ++ return sysfs_emit(buf, "0;1\n"); ++ case ASUS_WMI_DEVID_MINI_LED_MODE2: ++ return sysfs_emit(buf, "0;1;2\n"); ++ } ++ ++ return sysfs_emit(buf, "0\n"); ++} ++ ++ATTR_GROUP_ENUM_CUSTOM(mini_led_mode, "mini_led_mode", "Set the mini-LED backlight mode"); ++ ++static ssize_t gpu_mux_mode_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int result, err; ++ u32 optimus; ++ ++ err = kstrtou32(buf, 10, &optimus); ++ if (err) ++ return err; ++ ++ if (optimus > 1) ++ return -EINVAL; ++ ++ if (asus_bios.dgpu_disable_available) { ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_DGPU, &result); ++ if (err) ++ return err; ++ if (err && !optimus) { ++ err = -ENODEV; ++ pr_warn("Can not switch MUX to dGPU mode when dGPU is disabled: %d\n", err); ++ return err; ++ } ++ } ++ ++ if (asus_bios.egpu_enable_available) { ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_EGPU, &result); ++ if (err) ++ return err; ++ if (result && !optimus) { ++ err = -ENODEV; ++ pr_warn("Can not switch MUX to dGPU mode when eGPU is enabled: %d\n", err); ++ return err; ++ } ++ } ++ ++ err = asus_wmi_set_devstate(asus_bios.gpu_mux_dev_id, optimus, &result); ++ if (err) { ++ pr_err("%s Failed to set GPU MUX mode: %d\nn", __func__, err); ++ return err; ++ } ++ /* !1 is considered a fail by ASUS */ ++ if (result != 1) { ++ pr_warn("%s Failed to set GPU MUX mode (result): 0x%x\n", __func__, result); ++ return -EIO; ++ } ++ ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ return count; ++} ++WMI_SHOW_INT(gpu_mux_mode_current_value, "%d\n", asus_bios.gpu_mux_dev_id); ++ATTR_GROUP_BOOL_CUSTOM(gpu_mux_mode, "gpu_mux_mode", "Set the GPU display MUX mode"); ++ ++/* ++ * A user may be required to store the value twice, typcial store first, then ++ * rescan PCI bus to activate power, then store a second time to save correctly. ++ * The reason for this is that an extra code path in the ACPI is enabled when ++ * the device and bus are powered. ++ */ ++static ssize_t dgpu_disable_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int result, err; ++ u32 disable; ++ ++ result = kstrtou32(buf, 10, &disable); ++ if (result) ++ return result; ++ ++ if (disable > 1) ++ return -EINVAL; ++ ++ if (asus_bios.gpu_mux_dev_id) { ++ err = asus_wmi_get_devstate_dsts(asus_bios.gpu_mux_dev_id, &result); ++ if (err) ++ return err; ++ if (!result && disable) { ++ err = -ENODEV; ++ pr_warn("Can not disable dGPU when the MUX is in dGPU mode: %d\n", err); ++ return err; ++ } ++ } ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, disable, &result); ++ if (err) { ++ pr_warn("Failed to set dgpu disable: %d\n", err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_warn("Failed to set dgpu disable (result): 0x%x\n", result); ++ return -EIO; ++ } ++ ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ return count; ++} ++WMI_SHOW_INT(dgpu_disable_current_value, "%d\n", ASUS_WMI_DEVID_DGPU); ++ATTR_GROUP_BOOL_CUSTOM(dgpu_disable, "dgpu_disable", "Disable the dGPU"); ++ ++/* The ACPI call to enable the eGPU also disables the internal dGPU */ ++static ssize_t egpu_enable_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int result, err; ++ u32 enable; ++ ++ err = kstrtou32(buf, 10, &enable); ++ if (err) ++ return err; ++ ++ if (enable > 1) ++ return -EINVAL; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_EGPU_CONNECTED, &result); ++ if (err) { ++ pr_warn("Failed to get egpu connection status: %d\n", err); ++ return err; ++ } ++ ++ if (asus_bios.gpu_mux_dev_id) { ++ err = asus_wmi_get_devstate_dsts(asus_bios.gpu_mux_dev_id, &result); ++ if (err) { ++ pr_warn("Failed to get gpu mux status: %d\n", result); ++ return result; ++ } ++ if (!result && enable) { ++ err = -ENODEV; ++ pr_warn("Can not enable eGPU when the MUX is in dGPU mode: %d\n", err); ++ return err; ++ } ++ } ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_EGPU, enable, &result); ++ if (err) { ++ pr_warn("Failed to set egpu state: %d\n", err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_warn("Failed to set egpu state (retval): 0x%x\n", result); ++ return -EIO; ++ } ++ ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ return count; ++} ++WMI_SHOW_INT(egpu_enable_current_value, "%d\n", ASUS_WMI_DEVID_EGPU); ++ATTR_GROUP_BOOL_CUSTOM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); ++ ++/* Simple attribute creation */ ++ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo"); ++ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, ++ cpu_default, 5, cpu_max, 1, "Set the CPU slow package limit"); ++ATTR_GROUP_PPT_RW(ppt_pl2_sppt, "ppt_pl2_sppt", ASUS_WMI_DEVID_PPT_PL2_SPPT, ++ cpu_default, 5, cpu_max, 1, "Set the CPU fast package limit"); ++ATTR_GROUP_PPT_RW(ppt_apu_sppt, "ppt_apu_sppt", ASUS_WMI_DEVID_PPT_APU_SPPT, ++ platform_default, 5, platform_max, 1, "Set the CPU slow package limit"); ++ATTR_GROUP_PPT_RW(ppt_platform_sppt, "ppt_platform_sppt", ASUS_WMI_DEVID_PPT_PLAT_SPPT, ++ platform_default, 5, platform_max, 1, "Set the CPU slow package limit"); ++ATTR_GROUP_PPT_RW(ppt_fppt, "ppt_fppt", ASUS_WMI_DEVID_PPT_FPPT, ++ cpu_default, 5, cpu_max, 1, "Set the CPU slow package limit"); ++ ++ATTR_GROUP_PPT_RW(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_DYN_BOOST, ++ nv_boost_default, 5, nv_boost_max, 1, "Set the Nvidia dynamic boost limit"); ++ATTR_GROUP_PPT_RW(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET, ++ nv_temp_default, 75, nv_temp_max, 1, "Set the Nvidia max thermal limit"); ++ ++ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, 0, 0, "0;1;2", "Show the current mode of charging"); ++ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, "Set the boot POST sound"); ++ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, "Set MCU powersaving mode"); ++ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, "Set the panel refresh overdrive"); ++ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, "Show the eGPU connection status"); ++ ++static int asus_fw_attr_add(void) ++{ ++ int ret; ++ ret = fw_attributes_class_get(&fw_attr_class); ++ if (ret) ++ goto fail_class_created; ++ else ++ asus_bios.fw_attr_dev = device_create(fw_attr_class, NULL, ++ MKDEV(0, 0), NULL, "%s", DRIVER_NAME); ++ ++ if (IS_ERR(asus_bios.fw_attr_dev)) { ++ ret = PTR_ERR(asus_bios.fw_attr_dev); ++ goto fail_class_created; ++ } ++ ++ asus_bios.fw_attr_kset = kset_create_and_add("attributes", NULL, ++ &asus_bios.fw_attr_dev->kobj); ++ if (!asus_bios.fw_attr_dev) { ++ ret = -ENOMEM; ++ pr_debug("Failed to create and add attributes\n"); ++ goto err_destroy_classdev; ++ } ++ ++ /* Add any firmware_attributes required */ ++ ret = sysfs_create_file(&asus_bios.fw_attr_kset->kobj, &pending_reboot.attr); ++ if (ret) { ++ pr_warn("Failed to create sysfs level attributes\n"); ++ goto fail_class_created; ++ } ++ ++ // TODO: logging ++ asus_bios.mini_led_dev_id = 0; ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE)) { ++ asus_bios.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mini_led_mode_attr_group); ++ } ++ else if (asus_wmi_is_present(ASUS_WMI_DEVID_MINI_LED_MODE2)) { ++ asus_bios.mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mini_led_mode_attr_group); ++ } ++ ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX)) { ++ asus_bios.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); ++ } else if (asus_wmi_is_present(ASUS_WMI_DEVID_GPU_MUX_VIVO)) { ++ asus_bios.gpu_mux_dev_id = ASUS_WMI_DEVID_GPU_MUX_VIVO; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &gpu_mux_mode_attr_group); ++ } ++ ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU)) { ++ asus_bios.dgpu_disable_available = true; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_disable_attr_group); ++ } ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU)) { ++ asus_bios.egpu_enable_available = true; ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_enable_attr_group); ++ } ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU_CONNECTED)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_connected_attr_group); ++ ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &thermal_policy_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL1_SPL)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl1_spl_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL2_SPPT)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl2_sppt_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_APU_SPPT)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_apu_sppt_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PLAT_SPPT)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_platform_sppt_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_FPPT)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_fppt_attr_group); ++ ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_NV_DYN_BOOST)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_dynamic_boost_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_NV_THERM_TARGET)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_temp_target_attr_group); ++ ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_CHARGE_MODE)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &charge_mode_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_BOOT_SOUND)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &boot_sound_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_MCU_POWERSAVE)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mcu_powersave_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PANEL_OD)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &panel_od_attr_group); ++ ++ return 0; ++ ++err_destroy_classdev: ++ device_destroy(fw_attr_class, MKDEV(0, 0)); ++ ++fail_class_created: ++ fw_attributes_class_put(); ++ return ret; ++} ++ ++/* Init / exit ****************************************************************/ ++ ++/* Set up the min/max and defaults for ROG tunables */ ++static void init_rog_tunables(struct rog_tunables *rog) ++{ ++ const char *product; ++ u32 max_boost = NVIDIA_BOOST_MAX; ++ u32 cpu_default = PPT_CPU_LIMIT_DEFAULT; ++ u32 cpu_max = PPT_CPU_LIMIT_MAX; ++ u32 platform_default = PPT_PLATFORM_DEFAULT; ++ u32 platform_max = PPT_PLATFORM_MAX; ++ ++ /* ++ * ASUS product_name contains everything required, e.g, ++ * "ROG Flow X16 GV601VV_GV601VV_00185149B" ++ */ ++ product = dmi_get_system_info(DMI_PRODUCT_NAME); ++ ++ if (strstr(product, "GA402R")) { ++ cpu_default = 125; ++ } else if (strstr(product, "13QY")) { ++ cpu_max = 250; ++ } else if (strstr(product, "X13")) { ++ cpu_max = 75; ++ cpu_default = 50; ++ } else if (strstr(product, "RC71")) { ++ cpu_max = 50; ++ cpu_default = 30; ++ } else if (strstr(product, "G814") ++ || strstr(product, "G614") ++ || strstr(product, "G834") ++ || strstr(product, "G634")) { ++ cpu_max = 175; ++ } else if (strstr(product, "GA402X") ++ || strstr(product, "GA403") ++ || strstr(product, "FA507N") ++ || strstr(product, "FA507X") ++ || strstr(product, "FA707N") ++ || strstr(product, "FA707X")) { ++ cpu_max = 90; ++ } ++ ++ if (strstr(product, "GZ301ZE")) ++ max_boost = 5; ++ else if (strstr(product, "FX507ZC4")) ++ max_boost = 15; ++ else if (strstr(product, "GU605")) ++ max_boost = 20; ++ ++ /* ensure defaults for tunables */ ++ rog->cpu_default = cpu_default; ++ rog->cpu_max = cpu_max; ++ ++ rog->platform_default = platform_default; ++ rog->platform_max = platform_max; ++ ++ rog->ppt_pl1_spl = cpu_default; ++ rog->ppt_pl2_sppt = cpu_default; ++ rog->ppt_apu_sppt = cpu_default; ++ ++ rog->ppt_platform_sppt = platform_default; ++ rog->ppt_fppt = platform_default; ++ ++ rog->nv_boost_default = NVIDIA_BOOST_MAX; ++ rog->nv_boost_max = max_boost; ++ rog->nv_dynamic_boost = NVIDIA_BOOST_MIN; ++ ++ rog->nv_temp_default = NVIDIA_TEMP_MAX; ++ rog->nv_temp_max = NVIDIA_TEMP_MAX; ++ rog->nv_temp_target = NVIDIA_TEMP_MIN; ++ ++} ++ ++static int __init asus_fw_init(void) ++{ ++ int err; ++ ++ mutex_lock(&asus_bios.mutex); ++ ++ asus_bios.rog_tunables = kzalloc(sizeof(struct rog_tunables), GFP_KERNEL); ++ if (!asus_bios.rog_tunables) { ++ mutex_unlock(&asus_bios.mutex); ++ return -ENOMEM; ++ } ++ init_rog_tunables(asus_bios.rog_tunables); ++ ++ err = asus_fw_attr_add(); ++ mutex_unlock(&asus_bios.mutex); ++ if (err) ++ return err; ++ ++ return 0; ++} ++ ++static void __exit asus_fw_exit(void) ++{ ++ mutex_lock(&asus_bios.mutex); ++ ++ sysfs_remove_file(&asus_bios.fw_attr_kset->kobj, &pending_reboot.attr); ++ kset_unregister(asus_bios.fw_attr_kset); ++ device_destroy(fw_attr_class, MKDEV(0, 0)); ++ fw_attributes_class_put(); ++ ++ mutex_unlock(&asus_bios.mutex); ++} ++ ++module_init(asus_fw_init); ++module_exit(asus_fw_exit); +diff --git a/drivers/platform/x86/asus-bios.h b/drivers/platform/x86/asus-bios.h +new file mode 100644 +index 000000000000..acae11698a07 +--- /dev/null ++++ b/drivers/platform/x86/asus-bios.h +@@ -0,0 +1,234 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Definitions for kernel modules using asus-bios driver ++ * ++ * Copyright (c) 2024 Luke Jones <luke@ljones.dev> ++ */ ++ ++#ifndef _ASUS_BIOSCFG_H_ ++#define _ASUS_BIOSCFG_H_ ++ ++#include "firmware_attributes_class.h" ++#include <linux/types.h> ++ ++#define DRIVER_NAME "asus-bioscfg" ++ ++static ssize_t attr_int_store(struct kobject *kobj, struct kobj_attribute *attr, ++ const char *buf, size_t count, ++ u32 min, u32 max, u32 *store_value, u32 wmi_dev); ++ ++ ++static ssize_t int_type_show(struct kobject *kobj, struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "integer\n"); ++} ++ ++static ssize_t enum_type_show(struct kobject *kobj, struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sysfs_emit(buf, "enumeration\n"); ++} ++ ++#define __ASUS_ATTR_RO(_func, _name) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = _func##_##_name##_show, \ ++} ++ ++#define __ASUS_ATTR_RO_AS(_name, _show) { \ ++ .attr = { .name = __stringify(_name), .mode = 0444 }, \ ++ .show = _show, \ ++} ++ ++#define __ASUS_ATTR_RW(_func, _name) __ATTR(_name, 0644, _func##_##_name##_show, _func##_##_name##_store) ++ ++#define __WMI_STORE_INT(_attr, _min, _max, _wmi) \ ++static ssize_t _attr##_store(struct kobject *kobj, \ ++ struct kobj_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ return attr_int_store(kobj, attr, buf, count, _min, _max, NULL, _wmi); \ ++} ++ ++#define WMI_SHOW_INT(_attr, _fmt, _wmi) \ ++static ssize_t _attr##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ u32 result; \ ++ int err; \ ++ err = asus_wmi_get_devstate_dsts(_wmi, &result); \ ++ if (err) \ ++ return err; \ ++ return sysfs_emit(buf, _fmt, \ ++ result & ~ASUS_WMI_DSTS_PRESENCE_BIT); \ ++} ++ ++/* Create functions and attributes for use in other macros or on their own */ ++ ++#define __ROG_TUNABLE_RW(_attr, _min, _max, _wmi) \ ++static ssize_t _attr##_current_value_store(struct kobject *kobj, \ ++ struct kobj_attribute *attr, \ ++ const char *buf, size_t count) \ ++{ \ ++ return attr_int_store(kobj, attr, buf, count, \ ++ _min, asus_bios.rog_tunables->_max, \ ++ &asus_bios.rog_tunables->_attr, _wmi); \ ++} \ ++static ssize_t _attr##_current_value_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ return sysfs_emit(buf, "%u\n", asus_bios.rog_tunables->_attr); \ ++} \ ++static struct kobj_attribute attr_##_attr##_current_value = \ ++ __ASUS_ATTR_RW(_attr, current_value); ++ ++#define __ROG_TUNABLE_SHOW(_prop, _attrname, _val) \ ++static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->_val); \ ++} \ ++static struct kobj_attribute attr_##_attrname##_##_prop = \ ++ __ASUS_ATTR_RO(_attrname, _prop); ++ ++#define __ATTR_CURRENT_INT_RO(_attr, _wmi) \ ++WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \ ++static struct kobj_attribute attr_##_attr##_current_value = \ ++ __ASUS_ATTR_RO(_attr, current_value); ++ ++#define __ATTR_CURRENT_INT_RW(_attr, _minv, _maxv, _wmi) \ ++__WMI_STORE_INT(_attr##_current_value, _minv, _maxv, _wmi); \ ++WMI_SHOW_INT(_attr##_current_value, "%d\n", _wmi); \ ++static struct kobj_attribute attr_##_attr##_current_value = \ ++ __ASUS_ATTR_RW(_attr, current_value); ++ ++/* Shows a formatted static variable */ ++#define __ATTR_SHOW_FMT(_prop, _attrname, _fmt, _val) \ ++static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \ ++ struct kobj_attribute *attr, char *buf) \ ++{ \ ++ return sysfs_emit(buf, _fmt, _val); \ ++} \ ++static struct kobj_attribute attr_##_attrname##_##_prop = \ ++ __ASUS_ATTR_RO(_attrname, _prop); ++ ++/* Int style min/max range, base macro. Requires current_value show&|store */ ++#define __ATTR_GROUP_INT(_attrname, _fsname, _default, \ ++ _min, _max, _incstep, _dispname)\ ++__ATTR_SHOW_FMT(default_value, _attrname, "%d\n", _default); \ ++__ATTR_SHOW_FMT(min_value, _attrname, "%d\n", _min); \ ++__ATTR_SHOW_FMT(max_value, _attrname, "%d\n", _max); \ ++__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, int_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_default_value.attr, \ ++ &attr_##_attrname##_min_value.attr, \ ++ &attr_##_attrname##_max_value.attr, \ ++ &attr_##_attrname##_scalar_increment.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ ++/* Boolean style enumeration, base macro. Requires adding show/store */ ++#define __ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname) \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++__ATTR_SHOW_FMT(possible_values, _attrname, "%s\n", _possible); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, enum_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_possible_values.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ ++#define ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \ ++__ATTR_CURRENT_INT_RO(_attrname, _wmi); \ ++__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname); ++ ++#define ATTR_GROUP_BOOL_RW(_attrname, _fsname, _wmi, _dispname) \ ++__ATTR_CURRENT_INT_RW(_attrname, 0, 1, _wmi); \ ++__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname); ++ ++/* ++ * Requires <name>_current_value_show(), <name>_current_value_show() ++ */ ++#define ATTR_GROUP_BOOL_CUSTOM(_attrname, _fsname, _dispname) \ ++static struct kobj_attribute attr_##_attrname##_current_value = \ ++ __ASUS_ATTR_RW(_attrname, current_value); \ ++__ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname); ++ ++#define ATTR_GROUP_ENUM_INT_RO(_attrname, _fsname, _wmi, _min, \ ++ _max, _possible, _dispname) \ ++__ATTR_CURRENT_INT_RO(_attrname, _wmi); \ ++__ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname); ++ ++#define ATTR_GROUP_ENUM_INT_RW(_attrname, _fsname, _wmi, _min, \ ++ _max, _possible, _dispname) \ ++__ATTR_CURRENT_INT_RW(_attrname, _min, _max, _wmi); \ ++__ATTR_GROUP_ENUM(_attrname, _fsname, _possible, _dispname); ++ ++/* ++ * Requires <name>_current_value_show(), <name>_current_value_show() ++ * and <name>_possible_values_show() ++ */ ++#define ATTR_GROUP_ENUM_CUSTOM(_attrname, _fsname, _dispname) \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++static struct kobj_attribute attr_##_attrname##_current_value = \ ++ __ASUS_ATTR_RW(_attrname, current_value); \ ++static struct kobj_attribute attr_##_attrname##_possible_values = \ ++ __ASUS_ATTR_RO(_attrname, possible_values); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, enum_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_possible_values.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ ++/* ROG PPT attributes need a little different in setup */ ++#define ATTR_GROUP_PPT_RW(_attrname, _fsname, _wmi, _default, \ ++ _min, _max, _incstep, _dispname) \ ++__ROG_TUNABLE_RW(_attrname, _min, _max, _wmi); \ ++__ROG_TUNABLE_SHOW(default_value, _attrname, _default); \ ++__ATTR_SHOW_FMT(min_value, _attrname, "%d\n", _min); \ ++__ROG_TUNABLE_SHOW(max_value, _attrname, _max); \ ++__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", _incstep); \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, int_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_default_value.attr, \ ++ &attr_##_attrname##_min_value.attr, \ ++ &attr_##_attrname##_max_value.attr, \ ++ &attr_##_attrname##_scalar_increment.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ ++#endif /* _ASUS_BIOSCFG_H_ */ +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 7d87ff68f418..a6f2e5325a60 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -529,12 +529,28 @@ static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval) + return 0; + } + +-static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, ++int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval) ++{ ++ int err; ++ ++ err = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, dev_id, 0, retval); ++ if (err) ++ return err; ++ ++ if (*retval == ~0) ++ return -ENODEV; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(asus_wmi_get_devstate_dsts); ++ ++int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, + u32 *retval) + { + return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id, + ctrl_param, retval); + } ++EXPORT_SYMBOL_GPL(asus_wmi_set_devstate); + + /* Helper for special devices with magic return codes */ + static int asus_wmi_get_devstate_bits(struct asus_wmi *asus, +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 6ba0015e4386..525cb7c803fe 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -152,8 +152,18 @@ + #define ASUS_WMI_DSTS_LIGHTBAR_MASK 0x0000000F + + #if IS_REACHABLE(CONFIG_ASUS_WMI) ++int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval); ++int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval); + int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, u32 *retval); + #else ++static int asus_wmi_get_devstate_dsts(u32 dev_id, u32 *retval) ++{ ++ return -ENODEV; ++} ++static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param, u32 *retval) ++{ ++ return -ENODEV; ++} + static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, + u32 *retval) + { +-- +2.45.1 + diff --git a/0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch b/0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch new file mode 100644 index 000000000000..c950da8bd0db --- /dev/null +++ b/0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch @@ -0,0 +1,778 @@ +/* Default limits for tunables available on ASUS ROG laptops */ +#define PPT_CPU_LIMIT_MIN 5 +#define PPT_CPU_LIMIT_MAX 150 +#define PPT_CPU_LIMIT_DEFAULT 80 +#define PPT_PLATFORM_MIN 5 +#define PPT_PLATFORM_MAX 100 +#define PPT_PLATFORM_DEFAULT 80 +#define NVIDIA_BOOST_MIN 5 +#define NVIDIA_BOOST_MAX 25 +#define NVIDIA_TEMP_MIN 75 + +/* Tunables provided by ASUS for gaming laptops */ +struct rog_tunables { + u32 cpu_default; + u32 cpu_max; + + u32 platform_default; + u32 platform_max; + + u32 ppt_pl1_spl; // total + u32 ppt_pl2_sppt; // total + u32 ppt_apu_sppt; // cpu + u32 ppt_platform_sppt; // cpu + u32 ppt_fppt; // total + + u32 nv_boost_default; + u32 nv_boost_max; + u32 nv_dynamic_boost; + + u32 nv_temp_default; + u32 nv_temp_max; + u32 nv_temp_target; +}; + + +From 74b729c160f95f0bec8d7af3efc94514195b23e3 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Sat, 25 May 2024 17:31:07 +1200 +Subject: [PATCH 3/9] platform/x86: asus-wmi: add macros and expose min/max + sysfs for ppt tunables + +In most cases the safe min and max values of the various PPT tunables are +known for various ASUS ROG (and other) laptop models. We can match the +DMI string for these and expose min/max sysfs points, plus set some sane +default values. + +As part of the addition of the min/max and defaults, to reduce the amount +of code copy/paste and introduce some sanity a group of macros were added +specific to the PPT and NV tunables. The code becomes much cleaner and +easier to read. + +This makes the PPT functions much more usable and safe. + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + .../ABI/testing/sysfs-platform-asus-wmi | 23 +- + drivers/platform/x86/asus-wmi.c | 561 ++++++++---------- + 2 files changed, 245 insertions(+), 339 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi +index 28144371a0f1..984a04f32fd0 100644 +--- a/Documentation/ABI/testing/sysfs-platform-asus-wmi ++++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi +@@ -142,8 +142,8 @@ Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. + Shown on Intel+Nvidia or AMD+Nvidia based systems: +- +- * min=5, max=250 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/ppt_pl2_sppt + Date: Jun 2023 +@@ -152,8 +152,8 @@ Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT, + on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems: +- +- * min=5, max=250 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/ppt_fppt + Date: Jun 2023 +@@ -161,7 +161,8 @@ KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only: +- * min=5, max=250 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/ppt_apu_sppt + Date: Jun 2023 +@@ -169,7 +170,8 @@ KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the APU SPPT limit. Shown on full AMD systems only: +- * min=5, max=130 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/ppt_platform_sppt + Date: Jun 2023 +@@ -177,7 +179,8 @@ KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the platform SPPT limit. Shown on full AMD systems only: +- * min=5, max=130 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/nv_dynamic_boost + Date: Jun 2023 +@@ -185,7 +188,8 @@ KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the dynamic boost limit of the Nvidia dGPU: +- * min=5, max=25 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/nv_temp_target + Date: Jun 2023 +@@ -193,7 +197,8 @@ KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: + Set the target temperature limit of the Nvidia dGPU: +- * min=75, max=87 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default + + What: /sys/devices/platform/<platform>/boot_sound + Date: Apr 2024 +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 999cd658ec8b..d016acb23789 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -112,11 +112,13 @@ module_param(fnlock_default, bool, 0444); + /* Mask to determine if setting temperature or percentage */ + #define FAN_CURVE_PWM_MASK 0x04 + +-/* Limits for tunables available on ASUS ROG laptops */ +-#define PPT_TOTAL_MIN 5 +-#define PPT_TOTAL_MAX 250 +-#define PPT_CPU_MIN 5 +-#define PPT_CPU_MAX 130 ++/* Default limits for tunables available on ASUS ROG laptops */ ++#define PPT_CPU_LIMIT_MIN 5 ++#define PPT_CPU_LIMIT_MAX 150 ++#define PPT_CPU_LIMIT_DEFAULT 80 ++#define PPT_PLATFORM_MIN 5 ++#define PPT_PLATFORM_MAX 100 ++#define PPT_PLATFORM_DEFAULT 80 + #define NVIDIA_BOOST_MIN 5 + #define NVIDIA_BOOST_MAX 25 + #define NVIDIA_TEMP_MIN 75 +@@ -219,6 +221,29 @@ struct fan_curve_data { + u8 percents[FAN_CURVE_POINTS]; + }; + ++/* Tunables provided by ASUS for gaming laptops */ ++struct rog_tunables { ++ u32 cpu_default; ++ u32 cpu_max; ++ ++ u32 platform_default; ++ u32 platform_max; ++ ++ u32 ppt_pl1_spl; // total ++ u32 ppt_pl2_sppt; // total ++ u32 ppt_apu_sppt; // cpu ++ u32 ppt_platform_sppt; // cpu ++ u32 ppt_fppt; // total ++ ++ u32 nv_boost_default; ++ u32 nv_boost_max; ++ u32 nv_dynamic_boost; ++ ++ u32 nv_temp_default; ++ u32 nv_temp_max; ++ u32 nv_temp_target; ++}; ++ + struct asus_wmi { + int dsts_id; + int spec; +@@ -273,14 +298,7 @@ struct asus_wmi { + bool dgpu_disable_available; + u32 gpu_mux_dev; + +- /* Tunables provided by ASUS for gaming laptops */ +- u32 ppt_pl2_sppt; +- u32 ppt_pl1_spl; +- u32 ppt_apu_sppt; +- u32 ppt_platform_sppt; +- u32 ppt_fppt; +- u32 nv_dynamic_boost; +- u32 nv_temp_target; ++ struct rog_tunables rog_tunables; + + u32 kbd_rgb_dev; + bool kbd_rgb_state_available; +@@ -652,6 +670,98 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) + asus->inputdev = NULL; + } + ++/* Helper macros for generalised WMI calls */ ++ ++/* Generic store function for use with many ROG tunables */ ++static ssize_t rog_tunable_store(struct asus_wmi *asus, ++ struct attribute *attr, ++ const char *buf, size_t count, ++ u32 min, u32 max, u32 defaultv, ++ u32 *store_value, u32 wmi_dev) ++{ ++ int result, err, value; ++ ++ result = kstrtoint(buf, 10, &value); ++ if (result) ++ return result; ++ ++ if (value == -1 ) ++ value = defaultv; ++ if (value < min || value > max) ++ return -EINVAL; ++ ++ err = asus_wmi_set_devstate(wmi_dev, value, &result); ++ if (err) { ++ pr_err("Failed to set %s: %d\n", attr->name, err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_err("Failed to set %s (result): 0x%x\n", attr->name, result); ++ return -EIO; ++ } ++ ++ if (store_value != NULL) ++ *store_value = value; ++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, attr->name); ++ ++ return count; ++} ++ ++#define ROG_TUNABLE_STORE(_fname, _min, _max, _default, _wmi) \ ++static ssize_t _fname##_store(struct device *dev, \ ++ struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ struct asus_wmi *asus = dev_get_drvdata(dev); \ ++ return rog_tunable_store(asus, &attr->attr, buf, count, \ ++ _min, asus->rog_tunables._max, asus->rog_tunables._default, \ ++ &asus->rog_tunables._fname, _wmi); \ ++} ++ ++#define ROG_TUNABLE_SHOW(_fname) \ ++static ssize_t _fname##_show(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct asus_wmi *asus = dev_get_drvdata(dev); \ ++ return sysfs_emit(buf, "%u\n", asus->rog_tunables._fname); \ ++} ++ ++#define ROG_TUNABLE_MIN_SHOW(_fname, _minv) \ ++static ssize_t _fname##_min_show(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ return sysfs_emit(buf, "%u\n", _minv); \ ++} ++ ++#define ROG_TUNABLE_MAX_SHOW(_fname, _maxv) \ ++static ssize_t _fname##_max_show(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct asus_wmi *asus = dev_get_drvdata(dev); \ ++ return sysfs_emit(buf, "%u\n", asus->rog_tunables._maxv); \ ++} ++ ++#define ROG_ATTR_RW(_fname, _minv, _maxv, _defaultv, _wmi) \ ++ROG_TUNABLE_MIN_SHOW(_fname, _minv); \ ++ROG_TUNABLE_MAX_SHOW(_fname, _maxv); \ ++ROG_TUNABLE_STORE(_fname, _minv, _maxv, _defaultv, _wmi);\ ++ROG_TUNABLE_SHOW(_fname); \ ++static DEVICE_ATTR_RO(_fname##_min); \ ++static DEVICE_ATTR_RO(_fname##_max); \ ++static DEVICE_ATTR_RW(_fname) ++ ++ROG_ATTR_RW(ppt_platform_sppt, ++ PPT_PLATFORM_MIN, platform_max, platform_default, ASUS_WMI_DEVID_PPT_PLAT_SPPT); ++ROG_ATTR_RW(ppt_pl2_sppt, ++ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_PL2_SPPT); ++ROG_ATTR_RW(ppt_apu_sppt, ++ PPT_PLATFORM_MIN, platform_max, platform_default, ASUS_WMI_DEVID_PPT_APU_SPPT); ++ROG_ATTR_RW(ppt_pl1_spl, ++ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_PL1_SPL); ++ROG_ATTR_RW(ppt_fppt, ++ PPT_CPU_LIMIT_MIN, cpu_max, cpu_default, ASUS_WMI_DEVID_PPT_FPPT); ++ROG_ATTR_RW(nv_dynamic_boost, ++ NVIDIA_BOOST_MIN, nv_boost_max, nv_boost_default, ASUS_WMI_DEVID_NV_DYN_BOOST); ++ROG_ATTR_RW(nv_temp_target, ++ NVIDIA_TEMP_MIN, nv_temp_max, nv_temp_default, ASUS_WMI_DEVID_NV_THERM_TARGET); ++ + /* Tablet mode ****************************************************************/ + + static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) +@@ -1018,306 +1128,6 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { + NULL, + }; + +-/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/ +-static ssize_t ppt_pl2_sppt_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result); +- if (err) { +- pr_warn("Failed to set ppt_pl2_sppt: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->ppt_pl2_sppt = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt"); +- +- return count; +-} +- +-static ssize_t ppt_pl2_sppt_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->ppt_pl2_sppt); +-} +-static DEVICE_ATTR_RW(ppt_pl2_sppt); +- +-/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/ +-static ssize_t ppt_pl1_spl_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result); +- if (err) { +- pr_warn("Failed to set ppt_pl1_spl: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->ppt_pl1_spl = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl"); +- +- return count; +-} +-static ssize_t ppt_pl1_spl_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->ppt_pl1_spl); +-} +-static DEVICE_ATTR_RW(ppt_pl1_spl); +- +-/* Tunable: PPT APU FPPT ******************************************************/ +-static ssize_t ppt_fppt_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result); +- if (err) { +- pr_warn("Failed to set ppt_fppt: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->ppt_fppt = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt"); +- +- return count; +-} +- +-static ssize_t ppt_fppt_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->ppt_fppt); +-} +-static DEVICE_ATTR_RW(ppt_fppt); +- +-/* Tunable: PPT APU SPPT *****************************************************/ +-static ssize_t ppt_apu_sppt_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result); +- if (err) { +- pr_warn("Failed to set ppt_apu_sppt: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->ppt_apu_sppt = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt"); +- +- return count; +-} +- +-static ssize_t ppt_apu_sppt_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->ppt_apu_sppt); +-} +-static DEVICE_ATTR_RW(ppt_apu_sppt); +- +-/* Tunable: PPT platform SPPT ************************************************/ +-static ssize_t ppt_platform_sppt_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < PPT_CPU_MIN || value > PPT_CPU_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result); +- if (err) { +- pr_warn("Failed to set ppt_platform_sppt: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->ppt_platform_sppt = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt"); +- +- return count; +-} +- +-static ssize_t ppt_platform_sppt_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->ppt_platform_sppt); +-} +-static DEVICE_ATTR_RW(ppt_platform_sppt); +- +-/* Tunable: NVIDIA dynamic boost *********************************************/ +-static ssize_t nv_dynamic_boost_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result); +- if (err) { +- pr_warn("Failed to set nv_dynamic_boost: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->nv_dynamic_boost = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost"); +- +- return count; +-} +- +-static ssize_t nv_dynamic_boost_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->nv_dynamic_boost); +-} +-static DEVICE_ATTR_RW(nv_dynamic_boost); +- +-/* Tunable: NVIDIA temperature target ****************************************/ +-static ssize_t nv_temp_target_store(struct device *dev, +- struct device_attribute *attr, +- const char *buf, size_t count) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- int result, err; +- u32 value; +- +- result = kstrtou32(buf, 10, &value); +- if (result) +- return result; +- +- if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX) +- return -EINVAL; +- +- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result); +- if (err) { +- pr_warn("Failed to set nv_temp_target: %d\n", err); +- return err; +- } +- +- if (result > 1) { +- pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result); +- return -EIO; +- } +- +- asus->nv_temp_target = value; +- sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target"); +- +- return count; +-} +- +-static ssize_t nv_temp_target_show(struct device *dev, +- struct device_attribute *attr, +- char *buf) +-{ +- struct asus_wmi *asus = dev_get_drvdata(dev); +- +- return sysfs_emit(buf, "%u\n", asus->nv_temp_target); +-} +-static DEVICE_ATTR_RW(nv_temp_target); +- + /* Ally MCU Powersave ********************************************************/ + static ssize_t mcu_powersave_show(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -4367,13 +4177,27 @@ static struct attribute *platform_attributes[] = { + &dev_attr_als_enable.attr, + &dev_attr_fan_boost_mode.attr, + &dev_attr_throttle_thermal_policy.attr, +- &dev_attr_ppt_pl2_sppt.attr, + &dev_attr_ppt_pl1_spl.attr, ++ &dev_attr_ppt_pl1_spl_min.attr, ++ &dev_attr_ppt_pl1_spl_max.attr, ++ &dev_attr_ppt_pl2_sppt.attr, ++ &dev_attr_ppt_pl2_sppt_min.attr, ++ &dev_attr_ppt_pl2_sppt_max.attr, + &dev_attr_ppt_fppt.attr, ++ &dev_attr_ppt_fppt_min.attr, ++ &dev_attr_ppt_fppt_max.attr, + &dev_attr_ppt_apu_sppt.attr, ++ &dev_attr_ppt_apu_sppt_min.attr, ++ &dev_attr_ppt_apu_sppt_max.attr, + &dev_attr_ppt_platform_sppt.attr, ++ &dev_attr_ppt_platform_sppt_min.attr, ++ &dev_attr_ppt_platform_sppt_max.attr, + &dev_attr_nv_dynamic_boost.attr, ++ &dev_attr_nv_dynamic_boost_min.attr, ++ &dev_attr_nv_dynamic_boost_max.attr, + &dev_attr_nv_temp_target.attr, ++ &dev_attr_nv_temp_target_min.attr, ++ &dev_attr_nv_temp_target_max.attr, + &dev_attr_mcu_powersave.attr, + &dev_attr_boot_sound.attr, + &dev_attr_panel_od.attr, +@@ -4414,19 +4238,33 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + ok = asus->fan_boost_mode_available; + else if (attr == &dev_attr_throttle_thermal_policy.attr) + ok = asus->throttle_thermal_policy_available; +- else if (attr == &dev_attr_ppt_pl2_sppt.attr) ++ else if (attr == &dev_attr_ppt_pl2_sppt.attr ++ || attr == &dev_attr_ppt_pl2_sppt_min.attr ++ || attr == &dev_attr_ppt_pl2_sppt_max.attr) + devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; +- else if (attr == &dev_attr_ppt_pl1_spl.attr) ++ else if (attr == &dev_attr_ppt_pl1_spl.attr ++ || attr == &dev_attr_ppt_pl1_spl_min.attr ++ || attr == &dev_attr_ppt_pl1_spl_max.attr) + devid = ASUS_WMI_DEVID_PPT_PL1_SPL; +- else if (attr == &dev_attr_ppt_fppt.attr) ++ else if (attr == &dev_attr_ppt_fppt.attr ++ || attr == &dev_attr_ppt_fppt_min.attr ++ || attr == &dev_attr_ppt_fppt_max.attr) + devid = ASUS_WMI_DEVID_PPT_FPPT; +- else if (attr == &dev_attr_ppt_apu_sppt.attr) ++ else if (attr == &dev_attr_ppt_apu_sppt.attr ++ || attr == &dev_attr_ppt_apu_sppt_min.attr ++ || attr == &dev_attr_ppt_apu_sppt_max.attr) + devid = ASUS_WMI_DEVID_PPT_APU_SPPT; +- else if (attr == &dev_attr_ppt_platform_sppt.attr) ++ else if (attr == &dev_attr_ppt_platform_sppt.attr ++ || attr == &dev_attr_ppt_platform_sppt_min.attr ++ || attr == &dev_attr_ppt_platform_sppt_max.attr) + devid = ASUS_WMI_DEVID_PPT_PLAT_SPPT; +- else if (attr == &dev_attr_nv_dynamic_boost.attr) ++ else if (attr == &dev_attr_nv_dynamic_boost.attr ++ || attr == &dev_attr_nv_dynamic_boost_min.attr ++ || attr == &dev_attr_nv_dynamic_boost_max.attr) + devid = ASUS_WMI_DEVID_NV_DYN_BOOST; +- else if (attr == &dev_attr_nv_temp_target.attr) ++ else if (attr == &dev_attr_nv_temp_target.attr ++ || attr == &dev_attr_nv_temp_target_min.attr ++ || attr == &dev_attr_nv_temp_target_max.attr) + devid = ASUS_WMI_DEVID_NV_THERM_TARGET; + else if (attr == &dev_attr_mcu_powersave.attr) + devid = ASUS_WMI_DEVID_MCU_POWERSAVE; +@@ -4652,6 +4490,77 @@ static void asus_wmi_debugfs_init(struct asus_wmi *asus) + + /* Init / exit ****************************************************************/ + ++/* Set up the min/max and defaults for ROG tunables */ ++static void init_rog_tunables(struct asus_wmi *asus) ++{ ++ const char *product; ++ u32 max_boost = NVIDIA_BOOST_MAX; ++ u32 cpu_default = PPT_CPU_LIMIT_DEFAULT; ++ u32 cpu_max = PPT_CPU_LIMIT_MAX; ++ u32 platform_default = PPT_PLATFORM_DEFAULT; ++ u32 platform_max = PPT_PLATFORM_MAX; ++ ++ /* ++ * ASUS product_name contains everything required, e.g, ++ * "ROG Flow X16 GV601VV_GV601VV_00185149B" ++ */ ++ product = dmi_get_system_info(DMI_PRODUCT_NAME); ++ ++ if (strstr(product, "GA402R")) { ++ cpu_default = 125; ++ } else if (strstr(product, "13QY")) { ++ cpu_max = 250; ++ } else if (strstr(product, "X13")) { ++ cpu_max = 75; ++ cpu_default = 50; ++ } else if (strstr(product, "RC71")) { ++ cpu_max = 50; ++ cpu_default = 30; ++ } else if (strstr(product, "G814") ++ || strstr(product, "G614") ++ || strstr(product, "G834") ++ || strstr(product, "G634")) { ++ cpu_max = 175; ++ } else if (strstr(product, "GA402X") ++ || strstr(product, "GA403") ++ || strstr(product, "FA507N") ++ || strstr(product, "FA507X") ++ || strstr(product, "FA707N") ++ || strstr(product, "FA707X")) { ++ cpu_max = 90; ++ } ++ ++ if (strstr(product, "GZ301ZE")) ++ max_boost = 5; ++ else if (strstr(product, "FX507ZC4")) ++ max_boost = 15; ++ else if (strstr(product, "GU605")) ++ max_boost = 20; ++ ++ /* ensure defaults for tunables */ ++ asus->rog_tunables.cpu_default = cpu_default; ++ asus->rog_tunables.cpu_max = cpu_max; ++ ++ asus->rog_tunables.platform_default = platform_default; ++ asus->rog_tunables.platform_max = platform_max; ++ ++ asus->rog_tunables.ppt_pl1_spl = cpu_default; ++ asus->rog_tunables.ppt_pl2_sppt = cpu_default; ++ asus->rog_tunables.ppt_apu_sppt = cpu_default; ++ ++ asus->rog_tunables.ppt_platform_sppt = platform_default; ++ asus->rog_tunables.ppt_fppt = platform_default; ++ ++ asus->rog_tunables.nv_boost_default = NVIDIA_BOOST_MAX; ++ asus->rog_tunables.nv_boost_max = max_boost; ++ asus->rog_tunables.nv_dynamic_boost = NVIDIA_BOOST_MIN; ++ ++ asus->rog_tunables.nv_temp_default = NVIDIA_TEMP_MAX; ++ asus->rog_tunables.nv_temp_max = NVIDIA_TEMP_MAX; ++ asus->rog_tunables.nv_temp_target = NVIDIA_TEMP_MIN; ++ ++} ++ + static int asus_wmi_add(struct platform_device *pdev) + { + struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver); +@@ -4677,15 +4586,7 @@ static int asus_wmi_add(struct platform_device *pdev) + if (err) + goto fail_platform; + +- /* ensure defaults for tunables */ +- asus->ppt_pl2_sppt = 5; +- asus->ppt_pl1_spl = 5; +- asus->ppt_apu_sppt = 5; +- asus->ppt_platform_sppt = 5; +- asus->ppt_fppt = 5; +- asus->nv_dynamic_boost = 5; +- asus->nv_temp_target = 75; +- ++ init_rog_tunables(asus); + asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); + asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); + asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); +-- +2.45.1 + diff --git a/0004-asus-bios-add-panel-hd-control.patch b/0004-asus-bios-add-panel-hd-control.patch new file mode 100644 index 000000000000..20c298f05397 --- /dev/null +++ b/0004-asus-bios-add-panel-hd-control.patch @@ -0,0 +1,57 @@ +From 4a50aed36c4c202688226653511af52f5a4915e1 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Sun, 2 Jun 2024 13:44:22 +1200 +Subject: [PATCH 4/8] asus-bios: add panel-hd control + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-bios.c | 6 +++++- + include/linux/platform_data/x86/asus-wmi.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c +index c245a48c4072..9af7a8da9c05 100644 +--- a/drivers/platform/x86/asus-bios.c ++++ b/drivers/platform/x86/asus-bios.c +@@ -126,7 +126,8 @@ static ssize_t pending_reboot_show(struct kobject *kobj, + static struct kobj_attribute pending_reboot = __ATTR_RO(pending_reboot); + + static bool asus_bios_requires_reboot(struct kobj_attribute *attr) { +- return !strcmp(attr->attr.name, "gpu_mux_mode"); ++ return !strcmp(attr->attr.name, "gpu_mux_mode") || ++ !strcmp(attr->attr.name, "panel_hd_mode"); + } + + /* +@@ -445,6 +446,7 @@ ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, 0 + ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, "Set the boot POST sound"); + ATTR_GROUP_BOOL_RW(mcu_powersave, "mcu_powersave", ASUS_WMI_DEVID_MCU_POWERSAVE, "Set MCU powersaving mode"); + ATTR_GROUP_BOOL_RW(panel_od, "panel_overdrive", ASUS_WMI_DEVID_PANEL_OD, "Set the panel refresh overdrive"); ++ATTR_GROUP_BOOL_RW(panel_hd_mode, "panel_hd_mode", ASUS_WMI_DEVID_PANEL_HD, "Set the panel HD mode to UHD<0> or FHD<1>"); + ATTR_GROUP_BOOL_RO(egpu_connected, "egpu_connected", ASUS_WMI_DEVID_EGPU_CONNECTED, "Show the eGPU connection status"); + + static int asus_fw_attr_add(void) +@@ -533,6 +535,8 @@ static int asus_fw_attr_add(void) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &mcu_powersave_attr_group); + if (asus_wmi_is_present(ASUS_WMI_DEVID_PANEL_OD)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &panel_od_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_PANEL_HD)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &panel_hd_mode_attr_group); + + return 0; + +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 525cb7c803fe..c93068afc2b6 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -67,6 +67,7 @@ + #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 + + /* Misc */ ++#define ASUS_WMI_DEVID_PANEL_HD 0x0005001C + #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 + #define ASUS_WMI_DEVID_CAMERA 0x00060013 + #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 +-- +2.45.1 + diff --git a/0005-asus-bios-add-dgpu-tgp-control.patch b/0005-asus-bios-add-dgpu-tgp-control.patch new file mode 100644 index 000000000000..63cc4dd3e51b --- /dev/null +++ b/0005-asus-bios-add-dgpu-tgp-control.patch @@ -0,0 +1,105 @@ +From 59d69aba37bc9ca2a22a2c44d8a5dd8600d2a35c Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Sun, 2 Jun 2024 14:32:15 +1200 +Subject: [PATCH 5/8] asus-bios: add dgpu tgp control + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-bios.c | 8 +++++++ + drivers/platform/x86/asus-bios.h | 25 ++++++++++++++++++++++ + include/linux/platform_data/x86/asus-wmi.h | 3 +++ + 3 files changed, 36 insertions(+) + +diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c +index 9af7a8da9c05..d453f02a22fd 100644 +--- a/drivers/platform/x86/asus-bios.c ++++ b/drivers/platform/x86/asus-bios.c +@@ -53,6 +53,7 @@ MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); + #define NVIDIA_BOOST_MAX 25 + #define NVIDIA_TEMP_MIN 75 + #define NVIDIA_TEMP_MAX 87 ++#define NVIDIA_GPU_POWER_MAX 70 + + /* Tunables provided by ASUS for gaming laptops */ + struct rog_tunables { +@@ -441,6 +442,9 @@ ATTR_GROUP_PPT_RW(nv_dynamic_boost, "nv_dynamic_boost", ASUS_WMI_DEVID_NV_DYN_BO + nv_boost_default, 5, nv_boost_max, 1, "Set the Nvidia dynamic boost limit"); + ATTR_GROUP_PPT_RW(nv_temp_target, "nv_temp_target", ASUS_WMI_DEVID_NV_THERM_TARGET, + nv_temp_default, 75, nv_temp_max, 1, "Set the Nvidia max thermal limit"); ++ATTR_GROUP_INT_VALUE_ONLY_RO(dgpu_base_tgp, "dgpu_base_tgp", ASUS_WMI_DEVID_DGPU_BASE_TGP, "Read the base TGP value") ++ATTR_GROUP_INT_RW(dgpu_tgp, "dgpu_tgp", ASUS_WMI_DEVID_DGPU_SET_TGP, ++ 70, 0, NVIDIA_GPU_POWER_MAX, 1, "Set the additional TGP on top of the base TGP"); + + ATTR_GROUP_ENUM_INT_RO(charge_mode, "charge_mode", ASUS_WMI_DEVID_CHARGE_MODE, 0, 0, "0;1;2", "Show the current mode of charging"); + ATTR_GROUP_BOOL_RW(boot_sound, "boot_sound", ASUS_WMI_DEVID_BOOT_SOUND, "Set the boot POST sound"); +@@ -526,6 +530,10 @@ static int asus_fw_attr_add(void) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_dynamic_boost_attr_group); + if (asus_wmi_is_present(ASUS_WMI_DEVID_NV_THERM_TARGET)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &nv_temp_target_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU_BASE_TGP)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_base_tgp_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU_SET_TGP)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_tgp_attr_group); + + if (asus_wmi_is_present(ASUS_WMI_DEVID_CHARGE_MODE)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &charge_mode_attr_group); +diff --git a/drivers/platform/x86/asus-bios.h b/drivers/platform/x86/asus-bios.h +index acae11698a07..7c4176ab757a 100644 +--- a/drivers/platform/x86/asus-bios.h ++++ b/drivers/platform/x86/asus-bios.h +@@ -112,6 +112,22 @@ static ssize_t _attrname##_##_prop##_show(struct kobject *kobj, \ + static struct kobj_attribute attr_##_attrname##_##_prop = \ + __ASUS_ATTR_RO(_attrname, _prop); + ++/* Requires current_value show&|store */ ++#define __ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname) \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, int_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ + /* Int style min/max range, base macro. Requires current_value show&|store */ + #define __ATTR_GROUP_INT(_attrname, _fsname, _default, \ + _min, _max, _incstep, _dispname)\ +@@ -155,6 +171,15 @@ static const struct attribute_group _attrname##_attr_group = { \ + .attrs = _attrname##_attrs \ + }; + ++#define ATTR_GROUP_INT_VALUE_ONLY_RO(_attrname, _fsname, _wmi, _dispname) \ ++__ATTR_CURRENT_INT_RO(_attrname, _wmi); \ ++__ATTR_GROUP_INT_VALUE_ONLY(_attrname, _fsname, _dispname); ++ ++#define ATTR_GROUP_INT_RW(_attrname, _fsname, _wmi, _default, _min, \ ++ _max, _incstep, _dispname) \ ++__ATTR_CURRENT_INT_RW(_attrname, _min, _max, _wmi); \ ++__ATTR_GROUP_INT(_attrname, _fsname, _default, _min, _max, _incstep, _dispname); ++ + #define ATTR_GROUP_BOOL_RO(_attrname, _fsname, _wmi, _dispname) \ + __ATTR_CURRENT_INT_RO(_attrname, _wmi); \ + __ATTR_GROUP_ENUM(_attrname, _fsname, "0;1", _dispname); +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index c93068afc2b6..71f3f1d67479 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -128,6 +128,9 @@ + /* dgpu on/off */ + #define ASUS_WMI_DEVID_DGPU 0x00090020 + ++#define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 ++#define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 ++ + /* gpu mux switch, 0 = dGPU, 1 = Optimus */ + #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 + #define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 +-- +2.45.1 + diff --git a/0006-asus-bios-add-apu-mem.patch b/0006-asus-bios-add-apu-mem.patch new file mode 100644 index 000000000000..17ec6262547b --- /dev/null +++ b/0006-asus-bios-add-apu-mem.patch @@ -0,0 +1,160 @@ +From ae58c8b2e60a5feff3cf833d7f572414758d06c2 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Sun, 2 Jun 2024 14:44:31 +1200 +Subject: [PATCH 6/8] asus-bios: add apu-mem + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-bios.c | 116 +++++++++++++++++++++ + include/linux/platform_data/x86/asus-wmi.h | 1 + + 2 files changed, 117 insertions(+) + +diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c +index d453f02a22fd..bcb053b57102 100644 +--- a/drivers/platform/x86/asus-bios.c ++++ b/drivers/platform/x86/asus-bios.c +@@ -425,6 +425,120 @@ static ssize_t egpu_enable_current_value_store(struct kobject *kobj, + WMI_SHOW_INT(egpu_enable_current_value, "%d\n", ASUS_WMI_DEVID_EGPU); + ATTR_GROUP_BOOL_CUSTOM(egpu_enable, "egpu_enable", "Enable the eGPU (also disables dGPU)"); + ++/* Device memory available to APU */ ++ ++static ssize_t apu_mem_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int err; ++ u32 mem; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_APU_MEM, &mem); ++ if (err) ++ return err; ++ ++ switch (mem) { ++ case 256: ++ mem = 0; ++ break; ++ case 258: ++ mem = 1; ++ break; ++ case 259: ++ mem = 2; ++ break; ++ case 260: ++ mem = 3; ++ break; ++ case 261: ++ mem = 4; ++ break; ++ case 262: ++ /* This is out of order and looks wrong but is correct */ ++ mem = 8; ++ break; ++ case 263: ++ mem = 5; ++ break; ++ case 264: ++ mem = 6; ++ break; ++ case 265: ++ mem = 7; ++ break; ++ default: ++ mem = 4; ++ break; ++ } ++ ++ return sysfs_emit(buf, "%d\n", mem); ++} ++ ++static ssize_t apu_mem_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int result, err; ++ u32 requested, mem; ++ ++ result = kstrtou32(buf, 10, &requested); ++ if (result) ++ return result; ++ ++ switch (requested) { ++ case 0: ++ mem = 0; ++ break; ++ case 1: ++ mem = 258; ++ break; ++ case 2: ++ mem = 259; ++ break; ++ case 3: ++ mem = 260; ++ break; ++ case 4: ++ mem = 261; ++ break; ++ case 5: ++ mem = 263; ++ break; ++ case 6: ++ mem = 264; ++ break; ++ case 7: ++ mem = 265; ++ break; ++ case 8: ++ /* This is outof order and looks wrong but is correct */ ++ mem = 262; ++ break; ++ default: ++ return -EIO; ++ } ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_APU_MEM, mem, &result); ++ if (err) { ++ pr_warn("Failed to set apu_mem: %d\n", err); ++ return err; ++ } ++ ++ pr_info("APU memory changed to %dGB, reboot required\n", requested); ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ ++ asus_set_reboot_and_signal_event(); ++ ++ return count; ++} ++ ++static ssize_t apu_mem_possible_values_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sysfs_emit(buf, "0;1;2;3;4;5;6;7;8\n"); ++} ++ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use"); ++ + /* Simple attribute creation */ + ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo"); + ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, +@@ -534,6 +648,8 @@ static int asus_fw_attr_add(void) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_base_tgp_attr_group); + if (asus_wmi_is_present(ASUS_WMI_DEVID_DGPU_SET_TGP)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &dgpu_tgp_attr_group); ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_APU_MEM)) ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &apu_mem_attr_group); + + if (asus_wmi_is_present(ASUS_WMI_DEVID_CHARGE_MODE)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &charge_mode_attr_group); +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 71f3f1d67479..da0e423ecb06 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -130,6 +130,7 @@ + + #define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 + #define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 ++#define ASUS_WMI_DEVID_APU_MEM 0x000600C1 + + /* gpu mux switch, 0 = dGPU, 1 = Optimus */ + #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 +-- +2.45.1 + diff --git a/0007-asus-bios-add-core-count-control.patch b/0007-asus-bios-add-core-count-control.patch new file mode 100644 index 000000000000..4b3fc16b807e --- /dev/null +++ b/0007-asus-bios-add-core-count-control.patch @@ -0,0 +1,305 @@ +From f7e8fe2458a3f8aa091e5e282b67f2a78f5cc1c4 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Sun, 2 Jun 2024 16:21:32 +1200 +Subject: [PATCH 7/8] asus-bios: add core count control + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/platform/x86/asus-bios.c | 201 +++++++++++++++++++++ + drivers/platform/x86/asus-bios.h | 29 +++ + include/linux/platform_data/x86/asus-wmi.h | 4 + + 3 files changed, 234 insertions(+) + +diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c +index bcb053b57102..bd4c408fd062 100644 +--- a/drivers/platform/x86/asus-bios.c ++++ b/drivers/platform/x86/asus-bios.c +@@ -42,6 +42,18 @@ MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); + #define ASUS_MINI_LED_2024_STRONG 0x01 + #define ASUS_MINI_LED_2024_OFF 0x02 + ++enum cpu_core_type { ++ CPU_CORE_PERF = 0, ++ CPU_CORE_POWER, ++}; ++ ++enum cpu_core_value { ++ CPU_CORE_DEFAULT = 0, ++ CPU_CORE_MIN, ++ CPU_CORE_MAX, ++ CPU_CORE_CURRENT, ++}; ++ + /* Default limits for tunables available on ASUS ROG laptops */ + #define PPT_CPU_LIMIT_MIN 5 + #define PPT_CPU_LIMIT_MAX 150 +@@ -76,6 +88,10 @@ struct rog_tunables { + u32 nv_temp_default; + u32 nv_temp_max; + u32 nv_temp_target; ++ ++ u32 min_perf_cores; ++ u32 max_perf_cores; ++ u32 max_power_cores; + }; + + static const struct class *fw_attr_class; +@@ -539,6 +555,185 @@ static ssize_t apu_mem_possible_values_show(struct kobject *kobj, + } + ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use"); + ++static int asus_bios_set_max_cores(void) ++{ ++ u32 cores; ++ int err; ++ ++ asus_bios.rog_tunables->min_perf_cores = 4; ++ asus_bios.rog_tunables->max_perf_cores = 4; ++ asus_bios.rog_tunables->max_power_cores = 8; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES_MAX, &cores); ++ if (err) ++ return err; ++ ++ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; ++ asus_bios.rog_tunables->max_power_cores = (cores & 0xff00) >> 8; ++ asus_bios.rog_tunables->max_perf_cores = cores & 0xff; ++ ++ return 0; ++} ++ ++static ssize_t cores_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf, ++ enum cpu_core_type core_type, ++ enum cpu_core_value core_value) ++{ ++ u32 cores; ++ int err; ++ ++ switch (core_value) { ++ case CPU_CORE_DEFAULT: ++ case CPU_CORE_MAX: ++ if (core_type == CPU_CORE_PERF) ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_perf_cores); ++ else ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_power_cores); ++ case CPU_CORE_MIN: ++ if (core_type == CPU_CORE_PERF) ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->min_perf_cores); ++ else ++ return sysfs_emit(buf, "%d\n", 0); ++ default: ++ break; ++ } ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, &cores); ++ if (err) ++ return err; ++ ++ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; ++ if (core_type == CPU_CORE_PERF) ++ cores &= 0xff; ++ else ++ cores = (cores & 0xff00) >> 8; ++ return sysfs_emit(buf, "%d\n", cores); ++} ++ ++static ssize_t cores_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, const char *buf, ++ enum cpu_core_type core_type) ++{ ++ int result, err; ++ u32 cores, currentv, min, max; ++ ++ result = kstrtou32(buf, 10, &cores); ++ if (result) ++ return result; ++ ++ if (core_type == CPU_CORE_PERF) { ++ min = asus_bios.rog_tunables->min_perf_cores; ++ max = asus_bios.rog_tunables->max_perf_cores; ++ } else { ++ min = 0; ++ max = asus_bios.rog_tunables->max_power_cores; ++ } ++ if (cores < min || cores > max) ++ return -EINVAL; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, ¤tv); ++ if (err) ++ return err; ++ ++ if (core_type == CPU_CORE_PERF) ++ cores |= (currentv & 0xff00); ++ else ++ cores |= currentv & 0xff; ++ ++ if (cores == currentv) ++ return 0; ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CORES, cores, &result); ++ if (err) { ++ pr_warn("Failed to set perfromance core count: %d\n", err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_warn("Failed to set performance core count (result): 0x%x\n", result); ++ return -EIO; ++ } ++ ++ pr_info("CPU core count changed, reboot required\n"); ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ asus_set_reboot_and_signal_event(); ++ ++ return 0; ++} ++ ++static ssize_t cores_performance_min_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MIN); ++} ++ ++static ssize_t cores_performance_max_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MAX); ++} ++ ++static ssize_t cores_performance_default_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_DEFAULT); ++} ++ ++static ssize_t cores_performance_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_CURRENT); ++} ++ ++static ssize_t cores_performance_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF); ++ if (err) ++ return err; ++ ++ return count; ++} ++ATTR_GROUP_CORES_RW(cores_performance, "cores_performance", ASUS_WMI_DEVID_CORES, "Set the max available performance cores"); ++ ++static ssize_t cores_efficiency_min_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MIN); ++} ++ ++static ssize_t cores_efficiency_max_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MAX); ++} ++ ++static ssize_t cores_efficiency_default_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_DEFAULT); ++} ++ ++static ssize_t cores_efficiency_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_CURRENT); ++} ++ ++static ssize_t cores_efficiency_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER); ++ if (err) ++ return err; ++ ++ return count; ++} ++ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency", ASUS_WMI_DEVID_CORES, "Set the max available efficiency cores"); ++ + /* Simple attribute creation */ + ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo"); + ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, +@@ -627,8 +822,14 @@ static int asus_fw_attr_add(void) + if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU_CONNECTED)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_connected_attr_group); + ++ if (asus_wmi_is_present(ASUS_WMI_DEVID_CORES_MAX) && !asus_bios_set_max_cores()){ ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_performance_attr_group); ++ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_efficiency_attr_group); ++ } ++ + if (asus_wmi_is_present(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &thermal_policy_attr_group); ++ + if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL1_SPL)) + sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl1_spl_attr_group); + if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL2_SPPT)) +diff --git a/drivers/platform/x86/asus-bios.h b/drivers/platform/x86/asus-bios.h +index 7c4176ab757a..7016ec14efc1 100644 +--- a/drivers/platform/x86/asus-bios.h ++++ b/drivers/platform/x86/asus-bios.h +@@ -230,6 +230,35 @@ static const struct attribute_group _attrname##_attr_group = { \ + .attrs = _attrname##_attrs \ + }; + ++/* CPU core attributes need a little different in setup */ ++#define ATTR_GROUP_CORES_RW(_attrname, _fsname, _wmi, _dispname)\ ++__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", 1); \ ++__ATTR_SHOW_FMT(display_name, _attrname, "%s\n", _dispname); \ ++static struct kobj_attribute attr_##_attrname##_current_value = \ ++ __ASUS_ATTR_RW(_attrname, current_value); \ ++static struct kobj_attribute attr_##_attrname##_default_value = \ ++ __ASUS_ATTR_RO(_attrname, default_value); \ ++static struct kobj_attribute attr_##_attrname##_min_value = \ ++ __ASUS_ATTR_RO(_attrname, min_value); \ ++static struct kobj_attribute attr_##_attrname##_max_value = \ ++ __ASUS_ATTR_RO(_attrname, max_value); \ ++static struct kobj_attribute attr_##_attrname##_type = \ ++ __ASUS_ATTR_RO_AS(type, int_type_show); \ ++static struct attribute *_attrname##_attrs[] = { \ ++ &attr_##_attrname##_current_value.attr, \ ++ &attr_##_attrname##_default_value.attr, \ ++ &attr_##_attrname##_min_value.attr, \ ++ &attr_##_attrname##_max_value.attr, \ ++ &attr_##_attrname##_scalar_increment.attr, \ ++ &attr_##_attrname##_display_name.attr, \ ++ &attr_##_attrname##_type.attr, \ ++ NULL \ ++}; \ ++static const struct attribute_group _attrname##_attr_group = { \ ++ .name = _fsname, \ ++ .attrs = _attrname##_attrs \ ++}; ++ + /* ROG PPT attributes need a little different in setup */ + #define ATTR_GROUP_PPT_RW(_attrname, _fsname, _wmi, _default, \ + _min, _max, _incstep, _dispname) \ +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index da0e423ecb06..9756e595d2cd 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -128,6 +128,10 @@ + /* dgpu on/off */ + #define ASUS_WMI_DEVID_DGPU 0x00090020 + ++/* Intel E-core and P-core configuration in a format 0x0[E]0[P] */ ++#define ASUS_WMI_DEVID_CORES 0x001200D2 ++ /* Maximum Intel E-core and P-core availability */ ++#define ASUS_WMI_DEVID_CORES_MAX 0x001200D3 + #define ASUS_WMI_DEVID_DGPU_BASE_TGP 0x00120099 + #define ASUS_WMI_DEVID_DGPU_SET_TGP 0x00120098 + #define ASUS_WMI_DEVID_APU_MEM 0x000600C1 +-- +2.45.1 + diff --git a/0008-asus-wmi-deprecate-bios-features.patch b/0008-asus-wmi-deprecate-bios-features.patch new file mode 100644 index 000000000000..3eb5d138cdac --- /dev/null +++ b/0008-asus-wmi-deprecate-bios-features.patch @@ -0,0 +1,592 @@ +From 0c31b9b182c43ac0e72c04ce9e0f9fa4b7f62271 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Mon, 3 Jun 2024 12:04:41 +1200 +Subject: [PATCH 8/8] asus-wmi: deprecate bios features + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + .../ABI/testing/sysfs-platform-asus-wmi | 17 +++ + drivers/platform/x86/Kconfig | 8 ++ + drivers/platform/x86/asus-wmi.c | 126 ++++++++++++++---- + 3 files changed, 123 insertions(+), 28 deletions(-) + +diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi +index 28144371a0f1..765d50b0d9df 100644 +--- a/Documentation/ABI/testing/sysfs-platform-asus-wmi ++++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi +@@ -63,6 +63,7 @@ Date: Aug 2022 + KernelVersion: 6.1 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Switch the GPU hardware MUX mode. Laptops with this feature can + can be toggled to boot with only the dGPU (discrete mode) or in + standard Optimus/Hybrid mode. On switch a reboot is required: +@@ -75,6 +76,7 @@ Date: Aug 2022 + KernelVersion: 5.17 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Disable discrete GPU: + * 0 - Enable dGPU, + * 1 - Disable dGPU +@@ -84,6 +86,7 @@ Date: Aug 2022 + KernelVersion: 5.17 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Enable the external GPU paired with ROG X-Flow laptops. + Toggling this setting will also trigger ACPI to disable the dGPU: + +@@ -95,6 +98,7 @@ Date: Aug 2022 + KernelVersion: 5.17 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Enable an LCD response-time boost to reduce or remove ghosting: + * 0 - Disable, + * 1 - Enable +@@ -104,6 +108,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Get the current charging mode being used: + * 1 - Barrel connected charger, + * 2 - USB-C charging +@@ -114,6 +119,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Show if the egpu (XG Mobile) is correctly connected: + * 0 - False, + * 1 - True +@@ -123,6 +129,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Change the mini-LED mode: + * 0 - Single-zone, + * 1 - Multi-zone +@@ -133,6 +140,7 @@ Date: Apr 2024 + KernelVersion: 6.10 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + List the available mini-led modes. + + What: /sys/devices/platform/<platform>/ppt_pl1_spl +@@ -140,6 +148,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. + Shown on Intel+Nvidia or AMD+Nvidia based systems: + +@@ -150,6 +159,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the Slow Package Power Tracking Limit of CPU: PL2 on Intel, SPPT, + on AMD. Shown on Intel+Nvidia or AMD+Nvidia based systems: + +@@ -160,6 +170,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the Fast Package Power Tracking Limit of CPU. AMD+Nvidia only: + * min=5, max=250 + +@@ -168,6 +179,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the APU SPPT limit. Shown on full AMD systems only: + * min=5, max=130 + +@@ -176,6 +188,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the platform SPPT limit. Shown on full AMD systems only: + * min=5, max=130 + +@@ -184,6 +197,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the dynamic boost limit of the Nvidia dGPU: + * min=5, max=25 + +@@ -192,6 +206,7 @@ Date: Jun 2023 + KernelVersion: 6.5 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set the target temperature limit of the Nvidia dGPU: + * min=75, max=87 + +@@ -200,6 +215,7 @@ Date: Apr 2024 + KernelVersion: 6.10 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set if the BIOS POST sound is played on boot. + * 0 - False, + * 1 - True +@@ -209,6 +225,7 @@ Date: Apr 2024 + KernelVersion: 6.10 + Contact: "Luke Jones" <luke@ljones.dev> + Description: ++ DEPRECATED, WILL BE REMOVED SOON + Set if the MCU can go in to low-power mode on system sleep + * 0 - False, + * 1 - True +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 296b5c9bfbb0..f2dbdaae0665 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -300,6 +300,14 @@ config ASUS_WMI + To compile this driver as a module, choose M here: the module will + be called asus-wmi. + ++config ASUS_WMI_BIOS ++ bool "BIOS option support in WMI platform (DEPRECATED)" ++ depends on ASUS_WMI ++ help ++ Say Y to expose the configurable BIOS options through the asus-wmi ++ driver. This can be used with or without the new asus-bios driver as ++ the options are the same but the asus-bios driver has more features. ++ + config ASUS_NB_WMI + tristate "Asus Notebook WMI Driver" + depends on ASUS_WMI +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index a6f2e5325a60..903f8340b5aa 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -269,11 +269,12 @@ struct asus_wmi { + u8 fan_boost_mode_mask; + u8 fan_boost_mode; + ++ ++ /* Tunables provided by ASUS for gaming laptops */ ++ #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + bool egpu_enable_available; + bool dgpu_disable_available; + u32 gpu_mux_dev; +- +- /* Tunables provided by ASUS for gaming laptops */ + u32 ppt_pl2_sppt; + u32 ppt_pl1_spl; + u32 ppt_apu_sppt; +@@ -281,6 +282,9 @@ struct asus_wmi { + u32 ppt_fppt; + u32 nv_dynamic_boost; + u32 nv_temp_target; ++ bool panel_overdrive_available; ++ u32 mini_led_dev_id; ++ #endif + + u32 kbd_rgb_dev; + bool kbd_rgb_state_available; +@@ -299,9 +303,6 @@ struct asus_wmi { + // The RSOC controls the maximum charging percentage. + bool battery_rsoc_available; + +- bool panel_overdrive_available; +- u32 mini_led_dev_id; +- + struct hotplug_slot hotplug_slot; + struct mutex hotplug_lock; + struct mutex wmi_lock; +@@ -315,6 +316,15 @@ struct asus_wmi { + struct asus_wmi_driver *driver; + }; + ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) ++void asus_wmi_show_deprecated(void) ++{ ++ pr_notice_once("Accessing attributes through /sys/bus/platform/asus_wmi is \ ++ deprecated and will be removed in a future release. Please switch \ ++ over to /sys/class/firmware_attributes."); ++} ++#endif ++ + /* WMI ************************************************************************/ + + static int asus_wmi_evaluate_method3(u32 method_id, +@@ -683,6 +693,7 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) + } + + /* Charging mode, 1=Barrel, 2=USB ******************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t charge_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -693,12 +704,16 @@ static ssize_t charge_mode_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", value & 0xff); + } + + static DEVICE_ATTR_RO(charge_mode); ++#endif + + /* dGPU ********************************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t dgpu_disable_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -709,6 +724,8 @@ static ssize_t dgpu_disable_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -762,8 +779,10 @@ static ssize_t dgpu_disable_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(dgpu_disable); ++#endif + + /* eGPU ********************************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t egpu_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -774,6 +793,8 @@ static ssize_t egpu_enable_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -830,8 +851,10 @@ static ssize_t egpu_enable_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(egpu_enable); ++#endif + + /* Is eGPU connected? *********************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t egpu_connected_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -842,12 +865,16 @@ static ssize_t egpu_connected_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + + static DEVICE_ATTR_RO(egpu_connected); ++#endif + + /* gpu mux switch *************************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t gpu_mux_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -858,6 +885,8 @@ static ssize_t gpu_mux_mode_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -916,6 +945,7 @@ static ssize_t gpu_mux_mode_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(gpu_mux_mode); ++#endif + + /* TUF Laptop Keyboard RGB Modes **********************************************/ + static ssize_t kbd_rgb_mode_store(struct device *dev, +@@ -1035,6 +1065,7 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { + }; + + /* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t ppt_pl2_sppt_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +@@ -1073,6 +1104,8 @@ static ssize_t ppt_pl2_sppt_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->ppt_pl2_sppt); + } + static DEVICE_ATTR_RW(ppt_pl2_sppt); +@@ -1115,6 +1148,8 @@ static ssize_t ppt_pl1_spl_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->ppt_pl1_spl); + } + static DEVICE_ATTR_RW(ppt_pl1_spl); +@@ -1158,6 +1193,8 @@ static ssize_t ppt_fppt_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->ppt_fppt); + } + static DEVICE_ATTR_RW(ppt_fppt); +@@ -1201,6 +1238,8 @@ static ssize_t ppt_apu_sppt_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->ppt_apu_sppt); + } + static DEVICE_ATTR_RW(ppt_apu_sppt); +@@ -1244,6 +1283,8 @@ static ssize_t ppt_platform_sppt_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->ppt_platform_sppt); + } + static DEVICE_ATTR_RW(ppt_platform_sppt); +@@ -1287,6 +1328,8 @@ static ssize_t nv_dynamic_boost_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->nv_dynamic_boost); + } + static DEVICE_ATTR_RW(nv_dynamic_boost); +@@ -1330,11 +1373,15 @@ static ssize_t nv_temp_target_show(struct device *dev, + { + struct asus_wmi *asus = dev_get_drvdata(dev); + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%u\n", asus->nv_temp_target); + } + static DEVICE_ATTR_RW(nv_temp_target); ++#endif + + /* Ally MCU Powersave ********************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t mcu_powersave_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -1345,6 +1392,8 @@ static ssize_t mcu_powersave_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -1380,6 +1429,7 @@ static ssize_t mcu_powersave_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(mcu_powersave); ++#endif + + /* Battery ********************************************************************/ + +@@ -2209,6 +2259,7 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) + } + + /* Panel Overdrive ************************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t panel_od_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -2219,6 +2270,8 @@ static ssize_t panel_od_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -2255,9 +2308,10 @@ static ssize_t panel_od_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(panel_od); ++#endif + + /* Bootup sound ***************************************************************/ +- ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t boot_sound_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -2268,6 +2322,8 @@ static ssize_t boot_sound_show(struct device *dev, + if (result < 0) + return result; + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", result); + } + +@@ -2303,8 +2359,10 @@ static ssize_t boot_sound_store(struct device *dev, + return count; + } + static DEVICE_ATTR_RW(boot_sound); ++#endif + + /* Mini-LED mode **************************************************************/ ++#if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + static ssize_t mini_led_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -2335,6 +2393,8 @@ static ssize_t mini_led_mode_show(struct device *dev, + } + } + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "%d\n", value); + } + +@@ -2405,10 +2465,13 @@ static ssize_t available_mini_led_mode_show(struct device *dev, + return sysfs_emit(buf, "0 1 2\n"); + } + ++ asus_wmi_show_deprecated(); ++ + return sysfs_emit(buf, "0\n"); + } + + static DEVICE_ATTR_RO(available_mini_led_mode); ++#endif + + /* Quirks *********************************************************************/ + +@@ -4374,27 +4437,29 @@ static struct attribute *platform_attributes[] = { + &dev_attr_camera.attr, + &dev_attr_cardr.attr, + &dev_attr_touchpad.attr, +- &dev_attr_charge_mode.attr, +- &dev_attr_egpu_enable.attr, +- &dev_attr_egpu_connected.attr, +- &dev_attr_dgpu_disable.attr, +- &dev_attr_gpu_mux_mode.attr, + &dev_attr_lid_resume.attr, + &dev_attr_als_enable.attr, + &dev_attr_fan_boost_mode.attr, + &dev_attr_throttle_thermal_policy.attr, +- &dev_attr_ppt_pl2_sppt.attr, +- &dev_attr_ppt_pl1_spl.attr, +- &dev_attr_ppt_fppt.attr, +- &dev_attr_ppt_apu_sppt.attr, +- &dev_attr_ppt_platform_sppt.attr, +- &dev_attr_nv_dynamic_boost.attr, +- &dev_attr_nv_temp_target.attr, +- &dev_attr_mcu_powersave.attr, +- &dev_attr_boot_sound.attr, +- &dev_attr_panel_od.attr, +- &dev_attr_mini_led_mode.attr, +- &dev_attr_available_mini_led_mode.attr, ++ #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) ++ &dev_attr_charge_mode.attr, ++ &dev_attr_egpu_enable.attr, ++ &dev_attr_egpu_connected.attr, ++ &dev_attr_dgpu_disable.attr, ++ &dev_attr_gpu_mux_mode.attr, ++ &dev_attr_ppt_pl2_sppt.attr, ++ &dev_attr_ppt_pl1_spl.attr, ++ &dev_attr_ppt_fppt.attr, ++ &dev_attr_ppt_apu_sppt.attr, ++ &dev_attr_ppt_platform_sppt.attr, ++ &dev_attr_nv_dynamic_boost.attr, ++ &dev_attr_nv_temp_target.attr, ++ &dev_attr_mcu_powersave.attr, ++ &dev_attr_boot_sound.attr, ++ &dev_attr_panel_od.attr, ++ &dev_attr_mini_led_mode.attr, ++ &dev_attr_available_mini_led_mode.attr, ++ #endif + NULL + }; + +@@ -4416,7 +4481,13 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + devid = ASUS_WMI_DEVID_LID_RESUME; + else if (attr == &dev_attr_als_enable.attr) + devid = ASUS_WMI_DEVID_ALS_ENABLE; +- else if (attr == &dev_attr_charge_mode.attr) ++ else if (attr == &dev_attr_fan_boost_mode.attr) ++ ok = asus->fan_boost_mode_available; ++ else if (attr == &dev_attr_throttle_thermal_policy.attr) ++ ok = asus->throttle_thermal_policy_available; ++ ++ #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) ++ if (attr == &dev_attr_charge_mode.attr) + devid = ASUS_WMI_DEVID_CHARGE_MODE; + else if (attr == &dev_attr_egpu_enable.attr) + ok = asus->egpu_enable_available; +@@ -4426,10 +4497,6 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + ok = asus->dgpu_disable_available; + else if (attr == &dev_attr_gpu_mux_mode.attr) + ok = asus->gpu_mux_dev != 0; +- else if (attr == &dev_attr_fan_boost_mode.attr) +- ok = asus->fan_boost_mode_available; +- else if (attr == &dev_attr_throttle_thermal_policy.attr) +- ok = asus->throttle_thermal_policy_available; + else if (attr == &dev_attr_ppt_pl2_sppt.attr) + devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; + else if (attr == &dev_attr_ppt_pl1_spl.attr) +@@ -4454,6 +4521,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + ok = asus->mini_led_dev_id != 0; + else if (attr == &dev_attr_available_mini_led_mode.attr) + ok = asus->mini_led_dev_id != 0; ++ #endif + + if (devid != -1) { + ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); +@@ -4694,6 +4762,7 @@ static int asus_wmi_add(struct platform_device *pdev) + goto fail_platform; + + /* ensure defaults for tunables */ ++ #if IS_ENABLED(CONFIG_ASUS_WMI_BIOS) + asus->ppt_pl2_sppt = 5; + asus->ppt_pl1_spl = 5; + asus->ppt_apu_sppt = 5; +@@ -4717,6 +4786,7 @@ static int asus_wmi_add(struct platform_device *pdev) + asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX; + else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO)) + asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO; ++ #endif + + if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE)) + asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE; +-- +2.45.1 + @@ -3,7 +3,7 @@ # Contributor: Jan Alexander Steffens (heftig) <jan.steffens@gmail.com> pkgbase=linux-g14 -pkgver=6.9.5.arch1 +pkgver=6.9.6.arch1 pkgrel=1 pkgdesc='Linux-g14' url="https://gitlab.com/dragonn/linux-g14.git" @@ -37,32 +37,6 @@ source=( 0001-acpi-proc-idle-skip-dummy-wait.patch - 0027-mt76_-mt7921_-Disable-powersave-features-by-default.patch - -# 0001-linux6.8.y-bore5.1.0.patch - - 0032-Bluetooth-btusb-Add-a-new-PID-VID-0489-e0f6-for-MT7922.patch - 0035-Add_quirk_for_polling_the_KBD_port.patch - - "0001-sched-ext.patch"::"https://raw.githubusercontent.com/cachyos/kernel-patches/master/6.9/sched/0001-sched-ext.patch" - -# 0001-ALSA-PCI-HDA-Adjust-G814JZR-to-use-SPI-init-for-amp.patch - 0002-hid-asus-use-hid-for-brightness-control-on-keyboard.patch - 0003-Debugging.patch - 0004-asus-wmi-don-t-error-out-if-platform_profile-already.patch - 0005-hid-asus-add-USB_DEVICE_ID_ASUSTEK_DUO_KEYBOARD.patch - - 0001-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch - 0002-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch - - v2-0005-platform-x86-asus-wmi-don-t-allow-eGPU-switching-.patch - - 0038-mediatek-pci-reset.patch - 0040-workaround_hardware_decoding_amdgpu.patch - - 0001-platform-x86-asus-wmi-Support-2023-ROG-X16-tablet-mo.patch - amd-tablet-sfh.patch - 0001-v4-platform-x86-asus-wmi-add-support-for-2024-ROG-Mini-LED.patch 0002-v4-platform-x86-asus-wmi-add-support-for-Vivobook-GPU-MUX.patch 0003-v4-platform-x86-asus-wmi-add-support-variant-of-TUF-RGB.patch @@ -79,6 +53,43 @@ source=( 0003-HID-asus-add-ROG-Ally-N-Key-ID-and-keycodes.patch 0004-HID-asus-add-ROG-Z13-lightbar.patch + ## upstream no longer has these patches... + #0002-hid-asus-use-hid-for-brightness-control-on-keyboard.patch + #0003-Debugging.patch + #0004-asus-wmi-don-t-error-out-if-platform_profile-already.patch + #0005-hid-asus-add-USB_DEVICE_ID_ASUSTEK_DUO_KEYBOARD.patch + #v2-0005-platform-x86-asus-wmi-don-t-allow-eGPU-switching-.patch + #0001-platform-x86-asus-wmi-Support-2023-ROG-X16-tablet-mo.patch + ## to here... + + ## but these instead... + 0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch + 0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch + 0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch + 0004-asus-bios-add-panel-hd-control.patch + 0005-asus-bios-add-dgpu-tgp-control.patch + 0006-asus-bios-add-apu-mem.patch + 0007-asus-bios-add-core-count-control.patch + #0008-asus-wmi-deprecate-bios-features.patch + v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch + #0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch + ## to here... + + 0027-mt76_-mt7921_-Disable-powersave-features-by-default.patch + + 0032-Bluetooth-btusb-Add-a-new-PID-VID-0489-e0f6-for-MT7922.patch + 0035-Add_quirk_for_polling_the_KBD_port.patch + + 0001-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch + 0002-ACPI-resource-Skip-IRQ-override-on-ASUS-TUF-Gaming-A.patch + + 0038-mediatek-pci-reset.patch + 0040-workaround_hardware_decoding_amdgpu.patch + + amd-tablet-sfh.patch + + "0001-sched-ext.patch"::"https://raw.githubusercontent.com/cachyos/kernel-patches/master/6.9/sched/0001-sched-ext.patch" + "sys-kernel_arch-sources-g14_files-0047-asus-nb-wmi-Add-tablet_mode_sw-lid-flip.patch" "sys-kernel_arch-sources-g14_files-0048-asus-nb-wmi-fix-tablet_mode_sw_int.patch" ) @@ -88,30 +99,14 @@ validpgpkeys=( 83BC8889351B5DEBBB68416EB8AC08600F108CDF # Jan Alexander Steffens (heftig) ) -sha256sums=('c321c46401368774fc236f57095b205a5da57415f9a6008018902f9fd5eddfae' +sha256sums=('5d4366e2b89998f274abe03557ef3bc78b58e47fc62c102d51e6f49e5ed96b4b' 'SKIP' - 'cf11fe18d60f2bf85fa0dd61a2fb1d59bf40f98db48dfae2244c5839c1281919' + 'f11095f47da518ce4074be587438d30f424d98bcc5c59f7a1a8c00c58ddf5aa4' 'SKIP' - 'ccb010f9cf043f07dd2a2aba56cf2b7a82654dc7ee0b12a4984fcfed05d3e8ec' + 'd6c1352567ed50b9a24062f93d575dfb6b744995d7ea029beb897480c992f706' '278118011d7a2eeca9971ac97b31bf0c55ab55e99c662ab9ae4717b55819c9a2' 'f4e7fcd011f2691840d2c8c2361dca850a78ea33cc5c24d2e27c3e0294fd1dc5' '0a7ea482fe20c403788d290826cec42fe395e5a6eab07b88845f8b9a9829998d' - 'ed242f4be3f8eaade2a1d42157c5c6c86281917a08ae43221b088fafdc775ee7' - 'a8e1e11a4ab1995cc4975c9b134a43ddfe7054ef0c965e52a7d8f9223e15c3e0' - '315d1839630b37894a626bbc2aea012618b2e1ccb6f9d8aa27c0a3ce5e90e99c' - 'ecbd4fc71f04d391d6e3ec1d90ee84b04a026ae89c901257915e304aa4b3dd57' - '9152af5811a61dd196c520ac39792aebee325fda093ecf9acd19f80819cf8d7c' - '567efcbb400bf2dc7327a790839d2a441bd7ca9fb7f5b2b07591c4abc63554bf' - '6ab14523be3cadf4d495dd13b0ed12a1241118d93d8313f47a8dea6b1bf16df6' - 'c9835e39798d97ba0ca48c0d2353d1182715d4bfc99964051993dacc8f59ba83' - '423380be1902da29e695cb201516751759050fc0a50914a0459f05e1f4614087' - 'a00b952d53df9d3617d93e8fba4146a4d6169ebe79f029b3a55cca68f738d8ea' - '4912b1319e46ddd6670147f5e878b4aca8bcfbd7b5c852fe11e434e424666365' - '9f98765b43f5f31b33ed05f3611508113b02518e680ee82b251de80dae2e141d' - 'd673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1' - 'e41198b29cee4de7a5132d8df606f48c2d0f9c9076fe4230b00a33c7e0b22c71' - '1edb362a762c8858374027e30ff58ae0014e117fdc05cc7db6da50f80e7aab87' - '508f90cbe81a9a145cc540703470f1e6b5d21c7a7b9166d2ce6e56b401262b04' 'feaf5f5fb62e25e2369f92f77e8327dcd4cb4cf4bc6d0c91d9c7bc40c0f4de46' 'b9866121c69ce22b4651b3ef2a1956e6d0547e40a14d1224e2f367a4f716ca1a' '6f2f248a5ac9b1a37324cbce8d29a65b22a2b20d4b3564c0dc6063789ae733ba' @@ -122,10 +117,27 @@ sha256sums=('c321c46401368774fc236f57095b205a5da57415f9a6008018902f9fd5eddfae' 'f5b560d988c47033c44307da0b584599d1f59cc0028a594f4df87affffc219d5' 'de85da760f6692b284e39aa78479904d6ee78b349f1e98d1d210777f9ef17581' '3be072ed798becd91bae66a75d09235c9cb5e84547b1f4eb7768e954ba109e92' - '93c9a77f6c25494cecbe6b236bd2179065d5f5db5589dabaa425134c1a8c3481' + '9c8679f5995b69b6778539f48f30142e5a357213cf9a04ee0877f50f859d1233' 'c1d96328d96964c2ce3ef7609fb7c07e97eb136dfab9f6d4efcce072a5739838' '2414dc71174c90b92f975a7d16cabc99ba509397d843132764ea9ee91b643dc0' '107a08aa610d3ba3c7ecec301df2ea8f345bc74107fcf4dac96fe9e89a23dcf1' + '0ac28bb000cf2eb56f36d028588fd898dd8afa63ba247fcf326496570c2fe87e' + 'f45f61b9e023bf0224d70f76c73c0f667193a9915ba6ae9586046a9c4d73b8a0' + '9de67962522d07b9babe7c97e4240bb267939c2c6c97bb91d64ed14123f81e3f' + '9884ce2c34d9520e343dbaf33ef1d053deeb752c12bd595ec5c96a17859131d4' + 'cc7d6594d152b95d3edc82f4a01317881f94dd365b28264805840e33a523b4c6' + '5b6a2f1ac22c55f43cd7e7b8b79b7ee8a76d58acd74abecc3102b2c32ed15576' + '6f5325bf096668d25a9bcf7fdd9fc574fc1c16640f2d163c54b87527ed961d83' + 'b7422349428f0476477167f81d9cd9e3692f7ca7345eb6e1f861a0994f9a366e' + 'ed242f4be3f8eaade2a1d42157c5c6c86281917a08ae43221b088fafdc775ee7' + 'a8e1e11a4ab1995cc4975c9b134a43ddfe7054ef0c965e52a7d8f9223e15c3e0' + '315d1839630b37894a626bbc2aea012618b2e1ccb6f9d8aa27c0a3ce5e90e99c' + 'a00b952d53df9d3617d93e8fba4146a4d6169ebe79f029b3a55cca68f738d8ea' + '4912b1319e46ddd6670147f5e878b4aca8bcfbd7b5c852fe11e434e424666365' + 'd673d034fbcd80426fd8d9c6af56537c5fe5b55fe49d74e313474d7fc285ecc1' + 'e41198b29cee4de7a5132d8df606f48c2d0f9c9076fe4230b00a33c7e0b22c71' + '508f90cbe81a9a145cc540703470f1e6b5d21c7a7b9166d2ce6e56b401262b04' + 'b6e59b42ae96d69430aa78e5f7c5212e2092e7a17a9cd67575c76d79a68f28e1' '15e912a66e4bbce1cf0450f1dc6610653df29df8dd6d5426f9c1b039490436c8' '444f2d86de8c2177655b01596f939f99c2e7abfa8efad8a509e0a334f42dfa85') diff --git a/v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch b/v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch new file mode 100644 index 000000000000..445bf98a6a04 --- /dev/null +++ b/v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch @@ -0,0 +1,119 @@ +From b6c68cbdf90af5884914d6ce21558333b369d725 Mon Sep 17 00:00:00 2001 +From: "Luke D. Jones" <luke@ljones.dev> +Date: Mon, 13 May 2024 19:20:04 +1200 +Subject: [PATCH v2 1/2] hid-asus: use hid for brightness control on keyboard + +On almost all ASUS ROG series laptops the MCU used for the USB keyboard +also has a HID packet used for setting the brightness. This is usually +the same as the WMI method. But in some laptops the WMI method either +is missing or doesn't work, so we should default to the HID control. + +Signed-off-by: Luke D. Jones <luke@ljones.dev> +--- + drivers/hid/hid-asus.c | 7 ++++ + drivers/platform/x86/asus-wmi.c | 3 +- + include/linux/platform_data/x86/asus-wmi.h | 45 ++++++++++++++++++++++ + 3 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c +index 02de2bf4f790..0ed3708ef7e2 100644 +--- a/drivers/hid/hid-asus.c ++++ b/drivers/hid/hid-asus.c +@@ -492,12 +492,19 @@ static void asus_kbd_backlight_work(struct work_struct *work) + */ + static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev) + { ++ struct asus_drvdata *drvdata = hid_get_drvdata(hdev); + u32 value; + int ret; + + if (!IS_ENABLED(CONFIG_ASUS_WMI)) + return false; + ++ if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD && ++ dmi_check_system(asus_use_hid_led_dmi_ids)) { ++ hid_info(hdev, "using HID for asus::kbd_backlight\n"); ++ return false; ++ } ++ + ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, + ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value); + hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value); +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 3f9b6285c9a6..799d928c7d3d 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -1681,7 +1681,8 @@ static int asus_wmi_led_init(struct asus_wmi *asus) + goto error; + } + +- if (!kbd_led_read(asus, &led_val, NULL)) { ++ if (!kbd_led_read(asus, &led_val, NULL) && !dmi_check_system(asus_use_hid_led_dmi_ids)) { ++ pr_info("using asus-wmi for asus::kbd_backlight\n"); + asus->kbd_led_wk = led_val; + asus->kbd_led.name = "asus::kbd_backlight"; + asus->kbd_led.flags = LED_BRIGHT_HW_CHANGED; +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 3eb5cd6773ad..6ba0015e4386 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -4,6 +4,7 @@ + + #include <linux/errno.h> + #include <linux/types.h> ++#include <linux/dmi.h> + + /* WMI Methods */ + #define ASUS_WMI_METHODID_SPEC 0x43455053 /* BIOS SPECification */ +@@ -160,4 +161,48 @@ static inline int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, + } + #endif + ++/* To be used by both hid-asus and asus-wmi to determine which controls kbd_brightness */ ++#if IS_ENABLED(CONFIG_ASUS_WMI) ++bool asus_use_hid_led(void); ++#else ++static inline bool asus_use_hid_led(void) ++{ ++ return true; ++} ++#endif ++ ++static const struct dmi_system_id asus_use_hid_led_dmi_ids[] = { ++ { ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Zephyrus"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Strix"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_FAMILY, "ROG Flow"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GA403"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GU605"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "RC71L"), ++ }, ++ }, ++ NULL, ++}; ++ + #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */ +-- +2.45.1 + |