Commit a896f870 authored by Meenakshikumar Somasundaram's avatar Meenakshikumar Somasundaram Committed by Alex Deucher
Browse files

drm/amd/display: Fix for otg synchronization logic



[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: default avatarJun Lei <Jun.Lei@amd.com>
Reviewed-by: default avatarMustapha Ghaddar <mustapha.ghaddar@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarmeenakshikumar somasundaram <meenakshikumar.somasundaram@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent aba3c3fe
Loading
Loading
Loading
Loading
+21 −14
Original line number Diff line number Diff line
@@ -1422,20 +1422,27 @@ 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) {
		/* 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--;
				}
 			}
 		}

+54 −0
Original line number Diff line number Diff line
@@ -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);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -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 {
+8 −0
Original line number Diff line number Diff line
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -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) {
Loading