aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOder Chiou <oder_chiou@realtek.com>2014-05-20 03:01:54 -0400
committerMark Brown <broonie@linaro.org>2014-06-01 15:04:30 -0400
commit71c7a2d675c8fe9b6ab284dcf586f30a7109c96c (patch)
tree4e988ed02a95e9936accebff5c4e5a38b48c45b5
parent49ef7925c237a2f9da327ea3481dd5bba54693e8 (diff)
ASoC: rt5640: Add the function of the PLL clock calculation to RL6231 shared support
The patch adds the function of the PLL clock calculation to RL6231 shared support. Signed-off-by: Oder Chiou <oder_chiou@realtek.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/codecs/rl6231.c69
-rw-r--r--sound/soc/codecs/rl6231.h15
-rw-r--r--sound/soc/codecs/rt5640.c68
-rw-r--r--sound/soc/codecs/rt5640.h8
-rw-r--r--sound/soc/codecs/rt5645.c72
-rw-r--r--sound/soc/codecs/rt5645.h7
-rw-r--r--sound/soc/codecs/rt5651.c68
-rw-r--r--sound/soc/codecs/rt5651.h1
8 files changed, 102 insertions, 206 deletions
diff --git a/sound/soc/codecs/rl6231.c b/sound/soc/codecs/rl6231.c
index 13ac551f6c79..289024be1d40 100644
--- a/sound/soc/codecs/rl6231.c
+++ b/sound/soc/codecs/rl6231.c
@@ -62,6 +62,75 @@ int rl6231_calc_dmic_clk(int rate)
62} 62}
63EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk); 63EXPORT_SYMBOL_GPL(rl6231_calc_dmic_clk);
64 64
65/**
66 * rl6231_pll_calc - Calcualte PLL M/N/K code.
67 * @freq_in: external clock provided to codec.
68 * @freq_out: target clock which codec works on.
69 * @pll_code: Pointer to structure with M, N, K and bypass flag.
70 *
71 * Calcualte M/N/K code to configure PLL for codec.
72 *
73 * Returns 0 for success or negative error code.
74 */
75int rl6231_pll_calc(const unsigned int freq_in,
76 const unsigned int freq_out, struct rl6231_pll_code *pll_code)
77{
78 int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX;
79 int k, red, n_t, pll_out, in_t, out_t;
80 int n = 0, m = 0, m_t = 0;
81 int red_t = abs(freq_out - freq_in);
82 bool bypass = false;
83
84 if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in)
85 return -EINVAL;
86
87 k = 100000000 / freq_out - 2;
88 if (k > RL6231_PLL_K_MAX)
89 k = RL6231_PLL_K_MAX;
90 for (n_t = 0; n_t <= max_n; n_t++) {
91 in_t = freq_in / (k + 2);
92 pll_out = freq_out / (n_t + 2);
93 if (in_t < 0)
94 continue;
95 if (in_t == pll_out) {
96 bypass = true;
97 n = n_t;
98 goto code_find;
99 }
100 red = abs(in_t - pll_out);
101 if (red < red_t) {
102 bypass = true;
103 n = n_t;
104 m = m_t;
105 if (red == 0)
106 goto code_find;
107 red_t = red;
108 }
109 for (m_t = 0; m_t <= max_m; m_t++) {
110 out_t = in_t / (m_t + 2);
111 red = abs(out_t - pll_out);
112 if (red < red_t) {
113 bypass = false;
114 n = n_t;
115 m = m_t;
116 if (red == 0)
117 goto code_find;
118 red_t = red;
119 }
120 }
121 }
122 pr_debug("Only get approximation about PLL\n");
123
124code_find:
125
126 pll_code->m_bp = bypass;
127 pll_code->m_code = m;
128 pll_code->n_code = n;
129 pll_code->k_code = k;
130 return 0;
131}
132EXPORT_SYMBOL_GPL(rl6231_pll_calc);
133
65MODULE_DESCRIPTION("RL6231 class device shared support"); 134MODULE_DESCRIPTION("RL6231 class device shared support");
66MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>"); 135MODULE_AUTHOR("Oder Chiou <oder_chiou@realtek.com>");
67MODULE_LICENSE("GPL v2"); 136MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/rl6231.h b/sound/soc/codecs/rl6231.h
index 00032dba1aa9..efdfc869afe9 100644
--- a/sound/soc/codecs/rl6231.h
+++ b/sound/soc/codecs/rl6231.h
@@ -13,6 +13,21 @@
13#ifndef __RL6231_H__ 13#ifndef __RL6231_H__
14#define __RL6231_H__ 14#define __RL6231_H__
15 15
16#define RL6231_PLL_INP_MAX 40000000
17#define RL6231_PLL_INP_MIN 256000
18#define RL6231_PLL_N_MAX 0x1ff
19#define RL6231_PLL_K_MAX 0x1f
20#define RL6231_PLL_M_MAX 0xf
21
22struct rl6231_pll_code {
23 bool m_bp; /* Indicates bypass m code or not. */
24 int m_code;
25 int n_code;
26 int k_code;
27};
28
16int rl6231_calc_dmic_clk(int rate); 29int rl6231_calc_dmic_clk(int rate);
30int rl6231_pll_calc(const unsigned int freq_in,
31 const unsigned int freq_out, struct rl6231_pll_code *pll_code);
17 32
18#endif /* __RL6231_H__ */ 33#endif /* __RL6231_H__ */
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index d586228ae5b9..e945f8d0ffc5 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -1806,65 +1806,12 @@ static int rt5640_set_dai_sysclk(struct snd_soc_dai *dai,
1806 return 0; 1806 return 0;
1807} 1807}
1808 1808
1809/**
1810 * rt5640_pll_calc - Calculate PLL M/N/K code.
1811 * @freq_in: external clock provided to codec.
1812 * @freq_out: target clock which codec works on.
1813 * @pll_code: Pointer to structure with M, N, K and bypass flag.
1814 *
1815 * Calculate M/N/K code to configure PLL for codec. And K is assigned to 2
1816 * which make calculation more efficiently.
1817 *
1818 * Returns 0 for success or negative error code.
1819 */
1820static int rt5640_pll_calc(const unsigned int freq_in,
1821 const unsigned int freq_out, struct rt5640_pll_code *pll_code)
1822{
1823 int max_n = RT5640_PLL_N_MAX, max_m = RT5640_PLL_M_MAX;
1824 int n = 0, m = 0, red, n_t, m_t, in_t, out_t;
1825 int red_t = abs(freq_out - freq_in);
1826 bool bypass = false;
1827
1828 if (RT5640_PLL_INP_MAX < freq_in || RT5640_PLL_INP_MIN > freq_in)
1829 return -EINVAL;
1830
1831 for (n_t = 0; n_t <= max_n; n_t++) {
1832 in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
1833 if (in_t < 0)
1834 continue;
1835 if (in_t == freq_out) {
1836 bypass = true;
1837 n = n_t;
1838 goto code_find;
1839 }
1840 for (m_t = 0; m_t <= max_m; m_t++) {
1841 out_t = in_t / (m_t + 2);
1842 red = abs(out_t - freq_out);
1843 if (red < red_t) {
1844 n = n_t;
1845 m = m_t;
1846 if (red == 0)
1847 goto code_find;
1848 red_t = red;
1849 }
1850 }
1851 }
1852 pr_debug("Only get approximation about PLL\n");
1853
1854code_find:
1855 pll_code->m_bp = bypass;
1856 pll_code->m_code = m;
1857 pll_code->n_code = n;
1858 pll_code->k_code = 2;
1859 return 0;
1860}
1861
1862static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 1809static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1863 unsigned int freq_in, unsigned int freq_out) 1810 unsigned int freq_in, unsigned int freq_out)
1864{ 1811{
1865 struct snd_soc_codec *codec = dai->codec; 1812 struct snd_soc_codec *codec = dai->codec;
1866 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec); 1813 struct rt5640_priv *rt5640 = snd_soc_codec_get_drvdata(codec);
1867 struct rt5640_pll_code *pll_code = &rt5640->pll_code; 1814 struct rl6231_pll_code pll_code;
1868 int ret, dai_sel; 1815 int ret, dai_sel;
1869 1816
1870 if (source == rt5640->pll_src && freq_in == rt5640->pll_in && 1817 if (source == rt5640->pll_src && freq_in == rt5640->pll_in &&
@@ -1908,20 +1855,21 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1908 return -EINVAL; 1855 return -EINVAL;
1909 } 1856 }
1910 1857
1911 ret = rt5640_pll_calc(freq_in, freq_out, pll_code); 1858 ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
1912 if (ret < 0) { 1859 if (ret < 0) {
1913 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); 1860 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
1914 return ret; 1861 return ret;
1915 } 1862 }
1916 1863
1917 dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp, 1864 dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
1918 (pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code); 1865 pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
1866 pll_code.n_code, pll_code.k_code);
1919 1867
1920 snd_soc_write(codec, RT5640_PLL_CTRL1, 1868 snd_soc_write(codec, RT5640_PLL_CTRL1,
1921 pll_code->n_code << RT5640_PLL_N_SFT | pll_code->k_code); 1869 pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code);
1922 snd_soc_write(codec, RT5640_PLL_CTRL2, 1870 snd_soc_write(codec, RT5640_PLL_CTRL2,
1923 (pll_code->m_bp ? 0 : pll_code->m_code) << RT5640_PLL_M_SFT | 1871 (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT |
1924 pll_code->m_bp << RT5640_PLL_M_BP_SFT); 1872 pll_code.m_bp << RT5640_PLL_M_BP_SFT);
1925 1873
1926 rt5640->pll_in = freq_in; 1874 rt5640->pll_in = freq_in;
1927 rt5640->pll_out = freq_out; 1875 rt5640->pll_out = freq_out;
diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h
index 895ca149db2e..58ebe96b86da 100644
--- a/sound/soc/codecs/rt5640.h
+++ b/sound/soc/codecs/rt5640.h
@@ -2079,13 +2079,6 @@ enum {
2079 RT5640_DMIC2, 2079 RT5640_DMIC2,
2080}; 2080};
2081 2081
2082struct rt5640_pll_code {
2083 bool m_bp; /* Indicates bypass m code or not. */
2084 int m_code;
2085 int n_code;
2086 int k_code;
2087};
2088
2089struct rt5640_priv { 2082struct rt5640_priv {
2090 struct snd_soc_codec *codec; 2083 struct snd_soc_codec *codec;
2091 struct rt5640_platform_data pdata; 2084 struct rt5640_platform_data pdata;
@@ -2097,7 +2090,6 @@ struct rt5640_priv {
2097 int bclk[RT5640_AIFS]; 2090 int bclk[RT5640_AIFS];
2098 int master[RT5640_AIFS]; 2091 int master[RT5640_AIFS];
2099 2092
2100 struct rt5640_pll_code pll_code;
2101 int pll_src; 2093 int pll_src;
2102 int pll_in; 2094 int pll_in;
2103 int pll_out; 2095 int pll_out;
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index caa55199eb87..ee6db7c7c5e8 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -1964,80 +1964,12 @@ static int rt5645_set_dai_sysclk(struct snd_soc_dai *dai,
1964 return 0; 1964 return 0;
1965} 1965}
1966 1966
1967/**
1968 * rt5645_pll_calc - Calcualte PLL M/N/K code.
1969 * @freq_in: external clock provided to codec.
1970 * @freq_out: target clock which codec works on.
1971 * @pll_code: Pointer to structure with M, N, K and bypass flag.
1972 *
1973 * Calcualte M/N/K code to configure PLL for codec. And K is assigned to 2
1974 * which make calculation more efficiently.
1975 *
1976 * Returns 0 for success or negative error code.
1977 */
1978static int rt5645_pll_calc(const unsigned int freq_in,
1979 const unsigned int freq_out, struct rt5645_pll_code *pll_code)
1980{
1981 int max_n = RT5645_PLL_N_MAX, max_m = RT5645_PLL_M_MAX;
1982 int k, n = 0, m = 0, red, n_t, m_t, pll_out, in_t, out_t;
1983 int red_t = abs(freq_out - freq_in);
1984 bool bypass = false;
1985
1986 if (RT5645_PLL_INP_MAX < freq_in || RT5645_PLL_INP_MIN > freq_in)
1987 return -EINVAL;
1988
1989 k = 100000000 / freq_out - 2;
1990 if (k > RT5645_PLL_K_MAX)
1991 k = RT5645_PLL_K_MAX;
1992 for (n_t = 0; n_t <= max_n; n_t++) {
1993 in_t = freq_in / (k + 2);
1994 pll_out = freq_out / (n_t + 2);
1995 if (in_t < 0)
1996 continue;
1997 if (in_t == pll_out) {
1998 bypass = true;
1999 n = n_t;
2000 goto code_find;
2001 }
2002 red = abs(in_t - pll_out);
2003 if (red < red_t) {
2004 bypass = true;
2005 n = n_t;
2006 m = m_t;
2007 if (red == 0)
2008 goto code_find;
2009 red_t = red;
2010 }
2011 for (m_t = 0; m_t <= max_m; m_t++) {
2012 out_t = in_t / (m_t + 2);
2013 red = abs(out_t - pll_out);
2014 if (red < red_t) {
2015 bypass = false;
2016 n = n_t;
2017 m = m_t;
2018 if (red == 0)
2019 goto code_find;
2020 red_t = red;
2021 }
2022 }
2023 }
2024 pr_debug("Only get approximation about PLL\n");
2025
2026code_find:
2027
2028 pll_code->m_bp = bypass;
2029 pll_code->m_code = m;
2030 pll_code->n_code = n;
2031 pll_code->k_code = k;
2032 return 0;
2033}
2034
2035static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 1967static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
2036 unsigned int freq_in, unsigned int freq_out) 1968 unsigned int freq_in, unsigned int freq_out)
2037{ 1969{
2038 struct snd_soc_codec *codec = dai->codec; 1970 struct snd_soc_codec *codec = dai->codec;
2039 struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec); 1971 struct rt5645_priv *rt5645 = snd_soc_codec_get_drvdata(codec);
2040 struct rt5645_pll_code pll_code; 1972 struct rl6231_pll_code pll_code;
2041 int ret; 1973 int ret;
2042 1974
2043 if (source == rt5645->pll_src && freq_in == rt5645->pll_in && 1975 if (source == rt5645->pll_src && freq_in == rt5645->pll_in &&
@@ -2080,7 +2012,7 @@ static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
2080 return -EINVAL; 2012 return -EINVAL;
2081 } 2013 }
2082 2014
2083 ret = rt5645_pll_calc(freq_in, freq_out, &pll_code); 2015 ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
2084 if (ret < 0) { 2016 if (ret < 0) {
2085 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); 2017 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
2086 return ret; 2018 return ret;
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index 345aa3f5d14f..355b7e9eefab 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -2162,13 +2162,6 @@ enum {
2162 RT5645_DMIC_DATA_GPIO11, 2162 RT5645_DMIC_DATA_GPIO11,
2163}; 2163};
2164 2164
2165struct rt5645_pll_code {
2166 bool m_bp; /* Indicates bypass m code or not. */
2167 int m_code;
2168 int n_code;
2169 int k_code;
2170};
2171
2172struct rt5645_priv { 2165struct rt5645_priv {
2173 struct snd_soc_codec *codec; 2166 struct snd_soc_codec *codec;
2174 struct rt5645_platform_data pdata; 2167 struct rt5645_platform_data pdata;
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 7a7bec6f26e6..a627a1f9dfcb 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -1516,65 +1516,12 @@ static int rt5651_set_dai_sysclk(struct snd_soc_dai *dai,
1516 return 0; 1516 return 0;
1517} 1517}
1518 1518
1519/**
1520 * rt5651_pll_calc - Calcualte PLL M/N/K code.
1521 * @freq_in: external clock provided to codec.
1522 * @freq_out: target clock which codec works on.
1523 * @pll_code: Pointer to structure with M, N, K and bypass flag.
1524 *
1525 * Calcualte M/N/K code to configure PLL for codec. And K is assigned to 2
1526 * which make calculation more efficiently.
1527 *
1528 * Returns 0 for success or negative error code.
1529 */
1530static int rt5651_pll_calc(const unsigned int freq_in,
1531 const unsigned int freq_out, struct rt5651_pll_code *pll_code)
1532{
1533 int max_n = RT5651_PLL_N_MAX, max_m = RT5651_PLL_M_MAX;
1534 int n = 0, m = 0, red, n_t, m_t, in_t, out_t;
1535 int red_t = abs(freq_out - freq_in);
1536 bool bypass = false;
1537
1538 if (RT5651_PLL_INP_MAX < freq_in || RT5651_PLL_INP_MIN > freq_in)
1539 return -EINVAL;
1540
1541 for (n_t = 0; n_t <= max_n; n_t++) {
1542 in_t = (freq_in >> 1) + (freq_in >> 2) * n_t;
1543 if (in_t < 0)
1544 continue;
1545 if (in_t == freq_out) {
1546 bypass = true;
1547 n = n_t;
1548 goto code_find;
1549 }
1550 for (m_t = 0; m_t <= max_m; m_t++) {
1551 out_t = in_t / (m_t + 2);
1552 red = abs(out_t - freq_out);
1553 if (red < red_t) {
1554 n = n_t;
1555 m = m_t;
1556 if (red == 0)
1557 goto code_find;
1558 red_t = red;
1559 }
1560 }
1561 }
1562 pr_debug("Only get approximation about PLL\n");
1563
1564code_find:
1565 pll_code->m_bp = bypass;
1566 pll_code->m_code = m;
1567 pll_code->n_code = n;
1568 pll_code->k_code = 2;
1569 return 0;
1570}
1571
1572static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, 1519static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1573 unsigned int freq_in, unsigned int freq_out) 1520 unsigned int freq_in, unsigned int freq_out)
1574{ 1521{
1575 struct snd_soc_codec *codec = dai->codec; 1522 struct snd_soc_codec *codec = dai->codec;
1576 struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec); 1523 struct rt5651_priv *rt5651 = snd_soc_codec_get_drvdata(codec);
1577 struct rt5651_pll_code *pll_code = &rt5651->pll_code; 1524 struct rl6231_pll_code pll_code;
1578 int ret; 1525 int ret;
1579 1526
1580 if (source == rt5651->pll_src && freq_in == rt5651->pll_in && 1527 if (source == rt5651->pll_src && freq_in == rt5651->pll_in &&
@@ -1609,20 +1556,21 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source,
1609 return -EINVAL; 1556 return -EINVAL;
1610 } 1557 }
1611 1558
1612 ret = rt5651_pll_calc(freq_in, freq_out, pll_code); 1559 ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
1613 if (ret < 0) { 1560 if (ret < 0) {
1614 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in); 1561 dev_err(codec->dev, "Unsupport input clock %d\n", freq_in);
1615 return ret; 1562 return ret;
1616 } 1563 }
1617 1564
1618 dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=2\n", pll_code->m_bp, 1565 dev_dbg(codec->dev, "bypass=%d m=%d n=%d k=%d\n",
1619 (pll_code->m_bp ? 0 : pll_code->m_code), pll_code->n_code); 1566 pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code),
1567 pll_code.n_code, pll_code.k_code);
1620 1568
1621 snd_soc_write(codec, RT5651_PLL_CTRL1, 1569 snd_soc_write(codec, RT5651_PLL_CTRL1,
1622 pll_code->n_code << RT5651_PLL_N_SFT | pll_code->k_code); 1570 pll_code.n_code << RT5651_PLL_N_SFT | pll_code.k_code);
1623 snd_soc_write(codec, RT5651_PLL_CTRL2, 1571 snd_soc_write(codec, RT5651_PLL_CTRL2,
1624 (pll_code->m_bp ? 0 : pll_code->m_code) << RT5651_PLL_M_SFT | 1572 (pll_code.m_bp ? 0 : pll_code.m_code) << RT5651_PLL_M_SFT |
1625 pll_code->m_bp << RT5651_PLL_M_BP_SFT); 1573 pll_code.m_bp << RT5651_PLL_M_BP_SFT);
1626 1574
1627 rt5651->pll_in = freq_in; 1575 rt5651->pll_in = freq_in;
1628 rt5651->pll_out = freq_out; 1576 rt5651->pll_out = freq_out;
diff --git a/sound/soc/codecs/rt5651.h b/sound/soc/codecs/rt5651.h
index a28bd0c3d613..1bd33cfa6411 100644
--- a/sound/soc/codecs/rt5651.h
+++ b/sound/soc/codecs/rt5651.h
@@ -2069,7 +2069,6 @@ struct rt5651_priv {
2069 int bclk[RT5651_AIFS]; 2069 int bclk[RT5651_AIFS];
2070 int master[RT5651_AIFS]; 2070 int master[RT5651_AIFS];
2071 2071
2072 struct rt5651_pll_code pll_code;
2073 int pll_src; 2072 int pll_src;
2074 int pll_in; 2073 int pll_in;
2075 int pll_out; 2074 int pll_out;