summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv50_pm.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-10-30 23:10:55 +1000
committerBen Skeggs <bskeggs@redhat.com>2011-12-21 19:01:27 +1000
commit463464eb9bf7d0254f3effa8050246fa4e009ace (patch)
tree6ea459b2de31ab5262870add04df642b9f5f4de4 /drivers/gpu/drm/nouveau/nv50_pm.c
parent6805979fa9090b2c69c645cf19bba9a2849f336b (diff)
drm/nv50/pm: fix thinko which lead to clocks being slightly off sometimes
read_pll_ref() needs to take into account the refclk src bits in 0xc040 on some chipsets, it wasn't doing this. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_pm.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index ab8cfad5a9b..9d61bd45c47 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -66,7 +66,7 @@ read_div(struct drm_device *dev)
}
static u32
-read_pll_ref(struct drm_device *dev, u32 base)
+read_pll_src(struct drm_device *dev, u32 base)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 coef, ref = read_clk(dev, clk_src_crystal);
@@ -137,21 +137,12 @@ read_pll_ref(struct drm_device *dev, u32 base)
}
static u32
-read_pll(struct drm_device *dev, u32 base)
+read_pll_ref(struct drm_device *dev, u32 base)
{
- struct drm_nouveau_private *dev_priv = dev->dev_private;
- u32 mast = nv_rd32(dev, 0x00c040);
- u32 src = 0, ref = 0, clk = 0;
- u32 ctrl, coef;
- int N1, N2, M1, M2;
+ u32 src, mast = nv_rd32(dev, 0x00c040);
switch (base) {
case 0x004028:
- if (mast & 0x00100000) {
- /* wtf, appears to only disable post-divider on nva0 */
- if (dev_priv->chipset != 0xa0)
- return read_clk(dev, clk_src_dom6);
- }
src = !!(mast & 0x00200000);
break;
case 0x004020:
@@ -164,22 +155,33 @@ read_pll(struct drm_device *dev, u32 base)
src = !!(mast & 0x02000000);
break;
case 0x00e810:
- ref = read_clk(dev, clk_src_crystal);
- break;
+ return read_clk(dev, clk_src_crystal);
default:
NV_ERROR(dev, "bad pll 0x%06x\n", base);
return 0;
}
- if (ref == 0) {
- if (src)
- ref = read_clk(dev, clk_src_href);
- else
- ref = read_pll_ref(dev, base);
- }
+ if (src)
+ return read_clk(dev, clk_src_href);
+ return read_pll_src(dev, base);
+}
- ctrl = nv_rd32(dev, base + 0);
- coef = nv_rd32(dev, base + 4);
+static u32
+read_pll(struct drm_device *dev, u32 base)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ u32 mast = nv_rd32(dev, 0x00c040);
+ u32 ctrl = nv_rd32(dev, base + 0);
+ u32 coef = nv_rd32(dev, base + 4);
+ u32 ref = read_pll_ref(dev, base);
+ u32 clk = 0;
+ int N1, N2, M1, M2;
+
+ if (base == 0x004028 && (mast & 0x00100000)) {
+ /* wtf, appears to only disable post-divider on nva0 */
+ if (dev_priv->chipset != 0xa0)
+ return read_clk(dev, clk_src_dom6);
+ }
N2 = (coef & 0xff000000) >> 24;
M2 = (coef & 0x00ff0000) >> 16;