blob: a84e19dbd5c73236231070061186a142995a00fb [file] [log] [blame]
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)