提交 e614b2e7 编写于 作者: M Martin Peres 提交者: Ben Skeggs

drm/nouveau: Associate memtimings with performance levels on cards <= nv98

v2 (Ben Skeggs): fix ramcfg strap, and remove bogus handling of perf 0x40
Signed-off-by: NMartin Peres <martin.peres@ensi-bourges.fr>
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 dac55b58
...@@ -410,6 +410,19 @@ struct nouveau_pm_voltage { ...@@ -410,6 +410,19 @@ struct nouveau_pm_voltage {
int nr_level; int nr_level;
}; };
struct nouveau_pm_memtiming {
int id;
u32 reg_100220;
u32 reg_100224;
u32 reg_100228;
u32 reg_10022c;
u32 reg_100230;
u32 reg_100234;
u32 reg_100238;
u32 reg_10023c;
u32 reg_100240;
};
#define NOUVEAU_PM_MAX_LEVEL 8 #define NOUVEAU_PM_MAX_LEVEL 8
struct nouveau_pm_level { struct nouveau_pm_level {
struct device_attribute dev_attr; struct device_attribute dev_attr;
...@@ -425,6 +438,7 @@ struct nouveau_pm_level { ...@@ -425,6 +438,7 @@ struct nouveau_pm_level {
u8 fanspeed; u8 fanspeed;
u16 memscript; u16 memscript;
struct nouveau_pm_memtiming *timing;
}; };
struct nouveau_pm_temp_sensor_constants { struct nouveau_pm_temp_sensor_constants {
...@@ -441,18 +455,6 @@ struct nouveau_pm_threshold_temp { ...@@ -441,18 +455,6 @@ struct nouveau_pm_threshold_temp {
s16 fan_boost; s16 fan_boost;
}; };
struct nouveau_pm_memtiming {
u32 reg_100220;
u32 reg_100224;
u32 reg_100228;
u32 reg_10022c;
u32 reg_100230;
u32 reg_100234;
u32 reg_100238;
u32 reg_10023c;
u32 reg_100240;
};
struct nouveau_pm_memtimings { struct nouveau_pm_memtimings {
bool supported; bool supported;
struct nouveau_pm_memtiming *timing; struct nouveau_pm_memtiming *timing;
......
...@@ -704,6 +704,7 @@ nouveau_mem_timing_init(struct drm_device *dev) ...@@ -704,6 +704,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
/* XXX: reg_100240? */ /* XXX: reg_100240? */
} }
timing->id = i;
NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
timing->reg_100220, timing->reg_100224, timing->reg_100220, timing->reg_100224,
...@@ -715,7 +716,7 @@ nouveau_mem_timing_init(struct drm_device *dev) ...@@ -715,7 +716,7 @@ nouveau_mem_timing_init(struct drm_device *dev)
} }
memtimings->nr_timing = entries; memtimings->nr_timing = entries;
memtimings->supported = true; memtimings->supported = (dev_priv->chipset <= 0x98);
} }
void void
......
...@@ -82,6 +82,7 @@ nouveau_perf_init(struct drm_device *dev) ...@@ -82,6 +82,7 @@ nouveau_perf_init(struct drm_device *dev)
u8 version, headerlen, recordlen, entries; u8 version, headerlen, recordlen, entries;
u8 *perf, *entry; u8 *perf, *entry;
int vid, i; int vid, i;
u8 ramcfg = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 2;
if (bios->type == NVBIOS_BIT) { if (bios->type == NVBIOS_BIT) {
if (bit_table(dev, 'P', &P)) if (bit_table(dev, 'P', &P))
...@@ -124,6 +125,8 @@ nouveau_perf_init(struct drm_device *dev) ...@@ -124,6 +125,8 @@ nouveau_perf_init(struct drm_device *dev)
for (i = 0; i < entries; i++) { for (i = 0; i < entries; i++) {
struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
perflvl->timing = NULL;
if (entry[0] == 0xff) { if (entry[0] == 0xff) {
entry += recordlen; entry += recordlen;
continue; continue;
...@@ -190,6 +193,22 @@ nouveau_perf_init(struct drm_device *dev) ...@@ -190,6 +193,22 @@ nouveau_perf_init(struct drm_device *dev)
} }
} }
/* get the corresponding memory timings */
if (pm->memtimings.supported) {
u8 timing_id = 0xff;
u16 extra_data;
if (version > 0x15 && version < 0x40 &&
ramcfg < perf[4]) {
extra_data = perf[3] + (ramcfg * perf[5]);
timing_id = entry[extra_data + 1];
}
if (pm->memtimings.nr_timing > timing_id)
perflvl->timing =
&pm->memtimings.timing[timing_id];
}
snprintf(perflvl->name, sizeof(perflvl->name), snprintf(perflvl->name, sizeof(perflvl->name),
"performance_level_%d", i); "performance_level_%d", i);
perflvl->id = i; perflvl->id = i;
......
...@@ -156,7 +156,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) ...@@ -156,7 +156,7 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
static void static void
nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
{ {
char c[16], s[16], v[16], f[16]; char c[16], s[16], v[16], f[16], t[16];
c[0] = '\0'; c[0] = '\0';
if (perflvl->core) if (perflvl->core)
...@@ -174,8 +174,12 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len) ...@@ -174,8 +174,12 @@ nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
if (perflvl->fanspeed) if (perflvl->fanspeed)
snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed); snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
snprintf(ptr, len, "memory %dMHz%s%s%s%s\n", perflvl->memory / 1000, t[0] = '\0';
c, s, v, f); if (perflvl->timing)
snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
snprintf(ptr, len, "memory %dMHz%s%s%s%s%s\n", perflvl->memory / 1000,
c, s, v, f, t);
} }
static ssize_t static ssize_t
...@@ -476,10 +480,10 @@ nouveau_pm_init(struct drm_device *dev) ...@@ -476,10 +480,10 @@ nouveau_pm_init(struct drm_device *dev)
char info[256]; char info[256];
int ret, i; int ret, i;
nouveau_mem_timing_init(dev);
nouveau_volt_init(dev); nouveau_volt_init(dev);
nouveau_perf_init(dev); nouveau_perf_init(dev);
nouveau_temp_init(dev); nouveau_temp_init(dev);
nouveau_mem_timing_init(dev);
NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
for (i = 0; i < pm->nr_perflvl; i++) { for (i = 0; i < pm->nr_perflvl; i++) {
...@@ -525,10 +529,10 @@ nouveau_pm_fini(struct drm_device *dev) ...@@ -525,10 +529,10 @@ nouveau_pm_fini(struct drm_device *dev)
if (pm->cur != &pm->boot) if (pm->cur != &pm->boot)
nouveau_pm_perflvl_set(dev, &pm->boot); nouveau_pm_perflvl_set(dev, &pm->boot);
nouveau_mem_timing_fini(dev);
nouveau_temp_fini(dev); nouveau_temp_fini(dev);
nouveau_perf_fini(dev); nouveau_perf_fini(dev);
nouveau_volt_fini(dev); nouveau_volt_fini(dev);
nouveau_mem_timing_fini(dev);
#if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY) #if defined(CONFIG_ACPI) && defined(CONFIG_POWER_SUPPLY)
unregister_acpi_notifier(&pm->acpi_nb); unregister_acpi_notifier(&pm->acpi_nb);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册