|
|
@@ -30,6 +30,7 @@ struct rsnd_adg {
|
|
|
struct clk *clkout[CLKOUTMAX];
|
|
|
struct clk_onecell_data onecell;
|
|
|
struct rsnd_mod mod;
|
|
|
+ int clk_rate[CLKMAX];
|
|
|
u32 flags;
|
|
|
u32 ckr;
|
|
|
u32 rbga;
|
|
|
@@ -113,9 +114,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
|
|
|
unsigned int val, en;
|
|
|
unsigned int min, diff;
|
|
|
unsigned int sel_rate[] = {
|
|
|
- clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */
|
|
|
- clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */
|
|
|
- clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */
|
|
|
+ adg->clk_rate[CLKA], /* 0000: CLKA */
|
|
|
+ adg->clk_rate[CLKB], /* 0001: CLKB */
|
|
|
+ adg->clk_rate[CLKC], /* 0010: CLKC */
|
|
|
adg->rbga_rate_for_441khz, /* 0011: RBGA */
|
|
|
adg->rbgb_rate_for_48khz, /* 0100: RBGB */
|
|
|
};
|
|
|
@@ -331,7 +332,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
|
|
|
* AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
|
|
|
*/
|
|
|
for_each_rsnd_clk(clk, adg, i) {
|
|
|
- if (rate == clk_get_rate(clk))
|
|
|
+ if (rate == adg->clk_rate[i])
|
|
|
return sel_table[i];
|
|
|
}
|
|
|
|
|
|
@@ -398,10 +399,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
|
|
|
|
|
|
for_each_rsnd_clk(clk, adg, i) {
|
|
|
ret = 0;
|
|
|
- if (enable)
|
|
|
+ if (enable) {
|
|
|
ret = clk_prepare_enable(clk);
|
|
|
- else
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We shouldn't use clk_get_rate() under
|
|
|
+ * atomic context. Let's keep it when
|
|
|
+ * rsnd_adg_clk_enable() was called
|
|
|
+ */
|
|
|
+ adg->clk_rate[i] = clk_get_rate(adg->clk[i]);
|
|
|
+ } else {
|
|
|
clk_disable_unprepare(clk);
|
|
|
+ }
|
|
|
|
|
|
if (ret < 0)
|
|
|
dev_warn(dev, "can't use clk %d\n", i);
|