Commit 06e8f5c8 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown

ASoC: rsnd: don't call clk_get_rate() under atomic context

ADG is using clk_get_rate() under atomic context, thus, we might
have scheduling issue.
To avoid this issue, we need to get/keep clk rate under
non atomic context.

We need to handle ADG as special device at Renesas Sound driver.
From SW point of view, we want to impletent it as
rsnd_mod_ops :: prepare, but it makes code just complicate.

To avoid complicated code/patch, this patch adds new clk_rate[] array,
and keep clk IN rate when rsnd_adg_clk_enable() was called.
Reported-by: default avatarLeon Kong <Leon.KONG@cn.bosch.com>
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tested-by: default avatarLeon Kong <Leon.KONG@cn.bosch.com>
Link: https://lore.kernel.org/r/87v9vb0xkp.wl-kuninori.morimoto.gx@renesas.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7c076764
...@@ -30,6 +30,7 @@ struct rsnd_adg { ...@@ -30,6 +30,7 @@ struct rsnd_adg {
struct clk *clkout[CLKOUTMAX]; struct clk *clkout[CLKOUTMAX];
struct clk_onecell_data onecell; struct clk_onecell_data onecell;
struct rsnd_mod mod; struct rsnd_mod mod;
int clk_rate[CLKMAX];
u32 flags; u32 flags;
u32 ckr; u32 ckr;
u32 rbga; u32 rbga;
...@@ -114,9 +115,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, ...@@ -114,9 +115,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv,
unsigned int val, en; unsigned int val, en;
unsigned int min, diff; unsigned int min, diff;
unsigned int sel_rate[] = { unsigned int sel_rate[] = {
clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ adg->clk_rate[CLKA], /* 0000: CLKA */
clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ adg->clk_rate[CLKB], /* 0001: CLKB */
clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ adg->clk_rate[CLKC], /* 0010: CLKC */
adg->rbga_rate_for_441khz, /* 0011: RBGA */ adg->rbga_rate_for_441khz, /* 0011: RBGA */
adg->rbgb_rate_for_48khz, /* 0100: RBGB */ adg->rbgb_rate_for_48khz, /* 0100: RBGB */
}; };
...@@ -302,7 +303,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) ...@@ -302,7 +303,7 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
* AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI.
*/ */
for_each_rsnd_clk(clk, adg, i) { for_each_rsnd_clk(clk, adg, i) {
if (rate == clk_get_rate(clk)) if (rate == adg->clk_rate[i])
return sel_table[i]; return sel_table[i];
} }
...@@ -369,10 +370,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) ...@@ -369,10 +370,18 @@ void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
for_each_rsnd_clk(clk, adg, i) { for_each_rsnd_clk(clk, adg, i) {
ret = 0; ret = 0;
if (enable) if (enable) {
ret = clk_prepare_enable(clk); 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); clk_disable_unprepare(clk);
}
if (ret < 0) if (ret < 0)
dev_warn(dev, "can't use clk %d\n", i); dev_warn(dev, "can't use clk %d\n", i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment