drm/nouveau/bios: translate ramcfg strap through M0203
authorBen Skeggs <bskeggs@redhat.com>
Tue, 4 Nov 2014 05:13:30 +0000 (15:13 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 2 Dec 2014 05:44:06 +0000 (15:44 +1000)
A machine has been spotted where the ramcfg strap is "8", and the ramcfg
xlat table goes 0-7,0-7, resulting in us selecting config 0 for memory
items.  On this particular system, config "8" is available and supposed
to be used.  It appears that starting from GT21x (where Mv2 appears),
we're supposed to use the value in this table instead.

One concern here is that not all the places we currently use ramcfg xlat
are supposed to be treated the same now.  The strap xlat table wasn't
removed from the vbios either, presumably for some kind of good reason.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/subdev/bios/ramcfg.c

index 6c401f70ab99ae380b6c614983a997a9244a97d9..1623c8dfe797362042efddb17bb1e827e13cd6b7 100644 (file)
@@ -25,6 +25,7 @@
 #include <subdev/bios.h>
 #include <subdev/bios/bit.h>
 #include <subdev/bios/ramcfg.h>
+#include <subdev/bios/M0203.h>
 
 static u8
 nvbios_ramcfg_strap(struct nouveau_subdev *subdev)
@@ -54,12 +55,22 @@ nvbios_ramcfg_index(struct nouveau_subdev *subdev)
        u8 strap = nvbios_ramcfg_strap(subdev);
        u32 xlat = 0x00000000;
        struct bit_entry bit_M;
+       struct nvbios_M0203E M0203E;
+       u8 ver, hdr;
 
        if (!bit_entry(bios, 'M', &bit_M)) {
                if (bit_M.version == 1 && bit_M.length >= 5)
                        xlat = nv_ro16(bios, bit_M.offset + 3);
-               if (bit_M.version == 2 && bit_M.length >= 3)
+               if (bit_M.version == 2 && bit_M.length >= 3) {
+                       /*XXX: is M ever shorter than this?
+                        *     if not - what is xlat used for now?
+                        *     also - sigh..
+                        */
+                       if (bit_M.length >= 7 &&
+                           nvbios_M0203Em(bios, strap, &ver, &hdr, &M0203E))
+                               return M0203E.group;
                        xlat = nv_ro16(bios, bit_M.offset + 1);
+               }
        }
 
        if (xlat)