summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorTaijian2024-06-22 17:18:34 +0200
committerTaijian2024-06-22 17:18:34 +0200
commitca794d215234324a098d3095db5e2fb404a51bd6 (patch)
tree94f05131584767eb80b45e7d65e5016ebdf5c5ab
parent81c1be2adc2da072b2f9d1e407a50f813c376477 (diff)
downloadaur-ca794d215234324a098d3095db5e2fb404a51bd6.tar.gz
update to 6.9.6
-rw-r--r--.SRCINFO83
-rw-r--r--0001-platform-x86-asus-wmi-add-debug-print-in-more-key-pl.patch165
-rw-r--r--0001-platform-x86-asus-wmi-add-support-for-vivobook-fan-p.patch170
-rw-r--r--0002-platform-x86-asus-wmi-don-t-fail-if-platform_profile.patch48
-rw-r--r--0003-asus-bios-refactor-existing-tunings-in-to-asus-bios-.patch1022
-rw-r--r--0003-platform-x86-asus-wmi-add-macros-and-expose-min-max-.patch778
-rw-r--r--0004-asus-bios-add-panel-hd-control.patch57
-rw-r--r--0005-asus-bios-add-dgpu-tgp-control.patch105
-rw-r--r--0006-asus-bios-add-apu-mem.patch160
-rw-r--r--0007-asus-bios-add-core-count-control.patch305
-rw-r--r--0008-asus-wmi-deprecate-bios-features.patch592
-rw-r--r--PKGBUILD106
-rw-r--r--v2-0001-hid-asus-use-hid-for-brightness-control-on-keyboa.patch119
13 files changed, 3556 insertions, 154 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 95964ce6e677..1e26892d3b87 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -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, &currentv);
++ 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
+
diff --git a/PKGBUILD b/PKGBUILD
index 59c3153de82c..822084a50762 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -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
+