drm/nouveau/bios: cache ramcfg strap on later chipsets
authorBen Skeggs <bskeggs@redhat.com>
Wed, 19 Dec 2012 21:48:51 +0000 (07:48 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Sun, 23 Dec 2012 12:59:30 +0000 (22:59 +1000)
This fixes suspend/resume on at least Quadro 400.

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

index e69a8bdc6e97371072476b28c682a9d8f0427612..ca2f6bf37f46228d5e0b4f496c4ad78110adaf2d 100644 (file)
@@ -13,6 +13,7 @@ struct nvbios_init {
        u32 nested;
        u16 repeat;
        u16 repend;
+       u32 ramcfg;
 };
 
 int nvbios_exec(struct nvbios_init *);
index 98f78cf318b0eb297c7a01dba4d94e516f57bdae..2917d552689bca84e3c3dde8f059abdd9b80ebda 100644 (file)
@@ -410,10 +410,26 @@ init_ram_restrict_group_count(struct nvbios_init *init)
        return 0x00;
 }
 
+static u8
+init_ram_restrict_strap(struct nvbios_init *init)
+{
+       /* This appears to be the behaviour of the VBIOS parser, and *is*
+        * important to cache the NV_PEXTDEV_BOOT0 on later chipsets to
+        * avoid fucking up the memory controller (somehow) by reading it
+        * on every INIT_RAM_RESTRICT_ZM_GROUP opcode.
+        *
+        * Preserving the non-caching behaviour on earlier chipsets just
+        * in case *not* re-reading the strap causes similar breakage.
+        */
+       if (!init->ramcfg || init->bios->version.major < 0x70)
+               init->ramcfg = init_rd32(init, 0x101000);
+       return (init->ramcfg & 0x00000003c) >> 2;
+}
+
 static u8
 init_ram_restrict(struct nvbios_init *init)
 {
-       u32 strap = (init_rd32(init, 0x101000) & 0x0000003c) >> 2;
+       u8  strap = init_ram_restrict_strap(init);
        u16 table = init_ram_restrict_table(init);
        if (table)
                return nv_ro08(init->bios, table + strap);