From 03609ebc4cbdbdb32b72df2b611390d19b9a99bf Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 24 Jan 2017 10:57:22 -0500 Subject: [PATCH] drm/amd/powerplay: add power profile support for Polaris Signed-off-by: Eric Huang Acked-by: Rex Zhu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/smumgr/polaris10_smc.c | 64 +++++++++++++++++++ .../drm/amd/powerplay/smumgr/polaris10_smc.h | 2 + .../amd/powerplay/smumgr/polaris10_smumgr.c | 1 + 3 files changed, 67 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c index 80e2329a1b9e..1eedab143aa9 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c @@ -1613,6 +1613,42 @@ static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) } +static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend); + struct SMU74_Discrete_GraphicsLevel *levels = + data->smc_state_table.GraphicsLevel; + unsigned min_level = 1; + + hwmgr->default_gfx_power_profile.activity_threshold = + be16_to_cpu(levels[0].ActivityLevel); + hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; + hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; + hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; + + hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; + + /* Workaround compute SDMA instability: disable lowest SCLK + * DPM level. Optimize compute power profile: Use only highest + * 2 power levels (if more than 2 are available), Hysteresis: + * 0ms up, 5ms down + */ + if (data->smc_state_table.GraphicsDpmLevelCount > 2) + min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; + else if (data->smc_state_table.GraphicsDpmLevelCount == 2) + min_level = 1; + else + min_level = 0; + hwmgr->default_compute_power_profile.min_sclk = + be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency); + hwmgr->default_compute_power_profile.up_hyst = 0; + hwmgr->default_compute_power_profile.down_hyst = 5; + + hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; +} + /** * Initializes the SMC table and uploads it * @@ -1832,6 +1868,9 @@ int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) result = polaris10_populate_pm_fuses(hwmgr); PP_ASSERT_WITH_CODE(0 == result, "Failed to populate PM fuses to SMC memory!", return result); + + polaris10_save_default_power_profile(hwmgr); + return 0; } @@ -2298,3 +2337,28 @@ bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) ? true : false; } + +int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) + (hwmgr->smumgr->backend); + struct SMU74_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * + SMU74_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpHyst = request->up_hyst; + levels[i].DownHyst = request->down_hyst; + } + + return smu7_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h index 5ade3cea8bb7..1df8154d0626 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h @@ -37,6 +37,8 @@ uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member); uint32_t polaris10_get_mac_definition(uint32_t value); int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr); bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr); +int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request); #endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index ce20ae2e520e..9616cedc139c 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -409,4 +409,5 @@ const struct pp_smumgr_func polaris10_smu_funcs = { .populate_all_memory_levels = polaris10_populate_all_memory_levels, .get_mac_definition = polaris10_get_mac_definition, .is_dpm_running = polaris10_is_dpm_running, + .populate_requested_graphic_levels = polaris10_populate_requested_graphic_levels, }; -- 2.20.1