drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c
Extension
.c
Size
15448 bytes
Lines
520
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (temp_mpcc && temp_mpcc->mpcc_bot == insert_above_mpcc) {
			REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0, MPCC_BOT_SEL, mpcc_id);
			temp_mpcc->mpcc_bot = new_mpcc;
			if (!insert_above_mpcc)
				REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
						MPCC_MODE, MPCC_BLEND_MODE_TOP_BOT_BLENDING);
		}
	}

	/* update the blending configuration */
	mpc->funcs->update_blending(mpc, blnd_cfg, mpcc_id);

	/* update the stereo mix settings, if provided */
	if (sm_cfg != NULL) {
		new_mpcc->sm_cfg = *sm_cfg;
		mpc1_update_stereo_mix(mpc, sm_cfg, mpcc_id);
	}

	/* mark this mpcc as in use */
	mpc10->mpcc_in_use_mask |= 1 << mpcc_id;

	return new_mpcc;
}

/*
 * Remove a specified MPCC from the MPC tree.
 *
 * Parameters:
 * [in/out] mpc		- MPC context.
 * [in/out] tree	- MPC tree structure that plane will be removed from.
 * [in/out] mpcc	- MPCC to be removed from tree.
 *
 * Return:  void
 */
void mpc1_remove_mpcc(
	struct mpc *mpc,
	struct mpc_tree *tree,
	struct mpcc *mpcc_to_remove)
{
	struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
	bool found = false;
	int mpcc_id = mpcc_to_remove->mpcc_id;

	if (tree->opp_list == mpcc_to_remove) {
		found = true;
		/* remove MPCC from top of tree */
		if (mpcc_to_remove->mpcc_bot) {
			/* set the next MPCC in list to be the top MPCC */
			tree->opp_list = mpcc_to_remove->mpcc_bot;
			REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, tree->opp_list->mpcc_id);
		} else {
			/* there are no other MPCC is list */
			tree->opp_list = NULL;
			REG_UPDATE(MUX[tree->opp_id], MPC_OUT_MUX, 0xf);
		}
	} else {
		/* find mpcc to remove MPCC list */
		struct mpcc *temp_mpcc = tree->opp_list;

		while (temp_mpcc && temp_mpcc->mpcc_bot != mpcc_to_remove)
			temp_mpcc = temp_mpcc->mpcc_bot;

		if (temp_mpcc && temp_mpcc->mpcc_bot == mpcc_to_remove) {
			found = true;
			temp_mpcc->mpcc_bot = mpcc_to_remove->mpcc_bot;
			if (mpcc_to_remove->mpcc_bot) {
				/* remove MPCC in middle of list */
				REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
						MPCC_BOT_SEL, mpcc_to_remove->mpcc_bot->mpcc_id);
			} else {
				/* remove MPCC from bottom of list */
				REG_SET(MPCC_BOT_SEL[temp_mpcc->mpcc_id], 0,
						MPCC_BOT_SEL, 0xf);
				REG_UPDATE(MPCC_CONTROL[temp_mpcc->mpcc_id],
						MPCC_MODE, MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH);
			}
		}
	}

	if (found) {
		/* turn off MPCC mux registers */
		REG_SET(MPCC_TOP_SEL[mpcc_id], 0, MPCC_TOP_SEL, 0xf);
		REG_SET(MPCC_BOT_SEL[mpcc_id], 0, MPCC_BOT_SEL, 0xf);
		REG_SET(MPCC_OPP_ID[mpcc_id],  0, MPCC_OPP_ID,  0xf);
		REG_SET(MPCC_UPDATE_LOCK_SEL[mpcc_id], 0, MPCC_UPDATE_LOCK_SEL, 0xf);

		/* mark this mpcc as not in use */
		mpc10->mpcc_in_use_mask &= ~(1 << mpcc_id);
		mpcc_to_remove->dpp_id = 0xf;
		mpcc_to_remove->mpcc_bot = NULL;

Annotation

Implementation Notes