72
72
pm->nr_perflvl = 1;
75
static struct nouveau_pm_memtiming *
76
nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P,
77
u16 memclk, u8 *entry, u8 recordlen, u8 entries)
79
struct drm_nouveau_private *dev_priv = dev->dev_private;
80
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
81
struct nvbios *bios = &dev_priv->vbios;
85
/* perf v2 has a separate "timing map" table, we have to match
86
* the target memory clock to a specific entry, *then* use
87
* ramcfg to select the correct subentry
89
if (P->version == 2) {
90
u8 *tmap = ROMPTR(bios, P->data[4]);
92
NV_DEBUG(dev, "no timing map pointer\n");
96
if (tmap[0] != 0x10) {
97
NV_WARN(dev, "timing map 0x%02x unknown\n", tmap[0]);
101
entry = tmap + tmap[1];
102
recordlen = tmap[2] + (tmap[4] * tmap[3]);
103
for (i = 0; i < tmap[5]; i++, entry += recordlen) {
104
if (memclk >= ROM16(entry[0]) &&
105
memclk <= ROM16(entry[2]))
110
NV_WARN(dev, "no match in timing map table\n");
119
ramcfg = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x0000003c) >> 2;
120
if (bios->ram_restrict_tbl_ptr)
121
ramcfg = bios->data[bios->ram_restrict_tbl_ptr + ramcfg];
123
if (ramcfg >= entries) {
124
NV_WARN(dev, "ramcfg strap out of bounds!\n");
128
entry += ramcfg * recordlen;
129
if (entry[1] >= pm->memtimings.nr_timing) {
130
NV_WARN(dev, "timingset %d does not exist\n", entry[1]);
134
return &pm->memtimings.timing[entry[1]];
76
138
nouveau_perf_init(struct drm_device *dev)
120
182
entries = perf[2];
185
if (entries > NOUVEAU_PM_MAX_LEVEL) {
186
NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n");
187
entries = NOUVEAU_PM_MAX_LEVEL;
123
190
entry = perf + headerlen;
124
191
for (i = 0; i < entries; i++) {
125
192
struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
194
perflvl->timing = NULL;
127
196
if (entry[0] == 0xff) {
128
197
entry += recordlen;
174
243
#define subent(n) entry[perf[2] + ((n) * perf[3])]
175
244
perflvl->fanspeed = 0; /*XXX*/
176
245
perflvl->voltage = entry[2];
177
perflvl->core = (ROM16(subent(0)) & 0xfff) * 1000;
178
perflvl->shader = (ROM16(subent(1)) & 0xfff) * 1000;
179
perflvl->memory = (ROM16(subent(2)) & 0xfff) * 1000;
246
if (dev_priv->card_type == NV_50) {
247
perflvl->core = ROM16(subent(0)) & 0xfff;
248
perflvl->shader = ROM16(subent(1)) & 0xfff;
249
perflvl->memory = ROM16(subent(2)) & 0xfff;
251
perflvl->shader = ROM16(subent(3)) & 0xfff;
252
perflvl->core = perflvl->shader / 2;
253
perflvl->unk0a = ROM16(subent(4)) & 0xfff;
254
perflvl->memory = ROM16(subent(5)) & 0xfff;
257
perflvl->core *= 1000;
258
perflvl->shader *= 1000;
259
perflvl->memory *= 1000;
260
perflvl->unk0a *= 1000;
274
/* get the corresponding memory timings */
275
if (version > 0x15) {
276
/* last 3 args are for < 0x40, ignored for >= 0x40 */
278
nouveau_perf_timing(dev, &P,
279
perflvl->memory / 1000,
193
284
snprintf(perflvl->name, sizeof(perflvl->name),
194
285
"performance_level_%d", i);