Commit 59de751e authored by Samson Tam's avatar Samson Tam Committed by Alex Deucher
Browse files

drm/amd/display: add ODM case when looking for first split pipe



[Why]
When going from ODM 2:1 single display case to max displays, second
odm pipe needs to be repurposed for one of the new single displays.
However, acquire_first_split_pipe() only handles MPC case and not
ODM case

[How]
Add ODM conditions in acquire_first_split_pipe()
Add commit_minimal_transition_state() in commit_streams() to handle
odm 2:1 exit first, and then process new streams
Handle ODM condition in commit_minimal_transition_state()

Cc: Mario Limonciello <mario.limonciello@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: stable@vger.kernel.org
Acked-by: default avatarStylon Wang <stylon.wang@amd.com>
Signed-off-by: default avatarSamson Tam <samson.tam@amd.com>
Reviewed-by: default avatarAlvin Lee <Alvin.Lee2@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 99b3886f
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -1981,6 +1981,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
	return result;
}

static bool commit_minimal_transition_state(struct dc *dc,
		struct dc_state *transition_base_context);

/**
 * dc_commit_streams - Commit current stream state
 *
@@ -2002,6 +2005,8 @@ enum dc_status dc_commit_streams(struct dc *dc,
	struct dc_state *context;
	enum dc_status res = DC_OK;
	struct dc_validation_set set[MAX_STREAMS] = {0};
	struct pipe_ctx *pipe;
	bool handle_exit_odm2to1 = false;

	if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
		return res;
@@ -2026,6 +2031,22 @@ enum dc_status dc_commit_streams(struct dc *dc,
		}
	}

	/* Check for case where we are going from odm 2:1 to max
	 *  pipe scenario.  For these cases, we will call
	 *  commit_minimal_transition_state() to exit out of odm 2:1
	 *  first before processing new streams
	 */
	if (stream_count == dc->res_pool->pipe_count) {
		for (i = 0; i < dc->res_pool->pipe_count; i++) {
			pipe = &dc->current_state->res_ctx.pipe_ctx[i];
			if (pipe->next_odm_pipe)
				handle_exit_odm2to1 = true;
		}
	}

	if (handle_exit_odm2to1)
		res = commit_minimal_transition_state(dc, dc->current_state);

	context = dc_create_state(dc);
	if (!context)
		goto context_alloc_fail;
@@ -3872,6 +3893,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
	unsigned int i, j;
	unsigned int pipe_in_use = 0;
	bool subvp_in_use = false;
	bool odm_in_use = false;

	if (!transition_context)
		return false;
@@ -3900,6 +3922,18 @@ static bool commit_minimal_transition_state(struct dc *dc,
		}
	}

	/* If ODM is enabled and we are adding or removing planes from any ODM
	 * pipe, we must use the minimal transition.
	 */
	for (i = 0; i < dc->res_pool->pipe_count; i++) {
		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];

		if (pipe->stream && pipe->next_odm_pipe) {
			odm_in_use = true;
			break;
		}
	}

	/* When the OS add a new surface if we have been used all of pipes with odm combine
	 * and mpc split feature, it need use commit_minimal_transition_state to transition safely.
	 * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need
@@ -3908,7 +3942,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
	 * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
	 * enter/exit MPO when DCN still have enough resources.
	 */
	if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use) {
	if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use) {
		dc_release_state(transition_context);
		return true;
	}
+20 −0
Original line number Diff line number Diff line
@@ -1444,6 +1444,26 @@ static int acquire_first_split_pipe(
			split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
			split_pipe->pipe_idx = i;

			split_pipe->stream = stream;
			return i;
		} else if (split_pipe->prev_odm_pipe &&
				split_pipe->prev_odm_pipe->plane_state == split_pipe->plane_state) {
			split_pipe->prev_odm_pipe->next_odm_pipe = split_pipe->next_odm_pipe;
			if (split_pipe->next_odm_pipe)
				split_pipe->next_odm_pipe->prev_odm_pipe = split_pipe->prev_odm_pipe;

			if (split_pipe->prev_odm_pipe->plane_state)
				resource_build_scaling_params(split_pipe->prev_odm_pipe);

			memset(split_pipe, 0, sizeof(*split_pipe));
			split_pipe->stream_res.tg = pool->timing_generators[i];
			split_pipe->plane_res.hubp = pool->hubps[i];
			split_pipe->plane_res.ipp = pool->ipps[i];
			split_pipe->plane_res.dpp = pool->dpps[i];
			split_pipe->stream_res.opp = pool->opps[i];
			split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
			split_pipe->pipe_idx = i;

			split_pipe->stream = stream;
			return i;
		}