summaryrefslogtreecommitdiff
path: root/nvkm/subdev/fb/ramnva3.c
diff options
context:
space:
mode:
Diffstat (limited to 'nvkm/subdev/fb/ramnva3.c')
-rw-r--r--nvkm/subdev/fb/ramnva3.c84
1 files changed, 74 insertions, 10 deletions
diff --git a/nvkm/subdev/fb/ramnva3.c b/nvkm/subdev/fb/ramnva3.c
index 45e8a91f8..07dfbba3f 100644
--- a/nvkm/subdev/fb/ramnva3.c
+++ b/nvkm/subdev/fb/ramnva3.c
@@ -343,6 +343,66 @@ nva3_link_train_fini(struct nouveau_fb *pfb)
pfb->ram->put(pfb, &ram->ltrain.mem);
}
+/*
+ * RAM reclocking
+ */
+#define T(t) cfg->timing_10_##t
+static int
+nva3_ram_timing_calc(struct nouveau_fb *pfb, u32 *timing)
+{
+ struct nva3_ram *ram = (void *)pfb->ram;
+ struct nvbios_ramcfg *cfg = &ram->base.target.bios;
+ int tUNK_base;
+ u32 cur3, cur7, cur8;
+
+ cur3 = nv_rd32(pfb, 0x10022c);
+ cur7 = nv_rd32(pfb, 0x10023c);
+ cur8 = nv_rd32(pfb, 0x100240);
+
+ if (T(CWL) == 0)
+ T(CWL) = ((nv_rd32(pfb, 0x100228) & 0x0f000000) >> 24) + 1;
+
+ tUNK_base = ((cur7 & 0x00ff0000) >> 16) -
+ (cur3 & 0x000000ff) - 1;
+
+ 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 |
+ (5 + T(CL) - T(CWL));
+ timing[2] = (T(CWL) - 1) << 24 |
+ (T(RRD) << 16) |
+ (T(RCDWR) << 8) |
+ T(RCDRD);
+ timing[3] = (cur3 & 0x00ff0000) |
+ (0x30 + T(CL)) << 24 |
+ (0xb + T(CL)) << 8 |
+ (T(CL) - 1);
+ timing[4] = T(20) << 24 |
+ T(21) << 16 |
+ T(13) << 8 |
+ T(13);
+ timing[5] = T(RFC) << 24 |
+ max_t(u8,T(RCDRD), T(RCDWR)) << 16 |
+ (T(CWL) + 6) << 8 |
+ T(RP);
+ timing[6] = (0x5a + T(CL)) << 16 |
+ (6 - T(CL) + T(CWL)) << 8 |
+ (0x50 + T(CL) - T(CWL));
+ timing[7] = (cur7 & 0xff000000) |
+ ((tUNK_base + T(CL)) << 16) |
+ 0x202;
+ timing[8] = cur8 & 0xffffff00;
+
+ nv_debug(pfb, "Entry: 220: %08x %08x %08x %08x\n",
+ timing[0], timing[1], timing[2], timing[3]);
+ nv_debug(pfb, " 230: %08x %08x %08x %08x\n",
+ timing[4], timing[5], timing[6], timing[7]);
+ nv_debug(pfb, " 240: %08x\n", timing[8]);
+ return 0;
+}
+#undef T
+
static int
nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
{
@@ -356,6 +416,7 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
u32 r004018, r100760, ctrl;
u32 unk714, unk718, unk71c;
int ret, i;
+ u32 timing[9];
next = &ram->base.target;
next->freq = freq;
@@ -409,6 +470,8 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
return ret;
}
+ nva3_ram_timing_calc(pfb, timing);
+
ret = ram_init(fuc, pfb);
if (ret)
return ret;
@@ -519,16 +582,17 @@ nva3_ram_calc(struct nouveau_fb *pfb, u32 freq)
ram_mask(fuc, mr[0], 0x00000000, 0x00000000);
ram_nsec(fuc, 1000);
- ram_mask(fuc, 0x100220[3], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[1], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[6], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[7], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[2], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[4], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[5], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[0], 0x00000000, 0x00000000);
- ram_mask(fuc, 0x100220[8], 0x00000000, 0x00000000);
-
+ ram_wr32(fuc, 0x100220[3], timing[3]);
+ ram_wr32(fuc, 0x100220[1], timing[1]);
+ ram_wr32(fuc, 0x100220[6], timing[6]);
+ ram_wr32(fuc, 0x100220[7], timing[7]);
+ ram_wr32(fuc, 0x100220[2], timing[2]);
+ ram_wr32(fuc, 0x100220[4], timing[4]);
+ ram_wr32(fuc, 0x100220[5], timing[5]);
+ ram_wr32(fuc, 0x100220[0], timing[0]);
+ ram_wr32(fuc, 0x100220[8], timing[8]);
+
+ /* Misc */
ram_mask(fuc, 0x100200, 0x00001000, !next->bios.ramcfg_10_02_08 << 12);
unk714 = ram_rd32(fuc, 0x100714) & ~0xf0000010;