drm/amd/display: Enable Seamless Boot Transition for Multiple Streams
authorMartin Leung <martin.leung@amd.com>
Fri, 22 Nov 2019 00:13:54 +0000 (19:13 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 18 Dec 2019 21:09:08 +0000 (16:09 -0500)
[why]
dc previously had bugs that interfered with the ability to inherit a
timing from a device with multiple streams (without flash/blanking).
After this fix there is still a dependency on UEFI support.

[how]
fixed 3 bugs: loaded MPC state, changed bw_optimize flag to a counter
instead of a boolean, and reading dpp/disp clk from HW to ensure we
don't raise the clock's when we're not supposed to.

Signed-off-by: Martin Leung <martin.leung@amd.com>
Reviewed-by: Anthony Koo <Anthony.Koo@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.h
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h

index 25d7b7c..3ae1d23 100644 (file)
@@ -27,6 +27,7 @@
 #include "clk_mgr_internal.h"
 
 #include "dce100/dce_clk_mgr.h"
+#include "dcn20_clk_mgr.h"
 #include "reg_helper.h"
 #include "core_types.h"
 #include "dm_helpers.h"
@@ -161,6 +162,9 @@ void dcn2_update_clocks(struct clk_mgr *clk_mgr_base,
                dc->debug.force_clock_mode & 0x1) {
                //this is from resume or boot up, if forced_clock cfg option used, we bypass program dispclk and DPPCLK, but need set them for S3.
                force_reset = true;
+
+               dcn2_read_clocks_from_hw_dentist(clk_mgr_base);
+
                //force_clock_mode 0x1:  force reset the clock even it is the same clock as long as it is in Passive level.
        }
        display_count = clk_mgr_helper_get_active_display_cnt(dc, context);
@@ -339,6 +343,32 @@ void dcn2_enable_pme_wa(struct clk_mgr *clk_mgr_base)
        }
 }
 
+
+void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base)
+{
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       uint32_t dispclk_wdivider;
+       uint32_t dppclk_wdivider;
+       int disp_divider;
+       int dpp_divider;
+
+       REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider);
+       REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPPCLK_WDIVIDER, &dppclk_wdivider);
+
+       disp_divider = dentist_get_divider_from_did(dispclk_wdivider);
+       dpp_divider = dentist_get_divider_from_did(dispclk_wdivider);
+
+       if (disp_divider && dpp_divider) {
+               /* Calculate the current DFS clock, in kHz.*/
+               clk_mgr_base->clks.dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+                       * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+
+               clk_mgr_base->clks.dppclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
+                               * clk_mgr->base.dentist_vco_freq_khz) / dpp_divider;
+       }
+
+}
+
 void dcn2_get_clock(struct clk_mgr *clk_mgr,
                struct dc_state *context,
                        enum dc_clock_type clock_type,
index c9fd824..b64a4e9 100644 (file)
@@ -51,4 +51,8 @@ void dcn2_get_clock(struct clk_mgr *clk_mgr,
                        struct dc_clock_config *clock_cfg);
 
 void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr);
+
+void dcn2_read_clocks_from_hw_dentist(struct clk_mgr *clk_mgr_base);
+
+
 #endif //__DCN20_CLK_MGR_H__
index 879cedd..2cb31f4 100644 (file)
@@ -835,6 +835,7 @@ struct dc *dc_create(const struct dc_init_data *init_params)
                        full_pipe_count,
                        dc->res_pool->stream_enc_count);
 
+       dc->optimize_seamless_boot_streams = 0;
        dc->caps.max_links = dc->link_count;
        dc->caps.max_audios = dc->res_pool->audio_count;
        dc->caps.linear_pitch_alignment = 64;
@@ -1178,10 +1179,10 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
 
        for (i = 0; i < context->stream_count; i++) {
                if (context->streams[i]->apply_seamless_boot_optimization)
-                       dc->optimize_seamless_boot = true;
+                       dc->optimize_seamless_boot_streams++;
        }
 
-       if (!dc->optimize_seamless_boot)
+       if (dc->optimize_seamless_boot_streams == 0)
                dc->hwss.prepare_bandwidth(dc, context);
 
        /* re-program planes for existing stream, in case we need to
@@ -1254,7 +1255,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
 
        dc_enable_stereo(dc, context, dc_streams, context->stream_count);
 
-       if (!dc->optimize_seamless_boot) {
+       if (dc->optimize_seamless_boot_streams == 0) {
                /* Must wait for no flips to be pending before doing optimize bw */
                wait_for_no_pipes_pending(dc, context);
                /* pplib is notified if disp_num changed */
@@ -1300,7 +1301,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
        int i;
        struct dc_state *context = dc->current_state;
 
-       if (!dc->optimized_required || dc->optimize_seamless_boot)
+       if (!dc->optimized_required || dc->optimize_seamless_boot_streams > 0)
                return true;
 
        post_surface_trace(dc);
@@ -2084,7 +2085,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
 
                                        dc->hwss.optimize_bandwidth(dc, dc->current_state);
                                } else {
-                                       if (!dc->optimize_seamless_boot)
+                                       if (dc->optimize_seamless_boot_streams == 0)
                                                dc->hwss.prepare_bandwidth(dc, dc->current_state);
 
                                        core_link_enable_stream(dc->current_state, pipe_ctx);
@@ -2125,7 +2126,7 @@ static void commit_planes_for_stream(struct dc *dc,
        int i, j;
        struct pipe_ctx *top_pipe_to_program = NULL;
 
-       if (dc->optimize_seamless_boot && surface_count > 0) {
+       if (dc->optimize_seamless_boot_streams > 0 && surface_count > 0) {
                /* Optimize seamless boot flag keeps clocks and watermarks high until
                 * first flip. After first flip, optimization is required to lower
                 * bandwidth. Important to note that it is expected UEFI will
@@ -2134,12 +2135,14 @@ static void commit_planes_for_stream(struct dc *dc,
                 */
                if (stream->apply_seamless_boot_optimization) {
                        stream->apply_seamless_boot_optimization = false;
-                       dc->optimize_seamless_boot = false;
-                       dc->optimized_required = true;
+                       dc->optimize_seamless_boot_streams--;
+
+                       if (dc->optimize_seamless_boot_streams == 0)
+                               dc->optimized_required = true;
                }
        }
 
-       if (update_type == UPDATE_TYPE_FULL && !dc->optimize_seamless_boot) {
+       if (update_type == UPDATE_TYPE_FULL && dc->optimize_seamless_boot_streams == 0) {
                dc->hwss.prepare_bandwidth(dc, context);
                context_clock_trace(dc, context);
        }
index 4700c78..5947311 100644 (file)
@@ -1910,8 +1910,26 @@ static int acquire_resource_from_hw_enabled_state(
                pipe_ctx->plane_res.dpp = pool->dpps[tg_inst];
                pipe_ctx->stream_res.opp = pool->opps[tg_inst];
 
-               if (pool->dpps[tg_inst])
+               if (pool->dpps[tg_inst]) {
                        pipe_ctx->plane_res.mpcc_inst = pool->dpps[tg_inst]->inst;
+
+                       // Read DPP->MPCC->OPP Pipe from HW State
+                       if (pool->mpc->funcs->read_mpcc_state) {
+                               struct mpcc_state s = {0};
+
+                               pool->mpc->funcs->read_mpcc_state(pool->mpc, pipe_ctx->plane_res.mpcc_inst, &s);
+
+                               if (s.dpp_id < MAX_MPCC)
+                                       pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].dpp_id = s.dpp_id;
+
+                               if (s.bot_mpcc_id < MAX_MPCC)
+                                       pool->mpc->mpcc_array[pipe_ctx->plane_res.mpcc_inst].mpcc_bot =
+                                                       &pool->mpc->mpcc_array[s.bot_mpcc_id];
+
+                               if (s.opp_id < MAX_OPP)
+                                       pipe_ctx->stream_res.opp->mpc_tree_params.opp_id = s.opp_id;
+                       }
+               }
                pipe_ctx->pipe_idx = tg_inst;
 
                pipe_ctx->stream = stream;
index c246390..91b60a5 100644 (file)
@@ -513,7 +513,7 @@ struct dc {
        bool optimized_required;
 
        /* Require to maintain clocks and bandwidth for UEFI enabled HW */
-       bool optimize_seamless_boot;
+       int optimize_seamless_boot_streams;
 
        /* FBC compressor */
        struct compressor *fbc_compressor;