]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/amd/display: Check top sink only when multiple streams for DP2
authorSung Joon Kim <sungjoon.kim@amd.com>
Thu, 11 Jul 2024 15:24:07 +0000 (11:24 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 23 Jul 2024 21:37:01 +0000 (17:37 -0400)
[why]
When switching from extended to second display only
mode, the top remote sink is not removed while the top stream
itself is released. This causes DML to think there is no
DP2 output encoder because top remote sink does not match
with the second stream and disables DTBCLK and causes
hang.

[how]
For DP2.0 MST hubs, only treat 1st remote sink as an encoder
only when there are multiple displays connected.

Reviewed-by: Michael Strauss <michael.strauss@amd.com>
Signed-off-by: Sung Joon Kim <sungjoon.kim@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.h
drivers/gpu/drm/amd/display/dc/dml2/dml2_utils.c

index b566f53608c6d4883d502919427ad0422cdd3123..3ba184be25d3868801f81c58562e8235e6733b67 100644 (file)
@@ -101,6 +101,7 @@ struct dml2_wrapper_scratch {
        struct dml2_dml_to_dc_pipe_mapping dml_to_dc_pipe_mapping;
        bool enable_flexible_pipe_mapping;
        bool plane_duplicate_exists;
+       unsigned int dp2_mst_stream_count;
 };
 
 struct dml2_helper_det_policy_scratch {
index 8b9dcee772660c4e39623b2ee070cea85fafbb34..25d4ef04017377d62cdaa14774f3049e383b9ccc 100644 (file)
@@ -733,7 +733,8 @@ static void populate_dml_timing_cfg_from_stream_state(struct dml_timing_cfg_st *
 }
 
 static void populate_dml_output_cfg_from_stream_state(struct dml_output_cfg_st *out, unsigned int location,
-                               const struct dc_stream_state *in, const struct pipe_ctx *pipe)
+                               const struct dc_stream_state *in, const struct pipe_ctx *pipe,
+                               unsigned int dp2_mst_stream_count)
 {
        unsigned int output_bpc;
 
@@ -746,7 +747,7 @@ static void populate_dml_output_cfg_from_stream_state(struct dml_output_cfg_st *
        case SIGNAL_TYPE_DISPLAY_PORT_MST:
        case SIGNAL_TYPE_DISPLAY_PORT:
                out->OutputEncoder[location] = dml_dp;
-               if (is_dp2p0_output_encoder(pipe))
+               if (is_dp2p0_output_encoder(pipe, dp2_mst_stream_count))
                        out->OutputEncoder[location] = dml_dp2p0;
                break;
        case SIGNAL_TYPE_EDP:
@@ -1193,6 +1194,37 @@ static void dml2_populate_pipe_to_plane_index_mapping(struct dml2_context *dml2,
                plane_index = 0;
        }
 }
+
+static unsigned int calculate_dp2_mst_stream_count(struct dc_state *context)
+{
+       int i, j;
+       unsigned int dp2_mst_stream_count = 0;
+
+       for (i = 0; i < context->stream_count; i++) {
+               struct dc_stream_state *stream = context->streams[i];
+
+               if (!stream || stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST)
+                       continue;
+
+               for (j = 0; j < MAX_PIPES; j++) {
+                       struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+                       if (!pipe_ctx || !pipe_ctx->stream)
+                               continue;
+
+                       if (stream != pipe_ctx->stream)
+                               continue;
+
+                       if (pipe_ctx->stream_res.hpo_dp_stream_enc && pipe_ctx->link_res.hpo_dp_link_enc) {
+                               dp2_mst_stream_count++;
+                               break;
+                       }
+               }
+       }
+
+       return dp2_mst_stream_count;
+}
+
 static void populate_dml_writeback_cfg_from_stream_state(struct dml_writeback_cfg_st *out,
                unsigned int location, const struct dc_stream_state *in)
 {
@@ -1255,6 +1287,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
        if (dml2->v20.dml_core_ctx.ip.hostvm_enable)
                dml2->v20.dml_core_ctx.policy.AllowForPStateChangeOrStutterInVBlankFinal = dml_prefetch_support_uclk_fclk_and_stutter;
 
+       dml2->v20.scratch.dp2_mst_stream_count = calculate_dp2_mst_stream_count(context);
        dml2_populate_pipe_to_plane_index_mapping(dml2, context);
 
        for (i = 0; i < context->stream_count; i++) {
@@ -1276,7 +1309,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
                ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
 
                populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_stream_location, context->streams[i]);
-               populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context);
+               populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_stream_location, context->streams[i], current_pipe_context, dml2->v20.scratch.dp2_mst_stream_count);
                /*Call site for populate_dml_writeback_cfg_from_stream_state*/
                populate_dml_writeback_cfg_from_stream_state(&dml_dispcfg->writeback,
                        disp_cfg_stream_location, context->streams[i]);
@@ -1337,7 +1370,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
 
                                if (j >= 1) {
                                        populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_plane_location, context->streams[i]);
-                                       populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_plane_location, context->streams[i], current_pipe_context);
+                                       populate_dml_output_cfg_from_stream_state(&dml_dispcfg->output, disp_cfg_plane_location, context->streams[i], current_pipe_context, dml2->v20.scratch.dp2_mst_stream_count);
                                        switch (context->streams[i]->debug.force_odm_combine_segments) {
                                        case 2:
                                                dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_plane_location] = dml_odm_use_policy_combine_2to1;
index d764773938f4ef46b331e9b24bd5d6644241bd2b..55659b22d87f7f485d3f4745b84195225383fe49 100644 (file)
@@ -36,6 +36,6 @@ void dml2_translate_socbb_params(const struct dc *in_dc, struct soc_bounding_box
 void dml2_translate_soc_states(const struct dc *in_dc, struct soc_states_st *out, int num_states);
 void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_state *context, struct dml_display_cfg_st *dml_dispcfg);
 void dml2_update_pipe_ctx_dchub_regs(struct _vcs_dpi_dml_display_rq_regs_st *rq_regs, struct _vcs_dpi_dml_display_dlg_regs_st *disp_dlg_regs, struct _vcs_dpi_dml_display_ttu_regs_st *disp_ttu_regs, struct pipe_ctx *out);
-bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe);
+bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe, unsigned int dp2_mst_stream_count);
 
 #endif //__DML2_TRANSLATION_HELPER_H__
index 92238ff333a45d1d2d198d3dd5f02c0b0b6ca55e..7655501e75d4c86eec492bd08882665115f66e68 100644 (file)
@@ -153,7 +153,7 @@ unsigned int dml2_util_get_maximum_odm_combine_for_output(bool force_odm_4to1, e
        }
 }
 
-bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx)
+bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx, unsigned int dp2_mst_stream_count)
 {
        if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
                return false;
@@ -162,7 +162,7 @@ bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx)
        ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true);
 
        /* Count MST hubs once by treating only 1st remote sink in topology as an encoder */
-       if (pipe_ctx->stream->link && pipe_ctx->stream->link->remote_sinks[0]) {
+       if (pipe_ctx->stream->link && pipe_ctx->stream->link->remote_sinks[0] && dp2_mst_stream_count > 1) {
                return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
                        pipe_ctx->link_res.hpo_dp_link_enc &&
                        dc_is_dp_signal(pipe_ctx->stream->signal) &&
@@ -181,7 +181,7 @@ bool is_dtbclk_required(const struct dc *dc, struct dc_state *context)
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
                if (!context->res_ctx.pipe_ctx[i].stream)
                        continue;
-               if (is_dp2p0_output_encoder(&context->res_ctx.pipe_ctx[i]))
+               if (is_dp2p0_output_encoder(&context->res_ctx.pipe_ctx[i], context->bw_ctx.dml2->v20.scratch.dp2_mst_stream_count))
                        return true;
        }
        return false;