From 0fbb114af7ea63227599460c412fb8796556a169 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Mon, 20 Sep 2010 16:18:28 +0200 Subject: [PATCH] drm/nouveau: Parse old style perf tables. 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 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_perf.c | 47 +++++++++++++++++++++++++++++++++- drivers/gpu/drm/nouveau/nouveau_pm.c | 10 +++++--- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index a397420..00f8243 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -27,6 +27,51 @@ #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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 4e92d21..a07f274 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -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 -- 2.7.4