drm/amd/display: Fix for otg synchronization logic
authorMeenakshikumar Somasundaram <meenakshikumar.somasundaram@amd.com>
Mon, 15 Nov 2021 06:51:37 +0000 (01:51 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 1 Dec 2021 21:05:32 +0000 (16:05 -0500)
[Why]
During otg sync trigger, plane states are used to decide whether the otg
is already synchronized or not. There are scenarions when otgs are
disabled without plane state getting disabled and in such case the otg is
excluded from synchronization.

[How]
Introduced pipe_idx_syncd in pipe_ctx that tracks each otgs master pipe.
When a otg is disabled/enabled, pipe_idx_syncd is reset to itself.
On sync trigger, pipe_idx_syncd is checked to decide whether a otg is
already synchronized and the otg is further included or excluded from
synchronization.

Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Mustapha Ghaddar <mustapha.ghaddar@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: meenakshikumar somasundaram <meenakshikumar.somasundaram@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/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
drivers/gpu/drm/amd/display/dc/inc/core_types.h
drivers/gpu/drm/amd/display/dc/inc/resource.h

index 17b7408d84b70e1ac39c70675fa154be05cd9c0a..bd6541f1c8bbd1c48835b7a7fd33dbbc6b9df525 100644 (file)
@@ -1422,22 +1422,29 @@ static void program_timing_sync(
                                status->timing_sync_info.master = false;
 
                }
-               /* remove any other unblanked pipes as they have already been synced */
-               for (j = j + 1; j < group_size; j++) {
-                       bool is_blanked;
 
-                       if (pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked)
-                               is_blanked =
-                                       pipe_set[j]->stream_res.opp->funcs->dpg_is_blanked(pipe_set[j]->stream_res.opp);
-                       else
-                               is_blanked =
-                                       pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg);
-                       if (!is_blanked) {
-                               group_size--;
-                               pipe_set[j] = pipe_set[group_size];
-                               j--;
+               /* remove any other pipes that are already been synced */
+               if (dc->config.use_pipe_ctx_sync_logic) {
+                       /* check pipe's syncd to decide which pipe to be removed */
+                       for (j = 1; j < group_size; j++) {
+                               if (pipe_set[j]->pipe_idx_syncd == pipe_set[0]->pipe_idx_syncd) {
+                                       group_size--;
+                                       pipe_set[j] = pipe_set[group_size];
+                                       j--;
+                               } else
+                                       /* link slave pipe's syncd with master pipe */
+                                       pipe_set[j]->pipe_idx_syncd = pipe_set[0]->pipe_idx_syncd;
                        }
-               }
+               } else {
+                       /* remove any other pipes by checking valid plane */
+                       for (j = j + 1; j < group_size; j++) {
+                               if (pipe_set[j]->plane_state) {
+                                       group_size--;
+                                       pipe_set[j] = pipe_set[group_size];
+                                       j--;
+                               }
+                       }
+               }
 
                if (group_size > 1) {
                        if (sync_type == TIMING_SYNCHRONIZABLE) {
index 1da91f250afa050b8e4df9e01b30d96cfbe4213f..51e22b965ed6c28afe9dcc054005e2b51c98bb99 100644 (file)
@@ -3118,3 +3118,57 @@ struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder(
        return enc;
 }
 #endif
+
+void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
+               struct dc_state *context)
+{
+       int i, j;
+       struct pipe_ctx *pipe_ctx_old, *pipe_ctx, *pipe_ctx_syncd;
+
+       /* If pipe backend is reset, need to reset pipe syncd status */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               pipe_ctx_old =  &dc->current_state->res_ctx.pipe_ctx[i];
+               pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+               if (!pipe_ctx_old->stream)
+                       continue;
+
+               if (pipe_ctx_old->top_pipe || pipe_ctx_old->prev_odm_pipe)
+                       continue;
+
+               if (!pipe_ctx->stream ||
+                               pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) {
+
+                       /* Reset all the syncd pipes from the disabled pipe */
+                       for (j = 0; j < dc->res_pool->pipe_count; j++) {
+                               pipe_ctx_syncd = &context->res_ctx.pipe_ctx[j];
+                               if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_syncd) == pipe_ctx_old->pipe_idx) ||
+                                       !IS_PIPE_SYNCD_VALID(pipe_ctx_syncd))
+                                       SET_PIPE_SYNCD_TO_PIPE(pipe_ctx_syncd, j);
+                       }
+               }
+       }
+}
+
+void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc,
+       struct dc_state *context,
+       uint8_t disabled_master_pipe_idx)
+{
+       int i;
+       struct pipe_ctx *pipe_ctx, *pipe_ctx_check;
+
+       pipe_ctx = &context->res_ctx.pipe_ctx[disabled_master_pipe_idx];
+       if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx) != disabled_master_pipe_idx) ||
+               !IS_PIPE_SYNCD_VALID(pipe_ctx))
+               SET_PIPE_SYNCD_TO_PIPE(pipe_ctx, disabled_master_pipe_idx);
+
+       /* for the pipe disabled, check if any slave pipe exists and assert */
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               pipe_ctx_check = &context->res_ctx.pipe_ctx[i];
+
+               if ((GET_PIPE_SYNCD_FROM_PIPE(pipe_ctx_check) == disabled_master_pipe_idx) &&
+                       IS_PIPE_SYNCD_VALID(pipe_ctx_check) && (i != disabled_master_pipe_idx))
+                       DC_ERR("DC: Failure: pipe_idx[%d] syncd with disabled master pipe_idx[%d]\n",
+                               i, disabled_master_pipe_idx);
+       }
+}
index 2d001de42117dccad898129d5c0945bd075d10e3..0e27c0b14343e3f01b6fdf386aed945eb46e414b 100644 (file)
@@ -334,6 +334,7 @@ struct dc_config {
        uint8_t  vblank_alignment_max_frame_time_diff;
        bool is_asymmetric_memory;
        bool is_single_rank_dimm;
+       bool use_pipe_ctx_sync_logic;
 };
 
 enum visual_confirm {
index 3d421583e9ca3821cd122976e3ab7b38c36a42b3..67298aa890c4b9f8c223d48bdb2d22b901405f6f 100644 (file)
@@ -1564,6 +1564,10 @@ static enum dc_status apply_single_controller_ctx_to_hw(
                                &pipe_ctx->stream->audio_info);
        }
 
+       /* make sure no pipes syncd to the pipe being enabled */
+       if (!pipe_ctx->stream->apply_seamless_boot_optimization && dc->config.use_pipe_ctx_sync_logic)
+               check_syncd_pipes_for_disabled_master_pipe(dc, context, pipe_ctx->pipe_idx);
+
 #if defined(CONFIG_DRM_AMD_DC_DCN)
        /* DCN3.1 FPGA Workaround
         * Need to enable HPO DP Stream Encoder before setting OTG master enable.
@@ -2294,6 +2298,10 @@ enum dc_status dce110_apply_ctx_to_hw(
        enum dc_status status;
        int i;
 
+       /* reset syncd pipes from disabled pipes */
+       if (dc->config.use_pipe_ctx_sync_logic)
+               reset_syncd_pipes_from_disabled_pipes(dc, context);
+
        /* Reset old context */
        /* look up the targets that have been removed since last commit */
        hws->funcs.reset_hw_ctx_wrap(dc, context);
index 361a4a1da119c60e5f9df180f161946fe87ce7de..35296e8799a94f722ea3550050588a9478aa8c7f 100644 (file)
@@ -2239,6 +2239,9 @@ static bool dcn31_resource_construct(
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       /* Use pipe context based otg sync logic */
+       dc->config.use_pipe_ctx_sync_logic = true;
+
        /* read VBIOS LTTPR caps */
        {
                if (ctx->dc_bios->funcs->get_lttpr_caps) {
index 6fc6488c54c08467c9609d47b35f21fdb3998c7a..f3c0e70073da282340d4bbb780f06488a762eaf6 100644 (file)
@@ -367,6 +367,7 @@ struct pipe_ctx {
        struct pll_settings pll_settings;
 
        uint8_t pipe_idx;
+       uint8_t pipe_idx_syncd;
 
        struct pipe_ctx *top_pipe;
        struct pipe_ctx *bottom_pipe;
index 372c0898facdeb9956e44a34681dd7bb053e19d1..c208925f824719afbf88a7f4d000a6bd8ecaf430 100644 (file)
 #define MEMORY_TYPE_HBM 2
 
 
+#define IS_PIPE_SYNCD_VALID(pipe) ((((pipe)->pipe_idx_syncd) & 0x80)?1:0)
+#define GET_PIPE_SYNCD_FROM_PIPE(pipe) ((pipe)->pipe_idx_syncd & 0x7F)
+#define SET_PIPE_SYNCD_TO_PIPE(pipe, pipe_syncd) ((pipe)->pipe_idx_syncd = (0x80 | pipe_syncd))
+
 enum dce_version resource_parse_asic_id(
                struct hw_asic_id asic_id);
 
@@ -206,4 +210,11 @@ struct hpo_dp_link_encoder *resource_get_unused_hpo_dp_link_encoder(
                const struct resource_pool *pool);
 #endif
 
+void reset_syncd_pipes_from_disabled_pipes(struct dc *dc,
+       struct dc_state *context);
+
+void check_syncd_pipes_for_disabled_master_pipe(struct dc *dc,
+       struct dc_state *context,
+       uint8_t disabled_master_pipe_idx);
+
 #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */