From ff92a6cda74c0a51cb723f5e224124cf74e62f25 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 12 Dec 2011 23:03:14 +1000 Subject: drm/nv20-nv40: add memory type detection NV20/NV30 is partially educated guesswork at this point, based on any information around about available memory types and a horribly unspeakable amount of vbios image scouring. I'm not entirely certain the GDDR3 define is correct, I have not spotted a single vbios with that value yet (though it is mentioned in some 1218-using nv4x vbios), but there are reports that some nv3x did use it.. NV40(100914) confirmed by switching an NV49 to DDR1/DDR2 values and making sure that the binary driver behaviour showed it had detected DDR1/DDR2 instead of GDDR3 before dying horribly. NV40(100474) confirmed by doing much the same task as above on an NV44, except this was *much* easier as changing the values didn't seem to have any noticable effect on the memory controller aside from changing the binary driver's behaviour. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv40_fb.c | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/gpu/drm/nouveau/nv40_fb.c') diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c index f0ac2a768c67..7fbcb334c096 100644 --- a/drivers/gpu/drm/nouveau/nv40_fb.c +++ b/drivers/gpu/drm/nouveau/nv40_fb.c @@ -71,6 +71,51 @@ nv44_fb_init_gart(struct drm_device *dev) nv_wr32(dev, 0x100800, vinst | 0x00000010); } +int +nv40_fb_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + /* 0x001218 is actually present on a few other NV4X I looked at, + * and even contains sane values matching 0x100474. From looking + * at various vbios images however, this isn't the case everywhere. + * So, I chose to use the same regs I've seen NVIDIA reading around + * the memory detection, hopefully that'll get us the right numbers + */ + if (dev_priv->chipset == 0x40) { + u32 pbus1218 = nv_rd32(dev, 0x001218); + switch (pbus1218 & 0x00000300) { + case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break; + case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + } + } else + if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { + u32 pfb914 = nv_rd32(dev, 0x100914); + switch (pfb914 & 0x00000003) { + case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break; + case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break; + case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break; + case 0x00000003: break; + } + } else + if (dev_priv->chipset != 0x4e) { + u32 pfb474 = nv_rd32(dev, 0x100474); + if (pfb474 & 0x00000004) + dev_priv->vram_type = NV_MEM_TYPE_GDDR3; + if (pfb474 & 0x00000002) + dev_priv->vram_type = NV_MEM_TYPE_DDR2; + if (pfb474 & 0x00000001) + dev_priv->vram_type = NV_MEM_TYPE_DDR1; + } else { + dev_priv->vram_type = NV_MEM_TYPE_STOLEN; + } + + dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000; + return 0; +} + int nv40_fb_init(struct drm_device *dev) { -- cgit v1.2.1