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

Commit 797eb6ed authored by Roy Spliet's avatar Roy Spliet Committed by Ben Skeggs
Browse files

drm/nouveau/fb/ramnv50: Deal with cards without timing entries



Like Pierre's G94. We might want to structure Kepler similarly in a follow-up.

Signed-off-by: default avatarRoy Spliet <rspliet@eclipso.eu>
Tested-by: default avatarPierre Moreau <pierre.morrow@free.fr>
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent 1cf688dd
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ ramgddr3_wr_lo[] = {
	{ 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 },
	{ 11, 0 }, { 13 , 1 },
	/* the below are mentioned in some, but not all, gddr3 docs */
	{ 4, 1 }, { 6, 3 }, { 12, 1 },
	{ 4, 0 }, { 6, 3 }, { 12, 1 },
	{ -1 }
};

@@ -87,15 +87,17 @@ nvkm_gddr3_calc(struct nvkm_ram *ram)
		WR  = (ram->next->bios.timing[2] & 0x007f0000) >> 16;
		/* XXX: Get these values from the VBIOS instead */
		DLL = !(ram->mr[1] & 0x1);
		ODT =  (ram->mr[1] & 0x004) >> 2 |
		       (ram->mr[1] & 0x040) >> 5 |
		       (ram->mr[1] & 0x200) >> 7;
		RON = !(ram->mr[1] & 0x300) >> 8;
		break;
	default:
		return -ENOSYS;
	}

	if (ram->next->bios.timing_ver == 0x20 ||
	    ram->next->bios.ramcfg_timing == 0xff) {
		ODT =  (ram->mr[1] & 0xc) >> 2;
	}

	hi = ram->mr[2] & 0x1;
	CL  = ramxlat(hi ? ramgddr3_cl_hi : ramgddr3_cl_lo, CL);
	WR  = ramxlat(ramgddr3_wr_lo, WR);
+38 −3
Original line number Diff line number Diff line
@@ -146,6 +146,38 @@ nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing)
	nvkm_debug(subdev, " 240: %08x\n", timing[8]);
	return 0;
}

static int
nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing)
{
	unsigned int i;
	struct nvbios_ramcfg *cfg = &ram->base.target.bios;
	struct nvkm_subdev *subdev = &ram->base.fb->subdev;
	struct nvkm_device *device = subdev->device;

	for (i = 0; i <= 8; i++)
		timing[i] = nvkm_rd32(device, 0x100220 + (i * 4));

	/* Derive the bare minimum for the MR calculation to succeed */
	cfg->timing_ver = 0x10;
	T(CL) = (timing[3] & 0xff) + 1;

	switch (ram->base.type) {
	case NVKM_RAM_TYPE_DDR2:
		T(CWL) = T(CL) - 1;
		break;
	case NVKM_RAM_TYPE_GDDR3:
		T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1;
		break;
	default:
		return -ENOSYS;
		break;
	}

	T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL);

	return 0;
}
#undef T

static void
@@ -242,9 +274,10 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
				 strap, data, ver, hdr);
			return -EINVAL;
		}
	}

		nv50_ram_timing_calc(ram, timing);
	} else {
		nv50_ram_timing_read(ram, timing);
	}

	ret = ram_init(hwsq, subdev);
	if (ret)
@@ -264,8 +297,10 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
		break;
	}

	if (ret)
	if (ret) {
		nvkm_error(subdev, "Could not calculate MR\n");
		return ret;
	}

	/* Always disable this bit during reclock */
	ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000);
+6 −0
Original line number Diff line number Diff line
@@ -76,6 +76,12 @@ nvkm_sddr2_calc(struct nvkm_ram *ram)
		return -ENOSYS;
	}

	if (ram->next->bios.timing_ver == 0x20 ||
	    ram->next->bios.ramcfg_timing == 0xff) {
		ODT =  (ram->mr[1] & 0x004) >> 2 |
		       (ram->mr[1] & 0x040) >> 5;
	}

	CL  = ramxlat(ramddr2_cl, CL);
	WR  = ramxlat(ramddr2_wr, WR);
	if (CL < 0 || WR < 0)