From ff3953d49c0acafab527ec97a665df87ab6bbc70 Mon Sep 17 00:00:00 2001 From: Eric Huang Date: Tue, 24 Jan 2017 10:47:25 -0500 Subject: [PATCH] drm/amd/powerplay: add power profile support for SMU7 Signed-off-by: Eric Huang Acked-by: Rex Zhu Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 71 ++++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 5 ++ drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 10 ++++ 3 files changed, 86 insertions(+) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index f75ee33ec5bb..31289a8d5cec 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4502,6 +4502,76 @@ static int smu7_release_firmware(struct pp_hwmgr *hwmgr) return 0; } +static void smu7_find_min_clock_masks(struct pp_hwmgr *hwmgr, + uint32_t *sclk_mask, uint32_t *mclk_mask, + uint32_t min_sclk, uint32_t min_mclk) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &(data->dpm_table); + uint32_t i; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + if (dpm_table->sclk_table.dpm_levels[i].enabled && + dpm_table->sclk_table.dpm_levels[i].value >= min_sclk) + *sclk_mask |= 1 << i; + } + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + if (dpm_table->mclk_table.dpm_levels[i].enabled && + dpm_table->mclk_table.dpm_levels[i].value >= min_mclk) + *mclk_mask |= 1 << i; + } +} + +static int smu7_set_power_profile_state(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int tmp_result, result = 0; + uint32_t sclk_mask = 0, mclk_mask = 0; + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_AUTO) + return -EINVAL; + + tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to freeze SCLK MCLK DPM!", + result = tmp_result); + + tmp_result = smum_populate_requested_graphic_levels(hwmgr, request); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to populate requested graphic levels!", + result = tmp_result); + + tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to unfreeze SCLK MCLK DPM!", + result = tmp_result); + + smu7_find_min_clock_masks(hwmgr, &sclk_mask, &mclk_mask, + request->min_sclk, request->min_mclk); + + if (sclk_mask) { + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask. + sclk_dpm_enable_mask & + sclk_mask); + } + + if (mclk_mask) { + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask. + mclk_dpm_enable_mask & + mclk_mask); + } + + return result; +} + static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .backend_init = &smu7_hwmgr_backend_init, .backend_fini = &smu7_hwmgr_backend_fini, @@ -4551,6 +4621,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .dynamic_state_management_disable = smu7_disable_dpm_tasks, .request_firmware = smu7_request_firmware, .release_firmware = smu7_release_firmware, + .set_power_profile_state = smu7_set_power_profile_state, }; uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 7c318a95e0c2..52f56f40bc54 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -127,6 +127,8 @@ struct pp_smumgr_func { uint32_t (*get_offsetof)(uint32_t type, uint32_t member); uint32_t (*get_mac_definition)(uint32_t value); bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); + int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request); }; struct pp_smumgr { @@ -193,6 +195,9 @@ extern uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); +extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request); + #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index c0956a4207a9..454f4459131f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -374,3 +374,13 @@ bool smum_is_dpm_running(struct pp_hwmgr *hwmgr) return true; } + +int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + if (hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels) + return hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels( + hwmgr, request); + + return 0; +} -- 2.11.0