]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
drm/nouveau: correct memtiming table parsing for nv4x
authorRoy Spliet <r.spliet@student.tudelft.nl>
Wed, 9 Feb 2011 13:56:42 +0000 (14:56 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 5 Apr 2011 01:06:11 +0000 (11:06 +1000)
In line with envytools, verified on 4 or 5 BIOS'es.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: Roy Spliet <r.spliet@student.tudelft.nl>
drivers/gpu/drm/nouveau/nouveau_mem.c

index 2683377f4131ed73b29a9d57282c04fab8874246..78f467fe30be2524e8ee9b4ecc2f654619ec7577 100644 (file)
@@ -552,6 +552,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
        u8 tRC;         /* Byte 9 */
        u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
        u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
+       u8 magic_number = 0; /* Yeah... sorry*/
        u8 *mem = NULL, *entry;
        int i, recordlen, entries;
 
@@ -596,6 +597,12 @@ nouveau_mem_timing_init(struct drm_device *dev)
        if (!memtimings->timing)
                return;
 
+       /* Get "some number" from the timing reg for NV_40
+        * Used in calculations later */
+       if(dev_priv->card_type == NV_40) {
+               magic_number = (nv_rd32(dev,0x100228) & 0x0f000000) >> 24;
+       }
+
        entry = mem + mem[1];
        for (i = 0; i < entries; i++, entry += recordlen) {
                struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
@@ -635,36 +642,51 @@ nouveau_mem_timing_init(struct drm_device *dev)
 
                /* XXX: I don't trust the -1's and +1's... they must come
                 *      from somewhere! */
-               timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 |
+               timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
                                      tUNK_18 << 16 |
-                                     (tUNK_1 + tUNK_19 + 1) << 8 |
-                                     (tUNK_2 - 1));
+                                     (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
+               if(dev_priv->chipset == 0xa8) {
+                       timing->reg_100224 |= (tUNK_2 - 1);
+               } else {
+                       timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
+               }
 
                timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
-               if(recordlen > 19) {
-                       timing->reg_100228 += (tUNK_19 - 1) << 24;
-               }/* I cannot back-up this else-statement right now
-                        else {
-                       timing->reg_100228 += tUNK_12 << 24;
-               }*/
-
-               /* XXX: reg_10022c */
-               timing->reg_10022c = tUNK_2 - 1;
-
-               timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
-                                     tUNK_13 << 8  | tUNK_13);
-
-               /* XXX: +6? */
-               timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
-               timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
-
-               /* XXX; reg_100238, reg_10023c
-                * reg: 0x00??????
-                * reg_10023c:
-                *      0 for pre-NV50 cards
-                *      0x????0202 for NV50+ cards (empirical evidence) */
-               if(dev_priv->card_type >= NV_50) {
+               if(dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) {
+                       timing->reg_100228 |= (tUNK_19 - 1) << 24;
+               }
+
+               if(dev_priv->card_type == NV_40) {
+                       /* NV40: don't know what the rest of the regs are..
+                        * And don't need to know either */
+                       timing->reg_100228 |= 0x20200000 | magic_number << 24;
+               } else if(dev_priv->card_type >= NV_50) {
+                       /* XXX: reg_10022c */
+                       timing->reg_10022c = tUNK_2 - 1;
+
+                       timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
+                                                 tUNK_13 << 8  | tUNK_13);
+
+                       timing->reg_100234 = (tRAS << 24 | tRC);
+                       timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
+
+                       if(dev_priv->chipset < 0xa3) {
+                               timing->reg_100234 |= (tUNK_2 + 2) << 8;
+                       } else {
+                               /* XXX: +6? */
+                               timing->reg_100234 |= (tUNK_19 + 6) << 8;
+                       }
+
+                       /* XXX; reg_100238, reg_10023c
+                        * reg_100238: 0x00??????
+                        * reg_10023c: 0x!!??0202 for NV50+ cards (empirical evidence) */
                        timing->reg_10023c = 0x202;
+                       if(dev_priv->chipset < 0xa3) {
+                               timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
+                       } else {
+                               /* currently unknown
+                                * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
+                       }
                }
 
                NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
@@ -675,7 +697,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
                         timing->reg_100238, timing->reg_10023c);
        }
 
-       memtimings->nr_timing  = entries;
+       memtimings->nr_timing = entries;
        memtimings->supported = true;
 }