mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 06:01:57 +00:00
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: 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>
This commit is contained in:
parent
ec0d7abbb0
commit
fae1879dc2
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user