From: Chengming Gui <jack....@amd.com>

added main functions:
        get_fan_speed_percent
        set_fan_speed_percent.
added dependent functions:
        smc_fan_control
        set_fan_static_mode
        get_fan_speed_percent

Signed-off-by: Chengming Gui <jack....@amd.com>
Reviewed-by: Huang Rui <ray.hu...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c         | 18 ++++--
 drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h |  9 +++
 drivers/gpu/drm/amd/powerplay/smu_v11_0.c      | 89 ++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 92d0fb3..d40aa39 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1444,8 +1444,10 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev,
        if  ((adev->flags & AMD_IS_PX) &&
             (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
                return -EINVAL;
-
-       pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
+       if (is_support_sw_smu(adev))
+               pwm_mode = smu_get_fan_control_mode(&adev->smu);
+       else
+               pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
        if (pwm_mode != AMD_FAN_CTRL_MANUAL) {
                pr_info("manual fan speed control should be enabled first\n");
                return -EINVAL;
@@ -1457,7 +1459,11 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev,
 
        value = (value * 100) / 255;
 
-       if (adev->powerplay.pp_funcs->set_fan_speed_percent) {
+       if (is_support_sw_smu(adev)) {
+               err = smu_set_fan_speed_percent(&adev->smu, value);
+               if (err)
+                       return err;
+       } else if (adev->powerplay.pp_funcs->set_fan_speed_percent) {
                err = amdgpu_dpm_set_fan_speed_percent(adev, value);
                if (err)
                        return err;
@@ -1479,7 +1485,11 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev,
             (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
                return -EINVAL;
 
-       if (adev->powerplay.pp_funcs->get_fan_speed_percent) {
+       if (is_support_sw_smu(adev)) {
+               err = smu_get_fan_speed_percent(&adev->smu, &speed);
+               if (err)
+                       return err;
+       } else if (adev->powerplay.pp_funcs->get_fan_speed_percent) {
                err = amdgpu_dpm_get_fan_speed_percent(adev, &speed);
                if (err)
                        return err;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index d49bdee..f94d09d 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -532,6 +532,9 @@ struct smu_funcs
        uint32_t (*get_sclk)(struct smu_context *smu, bool low);
        uint32_t (*get_mclk)(struct smu_context *smu, bool low);
        int (*get_current_rpm)(struct smu_context *smu, uint32_t *speed);
+       uint32_t (*get_fan_control_mode)(struct smu_context *smu);
+       int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed);
+       int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
 };
 
 #define smu_init_microcode(smu) \
@@ -664,6 +667,12 @@ struct smu_funcs
        ((smu)->ppt_funcs->get_profiling_clk_mask ? 
(smu)->ppt_funcs->get_profiling_clk_mask((smu), (level), (sclk_mask), 
(mclk_mask), (soc_mask)) : 0)
 #define smu_set_cpu_power_state(smu) \
        ((smu)->ppt_funcs->set_cpu_power_state ? 
(smu)->ppt_funcs->set_cpu_power_state((smu)) : 0)
+#define smu_get_fan_control_mode(smu) \
+       ((smu)->funcs->get_fan_control_mode ? 
(smu)->funcs->get_fan_control_mode((smu)) : 0)
+#define smu_get_fan_speed_percent(smu, speed) \
+       ((smu)->funcs->get_fan_speed_percent ? 
(smu)->funcs->get_fan_speed_percent((smu), (speed)) : 0)
+#define smu_set_fan_speed_percent(smu, speed) \
+       ((smu)->funcs->set_fan_speed_percent ? 
(smu)->funcs->set_fan_speed_percent((smu), (speed)) : 0)
 
 #define smu_msg_get_index(smu, msg) \
        ((smu)->ppt_funcs? ((smu)->ppt_funcs->get_smu_msg_index? 
(smu)->ppt_funcs->get_smu_msg_index((smu), (msg)) : -EINVAL) : -EINVAL)
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c 
b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index 7397a63..d8917b2 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -1747,6 +1747,92 @@ static int smu_v11_0_get_current_rpm(struct smu_context 
*smu,
        return 0;
 }
 
+static uint32_t
+smu_v11_0_get_fan_control_mode(struct smu_context *smu)
+{
+       if (!smu_feature_is_enabled(smu, FEATURE_FAN_CONTROL_BIT))
+               return AMD_FAN_CTRL_MANUAL;
+       else
+               return AMD_FAN_CTRL_AUTO;
+}
+
+static int
+smu_v11_0_get_fan_speed_percent(struct smu_context * smu,
+                                          uint32_t *speed)
+{
+       int ret = 0;
+       uint32_t percent = 0;
+       uint32_t current_rpm;
+
+       PPTable_t *pptable = smu->smu_table.driver_pptable;
+       ret =  smu_v11_0_get_current_rpm(smu, &current_rpm);
+       percent = current_rpm * 100 / pptable->FanMaximumRpm;
+       *speed = percent > 100 ? 100 : percent;
+
+       return ret;
+}
+
+static int
+smu_v11_0_smc_fan_control(struct smu_context *smu, bool start)
+{
+       int ret = 0;
+
+       if (smu_feature_is_supported(smu, FEATURE_FAN_CONTROL_BIT))
+               return 0;
+
+       ret = smu_feature_set_enabled(smu, FEATURE_FAN_CONTROL_BIT, start);
+       if (ret)
+               pr_err("[%s]%s smc FAN CONTROL feature failed!",
+                      __func__, (start ? "Start" : "Stop"));
+
+       return ret;
+}
+
+static int
+smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
+{
+       struct amdgpu_device *adev = smu->adev;
+
+       WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
+                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
+                                  CG_FDO_CTRL2, TMIN, 0));
+       WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
+                    REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
+                                  CG_FDO_CTRL2, FDO_PWM_MODE, mode));
+
+       return 0;
+}
+
+static int
+smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed)
+{
+       struct amdgpu_device *adev = smu->adev;
+       uint32_t duty100;
+       uint32_t duty;
+       uint64_t tmp64;
+       bool stop = 0;
+
+       if (speed > 100)
+               speed = 100;
+
+       if (smu_v11_0_smc_fan_control(smu, stop))
+               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);
+}
+
 static const struct smu_funcs smu_v11_0_funcs = {
        .init_microcode = smu_v11_0_init_microcode,
        .load_microcode = smu_v11_0_load_microcode,
@@ -1798,6 +1884,9 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .dpm_set_uvd_enable = smu_v11_0_dpm_set_uvd_enable,
        .dpm_set_vce_enable = smu_v11_0_dpm_set_vce_enable,
        .get_current_rpm = smu_v11_0_get_current_rpm,
+       .get_fan_control_mode = smu_v11_0_get_fan_control_mode,
+       .get_fan_speed_percent = smu_v11_0_get_fan_speed_percent,
+       .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent,
 };
 
 void smu_v11_0_set_smu_funcs(struct smu_context *smu)
-- 
2.7.4

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

Reply via email to