ASoC: arizona: Fixed a bug in FLL fractional calculation
authorRyo Tsutsui <ryo.tsutsui@wolfsonmicro.com>
Sun, 3 Feb 2013 08:18:00 +0000 (17:18 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 4 Feb 2013 18:29:04 +0000 (18:29 +0000)
Previously arizona_calc_fll() was checking if the target frequency is
exactly divisible by reference frequency, but should have been product
of the ratio and the reference frequency.

Also scale down the Lamba and Theta coefficients be under 16-bits in
order to match the registers.

Signed-off-by: Ryo Tsutsui <ryo.tsutsui@wolfsonmicro.com>
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: stable@vger.kernel.org
sound/soc/codecs/arizona.c

index ef62c435848eb776421776d7e80e90527e3f2b72..2899cb909d1e1fb9c99e65700210c323eb70ac4e 100644 (file)
@@ -910,7 +910,7 @@ static int arizona_calc_fll(struct arizona_fll *fll,
 
        cfg->n = target / (ratio * Fref);
 
-       if (target % Fref) {
+       if (target % (ratio * Fref)) {
                gcd_fll = gcd(target, ratio * Fref);
                arizona_fll_dbg(fll, "GCD=%u\n", gcd_fll);
 
@@ -922,6 +922,15 @@ static int arizona_calc_fll(struct arizona_fll *fll,
                cfg->lambda = 0;
        }
 
+       /* Round down to 16bit range with cost of accuracy lost.
+        * Denominator must be bigger than numerator so we only
+        * take care of it.
+        */
+       while (cfg->lambda >= (1 << 16)) {
+               cfg->theta >>= 1;
+               cfg->lambda >>= 1;
+       }
+
        arizona_fll_dbg(fll, "N=%x THETA=%x LAMBDA=%x\n",
                        cfg->n, cfg->theta, cfg->lambda);
        arizona_fll_dbg(fll, "FRATIO=%x(%d) OUTDIV=%x REFCLK_DIV=%x\n",