drm/amd/pp: Revert gfx/compute profile switch sysfs
[linux-2.6-block.git] / drivers / gpu / drm / amd / powerplay / hwmgr / vega10_hwmgr.c
index 2d55dabc77d4112d0b1c50bf1e1ae38ac0505dd0..d90a0f1dbb5557a1d31bc9759f22596a7590b2b0 100644 (file)
 #include "vega10_pptable.h"
 #include "vega10_thermal.h"
 #include "pp_debug.h"
-#include "pp_acpi.h"
 #include "amd_pcie_helpers.h"
 #include "cgs_linux.h"
 #include "ppinterrupt.h"
 #include "pp_overdriver.h"
+#include "pp_thermal.h"
+
+#include "smuio/smuio_9_0_offset.h"
+#include "smuio/smuio_9_0_sh_mask.h"
 
 #define VOLTAGE_SCALE  4
 #define VOLTAGE_VID_OFFSET_SCALE1   625
@@ -187,8 +190,7 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
                        (struct vega10_hwmgr *)(hwmgr->backend);
        struct phm_ppt_v2_information *table_info =
                        (struct phm_ppt_v2_information *)hwmgr->pptable;
-       struct cgs_system_info sys_info = {0};
-       int result;
+       struct amdgpu_device *adev = hwmgr->adev;
 
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                        PHM_PlatformCaps_SclkDeepSleep);
@@ -203,15 +205,11 @@ static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr)
        phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                        PHM_PlatformCaps_EnableSMU7ThermalManagement);
 
-       sys_info.size = sizeof(struct cgs_system_info);
-       sys_info.info_id = CGS_SYSTEM_INFO_PG_FLAGS;
-       result = cgs_query_system_info(hwmgr->device, &sys_info);
-
-       if (!result && (sys_info.value & AMD_PG_SUPPORT_UVD))
+       if (adev->pg_flags & AMD_PG_SUPPORT_UVD)
                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                PHM_PlatformCaps_UVDPowerGating);
 
-       if (!result && (sys_info.value & AMD_PG_SUPPORT_VCE))
+       if (adev->pg_flags & AMD_PG_SUPPORT_VCE)
                phm_cap_set(hwmgr->platform_descriptor.platformCaps,
                                PHM_PlatformCaps_VCEPowerGating);
 
@@ -301,6 +299,8 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
        int i;
+       uint32_t sub_vendor_id, hw_revision;
+       struct amdgpu_device *adev = hwmgr->adev;
 
        vega10_initialize_power_tune_defaults(hwmgr);
 
@@ -365,6 +365,7 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
                        FEATURE_FAN_CONTROL_BIT;
        data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT;
        data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT;
+       data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT;
 
        if (!data->registry_data.prefetcher_dpm_key_disabled)
                data->smu_features[GNLD_DPM_PREFETCHER].supported = true;
@@ -434,6 +435,15 @@ static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr)
        if (data->registry_data.didt_support)
                data->smu_features[GNLD_DIDT].supported = true;
 
+       hw_revision = adev->pdev->revision;
+       sub_vendor_id = adev->pdev->subsystem_vendor;
+
+       if ((hwmgr->chip_id == 0x6862 ||
+               hwmgr->chip_id == 0x6861 ||
+               hwmgr->chip_id == 0x6868) &&
+               (hw_revision == 0) &&
+               (sub_vendor_id != 0x1002))
+               data->smu_features[GNLD_PCC_LIMIT].supported = true;
 }
 
 #ifdef PPLIB_VEGA10_EVV_SUPPORT
@@ -747,7 +757,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        struct vega10_hwmgr *data;
        uint32_t config_telemetry = 0;
        struct pp_atomfwctrl_voltage_table vol_table;
-       struct cgs_system_info sys_info = {0};
+       struct amdgpu_device *adev = hwmgr->adev;
        uint32_t reg;
 
        data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL);
@@ -756,6 +766,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+
        vega10_set_default_registry_data(hwmgr);
 
        data->disable_dpm_mask = 0xff;
@@ -837,10 +850,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        hwmgr->platform_descriptor.clockStep.engineClock = 500;
        hwmgr->platform_descriptor.clockStep.memoryClock = 500;
 
-       sys_info.size = sizeof(struct cgs_system_info);
-       sys_info.info_id = CGS_SYSTEM_INFO_GFX_CU_INFO;
-       result = cgs_query_system_info(hwmgr->device, &sys_info);
-       data->total_active_cus = sys_info.value;
+       data->total_active_cus = adev->gfx.cu_info.number;
        /* Setup default Overdrive Fan control settings */
        data->odn_fan_table.target_fan_speed =
                        hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM;
@@ -921,18 +931,9 @@ static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr)
                        "Failed to set up led dpm config!",
                        return -EINVAL);
 
-       return 0;
-}
+       smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_NumOfDisplays, 0);
 
-static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
-{
-       uint32_t features_enabled;
-
-       if (!vega10_get_smc_features(hwmgr, &features_enabled)) {
-               if (features_enabled & SMC_DPM_FEATURES)
-                       return true;
-       }
-       return false;
+       return 0;
 }
 
 /**
@@ -1380,14 +1381,12 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
 
        if (PP_CAP(PHM_PlatformCaps_ODNinACSupport) ||
            PP_CAP(PHM_PlatformCaps_ODNinDCSupport)) {
-               data->odn_dpm_table.odn_core_clock_dpm_levels.
-               number_of_performance_levels = data->dpm_table.gfx_table.count;
+               data->odn_dpm_table.odn_core_clock_dpm_levels.num_of_pl =
+                                               data->dpm_table.gfx_table.count;
                for (i = 0; i < data->dpm_table.gfx_table.count; i++) {
-                       data->odn_dpm_table.odn_core_clock_dpm_levels.
-                       performance_level_entries[i].clock =
+                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[i].clock =
                                        data->dpm_table.gfx_table.dpm_levels[i].value;
-                       data->odn_dpm_table.odn_core_clock_dpm_levels.
-                       performance_level_entries[i].enabled = true;
+                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[i].enabled = true;
                }
 
                data->odn_dpm_table.vdd_dependency_on_sclk.count =
@@ -1403,14 +1402,12 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
                                        dep_gfx_table->entries[i].cks_voffset;
                }
 
-               data->odn_dpm_table.odn_memory_clock_dpm_levels.
-               number_of_performance_levels = data->dpm_table.mem_table.count;
+               data->odn_dpm_table.odn_memory_clock_dpm_levels.num_of_pl =
+                                               data->dpm_table.mem_table.count;
                for (i = 0; i < data->dpm_table.mem_table.count; i++) {
-                       data->odn_dpm_table.odn_memory_clock_dpm_levels.
-                       performance_level_entries[i].clock =
+                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[i].clock =
                                        data->dpm_table.mem_table.dpm_levels[i].value;
-                       data->odn_dpm_table.odn_memory_clock_dpm_levels.
-                       performance_level_entries[i].enabled = true;
+                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[i].enabled = true;
                }
 
                data->odn_dpm_table.vdd_dependency_on_mclk.count = dep_mclk_table->count;
@@ -2411,34 +2408,6 @@ static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr)
        return result;
 }
 
-static int vega10_save_default_power_profile(struct pp_hwmgr *hwmgr)
-{
-       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
-       struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table);
-       uint32_t min_level;
-
-       hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE;
-       hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE;
-
-       /* Optimize compute power profile: Use only highest
-        * 2 power levels (if more than 2 are available)
-        */
-       if (dpm_table->count > 2)
-               min_level = dpm_table->count - 2;
-       else if (dpm_table->count == 2)
-               min_level = 1;
-       else
-               min_level = 0;
-
-       hwmgr->default_compute_power_profile.min_sclk =
-                       dpm_table->dpm_levels[min_level].value;
-
-       hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile;
-       hwmgr->compute_power_profile = hwmgr->default_compute_power_profile;
-
-       return 0;
-}
-
 /**
 * Initializes the SMC table and uploads it
 *
@@ -2582,7 +2551,6 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
        PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
                                        return result);
        vega10_acg_enable(hwmgr);
-       vega10_save_default_power_profile(hwmgr);
 
        return 0;
 }
@@ -2859,34 +2827,39 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
        return 0;
 }
 
-static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable)
 {
        struct vega10_hwmgr *data =
                        (struct vega10_hwmgr *)(hwmgr->backend);
-       int tmp_result, result = 0;
 
-       tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr,
-                       PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
-       PP_ASSERT_WITH_CODE(!tmp_result,
-                       "Failed to configure telemetry!",
-                       return tmp_result);
+       if (data->smu_features[GNLD_PCC_LIMIT].supported) {
+               if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled)
+                       pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled");
+               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr,
+                               enable, data->smu_features[GNLD_PCC_LIMIT].smu_feature_bitmap),
+                               "Attempt to Enable PCC Limit feature Failed!",
+                               return -EINVAL);
+               data->smu_features[GNLD_PCC_LIMIT].enabled = enable;
+       }
 
-       smum_send_msg_to_smc_with_parameter(hwmgr,
-                       PPSMC_MSG_NumOfDisplays, 0);
+       return 0;
+}
 
-       tmp_result = (!vega10_is_dpm_running(hwmgr)) ? 0 : -1;
-       PP_ASSERT_WITH_CODE(!tmp_result,
-                       "DPM is already running right , skipping re-enablement!",
-                       return 0);
+static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data =
+                       (struct vega10_hwmgr *)(hwmgr->backend);
+       int tmp_result, result = 0;
+
+       vega10_enable_disable_PCC_limit_feature(hwmgr, true);
 
        if ((hwmgr->smu_version == 0x001c2c00) ||
-                       (hwmgr->smu_version == 0x001c2d00)) {
-               tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr,
+                       (hwmgr->smu_version == 0x001c2d00))
+               smum_send_msg_to_smc_with_parameter(hwmgr,
                                PPSMC_MSG_UpdatePkgPwrPidAlpha, 1);
-               PP_ASSERT_WITH_CODE(!tmp_result,
-                               "Failed to set package power PID!",
-                               return tmp_result);
-       }
+
+       smum_send_msg_to_smc_with_parameter(hwmgr,
+               PPSMC_MSG_ConfigureTelemetry, data->config_telemetry);
 
        tmp_result = vega10_construct_voltage_tables(hwmgr);
        PP_ASSERT_WITH_CODE(!tmp_result,
@@ -3162,16 +3135,19 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr,
                minimum_clocks.memoryClock = stable_pstate_mclk;
        }
 
-       disable_mclk_switching_for_frame_lock = phm_cap_enabled(
-                                   hwmgr->platform_descriptor.platformCaps,
-                                   PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
-       disable_mclk_switching_for_vr = PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);
+       disable_mclk_switching_for_frame_lock =
+               PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock);
+       disable_mclk_switching_for_vr =
+               PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR);
        force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh);
 
-       disable_mclk_switching = (info.display_count > 1) ||
-                                   disable_mclk_switching_for_frame_lock ||
-                                   disable_mclk_switching_for_vr ||
-                                   force_mclk_high;
+       if (info.display_count == 0)
+               disable_mclk_switching = false;
+       else
+               disable_mclk_switching = (info.display_count > 1) ||
+                       disable_mclk_switching_for_frame_lock ||
+                       disable_mclk_switching_for_vr ||
+                       force_mclk_high;
 
        sclk = vega10_ps->performance_levels[0].gfx_clock;
        mclk = vega10_ps->performance_levels[0].mem_clock;
@@ -3348,11 +3324,9 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
                                        dpm_count < dpm_table->gfx_table.count;
                                        dpm_count++) {
                                dpm_table->gfx_table.dpm_levels[dpm_count].enabled =
-                                               data->odn_dpm_table.odn_core_clock_dpm_levels.
-                                               performance_level_entries[dpm_count].enabled;
+                                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[dpm_count].enabled;
                                dpm_table->gfx_table.dpm_levels[dpm_count].value =
-                                               data->odn_dpm_table.odn_core_clock_dpm_levels.
-                                               performance_level_entries[dpm_count].clock;
+                                       data->odn_dpm_table.odn_core_clock_dpm_levels.entries[dpm_count].clock;
                        }
                }
 
@@ -3362,11 +3336,9 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
                                        dpm_count < dpm_table->mem_table.count;
                                        dpm_count++) {
                                dpm_table->mem_table.dpm_levels[dpm_count].enabled =
-                                               data->odn_dpm_table.odn_memory_clock_dpm_levels.
-                                               performance_level_entries[dpm_count].enabled;
+                                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[dpm_count].enabled;
                                dpm_table->mem_table.dpm_levels[dpm_count].value =
-                                               data->odn_dpm_table.odn_memory_clock_dpm_levels.
-                                               performance_level_entries[dpm_count].clock;
+                                       data->odn_dpm_table.odn_memory_clock_dpm_levels.entries[dpm_count].clock;
                        }
                }
 
@@ -3398,8 +3370,7 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
                                dpm_table->
                                gfx_table.dpm_levels[dpm_table->gfx_table.count - 1].
                                value = sclk;
-                               if (PP_CAP(PHM_PlatformCaps_OD6PlusinACSupport) ||
-                                   PP_CAP(PHM_PlatformCaps_OD6PlusinDCSupport)) {
+                               if (hwmgr->od_enabled) {
                                        /* Need to do calculation based on the golden DPM table
                                         * as the Heatmap GPU Clock axis is also based on
                                         * the default values
@@ -3453,9 +3424,7 @@ static int vega10_populate_and_upload_sclk_mclk_dpm_levels(
                        mem_table.dpm_levels[dpm_table->mem_table.count - 1].
                        value = mclk;
 
-                       if (PP_CAP(PHM_PlatformCaps_OD6PlusinACSupport) ||
-                           PP_CAP(PHM_PlatformCaps_OD6PlusinDCSupport)) {
-
+                       if (hwmgr->od_enabled) {
                                PP_ASSERT_WITH_CODE(
                                        golden_dpm_table->mem_table.dpm_levels
                                        [golden_dpm_table->mem_table.count - 1].value,
@@ -3643,12 +3612,9 @@ static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
        if (!data->registry_data.sclk_dpm_key_disabled) {
                if (data->smc_state_table.gfx_boot_level !=
                                data->dpm_table.gfx_table.dpm_state.soft_min_level) {
-                               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr,
+                       smum_send_msg_to_smc_with_parameter(hwmgr,
                                PPSMC_MSG_SetSoftMinGfxclkByIndex,
-                               data->smc_state_table.gfx_boot_level),
-                               "Failed to set soft min sclk index!",
-                               return -EINVAL);
+                               data->smc_state_table.gfx_boot_level);
                        data->dpm_table.gfx_table.dpm_state.soft_min_level =
                                        data->smc_state_table.gfx_boot_level;
                }
@@ -3659,19 +3625,13 @@ static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr)
                                data->dpm_table.mem_table.dpm_state.soft_min_level) {
                        if (data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) {
                                socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr);
-                               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                                                       hwmgr,
+                               smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetSoftMinSocclkByIndex,
-                                               socclk_idx),
-                                               "Failed to set soft min uclk index!",
-                                               return -EINVAL);
+                                               socclk_idx);
                        } else {
-                               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                                               hwmgr,
+                               smum_send_msg_to_smc_with_parameter(hwmgr,
                                                PPSMC_MSG_SetSoftMinUclkByIndex,
-                                               data->smc_state_table.mem_boot_level),
-                                               "Failed to set soft min uclk index!",
-                                               return -EINVAL);
+                                               data->smc_state_table.mem_boot_level);
                        }
                        data->dpm_table.mem_table.dpm_state.soft_min_level =
                                        data->smc_state_table.mem_boot_level;
@@ -3690,13 +3650,10 @@ static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
 
        if (!data->registry_data.sclk_dpm_key_disabled) {
                if (data->smc_state_table.gfx_max_level !=
-                               data->dpm_table.gfx_table.dpm_state.soft_max_level) {
-                               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr,
+                       data->dpm_table.gfx_table.dpm_state.soft_max_level) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr,
                                PPSMC_MSG_SetSoftMaxGfxclkByIndex,
-                               data->smc_state_table.gfx_max_level),
-                               "Failed to set soft max sclk index!",
-                               return -EINVAL);
+                               data->smc_state_table.gfx_max_level);
                        data->dpm_table.gfx_table.dpm_state.soft_max_level =
                                        data->smc_state_table.gfx_max_level;
                }
@@ -3704,13 +3661,10 @@ static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr)
 
        if (!data->registry_data.mclk_dpm_key_disabled) {
                if (data->smc_state_table.mem_max_level !=
-                               data->dpm_table.mem_table.dpm_state.soft_max_level) {
-                               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr,
-                               PPSMC_MSG_SetSoftMaxUclkByIndex,
-                               data->smc_state_table.mem_max_level),
-                               "Failed to set soft max mclk index!",
-                               return -EINVAL);
+                       data->dpm_table.mem_table.dpm_state.soft_max_level) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr,
+                                       PPSMC_MSG_SetSoftMaxUclkByIndex,
+                                       data->smc_state_table.mem_max_level);
                        data->dpm_table.mem_table.dpm_state.soft_max_level =
                                        data->smc_state_table.mem_max_level;
                }
@@ -3780,7 +3734,6 @@ static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data =
                        (struct vega10_hwmgr *)(hwmgr->backend);
-       int result = 0;
        uint32_t low_sclk_interrupt_threshold = 0;
 
        if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) &&
@@ -3792,12 +3745,12 @@ static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr)
                                cpu_to_le32(low_sclk_interrupt_threshold);
 
                /* This message will also enable SmcToHost Interrupt */
-               result = smum_send_msg_to_smc_with_parameter(hwmgr,
+               smum_send_msg_to_smc_with_parameter(hwmgr,
                                PPSMC_MSG_SetLowGfxclkInterruptThreshold,
                                (uint32_t)low_sclk_interrupt_threshold);
        }
 
-       return result;
+       return 0;
 }
 
 static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr,
@@ -3888,13 +3841,11 @@ static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr,
 {
        uint32_t value;
 
-       PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
-                       PPSMC_MSG_GetCurrPkgPwr),
-                       "Failed to get current package power!",
-                       return -EINVAL);
-
+       smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr);
        vega10_read_arg_from_smc(hwmgr, &value);
+
        /* power value is an integer */
+       memset(query, 0, sizeof *query);
        query->average_gpu_power = value << 8;
 
        return 0;
@@ -3907,31 +3858,34 @@ static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
        struct vega10_dpm_table *dpm_table = &data->dpm_table;
        int ret = 0;
+       uint32_t reg, val_vid;
 
        switch (idx) {
        case AMDGPU_PP_SENSOR_GFX_SCLK:
-               ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex);
-               if (!ret) {
-                       vega10_read_arg_from_smc(hwmgr, &sclk_idx);
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex);
+               vega10_read_arg_from_smc(hwmgr, &sclk_idx);
+               if (sclk_idx <  dpm_table->gfx_table.count) {
                        *((uint32_t *)value) = dpm_table->gfx_table.dpm_levels[sclk_idx].value;
                        *size = 4;
+               } else {
+                       ret = -EINVAL;
                }
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
-               ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex);
-               if (!ret) {
-                       vega10_read_arg_from_smc(hwmgr, &mclk_idx);
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex);
+               vega10_read_arg_from_smc(hwmgr, &mclk_idx);
+               if (mclk_idx < dpm_table->mem_table.count) {
                        *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value;
                        *size = 4;
+               } else {
+                       ret = -EINVAL;
                }
                break;
        case AMDGPU_PP_SENSOR_GPU_LOAD:
-               ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0);
-               if (!ret) {
-                       vega10_read_arg_from_smc(hwmgr, &activity_percent);
-                       *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
-                       *size = 4;
-               }
+               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0);
+               vega10_read_arg_from_smc(hwmgr, &activity_percent);
+               *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent;
+               *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GPU_TEMP:
                *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr);
@@ -3953,17 +3907,27 @@ static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx,
                        ret = vega10_get_gpu_power(hwmgr, (struct pp_gpu_power *)value);
                }
                break;
+       case AMDGPU_PP_SENSOR_VDDGFX:
+               reg = soc15_get_register_offset(SMUIO_HWID, 0,
+                       mmSMUSVI0_PLANE0_CURRENTVID_BASE_IDX,
+                       mmSMUSVI0_PLANE0_CURRENTVID);
+               val_vid = (cgs_read_register(hwmgr->device, reg) &
+                       SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >>
+                       SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT;
+               *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid);
+               return 0;
        default:
                ret = -EINVAL;
                break;
        }
+
        return ret;
 }
 
-static int vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
+static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr,
                bool has_disp)
 {
-       return smum_send_msg_to_smc_with_parameter(hwmgr,
+       smum_send_msg_to_smc_with_parameter(hwmgr,
                        PPSMC_MSG_SetUclkFastSwitch,
                        has_disp ? 0 : 1);
 }
@@ -3998,7 +3962,7 @@ int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
 
        if (!result) {
                clk_request = (clk_freq << 16) | clk_select;
-               result = smum_send_msg_to_smc_with_parameter(hwmgr,
+               smum_send_msg_to_smc_with_parameter(hwmgr,
                                PPSMC_MSG_RequestDisplayClockByFreq,
                                clk_request);
        }
@@ -4067,10 +4031,9 @@ static int vega10_notify_smc_display_config_after_ps_adjustment(
                clock_req.clock_type = amd_pp_dcef_clock;
                clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value;
                if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) {
-                       PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
+                       smum_send_msg_to_smc_with_parameter(
                                        hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk,
-                                       min_clocks.dcefClockInSR /100),
-                                       "Attempt to set divider for DCEFCLK Failed!",);
+                                       min_clocks.dcefClockInSR / 100);
                } else {
                        pr_info("Attempt to set Hard Min for DCEFCLK Failed!");
                }
@@ -4169,6 +4132,8 @@ static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_fo
                *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL;
                *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL;
                *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL;
+               hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk;
+               hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk;
        }
 
        if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) {
@@ -4210,6 +4175,9 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
        uint32_t mclk_mask = 0;
        uint32_t soc_mask = 0;
 
+       if (hwmgr->pstate_sclk == 0)
+               vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask);
+
        switch (level) {
        case AMD_DPM_FORCED_LEVEL_HIGH:
                ret = vega10_force_dpm_highest(hwmgr);
@@ -4219,6 +4187,11 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
                break;
        case AMD_DPM_FORCED_LEVEL_AUTO:
                ret = vega10_unforce_dpm_levels(hwmgr);
+               if (hwmgr->default_power_profile_mode != hwmgr->power_profile_mode) {
+                               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+                                               1 << hwmgr->default_power_profile_mode);
+                               hwmgr->power_profile_mode = hwmgr->default_power_profile_mode;
+               }
                break;
        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
        case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
@@ -4242,6 +4215,7 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
                else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
                        vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO);
        }
+
        return ret;
 }
 
@@ -4488,26 +4462,11 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
                enum pp_clock_type type, uint32_t mask)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
-       int i;
-
-       if (hwmgr->request_dpm_level & (AMD_DPM_FORCED_LEVEL_AUTO |
-                               AMD_DPM_FORCED_LEVEL_LOW |
-                               AMD_DPM_FORCED_LEVEL_HIGH))
-               return -EINVAL;
 
        switch (type) {
        case PP_SCLK:
-               for (i = 0; i < 32; i++) {
-                       if (mask & (1 << i))
-                               break;
-               }
-               data->smc_state_table.gfx_boot_level = i;
-
-               for (i = 31; i >= 0; i--) {
-                       if (mask & (1 << i))
-                               break;
-               }
-               data->smc_state_table.gfx_max_level = i;
+               data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0;
+               data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0;
 
                PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
                        "Failed to upload boot level to lowest!",
@@ -4519,17 +4478,8 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
                break;
 
        case PP_MCLK:
-               for (i = 0; i < 32; i++) {
-                       if (mask & (1 << i))
-                               break;
-               }
-               data->smc_state_table.mem_boot_level = i;
-
-               for (i = 31; i >= 0; i--) {
-                       if (mask & (1 << i))
-                               break;
-               }
-               data->smc_state_table.mem_max_level = i;
+               data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0;
+               data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0;
 
                PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
                        "Failed to upload boot level to lowest!",
@@ -4563,14 +4513,8 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                if (data->registry_data.sclk_dpm_key_disabled)
                        break;
 
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
-                               PPSMC_MSG_GetCurrentGfxclkIndex),
-                               "Attempt to get current sclk index Failed!",
-                               return -1);
-               PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr,
-                               &now),
-                               "Attempt to read sclk index Failed!",
-                               return -1);
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex);
+               vega10_read_arg_from_smc(hwmgr, &now);
 
                for (i = 0; i < sclk_table->count; i++)
                        size += sprintf(buf + size, "%d: %uMhz %s\n",
@@ -4581,14 +4525,8 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                if (data->registry_data.mclk_dpm_key_disabled)
                        break;
 
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
-                               PPSMC_MSG_GetCurrentUclkIndex),
-                               "Attempt to get current mclk index Failed!",
-                               return -1);
-               PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr,
-                               &now),
-                               "Attempt to read mclk index Failed!",
-                               return -1);
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex);
+               vega10_read_arg_from_smc(hwmgr, &now);
 
                for (i = 0; i < mclk_table->count; i++)
                        size += sprintf(buf + size, "%d: %uMhz %s\n",
@@ -4596,14 +4534,8 @@ static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr,
                                        (i == now) ? "*" : "");
                break;
        case PP_PCIE:
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
-                               PPSMC_MSG_GetCurrentLinkIndex),
-                               "Attempt to get current mclk index Failed!",
-                               return -1);
-               PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(hwmgr,
-                               &now),
-                               "Attempt to read mclk index Failed!",
-                               return -1);
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex);
+               vega10_read_arg_from_smc(hwmgr, &now);
 
                for (i = 0; i < pcie_table->count; i++)
                        size += sprintf(buf + size, "%d: %s %s\n", i,
@@ -4744,11 +4676,6 @@ static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
 {
        int tmp_result, result = 0;
 
-       tmp_result = (vega10_is_dpm_running(hwmgr)) ? 0 : -1;
-       PP_ASSERT_WITH_CODE(tmp_result == 0,
-                       "DPM is not running right now, no need to disable DPM!",
-                       return 0);
-
        if (PP_CAP(PHM_PlatformCaps_ThermalController))
                vega10_disable_thermal_protection(hwmgr);
 
@@ -4779,6 +4706,8 @@ static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
        tmp_result =  vega10_acg_disable(hwmgr);
        PP_ASSERT_WITH_CODE((tmp_result == 0),
                        "Failed to disable acg!", result = tmp_result);
+
+       vega10_enable_disable_PCC_limit_feature(hwmgr, false);
        return result;
 }
 
@@ -4796,68 +4725,6 @@ static int vega10_power_off_asic(struct pp_hwmgr *hwmgr)
        return result;
 }
 
-static void vega10_find_min_clock_index(struct pp_hwmgr *hwmgr,
-               uint32_t *sclk_idx, uint32_t *mclk_idx,
-               uint32_t min_sclk, uint32_t min_mclk)
-{
-       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
-       struct vega10_dpm_table *dpm_table = &(data->dpm_table);
-       uint32_t i;
-
-       for (i = 0; i < dpm_table->gfx_table.count; i++) {
-               if (dpm_table->gfx_table.dpm_levels[i].enabled &&
-                       dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) {
-                       *sclk_idx = i;
-                       break;
-               }
-       }
-
-       for (i = 0; i < dpm_table->mem_table.count; i++) {
-               if (dpm_table->mem_table.dpm_levels[i].enabled &&
-                       dpm_table->mem_table.dpm_levels[i].value >= min_mclk) {
-                       *mclk_idx = i;
-                       break;
-               }
-       }
-}
-
-static int vega10_set_power_profile_state(struct pp_hwmgr *hwmgr,
-               struct amd_pp_profile *request)
-{
-       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
-       uint32_t sclk_idx = ~0, mclk_idx = ~0;
-
-       if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO)
-               return -EINVAL;
-
-       vega10_find_min_clock_index(hwmgr, &sclk_idx, &mclk_idx,
-                       request->min_sclk, request->min_mclk);
-
-       if (sclk_idx != ~0) {
-               if (!data->registry_data.sclk_dpm_key_disabled)
-                       PP_ASSERT_WITH_CODE(
-                                       !smum_send_msg_to_smc_with_parameter(
-                                       hwmgr,
-                                       PPSMC_MSG_SetSoftMinGfxclkByIndex,
-                                       sclk_idx),
-                                       "Failed to set soft min sclk index!",
-                                       return -EINVAL);
-       }
-
-       if (mclk_idx != ~0) {
-               if (!data->registry_data.mclk_dpm_key_disabled)
-                       PP_ASSERT_WITH_CODE(
-                                       !smum_send_msg_to_smc_with_parameter(
-                                       hwmgr,
-                                       PPSMC_MSG_SetSoftMinUclkByIndex,
-                                       mclk_idx),
-                                       "Failed to set soft min mclk index!",
-                                       return -EINVAL);
-       }
-
-       return 0;
-}
-
 static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
@@ -4988,6 +4855,20 @@ static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr,
+               struct PP_TemperatureRange *thermal_data)
+{
+       struct phm_ppt_v2_information *table_info =
+                       (struct phm_ppt_v2_information *)hwmgr->pptable;
+
+       memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange));
+
+       thermal_data->max = table_info->tdp_table->usSoftwareShutdownTemp *
+               PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+       return 0;
+}
+
 static int vega10_register_thermal_interrupt(struct pp_hwmgr *hwmgr,
                const void *info)
 {
@@ -5020,6 +4901,77 @@ static int vega10_register_thermal_interrupt(struct pp_hwmgr *hwmgr,
        return 0;
 }
 
+static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t i, size = 0;
+       static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,},
+                                               {90, 60, 0, 0,},
+                                               {70, 60, 0, 0,},
+                                               {70, 90, 0, 0,},
+                                               {30, 60, 0, 6,},
+                                               };
+       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+                                       "POWER_SAVING",
+                                       "VIDEO",
+                                       "VR",
+                                       "COMPUTE",
+                                       "CUSTOM"};
+       static const char *title[6] = {"NUM",
+                       "MODE_NAME",
+                       "BUSY_SET_POINT",
+                       "FPS",
+                       "USE_RLC_BUSY",
+                       "MIN_ACTIVE_LEVEL"};
+
+       if (!buf)
+               return -EINVAL;
+
+       size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0],
+                       title[1], title[2], title[3], title[4], title[5]);
+
+       for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++)
+               size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n",
+                       i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
+                       profile_mode_setting[i][0], profile_mode_setting[i][1],
+                       profile_mode_setting[i][2], profile_mode_setting[i][3]);
+       size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i,
+                       profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ",
+                       data->custom_profile_mode[0], data->custom_profile_mode[1],
+                       data->custom_profile_mode[2], data->custom_profile_mode[3]);
+       return size;
+}
+
+static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint8_t busy_set_point;
+       uint8_t FPS;
+       uint8_t use_rlc_busy;
+       uint8_t min_active_level;
+
+       hwmgr->power_profile_mode = input[size];
+
+       smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+                                               1<<hwmgr->power_profile_mode);
+
+       if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
+               if (size == 0 || size > 4)
+                       return -EINVAL;
+
+               data->custom_profile_mode[0] = busy_set_point = input[0];
+               data->custom_profile_mode[1] = FPS = input[1];
+               data->custom_profile_mode[2] = use_rlc_busy = input[2];
+               data->custom_profile_mode[3] = min_active_level = input[3];
+               smum_send_msg_to_smc_with_parameter(hwmgr,
+                                       PPSMC_MSG_SetCustomGfxDpmParameters,
+                                       busy_set_point | FPS<<8 |
+                                       use_rlc_busy << 16 | min_active_level<<24);
+       }
+
+       return 0;
+}
+
 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .backend_init = vega10_hwmgr_backend_init,
        .backend_fini = vega10_hwmgr_backend_fini,
@@ -5038,7 +4990,6 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .notify_smc_display_config_after_ps_adjustment =
                        vega10_notify_smc_display_config_after_ps_adjustment,
        .force_dpm_level = vega10_dpm_force_dpm_level,
-       .get_temperature = vega10_thermal_get_temperature,
        .stop_thermal_controller = vega10_thermal_stop_thermal_controller,
        .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info,
        .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent,
@@ -5067,15 +5018,18 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
                        vega10_check_smc_update_required_for_display_configuration,
        .power_off_asic = vega10_power_off_asic,
        .disable_smc_firmware_ctf = vega10_thermal_disable_alert,
-       .set_power_profile_state = vega10_set_power_profile_state,
        .get_sclk_od = vega10_get_sclk_od,
        .set_sclk_od = vega10_set_sclk_od,
        .get_mclk_od = vega10_get_mclk_od,
        .set_mclk_od = vega10_set_mclk_od,
        .avfs_control = vega10_avfs_enable,
        .notify_cac_buffer_info = vega10_notify_cac_buffer_info,
+       .get_thermal_temperature_range = vega10_get_thermal_temperature_range,
        .register_internal_thermal_interrupt = vega10_register_thermal_interrupt,
        .start_thermal_controller = vega10_start_thermal_controller,
+       .get_power_profile_mode = vega10_get_power_profile_mode,
+       .set_power_profile_mode = vega10_set_power_profile_mode,
+       .set_power_limit = vega10_set_power_limit,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)