drm/amd/powerplay: add get_max_sustainable_clock function

This patch adds get_max_sustainable_clock function for smu11.

Signed-off-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Kevin Wang <Kevin1.Wang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Huang Rui 2018-12-25 16:34:39 +08:00 committed by Alex Deucher
parent 86ac880307
commit 7457cf0254
4 changed files with 135 additions and 0 deletions

View File

@ -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;

View File

@ -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) \

View File

@ -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 */

View File

@ -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)