drm/amd/powerplay: implement pwm1 hwmon interface for SMU11 (v2)
authorChengming Gui <Jack.Gui@amd.com>
Thu, 24 Jan 2019 10:39:04 +0000 (18:39 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Mar 2019 20:04:01 +0000 (15:04 -0500)
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

v2: fix coding style issue

Signed-off-by: Chengming Gui <Jack.Gui@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/smu_v11_0.c

index c3508a7..284d28a 100644 (file)
@@ -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;
index d49bdee..f94d09d 100644 (file)
@@ -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)
index aee8d27..2eb5ad8 100644 (file)
@@ -1748,6 +1748,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,
@@ -1799,6 +1885,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)