Blob Blame History Raw
From 986936d1a9b29bd40be2acdf91d9e99ecda3bf33 Mon Sep 17 00:00:00 2001
From: Jun Lei <Jun.Lei@amd.com>
Date: Tue, 16 Jul 2019 13:02:41 -0400
Subject: drm/amd/display: wait for pending complete when enabling a plane
Git-commit: 986936d1a9b29bd40be2acdf91d9e99ecda3bf33
Patch-mainline: v5.4-rc1
References: bsc#1152489

[why]
When planes are enabled, they must be enabled using VSYNC update (not immediate).
However, before the VUPDATE occurs, DM may call with an "immediate" flip which is address
only.  This operation would normally be okay, but if the locking for immediate flip happens
to occur before the VUPDATE associated with the initial plane enablement, it will cause HW
to hang.

[how]
HWSS should enforce plane enable in HW to be synchronous with the call that enables the plane.

Signed-off-by: Jun Lei <Jun.Lei@amd.com>
Reviewed-by: Eric Yang <eric.yang2@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 .../drm/amd/display/dc/dcn20/dcn20_hwseq.c    | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
index fb7cde33c88b..c11de6f0fe5c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1353,13 +1353,15 @@ static void dcn20_apply_ctx_for_surface(
 		int num_planes,
 		struct dc_state *context)
 {
-
+	const unsigned int TIMEOUT_FOR_PIPE_ENABLE_MS = 100;
 	int i;
 	struct timing_generator *tg;
 	bool removed_pipe[6] = { false };
 	bool interdependent_update = false;
 	struct pipe_ctx *top_pipe_to_program =
 			find_top_pipe_for_stream(dc, context, stream);
+	struct pipe_ctx *prev_top_pipe_to_program =
+			find_top_pipe_for_stream(dc, dc->current_state, stream);
 	DC_LOGGER_INIT(dc->ctx->logger);
 
 	if (!top_pipe_to_program)
@@ -1453,6 +1455,22 @@ static void dcn20_apply_ctx_for_surface(
 	for (i = 0; i < dc->res_pool->pipe_count; i++)
 		if (removed_pipe[i])
 			dcn20_disable_plane(dc, &dc->current_state->res_ctx.pipe_ctx[i]);
+
+	/*
+	 * If we are enabling a pipe, we need to wait for pending clear as this is a critical
+	 * part of the enable operation otherwise, DM may request an immediate flip which
+	 * will cause HW to perform an "immediate enable" (as opposed to "vsync enable") which
+	 * is unsupported on DCN.
+	 */
+	i = 0;
+	if (num_planes > 0 && top_pipe_to_program &&
+			(prev_top_pipe_to_program == NULL || prev_top_pipe_to_program->plane_state == NULL)) {
+		while (i < TIMEOUT_FOR_PIPE_ENABLE_MS &&
+				top_pipe_to_program->plane_res.hubp->funcs->hubp_is_flip_pending(top_pipe_to_program->plane_res.hubp)) {
+			i += 1;
+			msleep(1);
+		}
+	}
 }
 
 
-- 
2.28.0