Commit 6ffaa6fc authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher
Browse files

drm/amd/display: fix odm pipe management



There are issues removing surfaces/streams when odm is active.
This is a step to fix that

Signed-off-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 661a8cd9
Loading
Loading
Loading
Loading
+51 −7
Original line number Diff line number Diff line
@@ -1251,6 +1251,40 @@ bool dc_add_plane_to_context(
	return true;
}

struct pipe_ctx *dc_res_get_odm_bottom_pipe(struct pipe_ctx *pipe_ctx)
{
	struct pipe_ctx *bottom_pipe = pipe_ctx->bottom_pipe;

	/* ODM should only be updated once per otg */
	if (pipe_ctx->top_pipe)
		return NULL;

	while (bottom_pipe) {
		if (bottom_pipe->stream_res.opp != pipe_ctx->stream_res.opp)
			break;
		bottom_pipe = bottom_pipe->bottom_pipe;
	}

	return bottom_pipe;
}

static bool dc_res_is_odm_bottom_pipe(struct pipe_ctx *pipe_ctx)
{
	struct pipe_ctx *top_pipe = pipe_ctx->top_pipe;
	bool result = false;

	if (top_pipe && top_pipe->stream_res.opp == pipe_ctx->stream_res.opp)
		return false;

	while (top_pipe) {
		if (!top_pipe->top_pipe && top_pipe->stream_res.opp != pipe_ctx->stream_res.opp)
			result = true;
		top_pipe = top_pipe->top_pipe;
	}

	return result;
}

bool dc_remove_plane_from_context(
		const struct dc *dc,
		struct dc_stream_state *stream,
@@ -1274,10 +1308,14 @@ bool dc_remove_plane_from_context(

	/* release pipe for plane*/
	for (i = pool->pipe_count - 1; i >= 0; i--) {
		struct pipe_ctx *pipe_ctx;
		struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];

		if (context->res_ctx.pipe_ctx[i].plane_state == plane_state) {
			pipe_ctx = &context->res_ctx.pipe_ctx[i];
		if (pipe_ctx->plane_state == plane_state) {
			if (dc_res_is_odm_bottom_pipe(pipe_ctx)) {
				pipe_ctx->plane_state = NULL;
				pipe_ctx->bottom_pipe = NULL;
				continue;
			}

			if (pipe_ctx->top_pipe)
				pipe_ctx->top_pipe->bottom_pipe = pipe_ctx->bottom_pipe;
@@ -1293,10 +1331,9 @@ bool dc_remove_plane_from_context(
			 * For head pipe detach surfaces from pipe for tail
			 * pipe just zero it out
			 */
			if (!pipe_ctx->top_pipe || (!pipe_ctx->top_pipe->top_pipe &&
					pipe_ctx->top_pipe->stream_res.opp != pipe_ctx->stream_res.opp)) {
				pipe_ctx->top_pipe = NULL;
			if (!pipe_ctx->top_pipe) {
				pipe_ctx->plane_state = NULL;
				if (!dc_res_get_odm_bottom_pipe(pipe_ctx))
					pipe_ctx->bottom_pipe = NULL;
			} else {
				memset(pipe_ctx, 0, sizeof(*pipe_ctx));
@@ -1703,6 +1740,9 @@ enum dc_status dc_remove_stream_from_ctx(
	for (i = 0; i < MAX_PIPES; i++) {
		if (new_ctx->res_ctx.pipe_ctx[i].stream == stream &&
				!new_ctx->res_ctx.pipe_ctx[i].top_pipe) {
			struct pipe_ctx *odm_pipe =
					dc_res_get_odm_bottom_pipe(&new_ctx->res_ctx.pipe_ctx[i]);

			del_pipe = &new_ctx->res_ctx.pipe_ctx[i];

			ASSERT(del_pipe->stream_res.stream_enc);
@@ -1727,6 +1767,10 @@ enum dc_status dc_remove_stream_from_ctx(
				dc->res_pool->funcs->remove_stream_from_ctx(dc, new_ctx, stream);

			memset(del_pipe, 0, sizeof(*del_pipe));
			if (odm_pipe)
				memset(odm_pipe, 0, sizeof(*odm_pipe));

			break;
		}
	}

+2 −0
Original line number Diff line number Diff line
@@ -172,4 +172,6 @@ void update_audio_usage(

unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format);

struct pipe_ctx *dc_res_get_odm_bottom_pipe(struct pipe_ctx *pipe_ctx);

#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */