*clock_req);
        uint32_t (*get_fan_control_mode)(struct smu_context *smu);
        int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode);
+       int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed);
        int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed);
        int (*set_xgmi_pstate)(struct smu_context *smu, uint32_t pstate);
        int (*gfx_off_control)(struct smu_context *smu, bool enable);
 
 smu_v11_0_set_fan_control_mode(struct smu_context *smu,
                               uint32_t mode);
 
+int
+smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed);
+
 int smu_v11_0_set_fan_speed_rpm(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 (speed > 100)
-                       speed = 100;
-               rpm = speed * smu->fan_max_rpm / 100;
-               ret = smu->ppt_funcs->set_fan_speed_rpm(smu, rpm);
-       }
+       if (smu->ppt_funcs->set_fan_speed_percent)
+               ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed);
 
        mutex_unlock(&smu->mutex);
 
 
        .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_percent = smu_v11_0_set_fan_speed_percent,
        .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
 
        .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_percent = smu_v11_0_set_fan_speed_percent,
        .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
 
        .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_percent = smu_v11_0_set_fan_speed_percent,
        .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm,
        .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate,
        .gfx_off_control = smu_v11_0_gfx_off_control,
 
        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)
 
        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);