Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f4a7253 authored by Eric Bernstein's avatar Eric Bernstein Committed by Alex Deucher
Browse files

drm/amd/display: update mpc add/remove functions

parent 98b49c2f
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -881,7 +881,8 @@ static void dcn10_init_hw(struct dc *dc)

		xfm->funcs->transform_reset(xfm);
		dc->res_pool->mpc->funcs->remove(
				dc->res_pool->mpc, dc->res_pool->opps[i], i);
				dc->res_pool->mpc, &(dc->res_pool->opps[i]->mpc_tree),
				dc->res_pool->opps[i]->inst, i);

		/* Blank controller using driver code instead of
		 * command table.
@@ -1079,7 +1080,8 @@ static void plane_atomic_disconnect(struct dc *dc,
	if (dc->debug.sanity_checks)
		verify_allow_pstate_change_high(dc->hwseq);

	mpc->funcs->remove(mpc, dc->res_pool->opps[opp_id], fe_idx);
	mpc->funcs->remove(mpc, &(dc->res_pool->opps[opp_id]->mpc_tree),
			dc->res_pool->opps[opp_id]->inst, fe_idx);
}

/* disable HW used by plane.
@@ -2299,8 +2301,9 @@ static void update_dchubp_dpp(
			plane_state->format,
			EXPANSION_MODE_ZERO);

	mpcc_cfg.mi = mi;
	mpcc_cfg.opp = pipe_ctx->stream_res.opp;
	mpcc_cfg.dpp_id = mi->inst;
	mpcc_cfg.opp_id = pipe_ctx->stream_res.opp->inst;
	mpcc_cfg.tree_cfg = &(pipe_ctx->stream_res.opp->mpc_tree);
	for (top_pipe = pipe_ctx->top_pipe; top_pipe; top_pipe = top_pipe->top_pipe)
		mpcc_cfg.z_index++;
	if (dc->debug.surface_visual_confirm)
@@ -2317,7 +2320,8 @@ static void update_dchubp_dpp(
	mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
			pipe_ctx->stream->output_color_space)
					&& per_pixel_alpha;
	dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg);
	mi->mpcc_id = dc->res_pool->mpc->funcs->add(dc->res_pool->mpc, &mpcc_cfg);
	mi->opp_id = mpcc_cfg.opp_id;

	pipe_ctx->plane_res.scl_data.lb_params.alpha_en = per_pixel_alpha;
	pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
@@ -2528,7 +2532,8 @@ static void dcn10_apply_ctx_for_surface(
			/* reset mpc */
			dc->res_pool->mpc->funcs->remove(
					dc->res_pool->mpc,
					old_pipe_ctx->stream_res.opp,
					&(old_pipe_ctx->stream_res.opp->mpc_tree),
					old_pipe_ctx->stream_res.opp->inst,
					old_pipe_ctx->pipe_idx);
			old_pipe_ctx->stream_res.opp->mpcc_disconnect_pending[old_pipe_ctx->plane_res.mi->mpcc_id] = true;

+113 −60
Original line number Diff line number Diff line
@@ -118,17 +118,19 @@ static void mpc10_assert_mpcc_idle_before_connect(struct dcn10_mpc *mpc10, int i

static void mpc10_mpcc_remove(
		struct mpc *mpc,
		struct output_pixel_processor *opp,
		struct mpc_tree_cfg *tree_cfg,
		int opp_id,
		int dpp_id)
{
	struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
	int mpcc_id, z_idx;

	for (z_idx = 0; z_idx < opp->mpc_tree.num_pipes; z_idx++)
		if (opp->mpc_tree.dpp[z_idx] == dpp_id)
	/* find z_idx for the dpp to be removed */
	for (z_idx = 0; z_idx < tree_cfg->num_pipes; z_idx++)
		if (tree_cfg->dpp[z_idx] == dpp_id)
			break;

	if (z_idx == opp->mpc_tree.num_pipes) {
	if (z_idx == tree_cfg->num_pipes) {
		/* In case of resume from S3/S4, remove mpcc from bios left over */
		REG_SET(MPCC_OPP_ID[dpp_id], 0,
				MPCC_OPP_ID, 0xf);
@@ -139,7 +141,7 @@ static void mpc10_mpcc_remove(
		return;
	}

	mpcc_id = opp->mpc_tree.mpcc[z_idx];
	mpcc_id = tree_cfg->mpcc[z_idx];

	REG_SET(MPCC_OPP_ID[mpcc_id], 0,
			MPCC_OPP_ID, 0xf);
@@ -149,82 +151,101 @@ static void mpc10_mpcc_remove(
			MPCC_BOT_SEL, 0xf);

	if (z_idx > 0) {
		int top_mpcc_id = opp->mpc_tree.mpcc[z_idx - 1];
		int top_mpcc_id = tree_cfg->mpcc[z_idx - 1];

		if (z_idx + 1 < opp->mpc_tree.num_pipes)
		if (z_idx + 1 < tree_cfg->num_pipes)
			/* mpcc to be removed is in the middle of the tree */
			REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0,
					MPCC_BOT_SEL, opp->mpc_tree.mpcc[z_idx + 1]);
					MPCC_BOT_SEL, tree_cfg->mpcc[z_idx + 1]);
		else {
			/* mpcc to be removed is at the bottom of the tree */
			REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0,
					MPCC_BOT_SEL, 0xf);
			REG_UPDATE(MPCC_CONTROL[top_mpcc_id],
					MPCC_MODE, MODE_TOP_ONLY);
		}
	} else if (opp->mpc_tree.num_pipes > 1)
		REG_SET(MUX[opp->inst], 0,
				MPC_OUT_MUX, opp->mpc_tree.mpcc[z_idx + 1]);
	} else if (tree_cfg->num_pipes > 1)
		/* mpcc to be removed is at the top of the tree */
		REG_SET(MUX[opp_id], 0,
				MPC_OUT_MUX, tree_cfg->mpcc[z_idx + 1]);
	else
		REG_SET(MUX[opp->inst], 0, MPC_OUT_MUX, 0xf);
		/* mpcc to be removed is the only one in the tree */
		REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, 0xf);

	/* mark this mpcc as not in use */
	mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
	opp->mpc_tree.num_pipes--;
	for (; z_idx < opp->mpc_tree.num_pipes; z_idx++) {
		opp->mpc_tree.dpp[z_idx] = opp->mpc_tree.dpp[z_idx + 1];
		opp->mpc_tree.mpcc[z_idx] = opp->mpc_tree.mpcc[z_idx + 1];
	tree_cfg->num_pipes--;
	for (; z_idx < tree_cfg->num_pipes; z_idx++) {
		tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx + 1];
		tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx + 1];
	}
	opp->mpc_tree.dpp[opp->mpc_tree.num_pipes] = 0xdeadbeef;
	opp->mpc_tree.mpcc[opp->mpc_tree.num_pipes] = 0xdeadbeef;
	tree_cfg->dpp[tree_cfg->num_pipes] = 0xdeadbeef;
	tree_cfg->mpcc[tree_cfg->num_pipes] = 0xdeadbeef;
}

static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg)
static void mpc10_add_to_tree_cfg(
	struct mpc *mpc,
	struct mpcc_cfg *cfg,
	int mpcc_id)
{
	struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
	int mpcc_mode = MODE_TOP_ONLY;
	int position = cfg->z_index;
	struct mpc_tree_cfg *tree_cfg = cfg->tree_cfg;
	int alpha_blnd_mode = cfg->per_pixel_alpha ?
			BLND_PP_ALPHA : BLND_GLOBAL_ALPHA;
	int mpcc_mode = MODE_TOP_ONLY;
	int mpcc_id, z_idx;
	int z_idx;

	ASSERT(cfg->z_index < mpc10->num_mpcc);
	REG_SET(MPCC_OPP_ID[mpcc_id], 0,
			MPCC_OPP_ID, cfg->opp_id);

	for (z_idx = 0; z_idx < cfg->opp->mpc_tree.num_pipes; z_idx++)
		if (cfg->opp->mpc_tree.dpp[z_idx] == cfg->mi->inst)
			break;
	if (z_idx == cfg->opp->mpc_tree.num_pipes) {
		ASSERT(cfg->z_index <= cfg->opp->mpc_tree.num_pipes);
		mpcc_id = mpc10_get_idle_mpcc_id(mpc10);
		/*todo: remove hack*/
		mpcc_id = cfg->mi->inst;
		ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id));
	REG_SET(MPCC_TOP_SEL[mpcc_id], 0,
			MPCC_TOP_SEL, cfg->dpp_id);

		if (mpc->ctx->dc->debug.sanity_checks)
			mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id);
	} else {
		ASSERT(cfg->z_index < cfg->opp->mpc_tree.num_pipes);
		mpcc_id = cfg->opp->mpc_tree.mpcc[z_idx];
		mpc10_mpcc_remove(mpc, cfg->opp, cfg->mi->inst);
	if (position == 0) {
		/* idle dpp/mpcc is added to the top layer of tree */

		if (tree_cfg->num_pipes > 0) {
			/* get instance of previous top mpcc */
			int prev_top_mpcc_id = tree_cfg->mpcc[0];

			REG_SET(MPCC_BOT_SEL[mpcc_id], 0,
					MPCC_BOT_SEL, prev_top_mpcc_id);
			mpcc_mode = MODE_BLEND;
		}

	REG_SET(MPCC_OPP_ID[mpcc_id], 0,
			MPCC_OPP_ID, cfg->opp->inst);
		/* opp will get new output. from new added mpcc */
		REG_SET(MUX[cfg->opp_id], 0, MPC_OUT_MUX, mpcc_id);

	REG_SET(MPCC_TOP_SEL[mpcc_id], 0,
			MPCC_TOP_SEL, cfg->mi->inst);
	} else if (position == tree_cfg->num_pipes) {
		/* idle dpp/mpcc is added to the bottom layer of tree */

	if (cfg->z_index > 0) {
		int top_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index - 1];
		/* get instance of previous bottom mpcc, set to middle layer */
		int prev_bot_mpcc_id = tree_cfg->mpcc[tree_cfg->num_pipes - 1];

		REG_SET(MPCC_BOT_SEL[top_mpcc_id], 0,
		REG_SET(MPCC_BOT_SEL[prev_bot_mpcc_id], 0,
				MPCC_BOT_SEL, mpcc_id);
		REG_UPDATE(MPCC_CONTROL[top_mpcc_id],
		REG_UPDATE(MPCC_CONTROL[prev_bot_mpcc_id],
				MPCC_MODE, MODE_BLEND);
	} else
		REG_SET(MUX[cfg->opp->inst], 0, MPC_OUT_MUX, mpcc_id);

	if (cfg->z_index < cfg->opp->mpc_tree.num_pipes) {
		int bot_mpcc_id = cfg->opp->mpc_tree.mpcc[cfg->z_index];
		/* mpcc_id become new bottom mpcc*/
		REG_SET(MPCC_BOT_SEL[mpcc_id], 0,
				MPCC_BOT_SEL, 0xf);

	} else {
		/* idle dpp/mpcc is added to middle of tree */
		int above_mpcc_id = tree_cfg->mpcc[position - 1];
		int below_mpcc_id = tree_cfg->mpcc[position];

		/* mpcc above new mpcc_id has new bottom mux*/
		REG_SET(MPCC_BOT_SEL[above_mpcc_id], 0,
				MPCC_BOT_SEL, mpcc_id);
		REG_UPDATE(MPCC_CONTROL[above_mpcc_id],
				MPCC_MODE, MODE_BLEND);

		/* mpcc_id bottom mux is from below mpcc*/
		REG_SET(MPCC_BOT_SEL[mpcc_id], 0,
				MPCC_BOT_SEL, bot_mpcc_id);
				MPCC_BOT_SEL, below_mpcc_id);
		mpcc_mode = MODE_BLEND;
	}

@@ -234,18 +255,50 @@ static void mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg)
		MPCC_ALPHA_MULTIPLIED_MODE, cfg->pre_multiplied_alpha,
		MPCC_BLND_ACTIVE_OVERLAP_ONLY, false);

	/* update mpc_tree_cfg with new mpcc */
	for (z_idx = tree_cfg->num_pipes; z_idx > position; z_idx--) {
		tree_cfg->dpp[z_idx] = tree_cfg->dpp[z_idx - 1];
		tree_cfg->mpcc[z_idx] = tree_cfg->mpcc[z_idx - 1];
	}
	tree_cfg->dpp[position] = cfg->dpp_id;
	tree_cfg->mpcc[position] = mpcc_id;
	tree_cfg->num_pipes++;
}

static int mpc10_mpcc_add(struct mpc *mpc, struct mpcc_cfg *cfg)
{
	struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
	int mpcc_id, z_idx;

	ASSERT(cfg->z_index < mpc10->num_mpcc);

	/* check in dpp already exists in mpc tree */
	for (z_idx = 0; z_idx < cfg->tree_cfg->num_pipes; z_idx++)
		if (cfg->tree_cfg->dpp[z_idx] == cfg->dpp_id)
			break;
	if (z_idx == cfg->tree_cfg->num_pipes) {
		ASSERT(cfg->z_index <= cfg->tree_cfg->num_pipes);
		mpcc_id = mpc10_get_idle_mpcc_id(mpc10);
		ASSERT(!(mpc10->mpcc_in_use_mask & 1 << mpcc_id));

		if (mpc->ctx->dc->debug.sanity_checks)
			mpc10_assert_mpcc_idle_before_connect(mpc10, mpcc_id);
	} else {
		ASSERT(cfg->z_index < cfg->tree_cfg->num_pipes);
		mpcc_id = cfg->tree_cfg->mpcc[z_idx];
		mpc10_mpcc_remove(mpc, cfg->tree_cfg, cfg->opp_id, cfg->dpp_id);
	}

	/* add dpp/mpcc pair to mpc_tree_cfg and update mpcc registers */
	mpc10_add_to_tree_cfg(mpc, cfg, mpcc_id);

	/* set background color */
	mpc10_set_bg_color(mpc10, &cfg->black_color, mpcc_id);

	/* mark this mpcc as in use */
	mpc10->mpcc_in_use_mask |= 1 << mpcc_id;
	for (z_idx = cfg->opp->mpc_tree.num_pipes; z_idx > cfg->z_index; z_idx--) {
		cfg->opp->mpc_tree.dpp[z_idx] = cfg->opp->mpc_tree.dpp[z_idx - 1];
		cfg->opp->mpc_tree.mpcc[z_idx] = cfg->opp->mpc_tree.mpcc[z_idx - 1];
	}
	cfg->opp->mpc_tree.dpp[cfg->z_index] = cfg->mi->inst;
	cfg->opp->mpc_tree.mpcc[cfg->z_index] = mpcc_id;
	cfg->opp->mpc_tree.num_pipes++;
	cfg->mi->opp_id = cfg->opp->inst;
	cfg->mi->mpcc_id = mpcc_id;

	return mpcc_id;
}

const struct mpc_funcs dcn10_mpc_funcs = {
+6 −4
Original line number Diff line number Diff line
@@ -29,8 +29,9 @@
#include "opp.h"

struct mpcc_cfg {
	struct mem_input *mi;
	struct output_pixel_processor *opp;
	int dpp_id;
	int opp_id;
	struct mpc_tree_cfg *tree_cfg;
	unsigned int z_index;

	struct tg_color black_color;
@@ -44,9 +45,10 @@ struct mpc {
};

struct mpc_funcs {
	void (*add)(struct mpc *mpc, struct mpcc_cfg *cfg);
	int (*add)(struct mpc *mpc, struct mpcc_cfg *cfg);
	void (*remove)(struct mpc *mpc,
			struct output_pixel_processor *opp,
			struct mpc_tree_cfg *tree_cfg,
			int opp_id,
			int mpcc_inst);
	void (*wait_for_idle)(struct mpc *mpc, int id);
};