Hook up the SW SMU power profile switch in KFD routine.
Signed-off-by: Evan Quan <evan.quan@amd.com>
Reviewed-by: Kevin Wang <kevin1.wang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
 
-       if (adev->powerplay.pp_funcs &&
-           adev->powerplay.pp_funcs->switch_power_profile)
+       if (is_support_sw_smu(adev))
+               smu_switch_power_profile(&adev->smu,
+                                        PP_SMC_POWER_PROFILE_COMPUTE,
+                                        !idle);
+       else if (adev->powerplay.pp_funcs &&
+                adev->powerplay.pp_funcs->switch_power_profile)
                amdgpu_dpm_switch_power_profile(adev,
                                                PP_SMC_POWER_PROFILE_COMPUTE,
                                                !idle);
 
        return ret;
 }
 
+int smu_switch_power_profile(struct smu_context *smu,
+                            enum PP_SMC_POWER_PROFILE type,
+                            bool en)
+{
+       struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
+       long workload;
+       uint32_t index;
+
+       if (!smu->pm_enabled)
+               return -EINVAL;
+
+       if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
+               return -EINVAL;
+
+       mutex_lock(&smu->mutex);
+
+       if (!en) {
+               smu->workload_mask &= ~(1 << smu->workload_prority[type]);
+               index = fls(smu->workload_mask);
+               index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+               workload = smu->workload_setting[index];
+       } else {
+               smu->workload_mask |= (1 << smu->workload_prority[type]);
+               index = fls(smu->workload_mask);
+               index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
+               workload = smu->workload_setting[index];
+       }
+
+       if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+               smu_set_power_profile_mode(smu, &workload, 0);
+
+       mutex_unlock(&smu->mutex);
+
+       return 0;
+}
+
 enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu)
 {
        struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
 
 extern int smu_handle_task(struct smu_context *smu,
                           enum amd_dpm_forced_level level,
                           enum amd_pp_task task_id);
+int smu_switch_power_profile(struct smu_context *smu,
+                            enum PP_SMC_POWER_PROFILE type,
+                            bool en);
 int smu_get_smc_version(struct smu_context *smu, uint32_t *if_version, uint32_t *smu_version);
 int smu_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_type,
                              uint16_t level, uint32_t *value);