aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung/audss.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/samsung/audss.c')
-rw-r--r--sound/soc/samsung/audss.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/sound/soc/samsung/audss.c b/sound/soc/samsung/audss.c
index 1c052b0..a5300de 100644
--- a/sound/soc/samsung/audss.c
+++ b/sound/soc/samsung/audss.c
@@ -52,13 +52,27 @@ static DEFINE_SPINLOCK(lock);
static int audss_clk_div_init(struct clk *src_clk)
{
- u32 clk_div = readl(S5P_CLKDIV_AUDSS);
+ struct clk *fout_epll;
u32 src_clk_rate = 0;
- u32 srp_div = 1;
- u32 bus_div = 2;
- u32 i2s_div = 2;
+ u64 srp_rate = 0;
+ u64 bus_rate = 0;
+ u64 i2s_rate = 0;
+ u32 srp_div;
+ u32 bus_div;
+ u32 i2s_div;
u32 ret = -1;
+ writel(0xF84, S5P_CLKDIV_AUDSS); /* to avoid over-clock */
+
+ fout_epll = clk_get(NULL, "fout_epll");
+ if (IS_ERR(fout_epll)) {
+ pr_err("%s: failed to get fout_epll\n", __func__);
+ return ret;
+ }
+ clk_set_parent(audss.mout_audss, fout_epll);
+
+ pr_debug("%s: CLKSRC[0x%x]\n", __func__, readl(S5P_CLKSRC_AUDSS));
+
src_clk_rate = clk_get_rate(src_clk);
if (!src_clk_rate) {
pr_err("%s: Can't get current clk_rate %d\n",
@@ -67,29 +81,32 @@ static int audss_clk_div_init(struct clk *src_clk)
}
pr_debug("%s: SRC Clock Rate[%d]\n", __func__, src_clk_rate);
- if (src_clk_rate > 100000000) {
- srp_div <<= 1;
- bus_div <<= 1;
- i2s_div <<= 1;
- }
- if (!strcmp(audss.rclksrc, "busclk"))
- i2s_div = 16; /* Use max div */
+ for (srp_div = 1; srp_div <= 16; srp_div++) {
+ if ((src_clk_rate >> (srp_div - 1)) <= 100000000)
+ break;
+ }
- clk_div &= ~(S5P_AUDSS_CLKDIV_RP_MASK
- | S5P_AUDSS_CLKDIV_BUSCLK_MASK
- | S5P_AUDSS_CLKDIV_I2SCLK_MASK);
+ for (bus_div = 1; bus_div <= 16; bus_div++) {
+ if ((src_clk_rate >> (bus_div - 1)) <= 50000000)
+ break;
+ }
- if (srp_div)
- clk_div |= (srp_div - 1) << S5P_AUDSS_CLKDIV_RP_SHIFT;
+ for (i2s_div = 1; i2s_div <= 16; i2s_div++) {
+ if ((src_clk_rate >> (i2s_div - 1)) <= 50000000)
+ break;
+ }
- if (bus_div)
- clk_div |= (bus_div - 1) << S5P_AUDSS_CLKDIV_BUSCLK_SHIFT;
+ if (!strcmp(audss.rclksrc, "busclk"))
+ i2s_div = 16; /* Use max div */
- if (i2s_div)
- clk_div |= (i2s_div - 1) << S5P_AUDSS_CLKDIV_I2SCLK_SHIFT;
+ srp_rate = src_clk_rate >> (srp_div - 1);
+ bus_rate = src_clk_rate >> (bus_div - 1);
+ i2s_rate = src_clk_rate >> (i2s_div - 1);
- writel(clk_div, S5P_CLKDIV_AUDSS);
+ clk_set_rate(audss.dout_srp, srp_rate);
+ clk_set_rate(audss.bus_clk, bus_rate);
+ clk_set_rate(audss.i2s_clk, i2s_rate);
pr_debug("%s: BUSCLK[%ld], I2SCLK[%ld]\n", __func__,
clk_get_rate(audss.bus_clk),