Commit 7457cf02 authored by Huang Rui's avatar Huang Rui Committed by Alex Deucher

drm/amd/powerplay: add get_max_sustainable_clock function

This patch adds get_max_sustainable_clock function for smu11.
Signed-off-by: default avatarHuang Rui <ray.huang@amd.com>
Reviewed-by: default avatarKevin Wang <Kevin1.Wang@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 86ac8803
...@@ -393,6 +393,10 @@ static int smu_smc_table_hw_init(struct smu_context *smu) ...@@ -393,6 +393,10 @@ static int smu_smc_table_hw_init(struct smu_context *smu)
if (ret) if (ret)
return ret; return ret;
ret = smu_init_max_sustainable_clocks(smu);
if (ret)
return ret;
ret = smu_populate_umd_state_clk(smu); ret = smu_populate_umd_state_clk(smu);
if (ret) if (ret)
return ret; return ret;
...@@ -539,6 +543,11 @@ static int smu_hw_fini(void *handle) ...@@ -539,6 +543,11 @@ static int smu_hw_fini(void *handle)
return -EINVAL; return -EINVAL;
kfree(table_context->driver_pptable); 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); ret = smu_fini_fb_allocations(smu);
if (ret) if (ret)
return ret; return ret;
......
...@@ -158,6 +158,7 @@ struct smu_table_context ...@@ -158,6 +158,7 @@ struct smu_table_context
void *power_play_table; void *power_play_table;
uint32_t power_play_table_size; uint32_t power_play_table_size;
void *max_sustainable_clocks;
struct smu_bios_boot_up_values boot_values; struct smu_bios_boot_up_values boot_values;
void *driver_pptable; void *driver_pptable;
struct smu_table *tables; struct smu_table *tables;
...@@ -253,6 +254,7 @@ struct smu_funcs ...@@ -253,6 +254,7 @@ struct smu_funcs
int (*notify_display_change)(struct smu_context *smu); int (*notify_display_change)(struct smu_context *smu);
int (*get_power_limit)(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 (*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) \ #define smu_init_microcode(smu) \
...@@ -297,6 +299,8 @@ struct smu_funcs ...@@ -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) ((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) \ #define smu_system_features_control(smu, en) \
((smu)->funcs->system_features_control ? (smu)->funcs->system_features_control((smu), (en)) : 0) ((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) \ #define smu_send_smc_msg(smu, msg) \
((smu)->funcs->send_smc_msg? (smu)->funcs->send_smc_msg((smu), (msg)) : 0) ((smu)->funcs->send_smc_msg? (smu)->funcs->send_smc_msg((smu), (msg)) : 0)
#define smu_send_smc_msg_with_param(smu, msg, param) \ #define smu_send_smc_msg_with_param(smu, msg, param) \
......
...@@ -36,6 +36,14 @@ ...@@ -36,6 +36,14 @@
#define smnMP0_FW_INTF 0x30101c0 #define smnMP0_FW_INTF 0x30101c0
#define smnMP1_PUB_CTRL 0x3010b14 #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 { struct smu_11_0_dpm_table {
uint32_t min; /* MHz */ uint32_t min; /* MHz */
......
...@@ -738,6 +738,119 @@ static int smu_v11_0_notify_display_change(struct smu_context *smu) ...@@ -738,6 +738,119 @@ static int smu_v11_0_notify_display_change(struct smu_context *smu)
return ret; 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) static int smu_v11_0_get_power_limit(struct smu_context *smu)
{ {
int ret; int ret;
...@@ -810,6 +923,7 @@ static const struct smu_funcs smu_v11_0_funcs = { ...@@ -810,6 +923,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
.notify_display_change = smu_v11_0_notify_display_change, .notify_display_change = smu_v11_0_notify_display_change,
.get_power_limit = smu_v11_0_get_power_limit, .get_power_limit = smu_v11_0_get_power_limit,
.get_current_clk_freq = smu_v11_0_get_current_clk_freq, .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) void smu_v11_0_set_smu_funcs(struct smu_context *smu)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment