From 797eb6ed8f13bb2f88bd605515990ef795a1eff7 Mon Sep 17 00:00:00 2001 From: Roy Spliet Date: Wed, 30 Sep 2015 00:23:49 +0100 Subject: [PATCH] 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 Tested-by: Pierre Moreau Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | 10 +++--- drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | 41 ++++++++++++++++++++++-- drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c | 6 ++++ 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 79b523aa52aa..60ece0a8a2e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c @@ -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); 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); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c index 86bf67456b14..b9f1ffdfc602 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c @@ -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) -- 2.11.0