summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nva3_pm.c
diff options
context:
space:
mode:
authorBen Skeggs2012-02-03 01:02:03 +0100
committerBen Skeggs2012-05-24 08:31:23 +0200
commit5f54d29ee9dace1e2ef4e8c9873ad4dd7a06d11a (patch)
tree18320c04c83f01d5c801b8a2f81dab2ce79935ee /drivers/gpu/drm/nouveau/nva3_pm.c
parentdrm/nva3/pm: attempt to bash a few 0x100200 bits correctly (diff)
downloadkernel-qcow2-linux-5f54d29ee9dace1e2ef4e8c9873ad4dd7a06d11a.tar.gz
kernel-qcow2-linux-5f54d29ee9dace1e2ef4e8c9873ad4dd7a06d11a.tar.xz
kernel-qcow2-linux-5f54d29ee9dace1e2ef4e8c9873ad4dd7a06d11a.zip
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/nouveau/nva3_pm.c')
-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)
{
struct drm_device *dev = exec->dev;
struct nva3_pm_state *info = exec->priv;
+ u32 ctrl;
+ ctrl = nv_rd32(dev, 0x004000);
+ if (!(ctrl & 0x00000008) && info->mclk.pll) {
+ nv_wr32(dev, 0x004000, (ctrl |= 0x00000008));
+ nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
+ nv_wr32(dev, 0x004018, 0x00001000); /*XXX*/
+ nv_wr32(dev, 0x004000, (ctrl &= ~0x00000001));
+ nv_wr32(dev, 0x004004, info->mclk.pll);
+ nv_wr32(dev, 0x004000, (ctrl |= 0x00000001));
+ udelay(64);
+ nv_wr32(dev, 0x004018, 0x10005000); /*XXX*/
+ udelay(20);
+ } else
if (!info->mclk.pll) {
nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk);
- nv_mask(dev, 0x004000, 0x00000008, 0x00000008);
+ nv_wr32(dev, 0x004000, (ctrl |= 0x00000008));
nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/
}
@@ -406,7 +419,7 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
if (info->mclk.pll) {
nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000);
- nv_mask(dev, 0x004000, 0x00000008, 0x00000000);
+ nv_wr32(dev, 0x004000, (ctrl &= ~0x00000008));
}
}
@@ -477,10 +490,12 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
nv_wr32(dev, 0x004000, (ctrl |= 0x00000004));
}
} else {
- if (!info->mclk.pll) {
- nv_mask(dev, 0x004168, 0x003f3141,
- 0x00000101 | info->mclk.clk);
- }
+ u32 ssel = 0x00000101;
+ if (info->mclk.clk)
+ ssel |= info->mclk.clk;
+ else
+ ssel |= 0x00080000; /* 324MHz, shouldn't matter... */
+ nv_mask(dev, 0x004168, 0x003f3141, ctrl);
}
if (info->rammap && !(info->rammap[4] & 0x02))