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 887a542..73e8878 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 497e44c..757820a 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 d218d66..4d2ea50 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
  ******************************************************************************/