| From d57fe0fdd88d7e8b51a6b855e4edc290064c542b Mon Sep 17 00:00:00 2001 |
| From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> |
| Date: Tue, 25 Oct 2016 00:37:35 +0000 |
| Subject: [PATCH 070/299] 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> |
| (cherry picked from commit 10a9cca13220888c20a259abbd42ea117cddfdb0) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| sound/soc/sh/rcar/core.c | 26 ++++++++++++++++++++++++++ |
| sound/soc/sh/rcar/rsnd.h | 15 ++++++++++++++- |
| 2 files changed, 40 insertions(+), 1 deletion(-) |
| |
| --- 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(str |
| 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, |
| --- 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) |