drm/amd/display: Add periodic detection when zstate is enabled
authorEric Yang <Eric.Yang2@amd.com>
Thu, 26 Aug 2021 00:02:22 +0000 (20:02 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 14 Sep 2021 19:57:10 +0000 (15:57 -0400)
[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@amd.com>
Acked-by: Mikita Lipski <mikita.lipski@amd.com>
Signed-off-by: Eric Yang <Eric.Yang2@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
13 files changed:
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
drivers/gpu/drm/amd/display/dc/dm_helpers.h
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dmub/dmub_srv.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.h
drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c

index 8c17926..1aa69dd 100644 (file)
@@ -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
index 1414da4..d7bf928 100644 (file)
@@ -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;
                }
 
index 822239b..7a1f910 100644 (file)
@@ -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);
index 61e4967..46933a4 100644 (file)
@@ -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);
index ece4479..134faa7 100644 (file)
@@ -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
 
index 83f223d..d3598ce 100644 (file)
@@ -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;
 
index 140435e..7ae45dd 100644 (file)
@@ -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);
index 8de554f..3a905fb 100644 (file)
@@ -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);
index ad5f2ad..d50f4bd 100644 (file)
@@ -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,
index caf961b..ef324fc 100644 (file)
@@ -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
index fc667cb..6ac370c 100644 (file)
@@ -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;
+}
+
index bb62605..59ddc81 100644 (file)
@@ -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_ */
index 75a91cf..a6188d0 100644 (file)
@@ -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);
+}