Commit 4719b55b authored by Ben Skeggs's avatar Ben Skeggs

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 30e53390
......@@ -360,14 +360,12 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
u32 freq = perflvl->memory;
u8 *rammap, *ramcfg, ver, hdr, cnt, len;
nv_wr32(dev, 0x004018, 0x00001000);
prog_pll(dev, 0x02, 0x004000, &info->mclk);
if (nv_rd32(dev, 0x4000) & 0x00000008)
nv_wr32(dev, 0x004018, 0x1000d000);
else
nv_wr32(dev, 0x004018, 0x10005000);
if (!info->mclk.pll) {
nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk);
nv_mask(dev, 0x004000, 0x00000008, 0x00000008);
nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000);
nv_wr32(dev, 0x004018, 0x1000d000); /*XXX*/
}
rammap = nouveau_perf_rammap(dev, freq, &ver, &hdr, &cnt, &len);
if (rammap && ver == 0x10 && hdr >= 5) {
......@@ -388,6 +386,11 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec)
nv_mask(dev, 0x10f804, 0x80000000, 0x00000000);
}
}
if (info->mclk.pll) {
nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000);
nv_mask(dev, 0x004000, 0x00000008, 0x00000000);
}
}
static void
......@@ -439,10 +442,39 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info)
.timing_set = mclk_timing_set,
.priv = info
};
u32 ctrl;
ctrl = nv_rd32(dev, 0x004000);
if (ctrl & 0x00000008) {
if (info->mclk.pll) {
nv_mask(dev, 0x004128, 0x00000101, 0x00000101);
nv_wr32(dev, 0x004004, info->mclk.pll);
nv_wr32(dev, 0x004000, (ctrl |= 0x00000001));
nv_wr32(dev, 0x004000, (ctrl &= 0xffffffef));
nv_wait(dev, 0x004000, 0x00020000, 0x00020000);
nv_wr32(dev, 0x004000, (ctrl |= 0x00000010));
nv_wr32(dev, 0x004018, 0x00005000); /*XXX*/
nv_wr32(dev, 0x004000, (ctrl |= 0x00000004));
}
} else {
if (!info->mclk.pll) {
nv_mask(dev, 0x004168, 0x003f3141,
0x00000101 | info->mclk.clk);
}
}
nv_wr32(dev, 0x611200, 0x00003300);
nouveau_mem_exec(&exec, info->perflvl);
nv_wr32(dev, 0x611200, 0x00003330);
if (info->mclk.pll) {
nv_mask(dev, 0x004168, 0x00000001, 0x00000000);
nv_mask(dev, 0x004168, 0x00000100, 0x00000000);
} else {
nv_mask(dev, 0x004000, 0x00000001, 0x00000000);
nv_mask(dev, 0x004128, 0x00000001, 0x00000000);
nv_mask(dev, 0x004128, 0x00000100, 0x00000000);
}
}
int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment