summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
diff options
context:
space:
mode:
authorRoy Spliet2014-08-21 13:45:12 +0200
committerBen Skeggs2014-09-15 14:24:59 +0200
commit3d896d349e43b953e5278c49ab812435231d64b4 (patch)
tree42bc0c90bd2130a3758de04c228a615ff40a0464 /drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
parentdrm/nouveau: Fix duplicate definition of NV04_PFB_BOOT_0_* (diff)
downloadkernel-qcow2-linux-3d896d349e43b953e5278c49ab812435231d64b4.tar.gz
kernel-qcow2-linux-3d896d349e43b953e5278c49ab812435231d64b4.tar.xz
kernel-qcow2-linux-3d896d349e43b953e5278c49ab812435231d64b4.zip
drm/nva3/clk: Parse clock control registers more accurately
Signed-off-by: Roy Spliet <rspliet@eclipso.eu> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c')
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
index 087012b18956..23adfbaae7f3 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
@@ -20,6 +20,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Ben Skeggs
+ * Roy Spliet
*/
#include <subdev/bios.h>
@@ -42,9 +43,17 @@ static u32
read_vco(struct nva3_clock_priv *priv, int clk)
{
u32 sctl = nv_rd32(priv, 0x4120 + (clk * 4));
- if ((sctl & 0x00000030) != 0x00000030)
+
+ switch (sctl & 0x00000030) {
+ case 0x00000000:
+ return nv_device(priv)->crystal;
+ case 0x00000020:
return read_pll(priv, 0x41, 0x00e820);
- return read_pll(priv, 0x42, 0x00e8a0);
+ case 0x00000030:
+ return read_pll(priv, 0x42, 0x00e8a0);
+ default:
+ return 0;
+ }
}
static u32
@@ -66,14 +75,25 @@ read_clk(struct nva3_clock_priv *priv, int clk, bool ignore_en)
if (!ignore_en && !(sctl & 0x00000100))
return 0;
+ /* out_alt */
+ if (sctl & 0x00000400)
+ return 108000;
+
+ /* vco_out */
switch (sctl & 0x00003000) {
case 0x00000000:
- return nv_device(priv)->crystal;
+ if (!(sctl & 0x00000200))
+ return nv_device(priv)->crystal;
+ return 0;
case 0x00002000:
if (sctl & 0x00000040)
return 108000;
return 100000;
case 0x00003000:
+ /* vco_enable */
+ if (!(sctl & 0x00000001))
+ return 0;
+
sclk = read_vco(priv, clk);
sdiv = ((sctl & 0x003f0000) >> 16) + 2;
return (sclk * 2) / sdiv;
@@ -95,7 +115,9 @@ read_pll(struct nva3_clock_priv *priv, int clk, u32 pll)
N = (coef & 0x0000ff00) >> 8;
P = (coef & 0x003f0000) >> 16;
- /* no post-divider on these.. */
+ /* no post-divider on these..
+ * XXX: it looks more like two post-"dividers" that
+ * cross each other out in the default RPLL config */
if ((pll & 0x00ff00) == 0x00e800)
P = 1;
@@ -136,6 +158,8 @@ nva3_clock_read(struct nouveau_clock *clk, enum nv_clk_src src)
nv_error(clk, "invalid clock source %d\n", src);
return -EINVAL;
}
+
+ return 0;
}
int