ASoC: rsnd: don't call clk_get_rate() under atomic context
[platform/kernel/linux-rpi.git] / sound / soc / sh / rcar / adg.c
index 051f964..549a137 100644 (file)
@@ -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);