diff options
Diffstat (limited to 'SOURCES/asus-linux.patch')
-rw-r--r-- | SOURCES/asus-linux.patch | 3890 |
1 files changed, 1023 insertions, 2867 deletions
diff --git a/SOURCES/asus-linux.patch b/SOURCES/asus-linux.patch index 99985c0..d7817b7 100644 --- a/SOURCES/asus-linux.patch +++ b/SOURCES/asus-linux.patch @@ -1,1927 +1,140 @@ -From a120838990cea1397e9bacb303b41ab83fa76d8c Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: "Luke D. Jones" <luke@ljones.dev> Date: Sun, 10 Mar 2024 15:14:37 +1300 -Subject: [PATCH v4 1/9] platform/x86: asus-wmi: add support for 2024 ROG - Mini-LED -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit +Subject: [PATCH] asus-linux -Support the 2024 mini-led backlight and adjust the related functions -to select the relevant dev-id. Also add `available_mini_led_mode` to the -platform sysfs since the available mini-led levels can be different. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 8 ++ - drivers/platform/x86/asus-wmi.c | 96 +++++++++++++++++-- - include/linux/platform_data/x86/asus-wmi.h | 1 + - 3 files changed, 95 insertions(+), 10 deletions(-) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 8a7e25bde085..ef1ac1a20a71 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -126,6 +126,14 @@ Description: - Change the mini-LED mode: - * 0 - Single-zone, - * 1 - Multi-zone -+ * 2 - Multi-zone strong (available on newer generation mini-led) -+ -+What: /sys/devices/platform/<platform>/available_mini_led_mode -+Date: Apr 2024 -+KernelVersion: 6.10 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ List the available mini-led modes. - - What: /sys/devices/platform/<platform>/ppt_pl1_spl - Date: Jun 2023 -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 3f07bbf809ef..aa2a3b402e33 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -126,6 +126,17 @@ module_param(fnlock_default, bool, 0444); - #define ASUS_SCREENPAD_BRIGHT_MAX 255 - #define ASUS_SCREENPAD_BRIGHT_DEFAULT 60 - -+#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 -+ - /* Controls the power state of the USB0 hub on ROG Ally which input is on */ - #define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" - /* 300ms so far seems to produce a reliable result on AC and battery */ -@@ -288,7 +299,7 @@ struct asus_wmi { - bool battery_rsoc_available; - - bool panel_overdrive_available; -- bool mini_led_mode_available; -+ u32 mini_led_dev_id; - - struct hotplug_slot hotplug_slot; - struct mutex hotplug_lock; -@@ -2108,13 +2119,33 @@ static ssize_t mini_led_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) - { - struct asus_wmi *asus = dev_get_drvdata(dev); -- int result; -+ u32 value; -+ int err; - -- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MINI_LED_MODE); -- if (result < 0) -- return result; -+ err = asus_wmi_get_devstate(asus, asus->mini_led_dev_id, &value); -+ if (err < 0) -+ return err; -+ value = value & ASUS_MINI_LED_MODE_MASK; - -- return sysfs_emit(buf, "%d\n", result); -+ /* -+ * 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->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_store(struct device *dev, -@@ -2130,11 +2161,32 @@ static ssize_t mini_led_mode_store(struct device *dev, - if (result) - return result; - -- if (mode > 1) -+ if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE && -+ mode > ASUS_MINI_LED_ON) -+ return -EINVAL; -+ if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 && -+ mode > ASUS_MINI_LED_STRONG_MODE) - return -EINVAL; - -- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MINI_LED_MODE, mode, &result); -+ /* -+ * Remap the mode values so expected behaviour is the same as the last -+ * generation of mini-LED with 0 == off, 1 == on. -+ */ -+ if (asus->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->mini_led_dev_id, mode, &result); - if (err) { - pr_warn("Failed to set mini-LED: %d\n", err); - return err; -@@ -2151,6 +2203,23 @@ static ssize_t mini_led_mode_store(struct device *dev, - } - static DEVICE_ATTR_RW(mini_led_mode); - -+static ssize_t available_mini_led_mode_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ switch (asus->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"); -+} -+ -+static DEVICE_ATTR_RO(available_mini_led_mode); -+ - /* Quirks *********************************************************************/ - - static void asus_wmi_set_xusb2pr(struct asus_wmi *asus) -@@ -4139,6 +4208,7 @@ static struct attribute *platform_attributes[] = { - &dev_attr_nv_temp_target.attr, - &dev_attr_panel_od.attr, - &dev_attr_mini_led_mode.attr, -+ &dev_attr_available_mini_led_mode.attr, - NULL - }; - -@@ -4191,7 +4261,9 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - else if (attr == &dev_attr_panel_od.attr) - ok = asus->panel_overdrive_available; - else if (attr == &dev_attr_mini_led_mode.attr) -- ok = asus->mini_led_mode_available; -+ ok = asus->mini_led_dev_id != 0; -+ else if (attr == &dev_attr_available_mini_led_mode.attr) -+ ok = asus->mini_led_dev_id != 0; - - if (devid != -1) - ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); -@@ -4444,10 +4516,14 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->nv_dyn_boost_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_DYN_BOOST); - asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); - asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); -- asus->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE); - asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_match(DMI_BOARD_NAME, "RC71L"); - -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE)) -+ asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE; -+ else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE2)) -+ asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; -+ - err = fan_boost_mode_check_present(asus); - if (err) - goto fail_fan_boost_mode; -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index ab1c7deff118..9cadce10ad9a 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -71,6 +71,7 @@ - #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 - #define ASUS_WMI_DEVID_LID_FLIP_ROG 0x00060077 - #define ASUS_WMI_DEVID_MINI_LED_MODE 0x0005001E -+#define ASUS_WMI_DEVID_MINI_LED_MODE2 0x0005002E - - /* Storage */ - #define ASUS_WMI_DEVID_CARDREADER 0x00080013 --- -2.44.0 - -From b54d273cb1fddcf9ae2618447e23b9f62730e15f Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 10 Mar 2024 17:10:05 +1300 -Subject: [PATCH v4 2/9] platform/x86: asus-wmi: add support for Vivobook GPU - MUX -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for the Vivobook dgpu MUX available on the ASUS Viviobook -and some of the other ranges (Zen). - -This MUX functions exactly the same as the existing ROG MUX support so -the existing functionality now detects which MUX is available and uses -that for control. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 22 +++++++++++++--------- - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 14 insertions(+), 9 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index aa2a3b402e33..1ab4380e9771 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -270,7 +270,7 @@ struct asus_wmi { - bool egpu_enable_available; - bool egpu_connect_available; - bool dgpu_disable_available; -- bool gpu_mux_mode_available; -+ u32 gpu_mux_dev; - - /* Tunables provided by ASUS for gaming laptops */ - bool ppt_pl2_sppt_available; -@@ -693,8 +693,8 @@ static ssize_t dgpu_disable_store(struct device *dev, - if (disable > 1) - return -EINVAL; - -- if (asus->gpu_mux_mode_available) { -- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -+ if (asus->gpu_mux_dev) { -+ result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); - if (result < 0) - /* An error here may signal greater failure of GPU handling */ - return result; -@@ -759,8 +759,8 @@ static ssize_t egpu_enable_store(struct device *dev, - return err; - } - -- if (asus->gpu_mux_mode_available) { -- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -+ if (asus->gpu_mux_dev) { -+ result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); - if (result < 0) { - /* An error here may signal greater failure of GPU handling */ - pr_warn("Failed to get gpu mux status: %d\n", result); -@@ -813,7 +813,7 @@ static ssize_t gpu_mux_mode_show(struct device *dev, - struct asus_wmi *asus = dev_get_drvdata(dev); - int result; - -- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_GPU_MUX); -+ result = asus_wmi_get_devstate_simple(asus, asus->gpu_mux_dev); - if (result < 0) - return result; - -@@ -859,7 +859,7 @@ static ssize_t gpu_mux_mode_store(struct device *dev, - } - } - -- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_GPU_MUX, optimus, &result); -+ err = asus_wmi_set_devstate(asus->gpu_mux_dev, optimus, &result); - if (err) { - dev_err(dev, "Failed to set GPU MUX mode: %d\n", err); - return err; -@@ -4239,7 +4239,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - else if (attr == &dev_attr_dgpu_disable.attr) - ok = asus->dgpu_disable_available; - else if (attr == &dev_attr_gpu_mux_mode.attr) -- ok = asus->gpu_mux_mode_available; -+ 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) -@@ -4505,7 +4505,6 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); - asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); -- asus->gpu_mux_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX); - asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); - asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); - asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); -@@ -4524,6 +4523,11 @@ static int asus_wmi_add(struct platform_device *pdev) - else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE2)) - asus->mini_led_dev_id = ASUS_WMI_DEVID_MINI_LED_MODE2; - -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX)) -+ 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; -+ - err = fan_boost_mode_check_present(asus); - if (err) - goto fail_fan_boost_mode; -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 9cadce10ad9a..b48b024dd844 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -128,6 +128,7 @@ - - /* gpu mux switch, 0 = dGPU, 1 = Optimus */ - #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 -+#define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 - - /* TUF laptop RGB modes/colours */ - #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 --- -2.44.0 - -From 3baa8b981e24bb1ae4e468085e89241a0439d259 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 10 Mar 2024 17:20:02 +1300 -Subject: [PATCH v4 3/9] platform/x86: asus-wmi: add support variant of TUF RGB -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Adds support for a second TUF RGB wmi call that some versions of the TUF -laptop come with. Also adjusts existing support to select whichever is -available. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 13 +++++++++---- - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 10 insertions(+), 4 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 1ab4380e9771..6896d056d227 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -281,7 +281,7 @@ struct asus_wmi { - bool nv_dyn_boost_available; - bool nv_temp_tgt_available; - -- bool kbd_rgb_mode_available; -+ u32 kbd_rgb_dev; - bool kbd_rgb_state_available; - - bool throttle_thermal_policy_available; -@@ -881,6 +881,7 @@ static ssize_t kbd_rgb_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) - { -+ struct asus_wmi *asus = dev_get_drvdata(dev); - u32 cmd, mode, r, g, b, speed; - int err; - -@@ -917,7 +918,7 @@ static ssize_t kbd_rgb_mode_store(struct device *dev, - speed = 0xeb; - } - -- err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, ASUS_WMI_DEVID_TUF_RGB_MODE, -+ err = asus_wmi_evaluate_method3(ASUS_WMI_METHODID_DEVS, asus->kbd_rgb_dev, - cmd | (mode << 8) | (r << 16) | (g << 24), b | (speed << 8), NULL); - if (err) - return err; -@@ -1560,7 +1561,7 @@ static int asus_wmi_led_init(struct asus_wmi *asus) - { - int rv = 0, num_rgb_groups = 0, led_val; - -- if (asus->kbd_rgb_mode_available) -+ if (asus->kbd_rgb_dev) - kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_mode_group; - if (asus->kbd_rgb_state_available) - kbd_rgb_mode_groups[num_rgb_groups++] = &kbd_rgb_state_group; -@@ -4505,7 +4506,6 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); - asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - asus->dgpu_disable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_DGPU); -- asus->kbd_rgb_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE); - asus->kbd_rgb_state_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_STATE); - asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); - asus->ppt_pl1_spl_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL1_SPL); -@@ -4528,6 +4528,11 @@ static int asus_wmi_add(struct platform_device *pdev) - else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_GPU_MUX_VIVO)) - asus->gpu_mux_dev = ASUS_WMI_DEVID_GPU_MUX_VIVO; - -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE)) -+ asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE; -+ else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) -+ asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; -+ - err = fan_boost_mode_check_present(asus); - if (err) - goto fail_fan_boost_mode; -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index b48b024dd844..3e9a01467c67 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -132,6 +132,7 @@ - - /* TUF laptop RGB modes/colours */ - #define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 -+#define ASUS_WMI_DEVID_TUF_RGB_MODE2 0x0010005A - - /* TUF laptop RGB power/state */ - #define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 --- -2.44.0 - -From 37f3b097a3f245ab8a12befd37e2d76ed6ebf85f Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 10 Mar 2024 19:03:11 +1300 -Subject: [PATCH v4 4/9] platform/x86: asus-wmi: support toggling POST sound -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for toggling the BIOS POST sound on some ASUS laptops. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> +Signed-off-by: Jan200101 <sentrycraft123@gmail.com> --- - .../ABI/testing/sysfs-platform-asus-wmi | 9 ++++ - drivers/platform/x86/asus-wmi.c | 51 +++++++++++++++++++ - include/linux/platform_data/x86/asus-wmi.h | 3 ++ - 3 files changed, 63 insertions(+) + .../ABI/testing/sysfs-platform-asus-wmi | 23 +- + drivers/hid/hid-asus.c | 7 + + drivers/hid/hid-ids.h | 1 + + drivers/platform/x86/Kconfig | 14 + + drivers/platform/x86/Makefile | 1 + + drivers/platform/x86/asus-bios.c | 983 ++++++++++++++++++ + drivers/platform/x86/asus-bios.h | 288 +++++ + drivers/platform/x86/asus-wmi.c | 754 +++++++------- + include/linux/platform_data/x86/asus-wmi.h | 65 ++ + 9 files changed, 1735 insertions(+), 401 deletions(-) + create mode 100644 drivers/platform/x86/asus-bios.c + create mode 100644 drivers/platform/x86/asus-bios.h diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index ef1ac1a20a71..72933527d2e4 100644 +index 28144371a0f1..984a04f32fd0 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -194,3 +194,12 @@ Contact: "Luke Jones" <luke@ljones.dev> +@@ -142,8 +142,8 @@ Contact: "Luke Jones" <luke@ljones.dev> Description: - Set the target temperature limit of the Nvidia dGPU: - * min=75, max=87 -+ -+What: /sys/devices/platform/<platform>/boot_sound -+Date: Apr 2024 -+KernelVersion: 6.10 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set if the BIOS POST sound is played on boot. -+ * 0 - False, -+ * 1 - True -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 6896d056d227..6c353b8e8da9 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -2115,6 +2115,54 @@ static ssize_t panel_od_store(struct device *dev, - } - static DEVICE_ATTR_RW(panel_od); - -+/* Bootup sound ***************************************************************/ -+ -+static ssize_t boot_sound_show(struct device *dev, -+ struct device_attribute *attr, char *buf) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int result; -+ -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BOOT_SOUND); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", result); -+} -+ -+static ssize_t boot_sound_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 snd; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &snd); -+ if (result) -+ return result; -+ -+ if (snd > 1) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BOOT_SOUND, snd, &result); -+ if (err) { -+ pr_warn("Failed to set boot sound: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set panel boot sound (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "boot_sound"); -+ -+ return count; -+} -+static DEVICE_ATTR_RW(boot_sound); -+ - /* Mini-LED mode **************************************************************/ - static ssize_t mini_led_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -@@ -4207,6 +4255,7 @@ static struct attribute *platform_attributes[] = { - &dev_attr_ppt_platform_sppt.attr, - &dev_attr_nv_dynamic_boost.attr, - &dev_attr_nv_temp_target.attr, -+ &dev_attr_boot_sound.attr, - &dev_attr_panel_od.attr, - &dev_attr_mini_led_mode.attr, - &dev_attr_available_mini_led_mode.attr, -@@ -4259,6 +4308,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - ok = asus->nv_dyn_boost_available; - else if (attr == &dev_attr_nv_temp_target.attr) - ok = asus->nv_temp_tgt_available; -+ else if (attr == &dev_attr_boot_sound.attr) -+ devid = ASUS_WMI_DEVID_BOOT_SOUND; - else if (attr == &dev_attr_panel_od.attr) - ok = asus->panel_overdrive_available; - else if (attr == &dev_attr_mini_led_mode.attr) -diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h -index 3e9a01467c67..3eb5cd6773ad 100644 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -137,6 +137,9 @@ - /* TUF laptop RGB power/state */ - #define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 - -+/* Bootup sound control */ -+#define ASUS_WMI_DEVID_BOOT_SOUND 0x00130022 -+ - /* DSTS masks */ - #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 - #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 --- -2.44.0 - -From eea03ef05c38fe9bfd8653b13b870bb8f96fe41d Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 11 Mar 2024 12:15:46 +1300 -Subject: [PATCH v4 5/9] platform/x86: asus-wmi: store a min default for ppt - options -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Laptops with any of the ppt or nv tunables default to the minimum setting -on boot so we can safely assume a stored value is correct. - -This patch adds storing of those values in the local struct, and enables -reading of those values back. To prevent creating a series of byte holes -in the struct the "<name>_available" bool is removed and -`asus_sysfs_is_visible()` uses the `ASUS_WMI_DEVID_<name>` directly. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 127 +++++++++++++++++++++++++------- - 1 file changed, 99 insertions(+), 28 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 6c353b8e8da9..f13606fc62e6 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -273,13 +273,13 @@ struct asus_wmi { - u32 gpu_mux_dev; - - /* Tunables provided by ASUS for gaming laptops */ -- bool ppt_pl2_sppt_available; -- bool ppt_pl1_spl_available; -- bool ppt_apu_sppt_available; -- bool ppt_plat_sppt_available; -- bool ppt_fppt_available; -- bool nv_dyn_boost_available; -- bool nv_temp_tgt_available; -+ 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; - - u32 kbd_rgb_dev; - bool kbd_rgb_state_available; -@@ -1031,11 +1031,21 @@ static ssize_t ppt_pl2_sppt_store(struct device *dev, - return -EIO; - } - -+ asus->ppt_pl2_sppt = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt"); - - return count; - } --static DEVICE_ATTR_WO(ppt_pl2_sppt); -+ -+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, -@@ -1065,11 +1075,20 @@ static ssize_t ppt_pl1_spl_store(struct device *dev, - return -EIO; - } - -+ asus->ppt_pl1_spl = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl"); - - return count; - } --static DEVICE_ATTR_WO(ppt_pl1_spl); -+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, -@@ -1099,11 +1118,21 @@ static ssize_t ppt_fppt_store(struct device *dev, - return -EIO; - } - -+ asus->ppt_fppt = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt"); - - return count; - } --static DEVICE_ATTR_WO(ppt_fppt); -+ -+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, -@@ -1133,11 +1162,21 @@ static ssize_t ppt_apu_sppt_store(struct device *dev, - return -EIO; - } - -+ asus->ppt_apu_sppt = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt"); - - return count; - } --static DEVICE_ATTR_WO(ppt_apu_sppt); -+ -+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, -@@ -1167,11 +1206,21 @@ static ssize_t ppt_platform_sppt_store(struct device *dev, - return -EIO; - } - -+ asus->ppt_platform_sppt = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt"); - - return count; - } --static DEVICE_ATTR_WO(ppt_platform_sppt); -+ -+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, -@@ -1201,11 +1250,21 @@ static ssize_t nv_dynamic_boost_store(struct device *dev, - return -EIO; - } - -+ asus->nv_dynamic_boost = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost"); - - return count; - } --static DEVICE_ATTR_WO(nv_dynamic_boost); -+ -+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, -@@ -1235,11 +1294,21 @@ static ssize_t nv_temp_target_store(struct device *dev, - return -EIO; - } - -+ asus->nv_temp_target = value; - sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target"); - - return count; - } --static DEVICE_ATTR_WO(nv_temp_target); -+ -+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); - - /* Battery ********************************************************************/ - -@@ -4295,19 +4364,19 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - else if (attr == &dev_attr_throttle_thermal_policy.attr) - ok = asus->throttle_thermal_policy_available; - else if (attr == &dev_attr_ppt_pl2_sppt.attr) -- ok = asus->ppt_pl2_sppt_available; -+ devid = ASUS_WMI_DEVID_PPT_PL2_SPPT; - else if (attr == &dev_attr_ppt_pl1_spl.attr) -- ok = asus->ppt_pl1_spl_available; -+ devid = ASUS_WMI_DEVID_PPT_PL1_SPL; - else if (attr == &dev_attr_ppt_fppt.attr) -- ok = asus->ppt_fppt_available; -+ devid = ASUS_WMI_DEVID_PPT_FPPT; - else if (attr == &dev_attr_ppt_apu_sppt.attr) -- ok = asus->ppt_apu_sppt_available; -+ devid = ASUS_WMI_DEVID_PPT_APU_SPPT; - else if (attr == &dev_attr_ppt_platform_sppt.attr) -- ok = asus->ppt_plat_sppt_available; -+ devid = ASUS_WMI_DEVID_PPT_PLAT_SPPT; - else if (attr == &dev_attr_nv_dynamic_boost.attr) -- ok = asus->nv_dyn_boost_available; -+ devid = ASUS_WMI_DEVID_NV_DYN_BOOST; - else if (attr == &dev_attr_nv_temp_target.attr) -- ok = asus->nv_temp_tgt_available; -+ devid = ASUS_WMI_DEVID_NV_THERM_TARGET; - else if (attr == &dev_attr_boot_sound.attr) - devid = ASUS_WMI_DEVID_BOOT_SOUND; - else if (attr == &dev_attr_panel_od.attr) -@@ -4553,18 +4622,20 @@ 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; -+ - asus->charge_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CHARGE_MODE); - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); - asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - 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); -- asus->ppt_pl2_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL2_SPPT); -- asus->ppt_pl1_spl_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PL1_SPL); -- asus->ppt_fppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_FPPT); -- asus->ppt_apu_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_APU_SPPT); -- asus->ppt_plat_sppt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PPT_PLAT_SPPT); -- asus->nv_dyn_boost_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_DYN_BOOST); -- asus->nv_temp_tgt_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_NV_THERM_TARGET); - asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_match(DMI_BOARD_NAME, "RC71L"); --- -2.44.0 - -From 43355f0d9ba2d6e9ef791c0fe5efbbff872d05ac Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 25 Mar 2024 16:20:57 +1300 -Subject: [PATCH v4 6/9] platform/x86: asus-wmi: adjust formatting of - ppt-<name>() functions -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Shift the call to dev_get_drvdata() up to top of the function block -in all of the ppt_<name>() functions as part of a minor cleanup. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 21 +++++++-------------- - 1 file changed, 7 insertions(+), 14 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index f13606fc62e6..976e26c82f80 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -1008,11 +1008,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1052,11 +1051,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1095,11 +1093,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1139,11 +1136,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1183,11 +1179,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1227,11 +1222,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; -@@ -1271,11 +1265,10 @@ 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; - -- struct asus_wmi *asus = dev_get_drvdata(dev); -- - result = kstrtou32(buf, 10, &value); - if (result) - return result; --- -2.44.0 - -From 4f772c2affe17d50c791d61c72662df81b18884a Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 25 Mar 2024 11:14:28 +1300 -Subject: [PATCH v4 7/9] platform/x86: asus-wmi: ROG Ally increase wait time, - allow MCU powersave -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -The previous work to allow the MCU to be resumed correctly after sleep -and resume tried to take the shortest possible time. However as work -continues in various other parts of the s2idle subsystems it has shown -that it wasn't entirely reliable. - -If the MCU disable/enable call is done correctly the MCU fully removes -its USB endpoints, and this shows as a full USB device reconnection on -resume. When we tried to short this as much as possible sometimes the -MCU doesn't get to complete what it needs to do before going to low-power -and this affected the reconnection. - -Through trial it is found that the minimum time required is approx 1200ms -to allow a proper disconnect and disable, and the same amount of time on -resume is required to prevent a rapid disconnect/reconnect happening on -seemingly random occasions. To be safe the time is now 1500ms for msleep. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 12 ++---------- - 1 file changed, 2 insertions(+), 10 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 976e26c82f80..ab98f91e573c 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -140,7 +140,7 @@ module_param(fnlock_default, bool, 0444); - /* Controls the power state of the USB0 hub on ROG Ally which input is on */ - #define ASUS_USB0_PWR_EC0_CSEE "\\_SB.PCI0.SBRG.EC0.CSEE" - /* 300ms so far seems to produce a reliable result on AC and battery */ --#define ASUS_USB0_PWR_EC0_CSEE_WAIT 300 -+#define ASUS_USB0_PWR_EC0_CSEE_WAIT 1500 - - static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL }; - -@@ -4829,6 +4829,7 @@ static int asus_hotk_resume_early(struct device *device) - struct asus_wmi *asus = dev_get_drvdata(device); - - if (asus->ally_mcu_usb_switch) { -+ /* sleep required to prevent USB0 being yanked then reappearing rapidly */ - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB8))) - dev_err(device, "ROG Ally MCU failed to connect USB dev\n"); - else -@@ -4840,17 +4841,8 @@ static int asus_hotk_resume_early(struct device *device) - static int asus_hotk_prepare(struct device *device) - { - struct asus_wmi *asus = dev_get_drvdata(device); -- int result, err; - - if (asus->ally_mcu_usb_switch) { -- /* When powersave is enabled it causes many issues with resume of USB hub */ -- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MCU_POWERSAVE); -- if (result == 1) { -- dev_warn(device, "MCU powersave enabled, disabling to prevent resume issues"); -- err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, 0, &result); -- if (err || result != 1) -- dev_err(device, "Failed to set MCU powersave mode: %d\n", err); -- } - /* sleep required to ensure USB0 is disabled before sleep continues */ - if (ACPI_FAILURE(acpi_execute_simple_method(NULL, ASUS_USB0_PWR_EC0_CSEE, 0xB7))) - dev_err(device, "ROG Ally MCU failed to disconnect USB dev\n"); --- -2.44.0 - -From 67529648f99081e63e66c831d2644181ca314c86 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 25 Mar 2024 16:43:12 +1300 -Subject: [PATCH v4 8/9] platform/x86: asus-wmi: Add support for MCU powersave -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add support for an MCU powersave WMI call. This is intended to set the -MCU in to a low-power mode when sleeping. This mode can cut sleep power -use by around half. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - .../ABI/testing/sysfs-platform-asus-wmi | 9 ++++ - drivers/platform/x86/asus-wmi.c | 50 +++++++++++++++++++ - 2 files changed, 59 insertions(+) - -diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi -index 72933527d2e4..28144371a0f1 100644 ---- a/Documentation/ABI/testing/sysfs-platform-asus-wmi -+++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi -@@ -203,3 +203,12 @@ Description: - Set if the BIOS POST sound is played on boot. - * 0 - False, - * 1 - True -+ -+What: /sys/devices/platform/<platform>/mcu_powersave -+Date: Apr 2024 -+KernelVersion: 6.10 -+Contact: "Luke Jones" <luke@ljones.dev> -+Description: -+ Set if the MCU can go in to low-power mode on system sleep -+ * 0 - False, -+ * 1 - True -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index ab98f91e573c..d06d9e0c498c 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -1303,6 +1303,53 @@ static ssize_t nv_temp_target_show(struct device *dev, - } - 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) -+{ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ int result; -+ -+ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_MCU_POWERSAVE); -+ if (result < 0) -+ return result; -+ -+ return sysfs_emit(buf, "%d\n", result); -+} -+ -+static ssize_t mcu_powersave_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int result, err; -+ u32 enable; -+ -+ struct asus_wmi *asus = dev_get_drvdata(dev); -+ -+ result = kstrtou32(buf, 10, &enable); -+ if (result) -+ return result; -+ -+ if (enable > 1) -+ return -EINVAL; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_MCU_POWERSAVE, enable, &result); -+ if (err) { -+ pr_warn("Failed to set MCU powersave: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set MCU powersave (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "mcu_powersave"); -+ -+ return count; -+} -+static DEVICE_ATTR_RW(mcu_powersave); -+ - /* Battery ********************************************************************/ - - /* The battery maximum charging percentage */ -@@ -4317,6 +4364,7 @@ static struct attribute *platform_attributes[] = { - &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, -@@ -4370,6 +4418,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - devid = ASUS_WMI_DEVID_NV_DYN_BOOST; - else if (attr == &dev_attr_nv_temp_target.attr) - devid = ASUS_WMI_DEVID_NV_THERM_TARGET; -+ else if (attr == &dev_attr_mcu_powersave.attr) -+ devid = ASUS_WMI_DEVID_MCU_POWERSAVE; - else if (attr == &dev_attr_boot_sound.attr) - devid = ASUS_WMI_DEVID_BOOT_SOUND; - else if (attr == &dev_attr_panel_od.attr) --- -2.44.0 - -From fb8027a2ca91fff199a21300ca2d2afaf264e1d3 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Mon, 25 Mar 2024 17:14:00 +1300 -Subject: [PATCH v4 9/9] platform/x86: asus-wmi: cleanup main struct to avoid - some holes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Reorganises some attr-available calls to remove a few unrequired -booleans in the main driver struct which combined with some -reorganisation prevents a series of large holes seen with pahole. - -Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-wmi.c | 17 ++++++----------- - 1 file changed, 6 insertions(+), 11 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index d06d9e0c498c..2d2b4eca7fd8 100644 ---- a/drivers/platform/x86/asus-wmi.c -+++ b/drivers/platform/x86/asus-wmi.c -@@ -254,6 +254,9 @@ struct asus_wmi { - u32 tablet_switch_dev_id; - bool tablet_switch_inverted; - -+ /* The ROG Ally device requires the MCU USB device be disconnected before suspend */ -+ bool ally_mcu_usb_switch; -+ - enum fan_type fan_type; - enum fan_type gpu_fan_type; - enum fan_type mid_fan_type; -@@ -266,9 +269,7 @@ struct asus_wmi { - u8 fan_boost_mode_mask; - u8 fan_boost_mode; - -- bool charge_mode_available; - bool egpu_enable_available; -- bool egpu_connect_available; - bool dgpu_disable_available; - u32 gpu_mux_dev; - -@@ -309,9 +310,6 @@ struct asus_wmi { - - bool fnlock_locked; - -- /* The ROG Ally device requires the MCU USB device be disconnected before suspend */ -- bool ally_mcu_usb_switch; + Set the Package Power Target total of CPU: PL1 on Intel, SPL on AMD. + Shown on Intel+Nvidia or AMD+Nvidia based systems: - - struct asus_wmi_debug debug; - - struct asus_wmi_driver *driver; -@@ -4391,11 +4389,11 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - else if (attr == &dev_attr_als_enable.attr) - devid = ASUS_WMI_DEVID_ALS_ENABLE; - else if (attr == &dev_attr_charge_mode.attr) -- ok = asus->charge_mode_available; -+ devid = ASUS_WMI_DEVID_CHARGE_MODE; - else if (attr == &dev_attr_egpu_enable.attr) - ok = asus->egpu_enable_available; - else if (attr == &dev_attr_egpu_connected.attr) -- ok = asus->egpu_connect_available; -+ devid = ASUS_WMI_DEVID_EGPU_CONNECTED; - else if (attr == &dev_attr_dgpu_disable.attr) - ok = asus->dgpu_disable_available; - else if (attr == &dev_attr_gpu_mux_mode.attr) -@@ -4423,7 +4421,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, - else if (attr == &dev_attr_boot_sound.attr) - devid = ASUS_WMI_DEVID_BOOT_SOUND; - else if (attr == &dev_attr_panel_od.attr) -- ok = asus->panel_overdrive_available; -+ devid = ASUS_WMI_DEVID_PANEL_OD; - else if (attr == &dev_attr_mini_led_mode.attr) - ok = asus->mini_led_dev_id != 0; - else if (attr == &dev_attr_available_mini_led_mode.attr) -@@ -4674,12 +4672,9 @@ static int asus_wmi_add(struct platform_device *pdev) - asus->nv_dynamic_boost = 5; - asus->nv_temp_target = 75; - -- asus->charge_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_CHARGE_MODE); - asus->egpu_enable_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU); -- asus->egpu_connect_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_EGPU_CONNECTED); - 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); -- asus->panel_overdrive_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_PANEL_OD); - asus->ally_mcu_usb_switch = acpi_has_method(NULL, ASUS_USB0_PWR_EC0_CSEE) - && dmi_match(DMI_BOARD_NAME, "RC71L"); - --- -2.44.0 - -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. - -As part of keeping the patch clean the throttle_thermal_policy_available -boolean stored in the driver struct is removed and -throttle_thermal_policy_dev is used in place (as on init it is zeroed). - -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 +++++++++++---------- - include/linux/platform_data/x86/asus-wmi.h | 1 + - 2 files changed, 55 insertions(+), 46 deletions(-) - -diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 2d2b4eca7fd8..439d330fb80b 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); - #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_OVERBOOST_VIVO 2 -+#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 -+#define ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED 3 -+ - #define USB_INTEL_XUSB2PR 0xD0 - #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 - -@@ -285,8 +290,8 @@ struct asus_wmi { - u32 kbd_rgb_dev; - bool kbd_rgb_state_available; - -- bool throttle_thermal_policy_available; - u8 throttle_thermal_policy_mode; -+ u32 throttle_thermal_policy_dev; - - 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) - int err, fan_idx; - u8 mode = 0; - -- if (asus->throttle_thermal_policy_available) -+ if (asus->throttle_thermal_policy_dev) - 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, - * For machines with throttle this is the only way to reset fans - * to default mode of operation (does not erase curve data). - */ -- if (asus->throttle_thermal_policy_available) { -+ if (asus->throttle_thermal_policy_dev) { - err = throttle_thermal_policy_write(asus); - if (err) - return err; -@@ -3577,8 +3582,8 @@ static const struct attribute_group asus_fan_curve_attr_group = { - __ATTRIBUTE_GROUPS(asus_fan_curve_attr); - - /* -- * Must be initialised after throttle_thermal_policy_check_present() as -- * we check the status of throttle_thermal_policy_available during init. -+ * Must be initialised after throttle_thermal_policy_dev is set as -+ * we check the status of throttle_thermal_policy_dev during init. - */ - 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) - } +- * min=5, max=250 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default - /* Throttle thermal policy ****************************************************/ -- --static int throttle_thermal_policy_check_present(struct asus_wmi *asus) --{ -- u32 result; -- int err; -- -- asus->throttle_thermal_policy_available = false; -- -- err = asus_wmi_get_devstate(asus, -- ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, -- &result); -- if (err) { -- if (err == -ENODEV) -- return 0; -- return err; -- } -- -- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) -- asus->throttle_thermal_policy_available = true; -- -- return 0; --} + 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: - - static int throttle_thermal_policy_write(struct asus_wmi *asus) - { -- int err; -- 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) - - static int throttle_thermal_policy_set_default(struct asus_wmi *asus) - { -- if (!asus->throttle_thermal_policy_available) -+ if (!asus->throttle_thermal_policy_dev) - 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) - { - 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) - 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); - 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) - return -EINVAL; - - asus->throttle_thermal_policy_mode = new_mode; -@@ -3748,7 +3755,10 @@ 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); +- * min=5, max=250 ++ * min/max varies, read *_min/*_max sysfs entries ++ * -1 resets to default - /* Platform profile ***********************************************************/ -@@ -3814,7 +3824,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. - */ -- if (!asus->throttle_thermal_policy_available) -+ if (!asus->throttle_thermal_policy_dev) - return 0; + 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 - 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) - if (code == NOTIFY_KBD_FBM || code == NOTIFY_KBD_TTP) { - if (asus->fan_boost_mode_available) - fan_boost_mode_switch_next(asus); -- if (asus->throttle_thermal_policy_available) -+ if (asus->throttle_thermal_policy_dev) - throttle_thermal_policy_switch_next(asus); - return; + 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 -@@ -4401,7 +4411,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) -- ok = asus->throttle_thermal_policy_available; -+ ok = asus->throttle_thermal_policy_dev != 0; - 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) - else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_TUF_RGB_MODE2)) - asus->kbd_rgb_dev = ASUS_WMI_DEVID_TUF_RGB_MODE2; + 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 -+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) -+ asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY; -+ else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO)) -+ asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; -+ - err = fan_boost_mode_check_present(asus); - if (err) - goto fail_fan_boost_mode; + 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 -- err = throttle_thermal_policy_check_present(asus); -- if (err) -- goto fail_throttle_thermal_policy; -- else -- throttle_thermal_policy_set_default(asus); -- - 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) - fail_input: - asus_wmi_sysfs_exit(asus->platform_device); - fail_sysfs: --fail_throttle_thermal_policy: - fail_custom_fan_curve: - 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 ---- a/include/linux/platform_data/x86/asus-wmi.h -+++ b/include/linux/platform_data/x86/asus-wmi.h -@@ -64,6 +64,7 @@ - #define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 - #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 - #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 -+#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 + 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 - /* Misc */ - #define ASUS_WMI_DEVID_PANEL_OD 0x00050019 --- -2.44.0 - -From de9b01c3b8869451d4cf44ab0baf55440e804fc6 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sat, 2 Dec 2023 17:47:59 +1300 -Subject: [PATCH 2/4] HID: asus: make asus_kbd_init() generic, remove - rog_nkey_led_init() - -Some of the n-key stuff is old and outdated, so -make asus_kbd_init() generic to use with other -report ID and remove rog_nkey_led_init(). - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/hid/hid-asus.c | 70 +++++++++++------------------------------- - 1 file changed, 18 insertions(+), 52 deletions(-) - + What: /sys/devices/platform/<platform>/boot_sound + Date: Apr 2024 diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c -index 855972a4470f..cdd998a761fe 100644 +index 37e6d25593c2..af57a5f03193 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c -@@ -386,9 +386,9 @@ static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t bu - return ret; - } - --static int asus_kbd_init(struct hid_device *hdev) -+static int asus_kbd_init(struct hid_device *hdev, u8 report_id) - { -- const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, -+ const u8 buf[] = { report_id, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, - 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; - int ret; - -@@ -400,9 +400,10 @@ static int asus_kbd_init(struct hid_device *hdev) - } - - static int asus_kbd_get_functions(struct hid_device *hdev, -- unsigned char *kbd_func) -+ unsigned char *kbd_func, -+ u8 report_id) - { -- const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }; -+ const u8 buf[] = { report_id, 0x05, 0x20, 0x31, 0x00, 0x08 }; - u8 *readbuf; - int ret; - -@@ -431,51 +432,6 @@ static int asus_kbd_get_functions(struct hid_device *hdev, - return ret; - } - --static int rog_nkey_led_init(struct hid_device *hdev) --{ -- const u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 }; -- u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20, -- 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; -- u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1, -- 0x05, 0x20, 0x31, 0x00, 0x08 }; -- int ret; -- -- hid_info(hdev, "Asus initialise N-KEY Device"); -- /* The first message is an init start */ -- ret = asus_kbd_set_report(hdev, buf_init_start, sizeof(buf_init_start)); -- if (ret < 0) { -- hid_warn(hdev, "Asus failed to send init start command: %d\n", ret); -- return ret; -- } -- /* Followed by a string */ -- ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); -- if (ret < 0) { -- hid_warn(hdev, "Asus failed to send init command 1.0: %d\n", ret); -- return ret; -- } -- /* Followed by a string */ -- ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); -- if (ret < 0) { -- hid_warn(hdev, "Asus failed to send init command 1.1: %d\n", ret); -- return ret; -- } -- -- /* begin second report ID with same data */ -- buf_init2[0] = FEATURE_KBD_LED_REPORT_ID2; -- buf_init3[0] = FEATURE_KBD_LED_REPORT_ID2; -- -- ret = asus_kbd_set_report(hdev, buf_init2, sizeof(buf_init2)); -- if (ret < 0) { -- hid_warn(hdev, "Asus failed to send init command 2.0: %d\n", ret); -- return ret; -- } -- ret = asus_kbd_set_report(hdev, buf_init3, sizeof(buf_init3)); -- if (ret < 0) -- hid_warn(hdev, "Asus failed to send init command 2.1: %d\n", ret); -- -- return ret; --} -- - static void asus_schedule_work(struct asus_kbd_leds *led) +@@ -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) { - unsigned long flags; -@@ -558,17 +514,27 @@ static int asus_kbd_register_leds(struct hid_device *hdev) ++ struct asus_drvdata *drvdata = hid_get_drvdata(hdev); + u32 value; int ret; - if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD) { -- ret = rog_nkey_led_init(hdev); -+ /* Initialize keyboard */ -+ ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID); -+ if (ret < 0) -+ return ret; -+ -+ /* The LED endpoint is initialised in two HID */ -+ ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID1); -+ if (ret < 0) -+ return ret; -+ -+ ret = asus_kbd_init(hdev, FEATURE_KBD_LED_REPORT_ID2); - if (ret < 0) - return ret; - } else { - /* Initialize keyboard */ -- ret = asus_kbd_init(hdev); -+ ret = asus_kbd_init(hdev, FEATURE_KBD_REPORT_ID); - if (ret < 0) - return ret; - - /* Get keyboard functions */ -- ret = asus_kbd_get_functions(hdev, &kbd_func); -+ ret = asus_kbd_get_functions(hdev, &kbd_func, FEATURE_KBD_REPORT_ID); - if (ret < 0) - return ret; - --- -2.44.0 - -From fe9fe2bbb769c5ffe0d096d9732029f900c65872 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Wed, 29 Nov 2023 22:18:11 +1300 -Subject: [PATCH 3/4] HID: asus: add ROG Ally N-Key ID and keycodes - ---- - drivers/hid/hid-asus.c | 7 +++++++ - drivers/hid/hid-ids.h | 1 + - 2 files changed, 8 insertions(+) - -diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c -index cdd998a761fe..3a1a6024d299 100644 ---- a/drivers/hid/hid-asus.c -+++ b/drivers/hid/hid-asus.c -@@ -847,6 +847,10 @@ static int asus_input_mapping(struct hid_device *hdev, - case 0xb3: asus_map_key_clear(KEY_PROG3); break; /* Fn+Left next aura */ - case 0x6a: asus_map_key_clear(KEY_F13); break; /* Screenpad toggle */ - case 0x4b: asus_map_key_clear(KEY_F14); break; /* Arrows/Pg-Up/Dn toggle */ -+ case 0xa5: asus_map_key_clear(KEY_F15); break; /* ROG Ally left back */ -+ case 0xa6: asus_map_key_clear(KEY_F16); break; /* ROG Ally QAM button */ -+ case 0xa7: asus_map_key_clear(KEY_F17); break; /* ROG Ally ROG long-press */ -+ case 0xa8: asus_map_key_clear(KEY_F18); break; /* ROG Ally ROG long-press-release */ - + if (!IS_ENABLED(CONFIG_ASUS_WMI)) + return false; - default: --- -2.44.0 - -From d9a40306ea83c8799634b6ee8b497d3801967831 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Tue, 2 Apr 2024 15:13:23 +1300 -Subject: [PATCH 4/4] HID: asus: add ROG Z13 lightbar - -Add init of the lightbar which is a small panel on the back of the ASUS -ROG Z13 and uses the same MCU as keyboards. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/hid/hid-asus.c | 3 +++ - drivers/hid/hid-ids.h | 1 + - 2 files changed, 4 insertions(+) - -diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c -index 3a1a6024d299..de0c13babc03 100644 ---- a/drivers/hid/hid-asus.c -+++ b/drivers/hid/hid-asus.c -@@ -1274,6 +1274,9 @@ - USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3), - QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, -+ USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR), -+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, -+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, - USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD), - QUIRK_ROG_CLAYMORE_II_KEYBOARD }, - { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, ++ 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/hid/hid-ids.h b/drivers/hid/hid-ids.h -index f1e508a7ef06..94501dbdd463 100644 +index 72d56ee7ce1b..8291699ec56c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h -@@ -208,6 +208,7 @@ - #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866 +@@ -209,6 +209,7 @@ #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6 #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30 -+#define USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR 0x18c6 + #define USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR 0x18c6 ++#define USB_DEVICE_ID_ASUSTEK_ROG_RAIKIRI_PAD 0x1abb + #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY 0x1abe #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 - --- -2.44.0 - -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 - -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; -@@ -4662,7 +4662,7 @@ - goto fail_fan_boost_mode; - - 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 - -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 +index 665fa9524986..b4a5a5bec7f3 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig -@@ -264,6 +264,18 @@ config ASUS_WIRELESS +@@ -265,6 +265,18 @@ config ASUS_WIRELESS If you choose to compile this driver as a module the module will be called asus-wireless. @@ -1940,7 +153,7 @@ index 0ec952b5d03e..296b5c9bfbb0 100644 config ASUS_WMI tristate "ASUS WMI Driver" depends on ACPI_WMI -@@ -275,6 +287,8 @@ config ASUS_WMI +@@ -276,6 +288,8 @@ config ASUS_WMI depends on HOTPLUG_PCI depends on ACPI_VIDEO || ACPI_VIDEO = n depends on SERIO_I8042 || SERIO_I8042 = n @@ -1963,10 +176,10 @@ index e1b142947067..d9b5b3f3b241 100644 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 +index 000000000000..bd4c408fd062 --- /dev/null +++ b/drivers/platform/x86/asus-bios.c -@@ -0,0 +1,654 @@ +@@ -0,0 +1,983 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Asus BIOS attributes driver @@ -2011,6 +224,18 @@ index 000000000000..c245a48c4072 +#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 @@ -2022,6 +247,7 @@ index 000000000000..c245a48c4072 +#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 { @@ -2044,6 +270,10 @@ index 000000000000..c245a48c4072 + 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; @@ -2095,7 +325,8 @@ index 000000000000..c245a48c4072 +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"); +} + +/* @@ -2392,6 +623,299 @@ index 000000000000..c245a48c4072 +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"); ++ ++static int asus_bios_set_max_cores(void) ++{ ++ u32 cores; ++ int err; ++ ++ asus_bios.rog_tunables->min_perf_cores = 4; ++ asus_bios.rog_tunables->max_perf_cores = 4; ++ asus_bios.rog_tunables->max_power_cores = 8; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES_MAX, &cores); ++ if (err) ++ return err; ++ ++ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; ++ asus_bios.rog_tunables->max_power_cores = (cores & 0xff00) >> 8; ++ asus_bios.rog_tunables->max_perf_cores = cores & 0xff; ++ ++ return 0; ++} ++ ++static ssize_t cores_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf, ++ enum cpu_core_type core_type, ++ enum cpu_core_value core_value) ++{ ++ u32 cores; ++ int err; ++ ++ switch (core_value) { ++ case CPU_CORE_DEFAULT: ++ case CPU_CORE_MAX: ++ if (core_type == CPU_CORE_PERF) ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_perf_cores); ++ else ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_power_cores); ++ case CPU_CORE_MIN: ++ if (core_type == CPU_CORE_PERF) ++ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->min_perf_cores); ++ else ++ return sysfs_emit(buf, "%d\n", 0); ++ default: ++ break; ++ } ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, &cores); ++ if (err) ++ return err; ++ ++ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; ++ if (core_type == CPU_CORE_PERF) ++ cores &= 0xff; ++ else ++ cores = (cores & 0xff00) >> 8; ++ return sysfs_emit(buf, "%d\n", cores); ++} ++ ++static ssize_t cores_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, const char *buf, ++ enum cpu_core_type core_type) ++{ ++ int result, err; ++ u32 cores, currentv, min, max; ++ ++ result = kstrtou32(buf, 10, &cores); ++ if (result) ++ return result; ++ ++ if (core_type == CPU_CORE_PERF) { ++ min = asus_bios.rog_tunables->min_perf_cores; ++ max = asus_bios.rog_tunables->max_perf_cores; ++ } else { ++ min = 0; ++ max = asus_bios.rog_tunables->max_power_cores; ++ } ++ if (cores < min || cores > max) ++ return -EINVAL; ++ ++ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, ¤tv); ++ if (err) ++ return err; ++ ++ if (core_type == CPU_CORE_PERF) ++ cores |= (currentv & 0xff00); ++ else ++ cores |= currentv & 0xff; ++ ++ if (cores == currentv) ++ return 0; ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CORES, cores, &result); ++ if (err) { ++ pr_warn("Failed to set perfromance core count: %d\n", err); ++ return err; ++ } ++ ++ if (result > 1) { ++ pr_warn("Failed to set performance core count (result): 0x%x\n", result); ++ return -EIO; ++ } ++ ++ pr_info("CPU core count changed, reboot required\n"); ++ sysfs_notify(kobj, NULL, attr->attr.name); ++ asus_set_reboot_and_signal_event(); ++ ++ return 0; ++} ++ ++static ssize_t cores_performance_min_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MIN); ++} ++ ++static ssize_t cores_performance_max_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MAX); ++} ++ ++static ssize_t cores_performance_default_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_DEFAULT); ++} ++ ++static ssize_t cores_performance_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_CURRENT); ++} ++ ++static ssize_t cores_performance_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF); ++ if (err) ++ return err; ++ ++ return count; ++} ++ATTR_GROUP_CORES_RW(cores_performance, "cores_performance", ASUS_WMI_DEVID_CORES, "Set the max available performance cores"); ++ ++static ssize_t cores_efficiency_min_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MIN); ++} ++ ++static ssize_t cores_efficiency_max_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MAX); ++} ++ ++static ssize_t cores_efficiency_default_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_DEFAULT); ++} ++ ++static ssize_t cores_efficiency_current_value_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_CURRENT); ++} ++ ++static ssize_t cores_efficiency_current_value_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER); ++ if (err) ++ return err; ++ ++ return count; ++} ++ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency", ASUS_WMI_DEVID_CORES, "Set the max available efficiency cores"); ++ +/* Simple attribute creation */ +ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo"); +ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, @@ -2409,11 +933,15 @@ index 000000000000..c245a48c4072 + 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"); +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) @@ -2476,8 +1004,14 @@ index 000000000000..c245a48c4072 + 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)) @@ -2493,6 +1027,12 @@ index 000000000000..c245a48c4072 + 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_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); @@ -2502,6 +1042,8 @@ index 000000000000..c245a48c4072 + 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; + @@ -2623,10 +1165,10 @@ index 000000000000..c245a48c4072 +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 +index 000000000000..7016ec14efc1 --- /dev/null +++ b/drivers/platform/x86/asus-bios.h -@@ -0,0 +1,234 @@ +@@ -0,0 +1,288 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Definitions for kernel modules using asus-bios driver @@ -2741,6 +1283,22 @@ index 000000000000..acae11698a07 +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)\ @@ -2784,6 +1342,15 @@ index 000000000000..acae11698a07 + .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); @@ -2834,15 +1401,18 @@ index 000000000000..acae11698a07 + .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); \ ++/* 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[] = { \ @@ -2860,656 +1430,15 @@ index 000000000000..acae11698a07 + .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 - -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 -@@ -68,6 +68,7 @@ - #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 - - /* 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 - -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 - -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 - -From f7e8fe2458a3f8aa091e5e282b67f2a78f5cc1c4 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Sun, 2 Jun 2024 16:21:32 +1200 -Subject: [PATCH 7/8] asus-bios: add core count control - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/platform/x86/asus-bios.c | 201 +++++++++++++++++++++ - drivers/platform/x86/asus-bios.h | 29 +++ - include/linux/platform_data/x86/asus-wmi.h | 4 + - 3 files changed, 234 insertions(+) - -diff --git a/drivers/platform/x86/asus-bios.c b/drivers/platform/x86/asus-bios.c -index bcb053b57102..bd4c408fd062 100644 ---- a/drivers/platform/x86/asus-bios.c -+++ b/drivers/platform/x86/asus-bios.c -@@ -42,6 +42,18 @@ MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID); - #define ASUS_MINI_LED_2024_STRONG 0x01 - #define ASUS_MINI_LED_2024_OFF 0x02 - -+enum cpu_core_type { -+ CPU_CORE_PERF = 0, -+ CPU_CORE_POWER, -+}; -+ -+enum cpu_core_value { -+ CPU_CORE_DEFAULT = 0, -+ CPU_CORE_MIN, -+ CPU_CORE_MAX, -+ CPU_CORE_CURRENT, -+}; -+ - /* Default limits for tunables available on ASUS ROG laptops */ - #define PPT_CPU_LIMIT_MIN 5 - #define PPT_CPU_LIMIT_MAX 150 -@@ -76,6 +88,10 @@ struct rog_tunables { - u32 nv_temp_default; - u32 nv_temp_max; - u32 nv_temp_target; -+ -+ u32 min_perf_cores; -+ u32 max_perf_cores; -+ u32 max_power_cores; - }; - - static const struct class *fw_attr_class; -@@ -539,6 +555,185 @@ static ssize_t apu_mem_possible_values_show(struct kobject *kobj, - } - ATTR_GROUP_ENUM_CUSTOM(apu_mem, "apu_mem", "Set the available system memory for the APU to use"); - -+static int asus_bios_set_max_cores(void) -+{ -+ u32 cores; -+ int err; -+ -+ asus_bios.rog_tunables->min_perf_cores = 4; -+ asus_bios.rog_tunables->max_perf_cores = 4; -+ asus_bios.rog_tunables->max_power_cores = 8; -+ -+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES_MAX, &cores); -+ if (err) -+ return err; -+ -+ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; -+ asus_bios.rog_tunables->max_power_cores = (cores & 0xff00) >> 8; -+ asus_bios.rog_tunables->max_perf_cores = cores & 0xff; -+ -+ return 0; -+} -+ -+static ssize_t cores_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf, -+ enum cpu_core_type core_type, -+ enum cpu_core_value core_value) -+{ -+ u32 cores; -+ int err; -+ -+ switch (core_value) { -+ case CPU_CORE_DEFAULT: -+ case CPU_CORE_MAX: -+ if (core_type == CPU_CORE_PERF) -+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_perf_cores); -+ else -+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->max_power_cores); -+ case CPU_CORE_MIN: -+ if (core_type == CPU_CORE_PERF) -+ return sysfs_emit(buf, "%d\n", asus_bios.rog_tunables->min_perf_cores); -+ else -+ return sysfs_emit(buf, "%d\n", 0); -+ default: -+ break; -+ } -+ -+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, &cores); -+ if (err) -+ return err; -+ -+ cores &= ~ASUS_WMI_DSTS_PRESENCE_BIT; -+ if (core_type == CPU_CORE_PERF) -+ cores &= 0xff; -+ else -+ cores = (cores & 0xff00) >> 8; -+ return sysfs_emit(buf, "%d\n", cores); -+} -+ -+static ssize_t cores_current_value_store(struct kobject *kobj, -+ struct kobj_attribute *attr, const char *buf, -+ enum cpu_core_type core_type) -+{ -+ int result, err; -+ u32 cores, currentv, min, max; -+ -+ result = kstrtou32(buf, 10, &cores); -+ if (result) -+ return result; -+ -+ if (core_type == CPU_CORE_PERF) { -+ min = asus_bios.rog_tunables->min_perf_cores; -+ max = asus_bios.rog_tunables->max_perf_cores; -+ } else { -+ min = 0; -+ max = asus_bios.rog_tunables->max_power_cores; -+ } -+ if (cores < min || cores > max) -+ return -EINVAL; -+ -+ err = asus_wmi_get_devstate_dsts(ASUS_WMI_DEVID_CORES, ¤tv); -+ if (err) -+ return err; -+ -+ if (core_type == CPU_CORE_PERF) -+ cores |= (currentv & 0xff00); -+ else -+ cores |= currentv & 0xff; -+ -+ if (cores == currentv) -+ return 0; -+ -+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_CORES, cores, &result); -+ if (err) { -+ pr_warn("Failed to set perfromance core count: %d\n", err); -+ return err; -+ } -+ -+ if (result > 1) { -+ pr_warn("Failed to set performance core count (result): 0x%x\n", result); -+ return -EIO; -+ } -+ -+ pr_info("CPU core count changed, reboot required\n"); -+ sysfs_notify(kobj, NULL, attr->attr.name); -+ asus_set_reboot_and_signal_event(); -+ -+ return 0; -+} -+ -+static ssize_t cores_performance_min_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MIN); -+} -+ -+static ssize_t cores_performance_max_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_MAX); -+} -+ -+static ssize_t cores_performance_default_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_DEFAULT); -+} -+ -+static ssize_t cores_performance_current_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_PERF, CPU_CORE_CURRENT); -+} -+ -+static ssize_t cores_performance_current_value_store(struct kobject *kobj, -+ struct kobj_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_PERF); -+ if (err) -+ return err; -+ -+ return count; -+} -+ATTR_GROUP_CORES_RW(cores_performance, "cores_performance", ASUS_WMI_DEVID_CORES, "Set the max available performance cores"); -+ -+static ssize_t cores_efficiency_min_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MIN); -+} -+ -+static ssize_t cores_efficiency_max_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_MAX); -+} -+ -+static ssize_t cores_efficiency_default_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_DEFAULT); -+} -+ -+static ssize_t cores_efficiency_current_value_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return cores_value_show(kobj, attr, buf, CPU_CORE_POWER, CPU_CORE_CURRENT); -+} -+ -+static ssize_t cores_efficiency_current_value_store(struct kobject *kobj, -+ struct kobj_attribute *attr, -+ const char *buf, size_t count) -+{ -+ int err = cores_current_value_store(kobj, attr, buf, CPU_CORE_POWER); -+ if (err) -+ return err; -+ -+ return count; -+} -+ATTR_GROUP_CORES_RW(cores_efficiency, "cores_efficiency", ASUS_WMI_DEVID_CORES, "Set the max available efficiency cores"); -+ - /* Simple attribute creation */ - ATTR_GROUP_ENUM_INT_RW(thermal_policy, "thermal_policy", ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, 0, 3, "0;1;2", "Fan stuff todo"); - ATTR_GROUP_PPT_RW(ppt_pl1_spl, "ppt_pl1_spl", ASUS_WMI_DEVID_PPT_PL1_SPL, -@@ -627,8 +822,14 @@ static int asus_fw_attr_add(void) - if (asus_wmi_is_present(ASUS_WMI_DEVID_EGPU_CONNECTED)) - sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &egpu_connected_attr_group); - -+ if (asus_wmi_is_present(ASUS_WMI_DEVID_CORES_MAX) && !asus_bios_set_max_cores()){ -+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_performance_attr_group); -+ sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &cores_efficiency_attr_group); -+ } -+ - if (asus_wmi_is_present(ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) - sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &thermal_policy_attr_group); -+ - if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL1_SPL)) - sysfs_create_group(&asus_bios.fw_attr_kset->kobj, &ppt_pl1_spl_attr_group); - if (asus_wmi_is_present(ASUS_WMI_DEVID_PPT_PL2_SPPT)) -diff --git a/drivers/platform/x86/asus-bios.h b/drivers/platform/x86/asus-bios.h -index 7c4176ab757a..7016ec14efc1 100644 ---- a/drivers/platform/x86/asus-bios.h -+++ b/drivers/platform/x86/asus-bios.h -@@ -230,6 +230,35 @@ static const struct attribute_group _attrname##_attr_group = { \ - .attrs = _attrname##_attrs \ - }; - -+/* CPU core attributes need a little different in setup */ -+#define ATTR_GROUP_CORES_RW(_attrname, _fsname, _wmi, _dispname)\ -+__ATTR_SHOW_FMT(scalar_increment, _attrname, "%d\n", 1); \ ++/* 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##_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[] = { \ @@ -3527,315 +1456,24 @@ index 7c4176ab757a..7016ec14efc1 100644 + .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 - -From 59cb165cde465df5380b809ecea6737d85405dac 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/3] 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); ++#endif /* _ASUS_BIOSCFG_H_ */ diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c -index 3f9b6285c9a6..799d928c7d3d 100644 +index bc9c5db38324..9c80aa073758 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..96c780efa0d7 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 +@@ -97,6 +97,11 @@ module_param(fnlock_default, bool, 0444); + #define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST 1 + #define ASUS_THROTTLE_THERMAL_POLICY_SILENT 2 -+/* 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, "GA403U"), -+ }, -+ }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "GU605M"), -+ }, -+ }, -+ { -+ .matches = { -+ DMI_MATCH(DMI_BOARD_NAME, "RC71L"), -+ }, -+ }, -+ NULL, -+}; ++#define ASUS_THROTTLE_THERMAL_POLICY_DEFAULT_VIVO 0 ++#define ASUS_THROTTLE_THERMAL_POLICY_OVERBOOST_VIVO 2 ++#define ASUS_THROTTLE_THERMAL_POLICY_SILENT_VIVO 1 ++#define ASUS_THROTTLE_THERMAL_POLICY_FULLSPEED 3 + - #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */ --- -2.45.2 - -From 671da604738dd6dd01903585e8e8a55d49ab06e9 Mon Sep 17 00:00:00 2001 -From: "Luke D. Jones" <luke@ljones.dev> -Date: Fri, 7 Jun 2024 15:58:01 +1200 -Subject: [PATCH v2 3/3] Input: xpad - add support for ASUS ROG RAIKIRI PRO - -Add the VID/PID for ASUS ROG RAIKIRI PRO to -xpad_device and the VID to xpad_table. - -Signed-off-by: Luke D. Jones <luke@ljones.dev> ---- - drivers/hid/hid-ids.h | 1 + - drivers/input/joystick/xpad.c | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h -index 61d2a21affa2..31c522fa4e87 100644 ---- a/drivers/hid/hid-ids.h -+++ b/drivers/hid/hid-ids.h -@@ -209,6 +209,7 @@ - #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6 - #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD3 0x1a30 - #define USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR 0x18c6 -+#define USB_DEVICE_ID_ASUSTEK_ROG_RAIKIRI_PAD 0x1abb - #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b - #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 - --- -2.45.2 - -/* 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 + #define USB_INTEL_XUSB2PR 0xD0 + #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 - 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); +@@ -112,11 +117,13 @@ module_param(fnlock_default, bool, 0444); /* Mask to determine if setting temperature or percentage */ #define FAN_CURVE_PWM_MASK 0x04 @@ -3854,7 +1492,7 @@ index 999cd658ec8b..d016acb23789 100644 #define NVIDIA_BOOST_MIN 5 #define NVIDIA_BOOST_MAX 25 #define NVIDIA_TEMP_MIN 75 -@@ -219,6 +221,29 @@ struct fan_curve_data { +@@ -219,6 +226,29 @@ struct fan_curve_data { u8 percents[FAN_CURVE_POINTS]; }; @@ -3884,7 +1522,7 @@ index 999cd658ec8b..d016acb23789 100644 struct asus_wmi { int dsts_id; int spec; -@@ -273,14 +298,7 @@ struct asus_wmi { +@@ -273,20 +303,13 @@ struct asus_wmi { bool dgpu_disable_available; u32 gpu_mux_dev; @@ -3900,7 +1538,144 @@ index 999cd658ec8b..d016acb23789 100644 u32 kbd_rgb_dev; bool kbd_rgb_state_available; -@@ -652,6 +670,98 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) + +- bool throttle_thermal_policy_available; + u8 throttle_thermal_policy_mode; ++ u32 throttle_thermal_policy_dev; + + bool cpu_fan_curve_available; + bool gpu_fan_curve_available; +@@ -334,20 +357,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 +409,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 +457,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 +499,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; + } +@@ -503,12 +552,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, +@@ -542,6 +607,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); + } +@@ -625,6 +691,98 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) asus->inputdev = NULL; } @@ -3999,7 +1774,7 @@ index 999cd658ec8b..d016acb23789 100644 /* 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[] = { +@@ -995,306 +1153,6 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = { NULL, }; @@ -4306,7 +2081,238 @@ index 999cd658ec8b..d016acb23789 100644 /* 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[] = { +@@ -1685,7 +1544,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; +@@ -2312,10 +2172,10 @@ static ssize_t mini_led_mode_store(struct device *dev, + return result; + + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE && +- mode > ASUS_MINI_LED_ON) ++ mode > ASUS_MINI_LED_ON) + return -EINVAL; + if (asus->mini_led_dev_id == ASUS_WMI_DEVID_MINI_LED_MODE2 && +- mode > ASUS_MINI_LED_STRONG_MODE) ++ mode > ASUS_MINI_LED_STRONG_MODE) + return -EINVAL; + + /* +@@ -3127,7 +2987,7 @@ static int fan_curve_get_factory_default(struct asus_wmi *asus, u32 fan_dev) + int err, fan_idx; + u8 mode = 0; + +- if (asus->throttle_thermal_policy_available) ++ if (asus->throttle_thermal_policy_dev) + mode = asus->throttle_thermal_policy_mode; + /* DEVID_<C/G>PU_FAN_CURVE is switched for OVERBOOST vs SILENT */ + if (mode == 2) +@@ -3334,7 +3194,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). + */ +- if (asus->throttle_thermal_policy_available) { ++ if (asus->throttle_thermal_policy_dev) { + err = throttle_thermal_policy_write(asus); + if (err) + return err; +@@ -3551,8 +3411,8 @@ static const struct attribute_group asus_fan_curve_attr_group = { + __ATTRIBUTE_GROUPS(asus_fan_curve_attr); + + /* +- * Must be initialised after throttle_thermal_policy_check_present() as +- * we check the status of throttle_thermal_policy_available during init. ++ * Must be initialised after throttle_thermal_policy_dev is set as ++ * we check the status of throttle_thermal_policy_dev during init. + */ + static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) + { +@@ -3562,18 +3422,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 +@@ -3593,38 +3462,31 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus) + } + + /* Throttle thermal policy ****************************************************/ +- +-static int throttle_thermal_policy_check_present(struct asus_wmi *asus) +-{ +- u32 result; +- int err; +- +- asus->throttle_thermal_policy_available = false; +- +- err = asus_wmi_get_devstate(asus, +- ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY, +- &result); +- if (err) { +- if (err == -ENODEV) +- return 0; +- return err; +- } +- +- if (result & ASUS_WMI_DSTS_PRESENCE_BIT) +- asus->throttle_thermal_policy_available = true; +- +- return 0; +-} +- + static int throttle_thermal_policy_write(struct asus_wmi *asus) + { +- int err; +- 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, +@@ -3654,7 +3516,7 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus) + + static int throttle_thermal_policy_set_default(struct asus_wmi *asus) + { +- if (!asus->throttle_thermal_policy_available) ++ if (!asus->throttle_thermal_policy_dev) + return 0; + + asus->throttle_thermal_policy_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; +@@ -3664,9 +3526,14 @@ static int throttle_thermal_policy_set_default(struct asus_wmi *asus) + 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) + new_mode = ASUS_THROTTLE_THERMAL_POLICY_DEFAULT; + + asus->throttle_thermal_policy_mode = new_mode; +@@ -3699,13 +3566,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); + 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) + return -EINVAL; + + asus->throttle_thermal_policy_mode = new_mode; +@@ -3722,7 +3593,10 @@ 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 ***********************************************************/ +@@ -3788,7 +3662,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. + */ +- if (!asus->throttle_thermal_policy_available) ++ if (!asus->throttle_thermal_policy_dev) + return 0; + + dev_info(dev, "Using throttle_thermal_policy for platform_profile support\n"); +@@ -3803,8 +3677,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; +@@ -4203,7 +4082,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); +- if (asus->throttle_thermal_policy_available) ++ if (asus->throttle_thermal_policy_dev) + throttle_thermal_policy_switch_next(asus); + return; + +@@ -4329,13 +4208,27 @@ static struct attribute *platform_attributes[] = { &dev_attr_als_enable.attr, &dev_attr_fan_boost_mode.attr, &dev_attr_throttle_thermal_policy.attr, @@ -4335,11 +2341,13 @@ index 999cd658ec8b..d016acb23789 100644 &dev_attr_mcu_powersave.attr, &dev_attr_boot_sound.attr, &dev_attr_panel_od.attr, -@@ -4294,19 +4294,33 @@ +@@ -4375,20 +4268,34 @@ 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) - ok = asus->throttle_thermal_policy_dev != 0; +- ok = asus->throttle_thermal_policy_available; - else if (attr == &dev_attr_ppt_pl2_sppt.attr) ++ ok = asus->throttle_thermal_policy_dev != 0; + 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) @@ -4376,7 +2384,19 @@ index 999cd658ec8b..d016acb23789 100644 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) +@@ -4401,8 +4308,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; + } +@@ -4612,6 +4521,77 @@ static void asus_wmi_debugfs_init(struct asus_wmi *asus) /* Init / exit ****************************************************************/ @@ -4454,7 +2474,7 @@ index 999cd658ec8b..d016acb23789 100644 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) +@@ -4637,15 +4617,7 @@ static int asus_wmi_add(struct platform_device *pdev) if (err) goto fail_platform; @@ -4471,6 +2491,142 @@ index 999cd658ec8b..d016acb23789 100644 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 - +@@ -4667,18 +4639,17 @@ 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; + ++ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY)) ++ asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY; ++ else if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO)) ++ asus->throttle_thermal_policy_dev = ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO; ++ + err = fan_boost_mode_check_present(asus); + if (err) + goto fail_fan_boost_mode; + +- err = throttle_thermal_policy_check_present(asus); +- if (err) +- goto fail_throttle_thermal_policy; +- else +- 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); +@@ -4771,7 +4742,6 @@ static int asus_wmi_add(struct platform_device *pdev) + fail_input: + asus_wmi_sysfs_exit(asus->platform_device); + fail_sysfs: +-fail_throttle_thermal_policy: + fail_custom_fan_curve: + 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..870f4bb57100 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 */ +@@ -64,8 +65,10 @@ + #define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032 + #define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 + #define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 ++#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY_VIVO 0x00110019 + + /* 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 +@@ -126,6 +129,14 @@ + /* 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 ++ + /* gpu mux switch, 0 = dGPU, 1 = Optimus */ + #define ASUS_WMI_DEVID_GPU_MUX 0x00090016 + #define ASUS_WMI_DEVID_GPU_MUX_VIVO 0x00090026 +@@ -151,8 +162,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) + { +@@ -160,4 +181,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, "GA403U"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "GU605M"), ++ }, ++ }, ++ { ++ .matches = { ++ DMI_MATCH(DMI_BOARD_NAME, "RC71L"), ++ }, ++ }, ++ NULL, ++}; ++ + #endif /* __PLATFORM_DATA_X86_ASUS_WMI_H */ |