Commit fae1879d authored by Sung Joon Kim's avatar Sung Joon Kim Committed by Alex Deucher

drm/amd/display: Check top sink only when multiple streams for DP2

[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: default avatarMichael Strauss <michael.strauss@amd.com>
Signed-off-by: default avatarSung Joon Kim <sungjoon.kim@amd.com>
Signed-off-by: default avatarAurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ec0d7abb
...@@ -101,6 +101,7 @@ struct dml2_wrapper_scratch { ...@@ -101,6 +101,7 @@ struct dml2_wrapper_scratch {
struct dml2_dml_to_dc_pipe_mapping dml_to_dc_pipe_mapping; struct dml2_dml_to_dc_pipe_mapping dml_to_dc_pipe_mapping;
bool enable_flexible_pipe_mapping; bool enable_flexible_pipe_mapping;
bool plane_duplicate_exists; bool plane_duplicate_exists;
unsigned int dp2_mst_stream_count;
}; };
struct dml2_helper_det_policy_scratch { struct dml2_helper_det_policy_scratch {
......
...@@ -733,7 +733,8 @@ static void populate_dml_timing_cfg_from_stream_state(struct dml_timing_cfg_st * ...@@ -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, 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; unsigned int output_bpc;
...@@ -746,7 +747,7 @@ static void populate_dml_output_cfg_from_stream_state(struct dml_output_cfg_st * ...@@ -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_MST:
case SIGNAL_TYPE_DISPLAY_PORT: case SIGNAL_TYPE_DISPLAY_PORT:
out->OutputEncoder[location] = dml_dp; 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; out->OutputEncoder[location] = dml_dp2p0;
break; break;
case SIGNAL_TYPE_EDP: case SIGNAL_TYPE_EDP:
...@@ -1193,6 +1194,37 @@ static void dml2_populate_pipe_to_plane_index_mapping(struct dml2_context *dml2, ...@@ -1193,6 +1194,37 @@ static void dml2_populate_pipe_to_plane_index_mapping(struct dml2_context *dml2,
plane_index = 0; 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, static void populate_dml_writeback_cfg_from_stream_state(struct dml_writeback_cfg_st *out,
unsigned int location, const struct dc_stream_state *in) 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 ...@@ -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) 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.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); dml2_populate_pipe_to_plane_index_mapping(dml2, context);
for (i = 0; i < context->stream_count; i++) { 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 ...@@ -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__); 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_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*/ /*Call site for populate_dml_writeback_cfg_from_stream_state*/
populate_dml_writeback_cfg_from_stream_state(&dml_dispcfg->writeback, populate_dml_writeback_cfg_from_stream_state(&dml_dispcfg->writeback,
disp_cfg_stream_location, context->streams[i]); 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 ...@@ -1337,7 +1370,7 @@ void map_dc_state_into_dml_display_cfg(struct dml2_context *dml2, struct dc_stat
if (j >= 1) { if (j >= 1) {
populate_dml_timing_cfg_from_stream_state(&dml_dispcfg->timing, disp_cfg_plane_location, context->streams[i]); 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) { switch (context->streams[i]->debug.force_odm_combine_segments) {
case 2: case 2:
dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_plane_location] = dml_odm_use_policy_combine_2to1; dml2->v20.dml_core_ctx.policy.ODMUse[disp_cfg_plane_location] = dml_odm_use_policy_combine_2to1;
......
...@@ -36,6 +36,6 @@ void dml2_translate_socbb_params(const struct dc *in_dc, struct soc_bounding_box ...@@ -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 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 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); 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__ #endif //__DML2_TRANSLATION_HELPER_H__
...@@ -153,7 +153,7 @@ unsigned int dml2_util_get_maximum_odm_combine_for_output(bool force_odm_4to1, e ...@@ -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) if (pipe_ctx == NULL || pipe_ctx->stream == NULL)
return false; return false;
...@@ -162,7 +162,7 @@ bool is_dp2p0_output_encoder(const struct pipe_ctx *pipe_ctx) ...@@ -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); 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 */ /* 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 && return (pipe_ctx->stream_res.hpo_dp_stream_enc &&
pipe_ctx->link_res.hpo_dp_link_enc && pipe_ctx->link_res.hpo_dp_link_enc &&
dc_is_dp_signal(pipe_ctx->stream->signal) && dc_is_dp_signal(pipe_ctx->stream->signal) &&
...@@ -181,7 +181,7 @@ bool is_dtbclk_required(const struct dc *dc, struct dc_state *context) ...@@ -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++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
if (!context->res_ctx.pipe_ctx[i].stream) if (!context->res_ctx.pipe_ctx[i].stream)
continue; 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 true;
} }
return false; return false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment