drm/amd/display: wait vblank when stream enabled and update dpp clock
authorLewis Huang <Lewis.Huang@amd.com>
Fri, 26 Mar 2021 08:12:45 +0000 (16:12 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 15 Apr 2021 20:32:05 +0000 (16:32 -0400)
[Why]
When boot into OS, seamless boot device won't blank stream.
Driver update dpp clock when scanline position in vactive will show
garbage on screen.

[How]
Wait for vblank for seamless boot edp display when driver update dpp clock.
The apply seamless boot flag will be clear when OS call SetVisibility on.
Therefore we only wait for vblank once after boot into OS.

Signed-off-by: Lewis Huang <Lewis.Huang@amd.com>
Acked-by: Bindu Ramamurthy <bindur12@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h

index 887a54246bde061ab1b0a5156d0945832351af4a..73e8878b03b6a26e86e4a3e150ab74c89437ecee 100644 (file)
@@ -128,7 +128,7 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(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 display_count, i;
        bool update_dppclk = false;
        bool update_dispclk = false;
        bool dpp_clock_lowered = false;
@@ -210,6 +210,14 @@ void rn_update_clocks(struct clk_mgr *clk_mgr_base,
                                clk_mgr_base->clks.dppclk_khz,
                                safe_to_lower);
 
+               for (i = 0; i < context->stream_count; i++) {
+                       if (context->streams[i]->signal == SIGNAL_TYPE_EDP &&
+                               context->streams[i]->apply_seamless_boot_optimization) {
+                               dc_wait_for_vblank(dc, context->streams[i]);
+                               break;
+                       }
+               }
+
                clk_mgr_base->clks.actual_dppclk_khz =
                                rn_vbios_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
 
index 497e44ca98c198de64fafec30a2cb6cca08d3981..757820a3f068ff3fb43a022d2be940b607bab2b8 100644 (file)
@@ -3214,6 +3214,19 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
        }
 }
 
+void dc_wait_for_vblank(struct dc *dc, struct dc_stream_state *stream)
+{
+       int i;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++)
+               if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
+                       struct timing_generator *tg =
+                               dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
+                       tg->funcs->wait_for_state(tg, CRTC_STATE_VBLANK);
+                       break;
+               }
+}
+
 void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info)
 {
        info->displayClock                              = (unsigned int)state->bw_ctx.bw.dcn.clk.dispclk_khz;
index d218d665ed273403470155f50574a46d7efcc16d..4d2ea508fa1387d4685cd5191dd016a4545acb8d 100644 (file)
@@ -717,6 +717,7 @@ void dc_init_callbacks(struct dc *dc,
 void dc_deinit_callbacks(struct dc *dc);
 void dc_destroy(struct dc **dc);
 
+void dc_wait_for_vblank(struct dc *dc, struct dc_stream_state *stream);
 /*******************************************************************************
  * Surface Interfaces
  ******************************************************************************/