From: Huang Rui Date: Tue, 25 Dec 2018 08:34:39 +0000 (+0800) Subject: drm/amd/powerplay: add get_max_sustainable_clock function X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=7457cf02540571e17ce464e5cb1865cfb020de31;p=android-x86%2Fkernel.git drm/amd/powerplay: add get_max_sustainable_clock function This patch adds get_max_sustainable_clock function for smu11. Signed-off-by: Huang Rui Reviewed-by: Kevin Wang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index b225cf876a91..cd04369c652b 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -393,6 +393,10 @@ static int smu_smc_table_hw_init(struct smu_context *smu) if (ret) return ret; + ret = smu_init_max_sustainable_clocks(smu); + if (ret) + return ret; + ret = smu_populate_umd_state_clk(smu); if (ret) return ret; @@ -539,6 +543,11 @@ static int smu_hw_fini(void *handle) return -EINVAL; kfree(table_context->driver_pptable); + if (table_context->max_sustainable_clocks) { + kfree(table_context->max_sustainable_clocks); + table_context->max_sustainable_clocks = NULL; + } + ret = smu_fini_fb_allocations(smu); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index a3c8b736af84..a68519ea6dc8 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -158,6 +158,7 @@ struct smu_table_context void *power_play_table; uint32_t power_play_table_size; + void *max_sustainable_clocks; struct smu_bios_boot_up_values boot_values; void *driver_pptable; struct smu_table *tables; @@ -253,6 +254,7 @@ struct smu_funcs int (*notify_display_change)(struct smu_context *smu); int (*get_power_limit)(struct smu_context *smu); int (*get_current_clk_freq)(struct smu_context *smu, uint32_t clk_id, uint32_t *value); + int (*init_max_sustainable_clocks)(struct smu_context *smu); }; #define smu_init_microcode(smu) \ @@ -297,6 +299,8 @@ struct smu_funcs ((smu)->funcs->set_last_dcef_min_deep_sleep_clk ? (smu)->funcs->set_last_dcef_min_deep_sleep_clk((smu)) : 0) #define smu_system_features_control(smu, en) \ ((smu)->funcs->system_features_control ? (smu)->funcs->system_features_control((smu), (en)) : 0) +#define smu_init_max_sustainable_clocks(smu) \ + ((smu)->funcs->init_max_sustainable_clocks ? (smu)->funcs->init_max_sustainable_clocks((smu)) : 0) #define smu_send_smc_msg(smu, msg) \ ((smu)->funcs->send_smc_msg? (smu)->funcs->send_smc_msg((smu), (msg)) : 0) #define smu_send_smc_msg_with_param(smu, msg, param) \ diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index 2853ab717d80..aa8d81f4111e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -36,6 +36,14 @@ #define smnMP0_FW_INTF 0x30101c0 #define smnMP1_PUB_CTRL 0x3010b14 +struct smu_11_0_max_sustainable_clocks { + uint32_t display_clock; + uint32_t phy_clock; + uint32_t pixel_clock; + uint32_t uclock; + uint32_t dcef_clock; + uint32_t soc_clock; +}; struct smu_11_0_dpm_table { uint32_t min; /* MHz */ diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index def64f5a967d..129d2b1c1487 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -738,6 +738,119 @@ static int smu_v11_0_notify_display_change(struct smu_context *smu) return ret; } +static int +smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock, + PPCLK_e clock_select) +{ + int ret = 0; + + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq, + clock_select << 16); + if (ret) { + pr_err("[GetMaxSustainableClock] Failed to get max DC clock from SMC!"); + return ret; + } + + ret = smu_read_smc_arg(smu, clock); + if (ret) + return ret; + + if (*clock != 0) + return 0; + + /* if DC limit is zero, return AC limit */ + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, + clock_select << 16); + if (ret) { + pr_err("[GetMaxSustainableClock] failed to get max AC clock from SMC!"); + return ret; + } + + ret = smu_read_smc_arg(smu, clock); + + return ret; +} + +static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) +{ + struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks; + int ret = 0; + + max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), + GFP_KERNEL); + smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks; + + max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100; + max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100; + max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100; + max_sustainable_clocks->display_clock = 0xFFFFFFFF; + max_sustainable_clocks->phy_clock = 0xFFFFFFFF; + max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; + + if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->uclock), + PPCLK_UCLK); + if (ret) { + pr_err("[%s] failed to get max UCLK from SMC!", + __func__); + return ret; + } + } + + if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->soc_clock), + PPCLK_SOCCLK); + if (ret) { + pr_err("[%s] failed to get max SOCCLK from SMC!", + __func__); + return ret; + } + } + + if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->dcef_clock), + PPCLK_DCEFCLK); + if (ret) { + pr_err("[%s] failed to get max DCEFCLK from SMC!", + __func__); + return ret; + } + + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->display_clock), + PPCLK_DISPCLK); + if (ret) { + pr_err("[%s] failed to get max DISPCLK from SMC!", + __func__); + return ret; + } + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->phy_clock), + PPCLK_PHYCLK); + if (ret) { + pr_err("[%s] failed to get max PHYCLK from SMC!", + __func__); + return ret; + } + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->pixel_clock), + PPCLK_PIXCLK); + if (ret) { + pr_err("[%s] failed to get max PIXCLK from SMC!", + __func__); + return ret; + } + } + + if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) + max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; + + return 0; +} + static int smu_v11_0_get_power_limit(struct smu_context *smu) { int ret; @@ -810,6 +923,7 @@ static const struct smu_funcs smu_v11_0_funcs = { .notify_display_change = smu_v11_0_notify_display_change, .get_power_limit = smu_v11_0_get_power_limit, .get_current_clk_freq = smu_v11_0_get_current_clk_freq, + .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, }; void smu_v11_0_set_smu_funcs(struct smu_context *smu)