diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-04-14 01:02:03 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-05-15 20:49:54 -0400 |
commit | 215f902e1555e0fa94c1de547dcd246c6f5306e2 (patch) | |
tree | 6e003635d468bb92f675fb0edf5e917867081748 | |
parent | ce521846b9bde836d010416b6120a694b5f06e96 (diff) |
drm/nva3: somewhat improve clock reporting
Definitely not 100% correct, but, for the configurations I've seen used
it'll read back the correct clocks now.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nva3_pm.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index dbbafed36406..5a68958f076b 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
@@ -27,10 +27,10 @@ | |||
27 | #include "nouveau_bios.h" | 27 | #include "nouveau_bios.h" |
28 | #include "nouveau_pm.h" | 28 | #include "nouveau_pm.h" |
29 | 29 | ||
30 | /*XXX: boards using limits 0x40 need fixing, the register layout | 30 | /* This is actually a lot more complex than it appears here, but hopefully |
31 | * is correct here, but, there's some other funny magic | 31 | * this should be able to deal with what the VBIOS leaves for us.. |
32 | * that modifies things, so it's not likely we'll set/read | 32 | * |
33 | * the correct timings yet.. working on it... | 33 | * If not, well, I'll jump off that bridge when I come to it. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | struct nva3_pm_state { | 36 | struct nva3_pm_state { |
@@ -38,21 +38,57 @@ struct nva3_pm_state { | |||
38 | int N, M, P; | 38 | int N, M, P; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static int | ||
42 | nva3_pm_pll_offset(u32 id) | ||
43 | { | ||
44 | static const u32 pll_map[] = { | ||
45 | 0x00, PLL_CORE, | ||
46 | 0x01, PLL_SHADER, | ||
47 | 0x02, PLL_MEMORY, | ||
48 | 0x00, 0x00 | ||
49 | }; | ||
50 | const u32 *map = pll_map; | ||
51 | |||
52 | while (map[1]) { | ||
53 | if (id == map[1]) | ||
54 | return map[0]; | ||
55 | map += 2; | ||
56 | } | ||
57 | |||
58 | return -ENOENT; | ||
59 | } | ||
60 | |||
41 | int | 61 | int |
42 | nva3_pm_clock_get(struct drm_device *dev, u32 id) | 62 | nva3_pm_clock_get(struct drm_device *dev, u32 id) |
43 | { | 63 | { |
64 | u32 src0, src1, ctrl, coef; | ||
44 | struct pll_lims pll; | 65 | struct pll_lims pll; |
45 | int P, N, M, ret; | 66 | int ret, off; |
46 | u32 reg; | 67 | int P, N, M; |
47 | 68 | ||
48 | ret = get_pll_limits(dev, id, &pll); | 69 | ret = get_pll_limits(dev, id, &pll); |
49 | if (ret) | 70 | if (ret) |
50 | return ret; | 71 | return ret; |
51 | 72 | ||
52 | reg = nv_rd32(dev, pll.reg + 4); | 73 | off = nva3_pm_pll_offset(id); |
53 | P = (reg & 0x003f0000) >> 16; | 74 | if (off < 0) |
54 | N = (reg & 0x0000ff00) >> 8; | 75 | return off; |
55 | M = (reg & 0x000000ff); | 76 | |
77 | src0 = nv_rd32(dev, 0x4120 + (off * 4)); | ||
78 | src1 = nv_rd32(dev, 0x4160 + (off * 4)); | ||
79 | ctrl = nv_rd32(dev, pll.reg + 0); | ||
80 | coef = nv_rd32(dev, pll.reg + 4); | ||
81 | NV_DEBUG(dev, "PLL %02x: 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
82 | id, src0, src1, ctrl, coef); | ||
83 | |||
84 | if (ctrl & 0x00000008) { | ||
85 | u32 div = ((src1 & 0x003c0000) >> 18) + 1; | ||
86 | return (pll.refclk * 2) / div; | ||
87 | } | ||
88 | |||
89 | P = (coef & 0x003f0000) >> 16; | ||
90 | N = (coef & 0x0000ff00) >> 8; | ||
91 | M = (coef & 0x000000ff); | ||
56 | return pll.refclk * N / M / P; | 92 | return pll.refclk * N / M / P; |
57 | } | 93 | } |
58 | 94 | ||