ASoC: codecs: ALC5639/40: Update pll calc logic
Manoj Gangwal [Tue, 21 May 2013 07:37:45 +0000 (12:37 +0530)]
Bug 1284439

Change-Id: Icb724360db819e5cef6b47878b635b0de6727b82
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/231109
Reviewed-by: Harshada Kale <hkale@nvidia.com>
Tested-by: Harshada Kale <hkale@nvidia.com>

sound/soc/codecs/rt5639.c
sound/soc/codecs/rt5640.c

index ef5efe8..67313c0 100644 (file)
@@ -2600,8 +2600,8 @@ static int rt5639_pll_calc(const unsigned int freq_in,
        const unsigned int freq_out, struct rt5639_pll_code *pll_code)
 {
        int max_n = RT5639_PLL_N_MAX, max_m = RT5639_PLL_M_MAX;
-       int k, n, m, red, n_t, m_t, pll_out, in_t, out_t, red_t =
-                                               abs(freq_out - freq_in);
+       int k, n = 0, m = 0, red, n_t, m_t, pll_out, in_t, out_t;
+       int red_t = abs(freq_out - freq_in);
        bool bypass = false;
 
        if (RT5639_PLL_INP_MAX < freq_in || RT5639_PLL_INP_MIN > freq_in)
@@ -2620,7 +2620,9 @@ static int rt5639_pll_calc(const unsigned int freq_in,
                        n = n_t;
                        goto code_find;
                }
-               red = abs(in_t - pll_out); /*m bypass*/
+
+               red = abs(in_t - pll_out);
+
                if (red < red_t) {
                        bypass = true;
                        n = n_t;
index e6a031c..984f72c 100644 (file)
@@ -2460,25 +2460,40 @@ static int rt5640_pll_calc(const unsigned int freq_in,
        const unsigned int freq_out, struct rt5640_pll_code *pll_code)
 {
        int max_n = RT5640_PLL_N_MAX, max_m = RT5640_PLL_M_MAX;
-       int n, m, red, n_t, m_t, in_t, out_t, red_t = abs(freq_out - freq_in);
+       int k, n = 0, m = 0, red, n_t, m_t, pll_out, in_t, out_t;
+       int red_t = abs(freq_out - freq_in);
        bool bypass = false;
 
        if (RT5640_PLL_INP_MAX < freq_in || RT5640_PLL_INP_MIN > freq_in)
                return -EINVAL;
 
+       k = 100000000 / freq_out - 2;
+       if (k > RT5640_PLL_K_MAX)
+               k = RT5640_PLL_K_MAX;
        for (n_t = 0; n_t <= max_n; n_t++) {
-               in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
+               in_t = freq_in / (k + 2);
+               pll_out = freq_out / (n_t + 2);
                if (in_t < 0)
                        continue;
-               if (in_t == freq_out) {
+               if (in_t == pll_out) {
                        bypass = true;
                        n = n_t;
                        goto code_find;
                }
+               red = abs(in_t - pll_out);
+               if (red < red_t) {
+                       bypass = true;
+                       n = n_t;
+                       m = m_t;
+                       if (red == 0)
+                               goto code_find;
+                       red_t = red;
+               }
                for (m_t = 0; m_t <= max_m; m_t++) {
                        out_t = in_t / (m_t + 2);
-                       red = abs(out_t - freq_out);
+                       red = abs(out_t - pll_out);
                        if (red < red_t) {
+                               bypass = false;
                                n = n_t;
                                m = m_t;
                                if (red == 0)
@@ -2494,7 +2509,7 @@ code_find:
        pll_code->m_bp = bypass;
        pll_code->m_code = m;
        pll_code->n_code = n;
-       pll_code->k_code = 2;
+       pll_code->k_code = k;
        return 0;
 }
 
@@ -2570,8 +2585,9 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
                return ret;
        }
 
-       dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code.m_bp,
-               (pll_code.m_bp ? 0 : pll_code.m_code), pll_code.n_code);
+       dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n", pll_code.m_bp,
+               (pll_code.m_bp ? 0 : pll_code.m_code),
+               pll_code.n_code, pll_code.k_code);
 
        snd_soc_write(codec, RT5640_PLL_CTRL1,
                pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code);