On some boards the rpm interface apparently does not work at all
leading to the fan not spinning or spinning at strange speeds.
Both interfaces work properly on the boards I have.
Let's try and use the percent interface instead.

Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1408
Signed-off-by: Alex Deucher <[email protected]>
---
 drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h       | 12 +--
 drivers/gpu/drm/amd/pm/inc/smu_v11_0.h        |  7 +-
 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c     | 35 ++++----
 .../gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 26 ++++--
 .../gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c   | 26 ++++--
 .../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c   | 26 ++++--
 .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    | 89 +++++++------------
 7 files changed, 117 insertions(+), 104 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index 631a36a75ae3..44279c2afccb 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -173,7 +173,7 @@ enum smu_memory_pool_size
 struct smu_user_dpm_profile {
        uint32_t fan_mode;
        uint32_t power_limit;
-       uint32_t fan_speed_rpm;
+       uint32_t fan_speed_percent;
        uint32_t flags;
 
        /* user clock state information */
@@ -472,7 +472,7 @@ struct smu_context
        struct work_struct interrupt_work;
 
        unsigned fan_max_rpm;
-       unsigned manual_fan_speed_rpm;
+       unsigned manual_fan_speed_percent;
 
        uint32_t gfx_default_hard_min_freq;
        uint32_t gfx_default_soft_max_freq;
@@ -648,9 +648,9 @@ struct pptable_funcs {
        bool (*is_dpm_running)(struct smu_context *smu);
 
        /**
-        * @get_fan_speed_rpm: Get the current fan speed in RPM.
+        * @get_fan_speed_percent: Get the current fan speed in percent.
         */
-       int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed);
+       int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
 
        /**
         * @set_watermarks_table: Configure and upload the watermarks tables to
@@ -951,9 +951,9 @@ struct pptable_funcs {
        int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
 
        /**
-        * @set_fan_speed_rpm: Set a static fan speed in RPM.
+        * @set_fan_speed_percent: Set a static fan speed in percent.
         */
-       int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
+       int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
 
        /**
         * @set_xgmi_pstate: Set inter-chip global memory interconnect pstate.
diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h 
b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
index 102a0cf12d7a..c7d57e9555cc 100644
--- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h
@@ -203,11 +203,8 @@ int
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode);
 
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed);
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed);
+int smu_v11_0_set_fan_speed_percent(struct smu_context *smu,
+                                   uint32_t speed);
 
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c 
b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index f958b02f9317..1c7ac81fe417 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -368,8 +368,8 @@ static void smu_restore_dpm_user_profile(struct smu_context 
*smu)
                        return;
                }
 
-               if (!ret && smu->user_dpm_profile.fan_speed_rpm) {
-                       ret = smu_set_fan_speed_rpm(smu, 
smu->user_dpm_profile.fan_speed_rpm);
+               if (!ret && smu->user_dpm_profile.fan_speed_percent) {
+                       ret = smu_set_fan_speed_percent(smu, 
smu->user_dpm_profile.fan_speed_percent);
                        if (ret)
                                dev_err(smu->adev->dev, "Failed to set manual 
fan speed\n");
                }
@@ -2025,6 +2025,7 @@ int smu_set_gfx_cgpg(struct smu_context *smu, bool 
enabled)
 
 int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed)
 {
+       u32 percent;
        int ret = 0;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
@@ -2032,10 +2033,11 @@ int smu_set_fan_speed_rpm(struct smu_context *smu, 
uint32_t speed)
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->set_fan_speed_rpm) {
-               ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed);
+       if (smu->ppt_funcs->set_fan_speed_percent) {
+               percent = speed * 100 / smu->fan_max_rpm;
+               ret = smu->ppt_funcs->set_fan_speed_percent(smu, percent);
                if (!ret && smu->user_dpm_profile.flags != 
SMU_DPM_USER_PROFILE_RESTORE)
-                       smu->user_dpm_profile.fan_speed_rpm = speed;
+                       smu->user_dpm_profile.fan_speed_percent = percent;
        }
 
        mutex_unlock(&smu->mutex);
@@ -2270,7 +2272,7 @@ int smu_set_fan_control_mode(struct smu_context *smu, int 
value)
        /* reset user dpm fan speed */
        if (!ret && value != AMD_FAN_CTRL_MANUAL &&
                        smu->user_dpm_profile.flags != 
SMU_DPM_USER_PROFILE_RESTORE)
-               smu->user_dpm_profile.fan_speed_rpm = 0;
+               smu->user_dpm_profile.fan_speed_percent = 0;
 
        return ret;
 }
@@ -2279,17 +2281,15 @@ int smu_get_fan_speed_percent(struct smu_context *smu, 
uint32_t *speed)
 {
        int ret = 0;
        uint32_t percent;
-       uint32_t current_rpm;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
                return -EOPNOTSUPP;
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->get_fan_speed_rpm) {
-               ret = smu->ppt_funcs->get_fan_speed_rpm(smu, &current_rpm);
+       if (smu->ppt_funcs->get_fan_speed_percent) {
+               ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
                if (!ret) {
-                       percent = current_rpm * 100 / smu->fan_max_rpm;
                        *speed = percent > 100 ? 100 : percent;
                }
        }
@@ -2303,18 +2303,18 @@ int smu_get_fan_speed_percent(struct smu_context *smu, 
uint32_t *speed)
 int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
 {
        int ret = 0;
-       uint32_t rpm;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
                return -EOPNOTSUPP;
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->set_fan_speed_rpm) {
+       if (smu->ppt_funcs->set_fan_speed_percent) {
                if (speed > 100)
                        speed = 100;
-               rpm = speed * smu->fan_max_rpm / 100;
-               ret = smu->ppt_funcs->set_fan_speed_rpm(smu, rpm);
+               ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed);
+               if (!ret && smu->user_dpm_profile.flags != 
SMU_DPM_USER_PROFILE_RESTORE)
+                       smu->user_dpm_profile.fan_speed_percent = speed;
        }
 
        mutex_unlock(&smu->mutex);
@@ -2325,14 +2325,17 @@ int smu_set_fan_speed_percent(struct smu_context *smu, 
uint32_t speed)
 int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed)
 {
        int ret = 0;
+       u32 percent;
 
        if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
                return -EOPNOTSUPP;
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->get_fan_speed_rpm)
-               ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed);
+       if (smu->ppt_funcs->get_fan_speed_percent) {
+               ret = smu->ppt_funcs->get_fan_speed_percent(smu, &percent);
+               *speed = percent * smu->fan_max_rpm / 100;
+       }
 
        mutex_unlock(&smu->mutex);
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index cd7b411457ff..f0cc4de9ced5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1080,15 +1080,27 @@ static int arcturus_read_sensor(struct smu_context *smu,
        return ret;
 }
 
-static int arcturus_get_fan_speed_rpm(struct smu_context *smu,
-                                     uint32_t *speed)
+static int arcturus_get_fan_speed_percent(struct smu_context *smu,
+                                         uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return arcturus_get_smu_metrics_data(smu,
-                                            METRICS_CURR_FANSPEED,
-                                            speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = arcturus_get_smu_metrics_data(smu,
+                                                   METRICS_CURR_FANSPEED,
+                                                   &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int arcturus_get_fan_parameters(struct smu_context *smu)
@@ -2281,7 +2293,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .print_clk_levels = arcturus_print_clk_levels,
        .force_clk_levels = arcturus_force_clk_levels,
        .read_sensor = arcturus_read_sensor,
-       .get_fan_speed_rpm = arcturus_get_fan_speed_rpm,
+       .get_fan_speed_percent = arcturus_get_fan_speed_percent,
        .get_power_profile_mode = arcturus_get_power_profile_mode,
        .set_power_profile_mode = arcturus_set_power_profile_mode,
        .set_performance_level = arcturus_set_performance_level,
@@ -2326,7 +2338,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
        .display_clock_voltage_request = 
smu_v11_0_display_clock_voltage_request,
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
+       .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 7ebf9588983f..f7f78daffd27 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -1317,15 +1317,27 @@ static bool navi10_is_dpm_running(struct smu_context 
*smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static int navi10_get_fan_speed_rpm(struct smu_context *smu,
-                                   uint32_t *speed)
+static int navi10_get_fan_speed_percent(struct smu_context *smu,
+                                       uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return navi10_get_smu_metrics_data(smu,
-                                          METRICS_CURR_FANSPEED,
-                                          speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = navi10_get_smu_metrics_data(smu,
+                                                 METRICS_CURR_FANSPEED,
+                                                 &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int navi10_get_fan_parameters(struct smu_context *smu)
@@ -2413,7 +2425,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .display_config_changed = navi10_display_config_changed,
        .notify_smc_display_config = navi10_notify_smc_display_config,
        .is_dpm_running = navi10_is_dpm_running,
-       .get_fan_speed_rpm = navi10_get_fan_speed_rpm,
+       .get_fan_speed_percent = navi10_get_fan_speed_percent,
        .get_power_profile_mode = navi10_get_power_profile_mode,
        .set_power_profile_mode = navi10_set_power_profile_mode,
        .set_watermarks_table = navi10_set_watermarks_table,
@@ -2456,7 +2468,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
        .display_clock_voltage_request = 
smu_v11_0_display_clock_voltage_request,
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
+       .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index 24f3c96a5e5e..e3ba40d9f83f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -1237,15 +1237,27 @@ static bool sienna_cichlid_is_dpm_running(struct 
smu_context *smu)
        return !!(feature_enabled & SMC_DPM_FEATURE);
 }
 
-static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu,
-                                   uint32_t *speed)
+static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu,
+                                               uint32_t *speed)
 {
+       int ret;
+       u32 rpm;
+
        if (!speed)
                return -EINVAL;
 
-       return sienna_cichlid_get_smu_metrics_data(smu,
-                                               METRICS_CURR_FANSPEED,
-                                               speed);
+       switch (smu_v11_0_get_fan_control_mode(smu)) {
+       case AMD_FAN_CTRL_AUTO:
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_CURR_FANSPEED,
+                                                         &rpm);
+               if (!ret && smu->fan_max_rpm)
+                       *speed = rpm * 100 / smu->fan_max_rpm;
+               return ret;
+       default:
+               *speed = smu->user_dpm_profile.fan_speed_percent;
+               return 0;
+       }
 }
 
 static int sienna_cichlid_get_fan_parameters(struct smu_context *smu)
@@ -3087,7 +3099,7 @@ static const struct pptable_funcs 
sienna_cichlid_ppt_funcs = {
        .display_config_changed = sienna_cichlid_display_config_changed,
        .notify_smc_display_config = sienna_cichlid_notify_smc_display_config,
        .is_dpm_running = sienna_cichlid_is_dpm_running,
-       .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm,
+       .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent,
        .get_power_profile_mode = sienna_cichlid_get_power_profile_mode,
        .set_power_profile_mode = sienna_cichlid_set_power_profile_mode,
        .set_watermarks_table = sienna_cichlid_set_watermarks_table,
@@ -3130,7 +3142,7 @@ static const struct pptable_funcs 
sienna_cichlid_ppt_funcs = {
        .display_clock_voltage_request = 
smu_v11_0_display_clock_voltage_request,
        .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
        .set_fan_control_mode = smu_v11_0_set_fan_control_mode,
-       .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
+       .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
        .register_irq_handler = smu_v11_0_register_irq_handler,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index 147efe12973c..cf6176afd4d5 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -1137,10 +1137,10 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, 
bool enable)
 uint32_t
 smu_v11_0_get_fan_control_mode(struct smu_context *smu)
 {
-       if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
-               return AMD_FAN_CTRL_MANUAL;
-       else
+       if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
                return AMD_FAN_CTRL_AUTO;
+       else
+               return smu->user_dpm_profile.fan_mode;
 }
 
 static int
@@ -1174,6 +1174,35 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, 
uint32_t mode)
        return 0;
 }
 
+int
+smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+{
+       struct amdgpu_device *adev = smu->adev;
+       uint32_t duty100, duty;
+       uint64_t tmp64;
+
+       if (speed > 100)
+               speed = 100;
+
+       if (smu_v11_0_auto_fan_control(smu, 0))
+               return -EINVAL;
+
+       duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+                               CG_FDO_CTRL1, FMAX_DUTY100);
+       if (!duty100)
+               return -EINVAL;
+
+       tmp64 = (uint64_t)speed * duty100;
+       do_div(tmp64, 100);
+       duty = (uint32_t)tmp64;
+
+       WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
+                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
+                                  CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
+
+       return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
+}
+
 int
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode)
@@ -1182,7 +1211,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
 
        switch (mode) {
        case AMD_FAN_CTRL_NONE:
-               ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm);
+               ret = smu_v11_0_set_fan_speed_percent(smu, 100);
                break;
        case AMD_FAN_CTRL_MANUAL:
                ret = smu_v11_0_auto_fan_control(smu, 0);
@@ -1202,58 +1231,6 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu,
        return ret;
 }
 
-int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
-                                      uint32_t speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       int ret;
-       uint32_t tach_period, crystal_clock_freq;
-
-       if (!speed)
-               return -EINVAL;
-
-       ret = smu_v11_0_auto_fan_control(smu, 0);
-       if (ret)
-               return ret;
-
-       /*
-        * crystal_clock_freq div by 4 is required since the fan control
-        * module refers to 25MHz
-        */
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev) / 4;
-       tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
-       WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
-                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                  CG_TACH_CTRL, TARGET_PERIOD,
-                                  tach_period));
-
-       ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
-
-       return ret;
-}
-
-int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
-                               uint32_t *speed)
-{
-       struct amdgpu_device *adev = smu->adev;
-       uint32_t tach_period, crystal_clock_freq;
-       uint64_t tmp64;
-
-       tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
-                                   CG_TACH_CTRL, TARGET_PERIOD);
-       if (!tach_period)
-               return -EINVAL;
-
-       crystal_clock_freq = amdgpu_asic_get_xclk(adev);
-
-       tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
-       do_div(tmp64, (tach_period * 8));
-       *speed = (uint32_t)tmp64;
-
-       return 0;
-}
-
 int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
                                     uint32_t pstate)
 {
-- 
2.29.2

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to