Commit 6e92e156 authored by Kenneth Feng's avatar Kenneth Feng Committed by Alex Deucher

drm/amdgpu/powerplay: provide the interface to disable uclk switch for DAL

provide the interface for DAL to disable uclk switch on navi10.
in this case, the uclk will be fixed to maximum.
this is a workaround when display configuration causes underflow issue.
Signed-off-by: default avatarKenneth Feng <kenneth.feng@amd.com>
Reviewed-by: default avatarKevin Wang <kevin1.wang@amd.com>
Reviewed-by: default avatarEvan Quan <evan.quan@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent c74dbe44
...@@ -801,6 +801,19 @@ enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) ...@@ -801,6 +801,19 @@ enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz)
return PP_SMU_RESULT_OK; return PP_SMU_RESULT_OK;
} }
enum pp_smu_status pp_nv_set_pstate_handshake_support(
struct pp_smu *pp, BOOLEAN pstate_handshake_supported)
{
const struct dc_context *ctx = pp->dm;
struct amdgpu_device *adev = ctx->driver_context;
struct smu_context *smu = &adev->smu;
if (smu_display_disable_memory_clock_switch(smu, !pstate_handshake_supported))
return PP_SMU_RESULT_FAIL;
return PP_SMU_RESULT_OK;
}
enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp, enum pp_smu_status pp_nv_set_voltage_by_freq(struct pp_smu *pp,
enum pp_smu_nv_clock_id clock_id, int mhz) enum pp_smu_nv_clock_id clock_id, int mhz)
{ {
...@@ -916,6 +929,7 @@ void dm_pp_get_funcs( ...@@ -916,6 +929,7 @@ void dm_pp_get_funcs(
funcs->nv_funcs.get_maximum_sustainable_clocks = pp_nv_get_maximum_sustainable_clocks; funcs->nv_funcs.get_maximum_sustainable_clocks = pp_nv_get_maximum_sustainable_clocks;
/*todo compare data with window driver */ /*todo compare data with window driver */
funcs->nv_funcs.get_uclk_dpm_states = pp_nv_get_uclk_dpm_states; funcs->nv_funcs.get_uclk_dpm_states = pp_nv_get_uclk_dpm_states;
funcs->nv_funcs.set_pstate_handshake_support = pp_nv_set_pstate_handshake_support;
break; break;
#endif #endif
default: default:
......
...@@ -365,6 +365,8 @@ struct smu_context ...@@ -365,6 +365,8 @@ struct smu_context
#define WATERMARKS_EXIST (1 << 0) #define WATERMARKS_EXIST (1 << 0)
#define WATERMARKS_LOADED (1 << 1) #define WATERMARKS_LOADED (1 << 1)
uint32_t watermarks_bitmap; uint32_t watermarks_bitmap;
uint32_t hard_min_uclk_req_from_dal;
bool disable_uclk_switch;
uint32_t workload_mask; uint32_t workload_mask;
uint32_t workload_prority[WORKLOAD_POLICY_MAX]; uint32_t workload_prority[WORKLOAD_POLICY_MAX];
...@@ -446,6 +448,7 @@ struct pptable_funcs { ...@@ -446,6 +448,7 @@ struct pptable_funcs {
int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states);
int (*set_default_od_settings)(struct smu_context *smu, bool initialize); int (*set_default_od_settings)(struct smu_context *smu, bool initialize);
int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level); int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch);
}; };
struct smu_funcs struct smu_funcs
...@@ -695,6 +698,8 @@ struct smu_funcs ...@@ -695,6 +698,8 @@ struct smu_funcs
((smu)->ppt_funcs->get_clock_by_type_with_voltage ? (smu)->ppt_funcs->get_clock_by_type_with_voltage((smu), (type), (clocks)) : 0) ((smu)->ppt_funcs->get_clock_by_type_with_voltage ? (smu)->ppt_funcs->get_clock_by_type_with_voltage((smu), (type), (clocks)) : 0)
#define smu_display_clock_voltage_request(smu, clock_req) \ #define smu_display_clock_voltage_request(smu, clock_req) \
((smu)->funcs->display_clock_voltage_request ? (smu)->funcs->display_clock_voltage_request((smu), (clock_req)) : 0) ((smu)->funcs->display_clock_voltage_request ? (smu)->funcs->display_clock_voltage_request((smu), (clock_req)) : 0)
#define smu_display_disable_memory_clock_switch(smu, disable_memory_clock_switch) \
((smu)->ppt_funcs->display_disable_memory_clock_switch ? (smu)->ppt_funcs->display_disable_memory_clock_switch((smu), (disable_memory_clock_switch)) : -EINVAL)
#define smu_get_dal_power_level(smu, clocks) \ #define smu_get_dal_power_level(smu, clocks) \
((smu)->funcs->get_dal_power_level ? (smu)->funcs->get_dal_power_level((smu), (clocks)) : 0) ((smu)->funcs->get_dal_power_level ? (smu)->funcs->get_dal_power_level((smu), (clocks)) : 0)
#define smu_get_perf_level(smu, designation, level) \ #define smu_get_perf_level(smu, designation, level) \
......
...@@ -1493,6 +1493,30 @@ static int navi10_get_thermal_temperature_range(struct smu_context *smu, ...@@ -1493,6 +1493,30 @@ static int navi10_get_thermal_temperature_range(struct smu_context *smu,
return 0; return 0;
} }
static int navi10_display_disable_memory_clock_switch(struct smu_context *smu,
bool disable_memory_clock_switch)
{
int ret = 0;
struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
(struct smu_11_0_max_sustainable_clocks *)
smu->smu_table.max_sustainable_clocks;
uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal;
uint32_t max_memory_clock = max_sustainable_clocks->uclock;
if(smu->disable_uclk_switch == disable_memory_clock_switch)
return 0;
if(disable_memory_clock_switch)
ret = smu_set_hard_freq_range(smu, SMU_UCLK, max_memory_clock, 0);
else
ret = smu_set_hard_freq_range(smu, SMU_UCLK, min_memory_clock, 0);
if(!ret)
smu->disable_uclk_switch = disable_memory_clock_switch;
return ret;
}
static const struct pptable_funcs navi10_ppt_funcs = { static const struct pptable_funcs navi10_ppt_funcs = {
.tables_init = navi10_tables_init, .tables_init = navi10_tables_init,
.alloc_dpm_context = navi10_allocate_dpm_context, .alloc_dpm_context = navi10_allocate_dpm_context,
...@@ -1529,6 +1553,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { ...@@ -1529,6 +1553,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.get_uclk_dpm_states = navi10_get_uclk_dpm_states, .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
.set_performance_level = navi10_set_performance_level, .set_performance_level = navi10_set_performance_level,
.get_thermal_temperature_range = navi10_get_thermal_temperature_range, .get_thermal_temperature_range = navi10_get_thermal_temperature_range,
.display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch,
}; };
void navi10_set_ppt_funcs(struct smu_context *smu) void navi10_set_ppt_funcs(struct smu_context *smu)
......
...@@ -1313,16 +1313,23 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu, ...@@ -1313,16 +1313,23 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
if (ret) if (ret)
goto failed; goto failed;
if (clk_select == SMU_UCLK && smu->disable_uclk_switch)
return 0;
clk_id = smu_clk_get_index(smu, clk_select); clk_id = smu_clk_get_index(smu, clk_select);
if (clk_id < 0) { if (clk_id < 0) {
ret = -EINVAL; ret = -EINVAL;
goto failed; goto failed;
} }
mutex_lock(&smu->mutex); mutex_lock(&smu->mutex);
ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq,
(clk_id << 16) | clk_freq); (clk_id << 16) | clk_freq);
mutex_unlock(&smu->mutex); mutex_unlock(&smu->mutex);
if(clk_select == SMU_UCLK)
smu->hard_min_uclk_req_from_dal = clk_freq;
} }
failed: failed:
......
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