drivers/gpu/drm/nouveau/dispnv50/disp.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/dispnv50/disp.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/dispnv50/disp.c
Extension
.c
Size
88283 bytes
Lines
3074
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

struct nv50_mstc {
	struct nv50_mstm *mstm;
	struct drm_dp_mst_port *port;
	struct drm_connector connector;

	struct drm_display_mode *native;
	struct edid *edid;
};

struct nv50_msto {
	struct drm_encoder encoder;

	/* head is statically assigned on msto creation */
	struct nv50_head *head;
	struct nv50_mstc *mstc;
	bool disabled;
	bool enabled;

	u32 display_id;
};

struct nouveau_encoder *nv50_real_outp(struct drm_encoder *encoder)
{
	struct nv50_msto *msto;

	if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST)
		return nouveau_encoder(encoder);

	msto = nv50_msto(encoder);
	if (!msto->mstc)
		return NULL;
	return msto->mstc->mstm->outp;
}

static void
nv50_msto_cleanup(struct drm_atomic_commit *state,
		  struct drm_dp_mst_topology_state *new_mst_state,
		  struct drm_dp_mst_topology_mgr *mgr,
		  struct nv50_msto *msto)
{
	struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
	struct drm_dp_mst_atomic_payload *new_payload =
		drm_atomic_get_mst_payload_state(new_mst_state, msto->mstc->port);
	struct drm_dp_mst_topology_state *old_mst_state =
		drm_atomic_get_old_mst_topology_state(state, mgr);
	const struct drm_dp_mst_atomic_payload *old_payload =
		drm_atomic_get_mst_payload_state(old_mst_state, msto->mstc->port);
	struct nv50_mstc *mstc = msto->mstc;
	struct nv50_mstm *mstm = mstc->mstm;

	NV_ATOMIC(drm, "%s: msto cleanup\n", msto->encoder.name);

	if (msto->disabled) {
		if (msto->head->func->display_id) {
			nvif_outp_dp_mst_id_put(&mstm->outp->outp, msto->display_id);
			msto->display_id = 0;
		}

		msto->mstc = NULL;
		msto->disabled = false;
		drm_dp_remove_payload_part2(mgr, new_mst_state, old_payload, new_payload);
	} else if (msto->enabled) {
		drm_dp_add_payload_part2(mgr, new_payload);
		msto->enabled = false;
	}
}

static void
nv50_msto_prepare(struct drm_atomic_commit *state,
		  struct drm_dp_mst_topology_state *mst_state,
		  struct drm_dp_mst_topology_mgr *mgr,
		  struct nv50_msto *msto)
{
	struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
	struct nv50_mstc *mstc = msto->mstc;
	struct nv50_mstm *mstm = mstc->mstm;
	struct drm_dp_mst_atomic_payload *payload;
	int ret = 0;

	NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);

	payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port);

	if (msto->disabled) {
		drm_dp_remove_payload_part1(mgr, mst_state, payload);
		nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
		ret = 1;
	} else {
		if (msto->enabled)
			ret = drm_dp_add_payload_part1(mgr, mst_state, payload);

Annotation

Implementation Notes