From: Eric Yang <Eric.Yang2@xxxxxxx> [Why] When system is in Z10 HPD interrupts cannot fire, we may miss display configuration changes. [How] When Zstate is enabled, if DMUB indicate DCN has lost power, do a complete detection periodically. Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@xxxxxxx> Acked-by: Mikita Lipski <mikita.lipski@xxxxxxx> Signed-off-by: Eric Yang <Eric.Yang2@xxxxxxx> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 ++++++ .../drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 4 ++++ drivers/gpu/drm/amd/display/dc/dc.h | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h | 2 +- drivers/gpu/drm/amd/display/dc/dm_helpers.h | 4 ++++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 2 +- drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 4 ++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c | 8 ++++++++ drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h | 2 ++ drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c | 10 +++++++++- 13 files changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 8c1792637836..1aa69dd8e02f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -793,4 +793,10 @@ void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz) // FPGA programming for this clock in diags framework that // needs to go through dm layer, therefore leave dummy interace here } + + +void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable) +{ + /* TODO: add peridic detection implementation */ +} #endif \ No newline at end of file diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c index 1414da4b95d7..d7bf9283dc90 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c @@ -142,6 +142,7 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_ALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { dcn31_smu_set_Z9_support(clk_mgr, true); + dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, true); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } @@ -166,6 +167,7 @@ static void dcn31_update_clocks(struct clk_mgr *clk_mgr_base, if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW && new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) { dcn31_smu_set_Z9_support(clk_mgr, false); + dm_helpers_enable_periodic_detection(clk_mgr_base->ctx, false); clk_mgr_base->clks.zstate_support = new_clocks->zstate_support; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 822239b59a78..7a1f910d711e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1562,7 +1562,7 @@ static uint8_t get_stream_mask(struct dc *dc, struct dc_state *context) } #if defined(CONFIG_DRM_AMD_DC_DCN) -void dc_z10_restore(struct dc *dc) +void dc_z10_restore(const struct dc *dc) { if (dc->hwss.z10_restore) dc->hwss.z10_restore(dc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 61e49671fed5..46933a43ef2e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1250,6 +1250,10 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) } } +#if defined(CONFIG_DRM_AMD_DC_DCN) + dc_z10_restore(dc); +#endif + /* get out of low power state */ if (!can_apply_seamless_boot && reason != DETECT_REASON_BOOT) clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr); diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ece44796a74f..134faa7a1937 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1363,7 +1363,7 @@ void dc_hardware_release(struct dc *dc); bool dc_set_psr_allow_active(struct dc *dc, bool enable); #if defined(CONFIG_DRM_AMD_DC_DCN) -void dc_z10_restore(struct dc *dc); +void dc_z10_restore(const struct dc *dc); void dc_z10_save_init(struct dc *dc); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c index 83f223d745fa..d3598ce1f5de 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c @@ -425,7 +425,7 @@ void dcn31_z10_save_init(struct dc *dc) dc_dmub_srv_wait_idle(dc->ctx->dmub_srv); } -void dcn31_z10_restore(struct dc *dc) +void dcn31_z10_restore(const struct dc *dc) { union dmub_rb_cmd cmd; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h index 140435e4f7ff..7ae45dd202d9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h @@ -43,7 +43,7 @@ void dcn31_enable_power_gating_plane( void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx); -void dcn31_z10_restore(struct dc *dc); +void dcn31_z10_restore(const struct dc *dc); void dcn31_z10_save_init(struct dc *dc); void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on); diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h index 8de554fb98b9..3a905fb667bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h +++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h @@ -160,6 +160,10 @@ void dm_set_dcn_clocks( struct dc_context *ctx, struct dc_clocks *clks); +#if defined(CONFIG_DRM_AMD_DC_DCN) +void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable); +#endif + void dm_set_phyd32clk(struct dc_context *ctx, int freq_khz); bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index ad5f2adcc40d..d50f4bd06b5d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -236,7 +236,7 @@ struct hw_sequencer_funcs { const struct tg_color *solid_color, int width, int height, int offset); - void (*z10_restore)(struct dc *dc); + void (*z10_restore)(const struct dc *dc); void (*z10_save_init)(struct dc *dc); void (*update_visual_confirm_color)(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index caf961bb633f..ef324fc39315 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -358,6 +358,8 @@ struct dmub_srv_hw_funcs { uint32_t (*get_current_time)(struct dmub_srv *dmub); void (*get_diagnostic_data)(struct dmub_srv *dmub, struct dmub_diagnostic_data *dmub_oca); + + bool (*should_detect)(struct dmub_srv *dmub); }; /** @@ -724,6 +726,8 @@ bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entr bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); +bool dmub_srv_should_detect(struct dmub_srv *dmub); + #if defined(__cplusplus) } #endif diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c index fc667cb17eb0..6ac370c15dea 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c @@ -432,3 +432,11 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnosti REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled); diag_data->is_cw6_enabled = is_cw6_enabled; } + +bool dmub_dcn31_should_detect(struct dmub_srv *dmub) +{ + uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0); + bool should_detect = fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED; + return should_detect; +} + diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h index bb62605d2ac8..59ddc81b5a0e 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h @@ -245,4 +245,6 @@ uint32_t dmub_dcn31_get_current_time(struct dmub_srv *dmub); void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data); +bool dmub_dcn31_should_detect(struct dmub_srv *dmub); + #endif /* _DMUB_DCN31_H_ */ diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index 75a91cfaf036..a6188d067d65 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -234,7 +234,7 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic) funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr; funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data; - + funcs->should_detect = dmub_dcn31_should_detect; funcs->get_current_time = dmub_dcn31_get_current_time; break; @@ -816,3 +816,11 @@ bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_ dmub->hw_funcs.get_diagnostic_data(dmub, diag_data); return true; } + +bool dmub_srv_should_detect(struct dmub_srv *dmub) +{ + if (!dmub->hw_init || !dmub->hw_funcs.should_detect) + return false; + + return dmub->hw_funcs.should_detect(dmub); +} -- 2.25.1