summarylogtreecommitdiffstats
path: root/v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch
diff options
context:
space:
mode:
Diffstat (limited to 'v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch')
-rw-r--r--v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch443
1 files changed, 443 insertions, 0 deletions
diff --git a/v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch b/v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch
new file mode 100644
index 000000000000..86f229993fcc
--- /dev/null
+++ b/v2-0008-platform-x86-asus-wmi-expose-dGPU-and-CPU-tunable.patch
@@ -0,0 +1,443 @@
+From b297ff51a7a10ed07f176cc8ba8ea7a653c5b725 Mon Sep 17 00:00:00 2001
+From: "Luke D. Jones" <luke@ljones.dev>
+Date: Tue, 6 Jun 2023 15:05:01 +1200
+Subject: [PATCH v2 8/8] platform/x86: asus-wmi: expose dGPU and CPU tunables
+ for ROG
+
+Expose various CPU and dGPU tunables that are available on many ASUS
+ROG laptops. The tunables shown in sysfs will vary depending on the CPU
+and dGPU vendor.
+
+All of these variables are write only and there is no easy way to find
+what the defaults are. In general they seem to default to the max value
+the vendor sets for the CPU and dGPU package - this is not the same as
+the min/max writable value. Values written to these variables that are
+beyond the capabilities of the CPU are ignored by the laptop.
+
+Signed-off-by: Luke D. Jones <luke@ljones.dev>
+---
+ .../ABI/testing/sysfs-platform-asus-wmi | 58 ++++
+ drivers/platform/x86/asus-wmi.c | 285 ++++++++++++++++++
+ include/linux/platform_data/x86/asus-wmi.h | 9 +
+ 3 files changed, 352 insertions(+)
+
+diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi
+index 5624bdef49cb..caaccd28fabf 100644
+--- a/Documentation/ABI/testing/sysfs-platform-asus-wmi
++++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi
+@@ -126,3 +126,61 @@ Description:
+ Change the mini-LED mode:
+ * 0 - Single-zone,
+ * 1 - Multi-zone
++
++What: /sys/devices/platform/<platform>/ppt_pl1_spl
++Date: Jun 2023
++KernelVersion: 6.5
++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
++
++What: /sys/devices/platform/<platform>/ppt_pl2_sppt
++Date: Jun 2023
++KernelVersion: 6.5
++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
++
++What: /sys/devices/platform/<platform>/ppt_fppt
++Date: Jun 2023
++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
++
++What: /sys/devices/platform/<platform>/ppt_apu_sppt
++Date: Jun 2023
++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
++
++What: /sys/devices/platform/<platform>/ppt_platform_sppt
++Date: Jun 2023
++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
++
++What: /sys/devices/platform/<platform>/nv_dynamic_boost
++Date: Jun 2023
++KernelVersion: 6.5
++Contact: "Luke Jones" <luke@ljones.dev>
++Description:
++ Set the dynamic boost limit of the Nvidia dGPU:
++ * min=5, max=25
++
++What: /sys/devices/platform/<platform>/nv_temp_target
++Date: Jun 2023
++KernelVersion: 6.5
++Contact: "Luke Jones" <luke@ljones.dev>
++Description:
++ Set the target temperature limit of the Nvidia dGPU:
++ * min=75, max=87
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index 1fc9e8afc2f3..d9a353081f91 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -117,6 +117,16 @@ module_param(fnlock_default, bool, 0444);
+ /* Mask to determine if setting temperature or percentage */
+ #define FAN_CURVE_PWM_MASK 0x04
+
++/* Limits for tunables available on ASUS ROG laptops */
++#define PPT_TOTAL_MIN 5
++#define PPT_TOTAL_MAX 250
++#define PPT_CPU_MIN 5
++#define PPT_CPU_MAX 130
++#define NVIDIA_BOOST_MIN 5
++#define NVIDIA_BOOST_MAX 25
++#define NVIDIA_TEMP_MIN 75
++#define NVIDIA_TEMP_MAX 87
++
+ static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
+
+ static int throttle_thermal_policy_write(struct asus_wmi *);
+@@ -247,6 +257,15 @@ struct asus_wmi {
+ bool dgpu_disable_available;
+ bool gpu_mux_mode_available;
+
++ /* 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;
++
+ bool kbd_rgb_mode_available;
+ bool kbd_rgb_state_available;
+
+@@ -946,6 +965,244 @@ static const struct attribute_group *kbd_rgb_mode_groups[] = {
+ NULL,
+ };
+
++/* Tunable: PPT: Intel=PL1, AMD=SPPT *****************************************/
++static ssize_t ppt_pl2_sppt_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL2_SPPT, value, &result);
++ if (err) {
++ pr_warn("Failed to set ppt_pl2_sppt: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set ppt_pl2_sppt (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl2_sppt");
++
++ return count;
++}
++static DEVICE_ATTR_WO(ppt_pl2_sppt);
++
++/* Tunable: PPT, Intel=PL1, AMD=SPL ******************************************/
++static ssize_t ppt_pl1_spl_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PL1_SPL, value, &result);
++ if (err) {
++ pr_warn("Failed to set ppt_pl1_spl: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set ppt_pl1_spl (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_pl1_spl");
++
++ return count;
++}
++static DEVICE_ATTR_WO(ppt_pl1_spl);
++
++/* Tunable: PPT APU FPPT ******************************************************/
++static ssize_t ppt_fppt_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < PPT_TOTAL_MIN || value > PPT_TOTAL_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_FPPT, value, &result);
++ if (err) {
++ pr_warn("Failed to set ppt_fppt: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set ppt_fppt (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_fpu_sppt");
++
++ return count;
++}
++static DEVICE_ATTR_WO(ppt_fppt);
++
++/* Tunable: PPT APU SPPT *****************************************************/
++static ssize_t ppt_apu_sppt_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_APU_SPPT, value, &result);
++ if (err) {
++ pr_warn("Failed to set ppt_apu_sppt: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set ppt_apu_sppt (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_apu_sppt");
++
++ return count;
++}
++static DEVICE_ATTR_WO(ppt_apu_sppt);
++
++/* Tunable: PPT platform SPPT ************************************************/
++static ssize_t ppt_platform_sppt_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < PPT_CPU_MIN || value > PPT_CPU_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_PPT_PLAT_SPPT, value, &result);
++ if (err) {
++ pr_warn("Failed to set ppt_platform_sppt: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set ppt_platform_sppt (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "ppt_platform_sppt");
++
++ return count;
++}
++static DEVICE_ATTR_WO(ppt_platform_sppt);
++
++/* Tunable: NVIDIA dynamic boost *********************************************/
++static ssize_t nv_dynamic_boost_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < NVIDIA_BOOST_MIN || value > NVIDIA_BOOST_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_DYN_BOOST, value, &result);
++ if (err) {
++ pr_warn("Failed to set nv_dynamic_boost: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set nv_dynamic_boost (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_dynamic_boost");
++
++ return count;
++}
++static DEVICE_ATTR_WO(nv_dynamic_boost);
++
++/* Tunable: NVIDIA temperature target ****************************************/
++static ssize_t nv_temp_target_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ int result, err;
++ u32 value;
++
++ struct asus_wmi *asus = dev_get_drvdata(dev);
++
++ result = kstrtou32(buf, 10, &value);
++ if (result)
++ return result;
++
++ if (value < NVIDIA_TEMP_MIN || value > NVIDIA_TEMP_MAX)
++ return -EINVAL;
++
++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_NV_THERM_TARGET, value, &result);
++ if (err) {
++ pr_warn("Failed to set nv_temp_target: %d\n", err);
++ return err;
++ }
++
++ if (result > 1) {
++ pr_warn("Failed to set nv_temp_target (result): 0x%x\n", result);
++ return -EIO;
++ }
++
++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "nv_temp_target");
++
++ return count;
++}
++static DEVICE_ATTR_WO(nv_temp_target);
++
+ /* Battery ********************************************************************/
+
+ /* The battery maximum charging percentage */
+@@ -3775,6 +4032,13 @@ static struct attribute *platform_attributes[] = {
+ &dev_attr_als_enable.attr,
+ &dev_attr_fan_boost_mode.attr,
+ &dev_attr_throttle_thermal_policy.attr,
++ &dev_attr_ppt_pl2_sppt.attr,
++ &dev_attr_ppt_pl1_spl.attr,
++ &dev_attr_ppt_fppt.attr,
++ &dev_attr_ppt_apu_sppt.attr,
++ &dev_attr_ppt_platform_sppt.attr,
++ &dev_attr_nv_dynamic_boost.attr,
++ &dev_attr_nv_temp_target.attr,
+ &dev_attr_panel_od.attr,
+ &dev_attr_mini_led_mode.attr,
+ NULL
+@@ -3812,6 +4076,20 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
+ ok = asus->fan_boost_mode_available;
+ else if (attr == &dev_attr_throttle_thermal_policy.attr)
+ ok = asus->throttle_thermal_policy_available;
++ else if (attr == &dev_attr_ppt_pl2_sppt.attr)
++ ok = asus->ppt_pl2_sppt_available;
++ else if (attr == &dev_attr_ppt_pl1_spl.attr)
++ ok = asus->ppt_pl1_spl_available;
++ else if (attr == &dev_attr_ppt_fppt.attr)
++ ok = asus->ppt_fppt_available;
++ else if (attr == &dev_attr_ppt_apu_sppt.attr)
++ ok = asus->ppt_apu_sppt_available;
++ else if (attr == &dev_attr_ppt_platform_sppt.attr)
++ ok = asus->ppt_plat_sppt_available;
++ else if (attr == &dev_attr_nv_dynamic_boost.attr)
++ 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_panel_od.attr)
+ ok = asus->panel_overdrive_available;
+ else if (attr == &dev_attr_mini_led_mode.attr)
+@@ -4077,6 +4355,13 @@ static int asus_wmi_add(struct platform_device *pdev)
+ 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);
++ 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->mini_led_mode_available = asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_MINI_LED_MODE);
+
+diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
+index ea80361ac6c7..16e99a1c37fc 100644
+--- a/include/linux/platform_data/x86/asus-wmi.h
++++ b/include/linux/platform_data/x86/asus-wmi.h
+@@ -86,6 +86,15 @@
+ #define ASUS_WMI_DEVID_GPU_FAN_CURVE 0x00110025
+ #define ASUS_WMI_DEVID_MID_FAN_CURVE 0x00110032
+
++/* Tunables for AUS ROG laptops */
++#define ASUS_WMI_DEVID_PPT_PL2_SPPT 0x001200A0
++#define ASUS_WMI_DEVID_PPT_PL1_SPL 0x001200A3
++#define ASUS_WMI_DEVID_PPT_APU_SPPT 0x001200B0
++#define ASUS_WMI_DEVID_PPT_PLAT_SPPT 0x001200B1
++#define ASUS_WMI_DEVID_PPT_FPPT 0x001200C1
++#define ASUS_WMI_DEVID_NV_DYN_BOOST 0x001200C0
++#define ASUS_WMI_DEVID_NV_THERM_TARGET 0x001200C2
++
+ /* Power */
+ #define ASUS_WMI_DEVID_PROCESSOR_STATE 0x00120012
+
+--
+2.41.0
+