drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
Extension
.c
Size
17364 bytes
Lines
676
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 lt_state {
	struct nvkm_outp *outp;

	int repeaters;
	int repeater;

	u8  stat[6];
	u8  conf[4];
	bool pc2;
	u8  pc2stat;
	u8  pc2conf[2];
};

static int
nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay)
{
	struct nvkm_outp *outp = lt->outp;
	u32 addr;
	int ret;

	usleep_range(delay, delay * 2);

	if (lt->repeater)
		addr = DPCD_LTTPR_LANE0_1_STATUS(lt->repeater);
	else
		addr = DPCD_LS02;

	ret = nvkm_rdaux(outp->dp.aux, addr, &lt->stat[0], 3);
	if (ret)
		return ret;

	if (lt->repeater)
		addr = DPCD_LTTPR_LANE0_1_ADJUST(lt->repeater);
	else
		addr = DPCD_LS06;

	ret = nvkm_rdaux(outp->dp.aux, addr, &lt->stat[4], 2);
	if (ret)
		return ret;

	if (pc) {
		ret = nvkm_rdaux(outp->dp.aux, DPCD_LS0C, &lt->pc2stat, 1);
		if (ret)
			lt->pc2stat = 0x00;

		OUTP_TRACE(outp, "status %6ph pc2 %02x", lt->stat, lt->pc2stat);
	} else {
		OUTP_TRACE(outp, "status %6ph", lt->stat);
	}

	return 0;
}

static int
nvkm_dp_train_drive(struct lt_state *lt, bool pc)
{
	struct nvkm_outp *outp = lt->outp;
	struct nvkm_ior *ior = outp->ior;
	struct nvkm_bios *bios = ior->disp->engine.subdev.device->bios;
	struct nvbios_dpout info;
	struct nvbios_dpcfg ocfg;
	u8  ver, hdr, cnt, len;
	u32 addr;
	u32 data;
	int ret, i;

	for (i = 0; i < ior->dp.nr; i++) {
		u8 lane = (lt->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf;
		u8 lpc2 = (lt->pc2stat >> (i * 2)) & 0x3;
		u8 lpre = (lane & 0x0c) >> 2;
		u8 lvsw = (lane & 0x03) >> 0;
		u8 hivs = 3 - lpre;
		u8 hipe = 3;
		u8 hipc = 3;

		if (lpc2 >= hipc)
			lpc2 = hipc | DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED;
		if (lpre >= hipe) {
			lpre = hipe | DPCD_LC03_MAX_SWING_REACHED; /* yes. */
			lvsw = hivs = 3 - (lpre & 3);
		} else
		if (lvsw >= hivs) {
			lvsw = hivs | DPCD_LC03_MAX_SWING_REACHED;
		}

		lt->conf[i] = (lpre << 3) | lvsw;
		lt->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4);

		OUTP_TRACE(outp, "config lane %d %02x %02x", i, lt->conf[i], lpc2);

Annotation

Implementation Notes