diff options
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c')
| -rw-r--r-- | drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 131 |
1 files changed, 86 insertions, 45 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index 08d000140eca..fbe3ef4ee45c 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -61,9 +61,6 @@ #define SMC_RAM_END 0x40000 -#define VOLTAGE_SCALE 4 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 #define CISLAND_MINIMUM_ENGINE_CLOCK 800 #define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 @@ -211,9 +208,7 @@ static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) { int ret; - if (!ci_is_smc_ram_running(hwmgr)) - return -EINVAL; - + cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); @@ -1182,7 +1177,6 @@ static int ci_populate_single_memory_level( struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); int result = 0; bool dll_state_on; - struct cgs_display_info info = {0}; uint32_t mclk_edc_wr_enable_threshold = 40000; uint32_t mclk_edc_enable_threshold = 40000; uint32_t mclk_strobe_mode_threshold = 40000; @@ -1236,8 +1230,7 @@ static int ci_populate_single_memory_level( /* default set to low watermark. Highest level will be set to high later.*/ memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - cgs_get_active_displays_info(hwmgr->device, &info); - data->display_timing.num_existing_displays = info.display_count; + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; /* stutter mode not support on ci */ @@ -1621,37 +1614,6 @@ static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, return result; } -static int ci_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_samu_clock_voltage_dependency_table *samu_table = - hwmgr->dyn_state.samu_clock_voltage_dependency_table; - - table->SamuBootLevel = 0; - table->SamuLevelCount = (uint8_t)(samu_table->count); - - for (count = 0; count < table->SamuLevelCount; count++) { - table->SamuLevel[count].Frequency = samu_table->entries[count].samclk; - table->SamuLevel[count].MinVoltage = samu_table->entries[count].v * VOLTAGE_SCALE; - table->SamuLevel[count].MinPhases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->SamuLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for samu clock", return result); - - table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->SamuLevel[count].MinVoltage); - } - return result; -} - static int ci_populate_memory_timing_parameters( struct pp_hwmgr *hwmgr, uint32_t engine_clock, @@ -2033,10 +1995,6 @@ static int ci_init_smc_table(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize ACP Level!", return result); - result = ci_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize SAMU Level!", return result); - /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ /* need to populate the ARB settings for the initial state. */ result = ci_program_memory_timing_parameters(hwmgr); @@ -2784,7 +2742,6 @@ static int ci_smu_fini(struct pp_hwmgr *hwmgr) { kfree(hwmgr->smu_backend); hwmgr->smu_backend = NULL; - cgs_rel_firmware(hwmgr->device, CGS_UCODE_ID_SMU); return 0; } @@ -2889,6 +2846,89 @@ static int ci_update_dpm_settings(struct pp_hwmgr *hwmgr, return 0; } +static int ci_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct smu7_hwmgr *data = hwmgr->backend; + struct ci_smumgr *smu_data = hwmgr->smu_backend; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; + int32_t i; + + if (PP_CAP(PHM_PlatformCaps_UVDDPM) || uvd_table->count <= 0) + smu_data->smc_state_table.UvdBootLevel = 0; + else + smu_data->smc_state_table.UvdBootLevel = uvd_table->count - 1; + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, + UvdBootLevel, smu_data->smc_state_table.UvdBootLevel); + + data->dpm_level_enable_mask.uvd_dpm_enable_mask = 0; + + for (i = uvd_table->count - 1; i >= 0; i--) { + if (uvd_table->entries[i].v <= max_vddc) + data->dpm_level_enable_mask.uvd_dpm_enable_mask |= 1 << i; + if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_UVDDPM)) + break; + } + ci_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, + data->dpm_level_enable_mask.uvd_dpm_enable_mask); + + return 0; +} + +static int ci_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct smu7_hwmgr *data = hwmgr->backend; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; + int32_t i; + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, + VceBootLevel, 0); /* temp hard code to level 0, vce can set min evclk*/ + + data->dpm_level_enable_mask.vce_dpm_enable_mask = 0; + + for (i = vce_table->count - 1; i >= 0; i--) { + if (vce_table->entries[i].v <= max_vddc) + data->dpm_level_enable_mask.vce_dpm_enable_mask |= 1 << i; + if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_VCEDPM)) + break; + } + ci_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, + data->dpm_level_enable_mask.vce_dpm_enable_mask); + + return 0; +} + +static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + ci_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + ci_update_vce_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + const struct pp_smumgr_func ci_smu_funcs = { .smu_init = ci_smu_init, .smu_fini = ci_smu_fini, @@ -2911,4 +2951,5 @@ const struct pp_smumgr_func ci_smu_funcs = { .initialize_mc_reg_table = ci_initialize_mc_reg_table, .is_dpm_running = ci_is_dpm_running, .update_dpm_settings = ci_update_dpm_settings, + .update_smc_table = ci_update_smc_table, }; |
