diff options
Diffstat (limited to 'sound/soc/samsung/audss.c')
-rw-r--r-- | sound/soc/samsung/audss.c | 59 |
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), |