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: Kenneth Feng <kenneth.feng@xxxxxxx> --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 17 +++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 5 +++++ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 25 ++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 7 ++++++ 4 files changed, 54 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 7bc7abc..5b4323b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -802,6 +802,22 @@ enum pp_smu_status pp_nv_set_hard_min_uclk_by_freq(struct pp_smu *pp, int mhz) 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->ppt_funcs) + return PP_SMU_RESULT_UNSUPPORTED; + + 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_nv_clock_id clock_id, int mhz) { @@ -917,6 +933,7 @@ void dm_pp_get_funcs( funcs->nv_funcs.get_maximum_sustainable_clocks = pp_nv_get_maximum_sustainable_clocks; /*todo compare data with window driver */ 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; #endif default: diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 33d2d75..642a1b1 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -549,6 +549,8 @@ struct smu_context #define WATERMARKS_EXIST (1 << 0) #define WATERMARKS_LOADED (1 << 1) uint32_t watermarks_bitmap; + uint32_t hard_min_uclk_req_from_dal; + bool disable_uclk_switch; uint32_t workload_mask; uint32_t workload_prority[WORKLOAD_POLICY_MAX]; @@ -632,6 +634,7 @@ struct pptable_funcs { 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_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 @@ -884,6 +887,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) #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) +#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)) : 0) #define smu_get_dal_power_level(smu, clocks) \ ((smu)->funcs->get_dal_power_level ? (smu)->funcs->get_dal_power_level((smu), (clocks)) : 0) #define smu_get_perf_level(smu, designation, level) \ diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index c873228..a8c98c4 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -1655,6 +1655,30 @@ static int navi10_get_thermal_temperature_range(struct smu_context *smu, 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 = { .tables_init = navi10_tables_init, .alloc_dpm_context = navi10_allocate_dpm_context, @@ -1693,6 +1717,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_ppfeature_status = navi10_set_ppfeature_status, .set_performance_level = navi10_set_performance_level, .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) diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index 745b35a..202b9d6 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1346,16 +1346,23 @@ smu_v11_0_display_clock_voltage_request(struct smu_context *smu, if (ret) goto failed; + if (clk_select == SMU_UCLK && smu->disable_uclk_switch) + return 0; + clk_id = smu_clk_get_index(smu, clk_select); if (clk_id < 0) { ret = -EINVAL; goto failed; } + mutex_lock(&smu->mutex); ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, (clk_id << 16) | clk_freq); mutex_unlock(&smu->mutex); + + if(clk_select == SMU_UCLK) + smu->hard_min_uclk_req_from_dal = clk_freq; } failed: -- 2.7.4 _______________________________________________ amd-gfx mailing list amd-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/amd-gfx