diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_perf.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_perf.c | 409 |
1 files changed, 228 insertions, 181 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 58f497343cec..69a528d106e6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c | |||
@@ -27,6 +27,178 @@ | |||
27 | #include "nouveau_drv.h" | 27 | #include "nouveau_drv.h" |
28 | #include "nouveau_pm.h" | 28 | #include "nouveau_pm.h" |
29 | 29 | ||
30 | static u8 * | ||
31 | nouveau_perf_table(struct drm_device *dev, u8 *ver) | ||
32 | { | ||
33 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
34 | struct nvbios *bios = &dev_priv->vbios; | ||
35 | struct bit_entry P; | ||
36 | |||
37 | if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { | ||
38 | u8 *perf = ROMPTR(dev, P.data[0]); | ||
39 | if (perf) { | ||
40 | *ver = perf[0]; | ||
41 | return perf; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | if (bios->type == NVBIOS_BMP) { | ||
46 | if (bios->data[bios->offset + 6] >= 0x25) { | ||
47 | u8 *perf = ROMPTR(dev, bios->data[bios->offset + 0x94]); | ||
48 | if (perf) { | ||
49 | *ver = perf[1]; | ||
50 | return perf; | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | static u8 * | ||
59 | nouveau_perf_entry(struct drm_device *dev, int idx, | ||
60 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||
61 | { | ||
62 | u8 *perf = nouveau_perf_table(dev, ver); | ||
63 | if (perf) { | ||
64 | if (*ver >= 0x12 && *ver < 0x20 && idx < perf[2]) { | ||
65 | *hdr = perf[3]; | ||
66 | *cnt = 0; | ||
67 | *len = 0; | ||
68 | return perf + perf[0] + idx * perf[3]; | ||
69 | } else | ||
70 | if (*ver >= 0x20 && *ver < 0x40 && idx < perf[2]) { | ||
71 | *hdr = perf[3]; | ||
72 | *cnt = perf[4]; | ||
73 | *len = perf[5]; | ||
74 | return perf + perf[1] + idx * (*hdr + (*cnt * *len)); | ||
75 | } else | ||
76 | if (*ver >= 0x40 && *ver < 0x41 && idx < perf[5]) { | ||
77 | *hdr = perf[2]; | ||
78 | *cnt = perf[4]; | ||
79 | *len = perf[3]; | ||
80 | return perf + perf[1] + idx * (*hdr + (*cnt * *len)); | ||
81 | } | ||
82 | } | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | static u8 * | ||
87 | nouveau_perf_rammap(struct drm_device *dev, u32 freq, | ||
88 | u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||
89 | { | ||
90 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
91 | struct bit_entry P; | ||
92 | u8 *perf, i = 0; | ||
93 | |||
94 | if (!bit_table(dev, 'P', &P) && P.version == 2) { | ||
95 | u8 *rammap = ROMPTR(dev, P.data[4]); | ||
96 | if (rammap) { | ||
97 | u8 *ramcfg = rammap + rammap[1]; | ||
98 | |||
99 | *ver = rammap[0]; | ||
100 | *hdr = rammap[2]; | ||
101 | *cnt = rammap[4]; | ||
102 | *len = rammap[3]; | ||
103 | |||
104 | freq /= 1000; | ||
105 | for (i = 0; i < rammap[5]; i++) { | ||
106 | if (freq >= ROM16(ramcfg[0]) && | ||
107 | freq <= ROM16(ramcfg[2])) | ||
108 | return ramcfg; | ||
109 | |||
110 | ramcfg += *hdr + (*cnt * *len); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | if (dev_priv->chipset == 0x49 || | ||
118 | dev_priv->chipset == 0x4b) | ||
119 | freq /= 2; | ||
120 | |||
121 | while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { | ||
122 | if (*ver >= 0x20 && *ver < 0x25) { | ||
123 | if (perf[0] != 0xff && freq <= ROM16(perf[11]) * 1000) | ||
124 | break; | ||
125 | } else | ||
126 | if (*ver >= 0x25 && *ver < 0x40) { | ||
127 | if (perf[0] != 0xff && freq <= ROM16(perf[12]) * 1000) | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | if (perf) { | ||
133 | u8 *ramcfg = perf + *hdr; | ||
134 | *ver = 0x00; | ||
135 | *hdr = 0; | ||
136 | return ramcfg; | ||
137 | } | ||
138 | |||
139 | return NULL; | ||
140 | } | ||
141 | |||
142 | u8 * | ||
143 | nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||
144 | { | ||
145 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
146 | struct nvbios *bios = &dev_priv->vbios; | ||
147 | u8 strap, hdr, cnt; | ||
148 | u8 *rammap; | ||
149 | |||
150 | strap = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; | ||
151 | if (bios->ram_restrict_tbl_ptr) | ||
152 | strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; | ||
153 | |||
154 | rammap = nouveau_perf_rammap(dev, freq, ver, &hdr, &cnt, len); | ||
155 | if (rammap && strap < cnt) | ||
156 | return rammap + hdr + (strap * *len); | ||
157 | |||
158 | return NULL; | ||
159 | } | ||
160 | |||
161 | u8 * | ||
162 | nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||
163 | { | ||
164 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
165 | struct nvbios *bios = &dev_priv->vbios; | ||
166 | struct bit_entry P; | ||
167 | u8 *perf, *timing = NULL; | ||
168 | u8 i = 0, hdr, cnt; | ||
169 | |||
170 | if (bios->type == NVBIOS_BMP) { | ||
171 | while ((perf = nouveau_perf_entry(dev, i++, ver, &hdr, &cnt, | ||
172 | len)) && *ver == 0x15) { | ||
173 | if (freq <= ROM32(perf[5]) * 20) { | ||
174 | *ver = 0x00; | ||
175 | *len = 14; | ||
176 | return perf + 41; | ||
177 | } | ||
178 | } | ||
179 | return NULL; | ||
180 | } | ||
181 | |||
182 | if (!bit_table(dev, 'P', &P)) { | ||
183 | if (P.version == 1) | ||
184 | timing = ROMPTR(dev, P.data[4]); | ||
185 | else | ||
186 | if (P.version == 2) | ||
187 | timing = ROMPTR(dev, P.data[8]); | ||
188 | } | ||
189 | |||
190 | if (timing && timing[0] == 0x10) { | ||
191 | u8 *ramcfg = nouveau_perf_ramcfg(dev, freq, ver, len); | ||
192 | if (ramcfg && ramcfg[1] < timing[2]) { | ||
193 | *ver = timing[0]; | ||
194 | *len = timing[3]; | ||
195 | return timing + timing[1] + (ramcfg[1] * timing[3]); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | return NULL; | ||
200 | } | ||
201 | |||
30 | static void | 202 | static void |
31 | legacy_perf_init(struct drm_device *dev) | 203 | legacy_perf_init(struct drm_device *dev) |
32 | { | 204 | { |
@@ -72,74 +244,11 @@ legacy_perf_init(struct drm_device *dev) | |||
72 | pm->nr_perflvl = 1; | 244 | pm->nr_perflvl = 1; |
73 | } | 245 | } |
74 | 246 | ||
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) | ||
78 | { | ||
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; | ||
82 | u8 ramcfg; | ||
83 | int i; | ||
84 | |||
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 | ||
88 | */ | ||
89 | if (P->version == 2) { | ||
90 | u8 *tmap = ROMPTR(dev, P->data[4]); | ||
91 | if (!tmap) { | ||
92 | NV_DEBUG(dev, "no timing map pointer\n"); | ||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | if (tmap[0] != 0x10) { | ||
97 | NV_WARN(dev, "timing map 0x%02x unknown\n", tmap[0]); | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
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])) | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | if (i == tmap[5]) { | ||
110 | NV_WARN(dev, "no match in timing map table\n"); | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | entry += tmap[2]; | ||
115 | recordlen = tmap[3]; | ||
116 | entries = tmap[4]; | ||
117 | } | ||
118 | |||
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]; | ||
122 | |||
123 | if (ramcfg >= entries) { | ||
124 | NV_WARN(dev, "ramcfg strap out of bounds!\n"); | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | entry += ramcfg * recordlen; | ||
129 | if (entry[1] >= pm->memtimings.nr_timing) { | ||
130 | if (entry[1] != 0xff) | ||
131 | NV_WARN(dev, "timingset %d does not exist\n", entry[1]); | ||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | return &pm->memtimings.timing[entry[1]]; | ||
136 | } | ||
137 | |||
138 | static void | 247 | static void |
139 | nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, | 248 | nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
140 | struct nouveau_pm_level *perflvl) | ||
141 | { | 249 | { |
142 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 250 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
251 | struct bit_entry P; | ||
143 | u8 *vmap; | 252 | u8 *vmap; |
144 | int id; | 253 | int id; |
145 | 254 | ||
@@ -158,13 +267,13 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, | |||
158 | /* on newer ones, the perflvl stores an index into yet another | 267 | /* on newer ones, the perflvl stores an index into yet another |
159 | * vbios table containing a min/max voltage value for the perflvl | 268 | * vbios table containing a min/max voltage value for the perflvl |
160 | */ | 269 | */ |
161 | if (P->version != 2 || P->length < 34) { | 270 | if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { |
162 | NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", | 271 | NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", |
163 | P->version, P->length); | 272 | P.version, P.length); |
164 | return; | 273 | return; |
165 | } | 274 | } |
166 | 275 | ||
167 | vmap = ROMPTR(dev, P->data[32]); | 276 | vmap = ROMPTR(dev, P.data[32]); |
168 | if (!vmap) { | 277 | if (!vmap) { |
169 | NV_DEBUG(dev, "volt map table pointer invalid\n"); | 278 | NV_DEBUG(dev, "volt map table pointer invalid\n"); |
170 | return; | 279 | return; |
@@ -183,130 +292,70 @@ nouveau_perf_init(struct drm_device *dev) | |||
183 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 292 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
184 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 293 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |
185 | struct nvbios *bios = &dev_priv->vbios; | 294 | struct nvbios *bios = &dev_priv->vbios; |
186 | struct bit_entry P; | 295 | u8 *perf, ver, hdr, cnt, len; |
187 | struct nouveau_pm_memtimings *memtimings = &pm->memtimings; | 296 | int ret, vid, i = -1; |
188 | struct nouveau_pm_tbl_header mt_hdr; | ||
189 | u8 version, headerlen, recordlen, entries; | ||
190 | u8 *perf, *entry; | ||
191 | int vid, i; | ||
192 | |||
193 | if (bios->type == NVBIOS_BIT) { | ||
194 | if (bit_table(dev, 'P', &P)) | ||
195 | return; | ||
196 | |||
197 | if (P.version != 1 && P.version != 2) { | ||
198 | NV_WARN(dev, "unknown perf for BIT P %d\n", P.version); | ||
199 | return; | ||
200 | } | ||
201 | |||
202 | perf = ROMPTR(dev, P.data[0]); | ||
203 | version = perf[0]; | ||
204 | headerlen = perf[1]; | ||
205 | if (version < 0x40) { | ||
206 | recordlen = perf[3] + (perf[4] * perf[5]); | ||
207 | entries = perf[2]; | ||
208 | |||
209 | pm->pwm_divisor = ROM16(perf[6]); | ||
210 | } else { | ||
211 | recordlen = perf[2] + (perf[3] * perf[4]); | ||
212 | entries = perf[5]; | ||
213 | } | ||
214 | } else { | ||
215 | if (bios->data[bios->offset + 6] < 0x25) { | ||
216 | legacy_perf_init(dev); | ||
217 | return; | ||
218 | } | ||
219 | 297 | ||
220 | perf = ROMPTR(dev, bios->data[bios->offset + 0x94]); | 298 | if (bios->type == NVBIOS_BMP && bios->data[bios->offset + 6] < 0x25) { |
221 | if (!perf) { | 299 | legacy_perf_init(dev); |
222 | NV_DEBUG(dev, "perf table pointer invalid\n"); | 300 | return; |
223 | return; | ||
224 | } | ||
225 | |||
226 | version = perf[1]; | ||
227 | headerlen = perf[0]; | ||
228 | recordlen = perf[3]; | ||
229 | entries = perf[2]; | ||
230 | } | ||
231 | |||
232 | if (entries > NOUVEAU_PM_MAX_LEVEL) { | ||
233 | NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n"); | ||
234 | entries = NOUVEAU_PM_MAX_LEVEL; | ||
235 | } | 301 | } |
236 | 302 | ||
237 | entry = perf + headerlen; | 303 | perf = nouveau_perf_table(dev, &ver); |
238 | 304 | if (ver >= 0x20 && ver < 0x40) | |
239 | /* For version 0x15, initialize memtiming table */ | 305 | pm->fan.pwm_divisor = ROM16(perf[6]); |
240 | if(version == 0x15) { | ||
241 | memtimings->timing = | ||
242 | kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL); | ||
243 | if (!memtimings->timing) { | ||
244 | NV_WARN(dev,"Could not allocate memtiming table\n"); | ||
245 | return; | ||
246 | } | ||
247 | |||
248 | mt_hdr.entry_cnt = entries; | ||
249 | mt_hdr.entry_len = 14; | ||
250 | mt_hdr.version = version; | ||
251 | mt_hdr.header_len = 4; | ||
252 | } | ||
253 | 306 | ||
254 | for (i = 0; i < entries; i++) { | 307 | while ((perf = nouveau_perf_entry(dev, ++i, &ver, &hdr, &cnt, &len))) { |
255 | struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; | 308 | struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; |
256 | 309 | ||
257 | perflvl->timing = NULL; | 310 | if (perf[0] == 0xff) |
258 | |||
259 | if (entry[0] == 0xff) { | ||
260 | entry += recordlen; | ||
261 | continue; | 311 | continue; |
262 | } | ||
263 | 312 | ||
264 | switch (version) { | 313 | switch (ver) { |
265 | case 0x12: | 314 | case 0x12: |
266 | case 0x13: | 315 | case 0x13: |
267 | case 0x15: | 316 | case 0x15: |
268 | perflvl->fanspeed = entry[55]; | 317 | perflvl->fanspeed = perf[55]; |
269 | if (recordlen > 56) | 318 | if (hdr > 56) |
270 | perflvl->volt_min = entry[56]; | 319 | perflvl->volt_min = perf[56]; |
271 | perflvl->core = ROM32(entry[1]) * 10; | 320 | perflvl->core = ROM32(perf[1]) * 10; |
272 | perflvl->memory = ROM32(entry[5]) * 20; | 321 | perflvl->memory = ROM32(perf[5]) * 20; |
273 | break; | 322 | break; |
274 | case 0x21: | 323 | case 0x21: |
275 | case 0x23: | 324 | case 0x23: |
276 | case 0x24: | 325 | case 0x24: |
277 | perflvl->fanspeed = entry[4]; | 326 | perflvl->fanspeed = perf[4]; |
278 | perflvl->volt_min = entry[5]; | 327 | perflvl->volt_min = perf[5]; |
279 | perflvl->shader = ROM16(entry[6]) * 1000; | 328 | perflvl->shader = ROM16(perf[6]) * 1000; |
280 | perflvl->core = perflvl->shader; | 329 | perflvl->core = perflvl->shader; |
281 | perflvl->core += (signed char)entry[8] * 1000; | 330 | perflvl->core += (signed char)perf[8] * 1000; |
282 | if (dev_priv->chipset == 0x49 || | 331 | if (dev_priv->chipset == 0x49 || |
283 | dev_priv->chipset == 0x4b) | 332 | dev_priv->chipset == 0x4b) |
284 | perflvl->memory = ROM16(entry[11]) * 1000; | 333 | perflvl->memory = ROM16(perf[11]) * 1000; |
285 | else | 334 | else |
286 | perflvl->memory = ROM16(entry[11]) * 2000; | 335 | perflvl->memory = ROM16(perf[11]) * 2000; |
287 | break; | 336 | break; |
288 | case 0x25: | 337 | case 0x25: |
289 | perflvl->fanspeed = entry[4]; | 338 | perflvl->fanspeed = perf[4]; |
290 | perflvl->volt_min = entry[5]; | 339 | perflvl->volt_min = perf[5]; |
291 | perflvl->core = ROM16(entry[6]) * 1000; | 340 | perflvl->core = ROM16(perf[6]) * 1000; |
292 | perflvl->shader = ROM16(entry[10]) * 1000; | 341 | perflvl->shader = ROM16(perf[10]) * 1000; |
293 | perflvl->memory = ROM16(entry[12]) * 1000; | 342 | perflvl->memory = ROM16(perf[12]) * 1000; |
294 | break; | 343 | break; |
295 | case 0x30: | 344 | case 0x30: |
296 | perflvl->memscript = ROM16(entry[2]); | 345 | perflvl->memscript = ROM16(perf[2]); |
297 | case 0x35: | 346 | case 0x35: |
298 | perflvl->fanspeed = entry[6]; | 347 | perflvl->fanspeed = perf[6]; |
299 | perflvl->volt_min = entry[7]; | 348 | perflvl->volt_min = perf[7]; |
300 | perflvl->core = ROM16(entry[8]) * 1000; | 349 | perflvl->core = ROM16(perf[8]) * 1000; |
301 | perflvl->shader = ROM16(entry[10]) * 1000; | 350 | perflvl->shader = ROM16(perf[10]) * 1000; |
302 | perflvl->memory = ROM16(entry[12]) * 1000; | 351 | perflvl->memory = ROM16(perf[12]) * 1000; |
303 | perflvl->vdec = ROM16(entry[16]) * 1000; | 352 | perflvl->vdec = ROM16(perf[16]) * 1000; |
304 | perflvl->dom6 = ROM16(entry[20]) * 1000; | 353 | perflvl->dom6 = ROM16(perf[20]) * 1000; |
305 | break; | 354 | break; |
306 | case 0x40: | 355 | case 0x40: |
307 | #define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 | 356 | #define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) |
308 | perflvl->fanspeed = 0; /*XXX*/ | 357 | perflvl->fanspeed = 0; /*XXX*/ |
309 | perflvl->volt_min = entry[2]; | 358 | perflvl->volt_min = perf[2]; |
310 | if (dev_priv->card_type == NV_50) { | 359 | if (dev_priv->card_type == NV_50) { |
311 | perflvl->core = subent(0); | 360 | perflvl->core = subent(0); |
312 | perflvl->shader = subent(1); | 361 | perflvl->shader = subent(1); |
@@ -329,36 +378,34 @@ nouveau_perf_init(struct drm_device *dev) | |||
329 | } | 378 | } |
330 | 379 | ||
331 | /* make sure vid is valid */ | 380 | /* make sure vid is valid */ |
332 | nouveau_perf_voltage(dev, &P, perflvl); | 381 | nouveau_perf_voltage(dev, perflvl); |
333 | if (pm->voltage.supported && perflvl->volt_min) { | 382 | if (pm->voltage.supported && perflvl->volt_min) { |
334 | vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); | 383 | vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); |
335 | if (vid < 0) { | 384 | if (vid < 0) { |
336 | NV_DEBUG(dev, "drop perflvl %d, bad vid\n", i); | 385 | NV_DEBUG(dev, "perflvl %d, bad vid\n", i); |
337 | entry += recordlen; | ||
338 | continue; | 386 | continue; |
339 | } | 387 | } |
340 | } | 388 | } |
341 | 389 | ||
342 | /* get the corresponding memory timings */ | 390 | /* get the corresponding memory timings */ |
343 | if (version == 0x15) { | 391 | ret = nouveau_mem_timing_calc(dev, perflvl->memory, |
344 | memtimings->timing[i].id = i; | 392 | &perflvl->timing); |
345 | nv30_mem_timing_entry(dev,&mt_hdr,(struct nouveau_pm_tbl_entry*) &entry[41],0,&memtimings->timing[i]); | 393 | if (ret) { |
346 | perflvl->timing = &memtimings->timing[i]; | 394 | NV_DEBUG(dev, "perflvl %d, bad timing: %d\n", i, ret); |
347 | } else if (version > 0x15) { | 395 | continue; |
348 | /* last 3 args are for < 0x40, ignored for >= 0x40 */ | ||
349 | perflvl->timing = | ||
350 | nouveau_perf_timing(dev, &P, | ||
351 | perflvl->memory / 1000, | ||
352 | entry + perf[3], | ||
353 | perf[5], perf[4]); | ||
354 | } | 396 | } |
355 | 397 | ||
356 | snprintf(perflvl->name, sizeof(perflvl->name), | 398 | snprintf(perflvl->name, sizeof(perflvl->name), |
357 | "performance_level_%d", i); | 399 | "performance_level_%d", i); |
358 | perflvl->id = i; | 400 | perflvl->id = i; |
359 | pm->nr_perflvl++; | ||
360 | 401 | ||
361 | entry += recordlen; | 402 | snprintf(perflvl->profile.name, sizeof(perflvl->profile.name), |
403 | "%d", perflvl->id); | ||
404 | perflvl->profile.func = &nouveau_pm_static_profile_func; | ||
405 | list_add_tail(&perflvl->profile.head, &pm->profiles); | ||
406 | |||
407 | |||
408 | pm->nr_perflvl++; | ||
362 | } | 409 | } |
363 | } | 410 | } |
364 | 411 | ||