diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2016-10-25 00:37:35 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-10-25 15:02:43 +0100 |
commit | 10a9cca13220888c20a259abbd42ea117cddfdb0 (patch) | |
tree | 839476bc3f9a3f86b5143ed144f226b55d4d7f45 /sound/soc/sh/rcar | |
parent | 161ba1f1a5c99c4525eb39cc71ec984e0a39e6d7 (diff) | |
download | linux-10a9cca13220888c20a259abbd42ea117cddfdb0.tar.gz linux-10a9cca13220888c20a259abbd42ea117cddfdb0.tar.xz |
ASoC: rsnd: add nolock_start/stop callback
Current Renesas Sound driver requests DMA channel when .probe timing,
and release it when .remove timing. And use DMA on .start/.stop
But, Audio DMAC power ON was handled when request timing (= .probe),
and power OFF was when release timing (= .remove).
This means Audio DMAC power is always ON during driver was enabled.
To fixup this issue, it should request/release DMA channel on each
playback/recorde timing.
But, DMA channel request/release function uses mutex lock inside.
This means it will breaks current spinlock's interrupt protect.
To solve this issue, DMA channel request/release function needs to
be called from non-spinlock area. This patch adds its callback.
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')
-rw-r--r-- | sound/soc/sh/rcar/core.c | 26 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 15 |
2 files changed, 40 insertions, 1 deletions
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index ea14a1470de2..9ffa29941ceb 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -716,7 +716,33 @@ static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } +static int rsnd_soc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); + struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); + + /* + * call rsnd_dai_call without spinlock + */ + return rsnd_dai_call(nolock_start, io, priv); +} + +static void rsnd_soc_dai_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai); + struct rsnd_dai_stream *io = rsnd_rdai_to_io(rdai, substream); + + /* + * call rsnd_dai_call without spinlock + */ + rsnd_dai_call(nolock_stop, io, priv); +} + static const struct snd_soc_dai_ops rsnd_soc_dai_ops = { + .startup = rsnd_soc_dai_startup, + .shutdown = rsnd_soc_dai_shutdown, .trigger = rsnd_soc_dai_trigger, .set_fmt = rsnd_soc_dai_set_fmt, .set_tdm_slot = rsnd_soc_set_dai_tdm_slot, diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index c1cee1ab3e62..422b5344b687 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -259,6 +259,12 @@ struct rsnd_mod_ops { int (*fallback)(struct rsnd_mod *mod, struct rsnd_dai_stream *io, struct rsnd_priv *priv); + int (*nolock_start)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv); + int (*nolock_stop)(struct rsnd_mod *mod, + struct rsnd_dai_stream *io, + struct rsnd_priv *priv); }; struct rsnd_dai_stream; @@ -276,8 +282,9 @@ struct rsnd_mod { /* * status * - * 0xH0000CB0 + * 0xH0000CBA * + * A 0: nolock_start 1: nolock_stop * B 0: init 1: quit * C 0: start 1: stop * @@ -287,6 +294,8 @@ struct rsnd_mod { * H 0: fallback * H 0: hw_params */ +#define __rsnd_mod_shift_nolock_start 0 +#define __rsnd_mod_shift_nolock_stop 0 #define __rsnd_mod_shift_init 4 #define __rsnd_mod_shift_quit 4 #define __rsnd_mod_shift_start 8 @@ -300,6 +309,8 @@ struct rsnd_mod { #define __rsnd_mod_add_probe 0 #define __rsnd_mod_add_remove 0 +#define __rsnd_mod_add_nolock_start 1 +#define __rsnd_mod_add_nolock_stop -1 #define __rsnd_mod_add_init 1 #define __rsnd_mod_add_quit -1 #define __rsnd_mod_add_start 1 @@ -319,6 +330,8 @@ struct rsnd_mod { #define __rsnd_mod_call_pcm_new 0 #define __rsnd_mod_call_fallback 0 #define __rsnd_mod_call_hw_params 0 +#define __rsnd_mod_call_nolock_start 0 +#define __rsnd_mod_call_nolock_stop 1 #define rsnd_mod_to_priv(mod) ((mod)->priv) #define rsnd_mod_id(mod) ((mod) ? (mod)->id : -1) |