diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2015-03-26 04:02:09 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-27 15:59:17 -0700 |
commit | 2f78dd7f40264697afed4c2ac0890df8f0588e49 (patch) | |
tree | 9d37d40fef4bbf1161f9d447def5273d242dbf93 /sound/soc/sh/rcar/core.c | |
parent | c517d838eb7d07bbe9507871fab3931deccff539 (diff) |
ASoC: rsnd: call clk_prepare/unprepare() in probe/remove
clk_prepare_enable()/clk_disable_unprepare() uses mutex inside,
in concretely clk_prepare()/clk_unprepare().And it uses __schedule().
Then, raw_spin_lock/unlock_irq() is called, and it breaks Renesas
sound driver's spin lock irq.
This patch separates thesse into clk_prepare()/clk_unprepare() and
clk_enable/clk_disable. And call clk_prepare()/clk_unprepare() from
probe/remove function. Special thanks to Das Biju.
Reported-by: Das Biju <biju.das@bp.renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/sh/rcar/core.c')
-rw-r--r-- | sound/soc/sh/rcar/core.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1b53605f7154..6046c10ef3c7 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -149,16 +149,29 @@ char *rsnd_mod_dma_name(struct rsnd_mod *mod) return mod->ops->dma_name(mod); } -void rsnd_mod_init(struct rsnd_mod *mod, +int rsnd_mod_init(struct rsnd_mod *mod, struct rsnd_mod_ops *ops, struct clk *clk, enum rsnd_mod_type type, int id) { + int ret = clk_prepare(clk); + + if (ret) + return ret; + mod->id = id; mod->ops = ops; mod->type = type; mod->clk = clk; + + return ret; +} + +void rsnd_mod_quit(struct rsnd_mod *mod) +{ + if (mod->clk) + clk_unprepare(mod->clk); } /* @@ -1290,6 +1303,12 @@ static int rsnd_remove(struct platform_device *pdev) { struct rsnd_priv *priv = dev_get_drvdata(&pdev->dev); struct rsnd_dai *rdai; + void (*remove_func[])(struct platform_device *pdev, + struct rsnd_priv *priv) = { + rsnd_ssi_remove, + rsnd_src_remove, + rsnd_dvc_remove, + }; int ret = 0, i; pm_runtime_disable(&pdev->dev); @@ -1299,6 +1318,9 @@ static int rsnd_remove(struct platform_device *pdev) ret |= rsnd_dai_call(remove, &rdai->capture, priv); } + for (i = 0; i < ARRAY_SIZE(remove_func); i++) + remove_func[i](pdev, priv); + snd_soc_unregister_component(&pdev->dev); snd_soc_unregister_platform(&pdev->dev); |