drm/nva3/clk: Parse clock control registers more accurately
authorRoy Spliet <rspliet@eclipso.eu>
Thu, 21 Aug 2014 11:45:12 +0000 (13:45 +0200)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 15 Sep 2014 12:24:59 +0000 (22:24 +1000)
Signed-off-by: Roy Spliet <rspliet@eclipso.eu>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c

index 087012b189569ee8cf21e1d2f02327023093f25d..23adfbaae7f362b7a21b6995102c1524930628ac 100644 (file)
@@ -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