summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
diff options
context:
space:
mode:
authorRoy Spliet <rspliet@eclipso.eu>2015-09-30 00:23:49 +0100
committerBen Skeggs <bskeggs@redhat.com>2015-11-03 15:02:18 +1000
commit797eb6ed8f13bb2f88bd605515990ef795a1eff7 (patch)
tree5007e058b077e606830e8c1af427da5a5ae75ce1 /drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
parent1cf688dd1b6f8f3ab998000e0f14b37041c77e30 (diff)
downloadlinux-797eb6ed8f13bb2f88bd605515990ef795a1eff7.tar.bz2
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: Roy Spliet <rspliet@eclipso.eu> Tested-by: Pierre Moreau <pierre.morrow@free.fr> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c')
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
index ae6b0c4043d3..1c6ae6bcd573 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c
@@ -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,10 +274,11 @@ 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);
}
- nv50_ram_timing_calc(ram, timing);
-
ret = ram_init(hwsq, subdev);
if (ret)
return 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);