Sapphire Vega 64 Nitro+ is too noisy at idle, frequently switching
between zero-rpm mode and 1200 RPM.

As pwm1_min is currently always 0 (and thus completely useless), I:
- Made it writable so I can adjust min fan speed for "automatic" fan
control
- Changed amdgpu_hwmon_get_pwm1_min to return the value from fan
configuration table instead of 0

Probably pwm1_auto_point#_pwm and pwm1_auto_point#_temp are a better
interface to configure the fan curve, but for me it is not clear how
zero-rpm mode and parameters like FanThrottlingRpm should map to it.

Signed-off-by: Aleksandr Mezin <mezin.alexan...@gmail.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c        | 37 +++++++++++++++++-
 .../gpu/drm/amd/include/kgd_pp_interface.h    |  2 +
 drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 39 +++++++++++++++++++
 .../drm/amd/powerplay/hwmgr/vega10_hwmgr.c    |  2 +
 .../drm/amd/powerplay/hwmgr/vega10_thermal.c  | 23 +++++++++++
 .../drm/amd/powerplay/hwmgr/vega10_thermal.h  |  4 ++
 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h     |  2 +
 7 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 8f98629fbe59..588f4b4fdc76 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1057,7 +1057,40 @@ static ssize_t amdgpu_hwmon_get_pwm1_min(struct device 
*dev,
                                         struct device_attribute *attr,
                                         char *buf)
 {
-       return sprintf(buf, "%i\n", 0);
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       void *handle = adev->powerplay.pp_handle;
+       int err;
+       u16 value = 0;
+
+       if (adev->powerplay.pp_funcs->get_min_fan_pwm) {
+               err = adev->powerplay.pp_funcs->get_min_fan_pwm(handle, &value);
+               if (err)
+                       return err;
+       }
+
+       return sprintf(buf, "%u\n", (unsigned int)value);
+}
+
+static ssize_t amdgpu_hwmon_set_pwm1_min(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct amdgpu_device *adev = dev_get_drvdata(dev);
+       void *handle = adev->powerplay.pp_handle;
+       int err;
+       u16 value;
+
+       err = kstrtou16(buf, 10, &value);
+       if (err)
+               return err;
+
+       if (adev->powerplay.pp_funcs->set_min_fan_pwm) {
+               err = adev->powerplay.pp_funcs->set_min_fan_pwm(handle, value);
+               if (err)
+                       return err;
+       }
+
+       return count;
 }
 
 static ssize_t amdgpu_hwmon_get_pwm1_max(struct device *dev,
@@ -1371,7 +1404,7 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, 
amdgpu_hwmon_show_temp_thresh, NU
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, 
amdgpu_hwmon_show_temp_thresh, NULL, 1);
 static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, 
amdgpu_hwmon_set_pwm1, 0);
 static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, 
amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 
0);
+static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO | S_IWUSR, 
amdgpu_hwmon_get_pwm1_min, amdgpu_hwmon_set_pwm1_min, 0);
 static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 
0);
 static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, 
NULL, 0);
 static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 
0);
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h 
b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index 6a41b81c7325..e421a6752d01 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -269,6 +269,8 @@ struct amd_pm_funcs {
        int (*get_display_mode_validation_clocks)(void *handle,
                struct amd_pp_simple_clock_info *clocks);
        int (*notify_smu_enable_pwe)(void *handle);
+       int (*set_min_fan_pwm)(void *handle, u16 value);
+       int (*get_min_fan_pwm)(void *handle, u16 *value);
 };
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c 
b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index 7a646f94b478..f3c4b0b937e3 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -522,6 +522,43 @@ static uint32_t pp_dpm_get_fan_control_mode(void *handle)
        return mode;
 }
 
+static int pp_dpm_set_min_fan_pwm(void *handle, uint16_t value)
+{
+       struct pp_hwmgr *hwmgr = handle;
+       int ret = 0;
+
+       if (!hwmgr || !hwmgr->pm_en)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->set_min_fan_pwm == NULL) {
+               pr_info("%s was not implemented.\n", __func__);
+               return 0;
+       }
+       mutex_lock(&hwmgr->smu_lock);
+       ret = hwmgr->hwmgr_func->set_min_fan_pwm(hwmgr, value);
+       mutex_unlock(&hwmgr->smu_lock);
+       return ret;
+}
+
+static int pp_dpm_get_min_fan_pwm(void *handle, uint16_t *value)
+{
+       struct pp_hwmgr *hwmgr = handle;
+       int ret = 0;
+
+       if (!hwmgr || !hwmgr->pm_en)
+               return -EINVAL;
+
+       if (hwmgr->hwmgr_func->get_min_fan_pwm == NULL) {
+               *value = 0;
+               return 0;
+       }
+
+       mutex_lock(&hwmgr->smu_lock);
+       ret = hwmgr->hwmgr_func->get_min_fan_pwm(hwmgr, value);
+       mutex_unlock(&hwmgr->smu_lock);
+       return ret;
+}
+
 static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent)
 {
        struct pp_hwmgr *hwmgr = handle;
@@ -1269,4 +1306,6 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
        .display_clock_voltage_request = pp_display_clock_voltage_request,
        .get_display_mode_validation_clocks = 
pp_get_display_mode_validation_clocks,
        .notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
+       .set_min_fan_pwm = pp_dpm_set_min_fan_pwm,
+       .get_min_fan_pwm = pp_dpm_get_min_fan_pwm,
 };
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index fb86c24394ff..6d766949ff26 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -4913,6 +4913,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .set_power_profile_mode = vega10_set_power_profile_mode,
        .set_power_limit = vega10_set_power_limit,
        .odn_edit_dpm_table = vega10_odn_edit_dpm_table,
+       .get_min_fan_pwm = vega10_fan_ctrl_get_min_pwm,
+       .set_min_fan_pwm = vega10_fan_ctrl_set_min_pwm,
 };
 
 int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
index aa044c1955fe..28ebea24576b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -616,3 +616,26 @@ int 
vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr)
        }
        return 0;
 }
+
+int vega10_fan_ctrl_get_min_pwm(struct pp_hwmgr *hwmgr, uint16_t *value)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       PPTable_t *table = &(data->smc_state_table.pp_table);
+
+       *value = table->FanPwmMin;
+       return 0;
+}
+
+int vega10_fan_ctrl_set_min_pwm(struct pp_hwmgr *hwmgr, uint16_t value)
+{
+       struct vega10_hwmgr *data = hwmgr->backend;
+       PPTable_t *table = &(data->smc_state_table.pp_table);
+
+       if (value > 255)
+               value = 255;
+
+       table->FanPwmMin = value;
+       hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = value 
* 100 / 255;
+
+       return smum_send_msg_to_smc_with_parameter(hwmgr, 
PPSMC_MSG_SetFanMinPwm, table->FanPwmMin);
+}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
index 21e7c4dfa2ca..bce15e293e6b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
@@ -73,6 +73,10 @@ extern int vega10_thermal_disable_alert(struct pp_hwmgr 
*hwmgr);
 extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
 extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr,
                                struct PP_TemperatureRange *range);
+extern int vega10_fan_ctrl_get_min_pwm(struct pp_hwmgr *hwmgr,
+                               uint16_t *value);
+extern int vega10_fan_ctrl_set_min_pwm(struct pp_hwmgr *hwmgr,
+                               uint16_t value);
 
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h 
b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index d3d96260f440..f104b8212e89 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -328,6 +328,8 @@ struct pp_hwmgr_func {
        int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
        int (*powergate_mmhub)(struct pp_hwmgr *hwmgr);
        int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr);
+       int (*get_min_fan_pwm)(struct pp_hwmgr *hwmgr, uint16_t *value);
+       int (*set_min_fan_pwm)(struct pp_hwmgr *hwmgr, uint16_t value);
 };
 
 struct pp_table_func {
-- 
2.18.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to