drm/nv50: hopefully handle the DDR2/DDR3 memtype detection somewhat better
authorBen Skeggs <bskeggs@redhat.com>
Tue, 13 Dec 2011 01:57:55 +0000 (11:57 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 13 Mar 2012 07:05:46 +0000 (17:05 +1000)
M version 2 appears to have a table with some form of memory type info
available.

NVIDIA appear to ignore the table information except for this DDR2/DDR3
case (which has the same value in 0x100714).  My guess is this is due to
some of the supported memory types not being represented in the table.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_drv.h
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nv50_vram.c

index 59031d308fccd7bbff86de5e80e5a69175d3cc17..5a4947919f1ce7ff1f577a95fb4d70f567823a75 100644 (file)
@@ -909,6 +909,7 @@ extern int  nouveau_mem_init_agp(struct drm_device *);
 extern int  nouveau_mem_reset_agp(struct drm_device *);
 extern void nouveau_mem_close(struct drm_device *);
 extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
+extern int nouveau_mem_vbios_type(struct drm_device *);
 extern struct nouveau_tile_reg *nv10_mem_set_tiling(
        struct drm_device *dev, uint32_t addr, uint32_t size,
        uint32_t pitch, uint32_t flags);
index 4a658310c29a3c01dd035ddd09f9cdae2aee4f97..c5ba6c2eab883b1f36ea9c575ea3149fdba3ab91 100644 (file)
@@ -683,6 +683,29 @@ nouveau_mem_timing_fini(struct drm_device *dev)
        }
 }
 
+int
+nouveau_mem_vbios_type(struct drm_device *dev)
+{
+       struct bit_entry M;
+       u8 ramcfg = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2;
+       if (!bit_table(dev, 'M', &M) || M.version != 2 || M.length < 5) {
+               u8 *table = ROMPTR(dev, M.data[3]);
+               if (table && table[0] == 0x10 && ramcfg < table[3]) {
+                       u8 *entry = table + table[1] + (ramcfg * table[2]);
+                       switch (entry[0] & 0x0f) {
+                       case 0: return NV_MEM_TYPE_DDR2;
+                       case 1: return NV_MEM_TYPE_DDR3;
+                       case 2: return NV_MEM_TYPE_GDDR3;
+                       case 3: return NV_MEM_TYPE_GDDR5;
+                       default:
+                               break;
+                       }
+
+               }
+       }
+       return NV_MEM_TYPE_UNKNOWN;
+}
+
 static int
 nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
 {
index 84069669461187d88f6787149125080fd57a8a69..1467efc6d61dea2dc43bc75fed59399efd9e2054 100644 (file)
@@ -195,10 +195,10 @@ nv50_vram_init(struct drm_device *dev)
        switch (pfb714 & 0x00000007) {
        case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
        case 1:
-               if (0 /* some currently unknown condition */)
-                       dev_priv->vram_type = NV_MEM_TYPE_DDR2;
-               else
+               if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3)
                        dev_priv->vram_type = NV_MEM_TYPE_DDR3;
+               else
+                       dev_priv->vram_type = NV_MEM_TYPE_DDR2;
                break;
        case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
        case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break;