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 */
        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;
        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
        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.
         * &pstate: Pstate to set. D0 if Nonzero, D3 otherwise.
 
 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_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);
 
                        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");
                }
 
 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)
 
        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);
        /* 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;
 }
 {
        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, ¤t_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;
                }
        }
 
        mutex_lock(&smu->mutex);
 
-       if (smu->ppt_funcs->set_fan_speed_percent)
+       if (smu->ppt_funcs->set_fan_speed_percent) {
+               if (speed > 100)
+                       speed = 100;
                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);
 
 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);
 
 
        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)
        .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,
        .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,
        .register_irq_handler = smu_v11_0_register_irq_handler,
 
        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)
        .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,
        .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,
        .register_irq_handler = smu_v11_0_register_irq_handler,
 
        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)
        .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,
        .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,
        .register_irq_handler = smu_v11_0_register_irq_handler,
 
 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
        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)
 {