diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c6f494f0dcea..3fabf32a0558 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -42,6 +42,7 @@ #include "clk/clk_10_0_2_sh_mask.h" #include "renoir_ip_offset.h" +#include "irq/dcn21/irq_service_dcn21.h" /* Constants */ @@ -129,9 +130,11 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; struct dc *dc = clk_mgr_base->ctx->dc; int display_count; + int irq_src; bool update_dppclk = false; bool update_dispclk = false; bool dpp_clock_lowered = false; + uint32_t hpd_state; struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; @@ -147,8 +150,15 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base, if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) { display_count = rn_get_active_display_cnt_wa(dc, context); + + for (irq_src = DC_IRQ_SOURCE_HPD1; irq_src <= DC_IRQ_SOURCE_HPD5; irq_src++) { + hpd_state = dal_get_hpd_state_dcn21(dc->res_pool->irqs, irq_src); + if (hpd_state) + break; + } + /* if we can go lower, go lower */ - if (display_count == 0) { + if (display_count == 0 && !hpd_state) { rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); /* update power state */ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c index ed54e1c819be..685528734575 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c @@ -135,6 +135,31 @@ enum dc_irq_source to_dal_irq_source_dcn21( return DC_IRQ_SOURCE_INVALID; } +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source) +{ + const struct irq_source_info *info; + uint32_t addr; + uint32_t value; + uint32_t current_status; + + info = find_irq_source_info(irq_service, source); + if (!info) + return 0; + + addr = info->status_reg; + if (!addr) + return 0; + + value = dm_read_reg(irq_service->ctx, addr); + current_status = + get_reg_field_value( + value, + HPD0_DC_HPD_INT_STATUS, + DC_HPD_SENSE); + + return current_status; +} + static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h index da2bd0e93d7a..3df2ceeb2b70 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h +++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.h @@ -31,4 +31,6 @@ struct irq_service *dal_irq_service_dcn21_create( struct irq_service_init_data *init_data); +uint32_t dal_get_hpd_state_dcn21(struct irq_service *irq_service, enum dc_irq_source source); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c index a2a4fbeb83f8..4db1133e4466 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c @@ -79,7 +79,7 @@ void dal_irq_service_destroy(struct irq_service **irq_service) *irq_service = NULL; } -static const struct irq_source_info *find_irq_source_info( +const struct irq_source_info *find_irq_source_info( struct irq_service *irq_service, enum dc_irq_source source) { diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h index dbfcb096eedd..e60b82480093 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.h +++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.h @@ -69,6 +69,10 @@ struct irq_service { const struct irq_service_funcs *funcs; }; +const struct irq_source_info *find_irq_source_info( + struct irq_service *irq_service, + enum dc_irq_source source); + void dal_irq_service_construct( struct irq_service *irq_service, struct irq_service_init_data *init_data);