[02/11] nvkm/ramgf100: Calculate timings

Submitted by Roy Spliet on April 10, 2017, 7:37 p.m.

Details

Message ID 20170410193728.29026-3-nouveau@spliet.org
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Roy Spliet April 10, 2017, 7:37 p.m.
Todo:
- Determine source of R[10f298] & 0x11

Signed-off-by: Roy Spliet <nouveau@spliet.org>
---
 drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 115 ++++++++++++++--------
 1 file changed, 76 insertions(+), 39 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
index fffd01a..6ebdc4c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
@@ -48,11 +48,7 @@  struct gf100_ramfuc {
 
 	struct ramfuc_reg r_0x137390;
 
-	struct ramfuc_reg r_0x10f290;
-	struct ramfuc_reg r_0x10f294;
-	struct ramfuc_reg r_0x10f298;
-	struct ramfuc_reg r_0x10f29c;
-	struct ramfuc_reg r_0x10f2a0;
+	struct ramfuc_reg r_0x10f290[5];
 
 	struct ramfuc_reg r_0x10f300;
 	struct ramfuc_reg r_0x10f338;
@@ -104,6 +100,50 @@  struct gf100_ram {
 	struct nvbios_pll mempll;
 };
 
+#define T(t) cfg->timing_10_##t
+static int
+gf100_ram_timing_calc(struct gf100_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 cur1, cur2, cur4;
+
+	cur1 = nvkm_rd32(device, 0x10f294);
+	cur2 = nvkm_rd32(device, 0x10f298);
+	cur4 = nvkm_rd32(device, 0x10f2a0);
+
+	/* XXX: (G)DDR3? */
+	switch ((!T(CWL)) * ram->base.type) {
+	case NVKM_RAM_TYPE_GDDR5:
+		T(CWL) = (cur1 & 0x00000380) >> 7;
+		break;
+	}
+
+	timing[0] = (T(RP) << 24 | T(RAS) << 17 | T(RFC) << 8 | T(RC));
+	timing[1] = (cur1 & ~0x03ffc07f) |
+		    (T(RCDWR) << 20) |
+		    (T(RCDRD) << 14) |
+		    (T(CWL) << 7) |
+		    (T(CL));
+	/* XXX: lower 8 bytes are two bits indicating "feature(s) X" */
+	timing[2] = (cur2 & ~0x00ffffff) |
+		    (T(WR) << 16) |
+		    (T(WTR) << 8);
+	timing[3] = (T(FAW)) << 9 |
+		    (T(CKE)) << 5 |
+		    (T(XPDLL));
+	timing[4] = (cur4 & ~0x001f8000) |
+		    (T(RRD) << 15);
+
+	nvkm_debug(subdev, "Entry: 290: %08x %08x %08x %08x\n",
+		   timing[0], timing[1], timing[2], timing[3]);
+	nvkm_debug(subdev, "  2a0: %08x\n",
+		   timing[4]);
+	return 0;
+}
+#undef T
+
 static void
 gf100_ram_train(struct gf100_ramfuc *fuc, u32 magic)
 {
@@ -136,10 +176,11 @@  gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 	struct nvkm_ram_data *next;
 	u8  ver, hdr, cnt, len, strap;
 	u32 data;
+	u32 timing[5];
 	int ref, div, out;
 	int from, mode;
 	int N1, M1, P;
-	int ret;
+	int i, ret;
 
 	next = &ram->base.target;
 	next->freq = freq;
@@ -179,6 +220,8 @@  gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		}
 	}
 
+	gf100_ram_timing_calc(ram, timing);
+
 	ret = ram_init(fuc, ram->base.fb);
 	if (ret)
 		return ret;
@@ -314,28 +357,6 @@  gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		ram_wr32(fuc, 0x10f338, 0x00300220);
 		ram_wr32(fuc, 0x10f300, 0x0000011d);
 		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f290, 0x02060505);
-		ram_wr32(fuc, 0x10f294, 0x34208288);
-		ram_wr32(fuc, 0x10f298, 0x44050411);
-		ram_wr32(fuc, 0x10f29c, 0x0000114c);
-		ram_wr32(fuc, 0x10f2a0, 0x42e10069);
-		ram_wr32(fuc, 0x10f614, 0x40044f77);
-		ram_wr32(fuc, 0x10f610, 0x40044f77);
-		ram_wr32(fuc, 0x10f344, 0x00600009);
-		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f348, 0x00700008);
-		ram_wr32(fuc, 0x61c140, 0x19240000);
-		ram_wr32(fuc, 0x10f830, 0x00300017);
-		gf100_ram_train(fuc, 0x80021001);
-		gf100_ram_train(fuc, 0x80081001);
-		ram_wr32(fuc, 0x10f340, 0x00500004);
-		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f830, 0x01300017);
-		ram_wr32(fuc, 0x10f830, 0x00300017);
-// 0x00030020 // 0x00000000 // 0x00000000
-// 0x00020034 // 0x0000000b
-		ram_wr32(fuc, 0x100b0c, 0x00080028);
-		ram_wr32(fuc, 0x611200, 0x00003330);
 	} else {
 		ram_wr32(fuc, 0x10f800, 0x00001800);
 		ram_wr32(fuc, 0x13d8f4, 0x00000000);
@@ -364,11 +385,30 @@  gf100_ram_calc(struct nvkm_ram *base, u32 freq)
 		ram_wr32(fuc, 0x10f338, 0x00300200);
 		ram_wr32(fuc, 0x10f300, 0x0000084d);
 		ram_nsec(fuc, 1000);
-		ram_wr32(fuc, 0x10f290, 0x0b343825);
-		ram_wr32(fuc, 0x10f294, 0x3483028e);
-		ram_wr32(fuc, 0x10f298, 0x440c0600);
-		ram_wr32(fuc, 0x10f29c, 0x0000214c);
-		ram_wr32(fuc, 0x10f2a0, 0x42e20069);
+	}
+
+	for (i = 0; i < 5; i++)
+		ram_wr32(fuc, 0x10f290[i], timing[i]);
+
+	if (mode == 0) {
+		ram_wr32(fuc, 0x10f614, 0x40044f77);
+		ram_wr32(fuc, 0x10f610, 0x40044f77);
+		ram_wr32(fuc, 0x10f344, 0x00600009);
+		ram_nsec(fuc, 1000);
+		ram_wr32(fuc, 0x10f348, 0x00700008);
+		ram_wr32(fuc, 0x61c140, 0x19240000);
+		ram_wr32(fuc, 0x10f830, 0x00300017);
+		gf100_ram_train(fuc, 0x80021001);
+		gf100_ram_train(fuc, 0x80081001);
+		ram_wr32(fuc, 0x10f340, 0x00500004);
+		ram_nsec(fuc, 1000);
+		ram_wr32(fuc, 0x10f830, 0x01300017);
+		ram_wr32(fuc, 0x10f830, 0x00300017);
+// 0x00030020 // 0x00000000 // 0x00000000
+// 0x00020034 // 0x0000000b
+		ram_wr32(fuc, 0x100b0c, 0x00080028);
+		ram_wr32(fuc, 0x611200, 0x00003330);
+	} else {
 		ram_wr32(fuc, 0x10f200, 0x00ce0000);
 		ram_wr32(fuc, 0x10f614, 0x60044e77);
 		ram_wr32(fuc, 0x10f610, 0x60044e77);
@@ -630,7 +670,7 @@  gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
 	struct nvkm_subdev *subdev = &fb->subdev;
 	struct nvkm_bios *bios = subdev->device->bios;
 	struct gf100_ram *ram;
-	int ret;
+	int i, ret;
 
 	if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL)))
 		return -ENOMEM;
@@ -663,11 +703,8 @@  gf100_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
 
 	ram->fuc.r_0x137390 = ramfuc_reg(0x137390);
 
-	ram->fuc.r_0x10f290 = ramfuc_reg(0x10f290);
-	ram->fuc.r_0x10f294 = ramfuc_reg(0x10f294);
-	ram->fuc.r_0x10f298 = ramfuc_reg(0x10f298);
-	ram->fuc.r_0x10f29c = ramfuc_reg(0x10f29c);
-	ram->fuc.r_0x10f2a0 = ramfuc_reg(0x10f2a0);
+	for (i = 0; i < 5; i++)
+		ram->fuc.r_0x10f290[i] = ramfuc_reg(0x10f290 + (i * 4));
 
 	ram->fuc.r_0x10f300 = ramfuc_reg(0x10f300);
 	ram->fuc.r_0x10f338 = ramfuc_reg(0x10f338);