aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-02-01 20:43:31 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-05-24 02:31:20 -0400
commit4719b55be5d43420b29e48c17208ec3db66e730f (patch)
tree9077de3101181dd8c957b26e5aa6572f9ad84dca /drivers/gpu/drm
parent30e533900ea74a3499dad5c4660ebaf80b50d152 (diff)
drm/nva3/pm: begin to restructure memory clock changes + another magic
The binary driver appears to do various bits and pieces of the memory clock frequency change at different times, depending on the particular transition that's occuring. I've attempted to replicate this here for div->pll, pll->div and div->div transitions. With some additional (patches upcoming) magic regs being bashed, this allows me to correctly transition between all 3 perflvls on NVS300. pll->pll transitions will *not* work correctly at the moment, pending me tricking the binary driver into doing one and seeing how to correctly handle it. This patch also handles (hopefully) 0x1110e0, which appears to need changing depending on whether in PLL or divider mode.. Maybe. We'll see. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index 98588292c802..c9a1f63d1c93 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -360,14 +360,12 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
360 u32 freq = perflvl->memory; 360 u32 freq = perflvl->memory;
361 u8 *rammap, *ramcfg, ver, hdr, cnt, len; 361 u8 *rammap, *ramcfg, ver, hdr, cnt, len;
362 362
363 nv_wr32(dev, 0x004018, 0x00001000); 363 if (!info->mclk.pll) {
364 364 nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk);
365 prog_pll(dev, 0x02, 0x004000, &info->mclk); 365 nv_mask(dev, 0x004000, 0x00000008, 0x00000008);
366 366 nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
367 if (nv_rd32(dev, 0x4000) & 0x00000008) 367 nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/
368 nv_wr32(dev, 0x004018, 0x1000d000); 368 }
369 else
370 nv_wr32(dev, 0x004018, 0x10005000);
371 369
372 rammap = nouveau_perf_rammap(dev, freq, &ver, &hdr, &cnt, &len); 370 rammap = nouveau_perf_rammap(dev, freq, &ver, &hdr, &cnt, &len);
373 if (rammap && ver == 0x10 && hdr >= 5) { 371 if (rammap && ver == 0x10 && hdr >= 5) {
@@ -388,6 +386,11 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
388 nv_mask(dev, 0x10f804, 0x80000000, 0x00000000); 386 nv_mask(dev, 0x10f804, 0x80000000, 0x00000000);
389 } 387 }
390 } 388 }
389
390 if (info->mclk.pll) {
391 nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000);
392 nv_mask(dev, 0x004000, 0x00000008, 0x00000000);
393 }
391} 394}
392 395
393static void 396static void
@@ -439,10 +442,39 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
439 .timing_set = mclk_timing_set, 442 .timing_set = mclk_timing_set,
440 .priv = info 443 .priv = info
441 }; 444 };
445 u32 ctrl;
446
447 ctrl = nv_rd32(dev, 0x004000);
448 if (ctrl & 0x00000008) {
449 if (info->mclk.pll) {
450 nv_mask(dev, 0x004128, 0x00000101, 0x00000101);
451 nv_wr32(dev, 0x004004, info->mclk.pll);
452 nv_wr32(dev, 0x004000, (ctrl |= 0x00000001));
453 nv_wr32(dev, 0x004000, (ctrl &= 0xffffffef));
454 nv_wait(dev, 0x004000, 0x00020000, 0x00020000);
455 nv_wr32(dev, 0x004000, (ctrl |= 0x00000010));
456 nv_wr32(dev, 0x004018, 0x00005000); /*XXX*/
457 nv_wr32(dev, 0x004000, (ctrl |= 0x00000004));
458 }
459 } else {
460 if (!info->mclk.pll) {
461 nv_mask(dev, 0x004168, 0x003f3141,
462 0x00000101 | info->mclk.clk);
463 }
464 }
442 465
443 nv_wr32(dev, 0x611200, 0x00003300); 466 nv_wr32(dev, 0x611200, 0x00003300);
444 nouveau_mem_exec(&exec, info->perflvl); 467 nouveau_mem_exec(&exec, info->perflvl);
445 nv_wr32(dev, 0x611200, 0x00003330); 468 nv_wr32(dev, 0x611200, 0x00003330);
469
470 if (info->mclk.pll) {
471 nv_mask(dev, 0x004168, 0x00000001, 0x00000000);
472 nv_mask(dev, 0x004168, 0x00000100, 0x00000000);
473 } else {
474 nv_mask(dev, 0x004000, 0x00000001, 0x00000000);
475 nv_mask(dev, 0x004128, 0x00000001, 0x00000000);
476 nv_mask(dev, 0x004128, 0x00000100, 0x00000000);
477 }
446} 478}
447 479
448int 480int