drm/nouveau: Parse old style perf tables.
authorFrancisco Jerez <currojerez@riseup.net>
Mon, 20 Sep 2010 14:18:28 +0000 (16:18 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 24 Sep 2010 06:28:12 +0000 (16:28 +1000)
Used on nv17-nv28, they contain memory clocks and timings, only one of
the table entries can actually be used, depending on the RAMCFG
straps, and it's usually higher than the frequency programmed on boot
by the BIOS.

The memory timings listed in table version 0x1x are used to init the
0x12xx range but they aren't required for reclocking to work.

Signed-off-by: Francisco Jerez <currojerez@riseup.net>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_pm.c

index a397420e46c68501dcb7167830defc75293c5955..00f8243c6c7385dc73d61ee430bfb5ac57fdb328 100644 (file)
 #include "nouveau_drv.h"
 #include "nouveau_pm.h"
 
+static void
+legacy_perf_init(struct drm_device *dev)
+{
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nvbios *bios = &dev_priv->vbios;
+       struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
+       char *perf, *entry, *bmp = &bios->data[bios->offset];
+       int headerlen, use_straps;
+
+       if (bmp[5] < 0x5 || bmp[6] < 0x14) {
+               NV_DEBUG(dev, "BMP version too old for perf\n");
+               return;
+       }
+
+       perf = ROMPTR(bios, bmp[0x73]);
+       if (!perf) {
+               NV_DEBUG(dev, "No memclock table pointer found.\n");
+               return;
+       }
+
+       switch (perf[0]) {
+       case 0x12:
+       case 0x14:
+       case 0x18:
+               use_straps = 0;
+               headerlen = 1;
+               break;
+       case 0x01:
+               use_straps = perf[1] & 1;
+               headerlen = (use_straps ? 8 : 2);
+               break;
+       default:
+               NV_WARN(dev, "Unknown memclock table version %x.\n", perf[0]);
+               return;
+       }
+
+       entry = perf + headerlen;
+       if (use_straps)
+               entry += (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1;
+
+       sprintf(pm->perflvl[0].name, "performance_level_0");
+       pm->perflvl[0].memory = ROM16(entry[0]) * 20;
+       pm->nr_perflvl = 1;
+}
+
 void
 nouveau_perf_init(struct drm_device *dev)
 {
@@ -59,7 +104,7 @@ nouveau_perf_init(struct drm_device *dev)
                }
        } else {
                if (bios->data[bios->offset + 6] < 0x27) {
-                       NV_DEBUG(dev, "BMP version too old for perf\n");
+                       legacy_perf_init(dev);
                        return;
                }
 
index 4e92d215f05dc073e251d69da0bf1007ff431f1b..a07f27447cf9bc66ee5ff014cd5f726a4aae7101 100644 (file)
@@ -148,7 +148,11 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
 static void
 nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
 {
-       char s[16], v[16], f[16];
+       char c[16], s[16], v[16], f[16];
+
+       c[0] = '\0';
+       if (perflvl->core)
+               snprintf(c, sizeof(c), " core %dMHz", perflvl->core / 1000);
 
        s[0] = '\0';
        if (perflvl->shader)
@@ -162,8 +166,8 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
        if (perflvl->fanspeed)
                snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
 
-       snprintf(ptr, len, "core %dMHz memory %dMHz%s%s%s\n",
-                perflvl->core / 1000, perflvl->memory / 1000, s, v, f);
+       snprintf(ptr, len, "memory %dMHz%s%s%s%s\n", perflvl->memory / 1000,
+                c, s, v, f);
 }
 
 static ssize_t