aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-02-02 19:02:03 -0500
committerBen Skeggs <bskeggs@redhat.com>2012-05-24 02:31:23 -0400
commit5f54d29ee9dace1e2ef4e8c9873ad4dd7a06d11a (patch)
tree18320c04c83f01d5c801b8a2f81dab2ce79935ee /drivers/gpu/drm
parent001a3990f6f767d364edab3c4b01a9ce4dde9cda (diff)
drm/nva3/pm: make pll->pll mode work
This probably wants a cleanup, but I'm holding off until I know for sure how the rest of the things that need doing fit together. Tested on NVS300 by hacking up perflvl 1 to require PLL mode, and switching between perflvl 3 and 1. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nva3_pm.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c
index 0ab6d436fbd1..3a237887961e 100644
--- a/drivers/gpu/drm/nouveau/nva3_pm.c
+++ b/drivers/gpu/drm/nouveau/nva3_pm.c
@@ -377,10 +377,23 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
377{ 377{
378 struct drm_device *dev = exec->dev; 378 struct drm_device *dev = exec->dev;
379 struct nva3_pm_state *info = exec->priv; 379 struct nva3_pm_state *info = exec->priv;
380 u32 ctrl;
380 381
382 ctrl = nv_rd32(dev, 0x004000);
383 if (!(ctrl & 0x00000008) && info->mclk.pll) {
384 nv_wr32(dev, 0x004000, (ctrl |= 0x00000008));
385 nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
386 nv_wr32(dev, 0x004018, 0x00001000); /*XXX*/
387 nv_wr32(dev, 0x004000, (ctrl &= ~0x00000001));
388 nv_wr32(dev, 0x004004, info->mclk.pll);
389 nv_wr32(dev, 0x004000, (ctrl |= 0x00000001));
390 udelay(64);
391 nv_wr32(dev, 0x004018, 0x10005000); /*XXX*/
392 udelay(20);
393 } else
381 if (!info->mclk.pll) { 394 if (!info->mclk.pll) {
382 nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk); 395 nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk);
383 nv_mask(dev, 0x004000, 0x00000008, 0x00000008); 396 nv_wr32(dev, 0x004000, (ctrl |= 0x00000008));
384 nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); 397 nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
385 nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/ 398 nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/
386 } 399 }
@@ -406,7 +419,7 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
406 419
407 if (info->mclk.pll) { 420 if (info->mclk.pll) {
408 nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000); 421 nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000);
409 nv_mask(dev, 0x004000, 0x00000008, 0x00000000); 422 nv_wr32(dev, 0x004000, (ctrl &= ~0x00000008));
410 } 423 }
411} 424}
412 425
@@ -477,10 +490,12 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
477 nv_wr32(dev, 0x004000, (ctrl |= 0x00000004)); 490 nv_wr32(dev, 0x004000, (ctrl |= 0x00000004));
478 } 491 }
479 } else { 492 } else {
480 if (!info->mclk.pll) { 493 u32 ssel = 0x00000101;
481 nv_mask(dev, 0x004168, 0x003f3141, 494 if (info->mclk.clk)
482 0x00000101 | info->mclk.clk); 495 ssel |= info->mclk.clk;
483 } 496 else
497 ssel |= 0x00080000; /* 324MHz, shouldn't matter... */
498 nv_mask(dev, 0x004168, 0x003f3141, ctrl);
484 } 499 }
485 500
486 if (info->rammap && !(info->rammap[4] & 0x02)) 501 if (info->rammap && !(info->rammap[4] & 0x02))