[Nouveau] [PATCH 02/11] nvkm/ramgf100: Calculate timings
Roy Spliet
nouveau at spliet.org
Mon Apr 10 19:37:19 UTC 2017
Todo:
- Determine source of R[10f298] & 0x11
Signed-off-by: Roy Spliet <nouveau at spliet.org>
---
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c | 115 ++++++++++++++--------
1 file changed, 76 insertions(+), 39 deletions(-)
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);
--
2.9.3
More information about the Nouveau
mailing list