aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nva3_pm.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-02-02 00:07:13 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-05-24 02:31:21 -0400
commit001a3990f6f767d364edab3c4b01a9ce4dde9cda (patch)
tree556152e15c279871b4aaefb01a5df1033d57eafe /drivers/gpu/drm/nouveau/nva3_pm.c
parent4719b55be5d43420b29e48c17208ec3db66e730f (diff)
drm/nva3/pm: attempt to bash a few 0x100200 bits correctly
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c66
1 files changed, 46 insertions, 20 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index c9a1f63d1c93..0ab6d436fbd1 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -236,17 +236,25 @@ nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl)
236 236
237struct nva3_pm_state { 237struct nva3_pm_state {
238 struct nouveau_pm_level *perflvl; 238 struct nouveau_pm_level *perflvl;
239
239 struct creg nclk; 240 struct creg nclk;
240 struct creg sclk; 241 struct creg sclk;
241 struct creg mclk;
242 struct creg vdec; 242 struct creg vdec;
243 struct creg unka0; 243 struct creg unka0;
244
245 struct creg mclk;
246 u8 *rammap;
247 u8 rammap_ver;
248 u8 rammap_len;
249 u8 *ramcfg;
250 u8 ramcfg_len;
244}; 251};
245 252
246void * 253void *
247nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) 254nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
248{ 255{
249 struct nva3_pm_state *info; 256 struct nva3_pm_state *info;
257 u8 ramcfg_cnt;
250 int ret; 258 int ret;
251 259
252 info = kzalloc(sizeof(*info), GFP_KERNEL); 260 info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -273,6 +281,19 @@ nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
273 if (ret < 0) 281 if (ret < 0)
274 goto out; 282 goto out;
275 283
284 info->rammap = nouveau_perf_rammap(dev, perflvl->memory,
285 &info->rammap_ver,
286 &info->rammap_len,
287 &ramcfg_cnt, &info->ramcfg_len);
288 if (info->rammap_ver != 0x10 || info->rammap_len < 5)
289 info->rammap = NULL;
290
291 info->ramcfg = nouveau_perf_ramcfg(dev, perflvl->memory,
292 &info->rammap_ver,
293 &info->ramcfg_len);
294 if (info->rammap_ver != 0x10)
295 info->ramcfg = NULL;
296
276 info->perflvl = perflvl; 297 info->perflvl = perflvl;
277out: 298out:
278 if (ret < 0) { 299 if (ret < 0) {
@@ -356,9 +377,6 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
356{ 377{
357 struct drm_device *dev = exec->dev; 378 struct drm_device *dev = exec->dev;
358 struct nva3_pm_state *info = exec->priv; 379 struct nva3_pm_state *info = exec->priv;
359 struct nouveau_pm_level *perflvl = info->perflvl;
360 u32 freq = perflvl->memory;
361 u8 *rammap, *ramcfg, ver, hdr, cnt, len;
362 380
363 if (!info->mclk.pll) { 381 if (!info->mclk.pll) {
364 nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk); 382 nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk);
@@ -367,15 +385,14 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
367 nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/ 385 nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/
368 } 386 }
369 387
370 rammap = nouveau_perf_rammap(dev, freq, &ver, &hdr, &cnt, &len); 388 if (info->rammap) {
371 if (rammap && ver == 0x10 && hdr >= 5) { 389 if (info->ramcfg && (info->rammap[4] & 0x08)) {
372 ramcfg = nouveau_perf_ramcfg(dev, freq, &ver, &len); 390 u32 unk5a0 = (ROM16(info->ramcfg[5]) << 8) |
373 if (ramcfg && (rammap[4] & 0x08)) { 391 info->ramcfg[5];
374 u32 unk5a0 = (ROM16(ramcfg[5]) << 8) | ramcfg[5]; 392 u32 unk5a4 = ROM16(info->ramcfg[7]);
375 u32 unk5a4 = ROM16(ramcfg[7]); 393 u32 unk804 = (info->ramcfg[9] & 0xf0) << 16 |
376 u32 unk804 = (ramcfg[9] & 0xf0) << 16 | 394 (info->ramcfg[3] & 0x0f) << 16 |
377 (ramcfg[3] & 0x0f) << 16 | 395 (info->ramcfg[9] & 0x0f) |
378 (ramcfg[9] & 0x0f) |
379 0x80000000; 396 0x80000000;
380 nv_wr32(dev, 0x1005a0, unk5a0); 397 nv_wr32(dev, 0x1005a0, unk5a0);
381 nv_wr32(dev, 0x1005a4, unk5a4); 398 nv_wr32(dev, 0x1005a4, unk5a4);
@@ -399,28 +416,31 @@ mclk_timing_set(struct nouveau_mem_exec_func *exec)
399 struct drm_device *dev = exec->dev; 416 struct drm_device *dev = exec->dev;
400 struct nva3_pm_state *info = exec->priv; 417 struct nva3_pm_state *info = exec->priv;
401 struct nouveau_pm_level *perflvl = info->perflvl; 418 struct nouveau_pm_level *perflvl = info->perflvl;
402 u8 *ramcfg, ver, len;
403 int i; 419 int i;
404 420
405 for (i = 0; i < 9; i++) 421 for (i = 0; i < 9; i++)
406 nv_wr32(dev, 0x100220 + (i * 4), perflvl->timing.reg[i]); 422 nv_wr32(dev, 0x100220 + (i * 4), perflvl->timing.reg[i]);
407 423
408 ramcfg = nouveau_perf_ramcfg(dev, perflvl->memory, &ver, &len); 424 if (info->ramcfg) {
409 if (ramcfg) { 425 u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000;
426 nv_mask(dev, 0x100200, 0x00001000, data);
427 }
428
429 if (info->ramcfg) {
410 u32 unk714 = nv_rd32(dev, 0x100714) & ~0xf0000010; 430 u32 unk714 = nv_rd32(dev, 0x100714) & ~0xf0000010;
411 u32 unk718 = nv_rd32(dev, 0x100718) & ~0x00000100; 431 u32 unk718 = nv_rd32(dev, 0x100718) & ~0x00000100;
412 u32 unk71c = nv_rd32(dev, 0x10071c) & ~0x00000100; 432 u32 unk71c = nv_rd32(dev, 0x10071c) & ~0x00000100;
413 if ( (ramcfg[2] & 0x20)) 433 if ( (info->ramcfg[2] & 0x20))
414 unk714 |= 0xf0000000; 434 unk714 |= 0xf0000000;
415 if (!(ramcfg[2] & 0x04)) 435 if (!(info->ramcfg[2] & 0x04))
416 unk714 |= 0x00000010; 436 unk714 |= 0x00000010;
417 nv_wr32(dev, 0x100714, unk714); 437 nv_wr32(dev, 0x100714, unk714);
418 438
419 if (ramcfg[2] & 0x01) 439 if (info->ramcfg[2] & 0x01)
420 unk71c |= 0x00000100; 440 unk71c |= 0x00000100;
421 nv_wr32(dev, 0x10071c, unk71c); 441 nv_wr32(dev, 0x10071c, unk71c);
422 442
423 if (ramcfg[2] & 0x02) 443 if (info->ramcfg[2] & 0x02)
424 unk718 |= 0x00000100; 444 unk718 |= 0x00000100;
425 nv_wr32(dev, 0x100718, unk718); 445 nv_wr32(dev, 0x100718, unk718);
426 } 446 }
@@ -463,9 +483,15 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
463 } 483 }
464 } 484 }
465 485
486 if (info->rammap && !(info->rammap[4] & 0x02))
487 nv_mask(dev, 0x100200, 0x00000800, 0x00000000);
466 nv_wr32(dev, 0x611200, 0x00003300); 488 nv_wr32(dev, 0x611200, 0x00003300);
489
467 nouveau_mem_exec(&exec, info->perflvl); 490 nouveau_mem_exec(&exec, info->perflvl);
491
468 nv_wr32(dev, 0x611200, 0x00003330); 492 nv_wr32(dev, 0x611200, 0x00003330);
493 if (info->rammap && (info->rammap[4] & 0x02))
494 nv_mask(dev, 0x100200, 0x00000800, 0x00000800);
469 495
470 if (info->mclk.pll) { 496 if (info->mclk.pll) {
471 nv_mask(dev, 0x004168, 0x00000001, 0x00000000); 497 nv_mask(dev, 0x004168, 0x00000001, 0x00000000);