drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
Extension
.c
Size
18588 bytes
Lines
642
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_ramseq {
	struct hwsq base;
	struct hwsq_reg r_0x002504;
	struct hwsq_reg r_0x004008;
	struct hwsq_reg r_0x00400c;
	struct hwsq_reg r_0x00c040;
	struct hwsq_reg r_0x100200;
	struct hwsq_reg r_0x100210;
	struct hwsq_reg r_0x10021c;
	struct hwsq_reg r_0x1002d0;
	struct hwsq_reg r_0x1002d4;
	struct hwsq_reg r_0x1002dc;
	struct hwsq_reg r_0x10053c;
	struct hwsq_reg r_0x1005a0;
	struct hwsq_reg r_0x1005a4;
	struct hwsq_reg r_0x100710;
	struct hwsq_reg r_0x100714;
	struct hwsq_reg r_0x100718;
	struct hwsq_reg r_0x10071c;
	struct hwsq_reg r_0x100da0;
	struct hwsq_reg r_0x100e20;
	struct hwsq_reg r_0x100e24;
	struct hwsq_reg r_0x611200;
	struct hwsq_reg r_timing[9];
	struct hwsq_reg r_mr[4];
	struct hwsq_reg r_gpio[4];
};

struct nv50_ram {
	struct nvkm_ram base;
	struct nv50_ramseq hwsq;
};

#define T(t) cfg->timing_10_##t
static int
nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing)
{
	struct nvbios_ramcfg *cfg = &ram->base.target.bios;
	struct nvkm_subdev *subdev = &ram->base.fb->subdev;
	struct nvkm_device *device = subdev->device;
	u32 cur2, cur4, cur7, cur8;
	u8 unkt3b;

	cur2 = nvkm_rd32(device, 0x100228);
	cur4 = nvkm_rd32(device, 0x100230);
	cur7 = nvkm_rd32(device, 0x10023c);
	cur8 = nvkm_rd32(device, 0x100240);

	switch ((!T(CWL)) * ram->base.type) {
	case NVKM_RAM_TYPE_DDR2:
		T(CWL) = T(CL) - 1;
		break;
	case NVKM_RAM_TYPE_GDDR3:
		T(CWL) = ((cur2 & 0xff000000) >> 24) + 1;
		break;
	}

	/* XXX: N=1 is not proper statistics */
	if (device->chipset == 0xa0) {
		unkt3b = 0x19 + ram->base.next->bios.rammap_00_16_40;
		timing[6] = (0x2d + T(CL) - T(CWL) +
				ram->base.next->bios.rammap_00_16_40) << 16 |
			    T(CWL) << 8 |
			    (0x2f + T(CL) - T(CWL));
	} else {
		unkt3b = 0x16;
		timing[6] = (0x2b + T(CL) - T(CWL)) << 16 |
			    max_t(s8, T(CWL) - 2, 1) << 8 |
			    (0x2e + T(CL) - T(CWL));
	}

	timing[0] = (T(RP) << 24 | T(RAS) << 16 | T(RFC) << 8 | T(RC));
	timing[1] = (T(WR) + 1 + T(CWL)) << 24 |
		    max_t(u8, T(18), 1) << 16 |
		    (T(WTR) + 1 + T(CWL)) << 8 |
		    (3 + T(CL) - T(CWL));
	timing[2] = (T(CWL) - 1) << 24 |
		    (T(RRD) << 16) |
		    (T(RCDWR) << 8) |
		    T(RCDRD);
	timing[3] = (unkt3b - 2 + T(CL)) << 24 |
		    unkt3b << 16 |
		    (T(CL) - 1) << 8 |
		    (T(CL) - 1);
	timing[4] = (cur4 & 0xffff0000) |
		    T(13) << 8 |
		    T(13);
	timing[5] = T(RFC) << 24 |
		    max_t(u8, T(RCDRD), T(RCDWR)) << 16 |
		    T(RP);

Annotation

Implementation Notes