All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support
@ 2016-10-25  0:35 Kuninori Morimoto
  2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
                   ` (7 more replies)
  0 siblings, 8 replies; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:35 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


Hi Mark

These patches are for Renesas sound DMA.
1st feature is that it can power save for Audio DMAC.
2nd feature is that it can support IOMMU

1) - 5) : cleanup for 6) - 8)
6) - 7) : Audio DMAC power save
8)      : IOMMU support

Kuninori Morimoto (8):
      1) ASoC: rsnd: depends on OF
      2) ASoC: rsnd: remove non DT support for DMA
      3) ASoC: rsnd: don't use devm_request_irq() for SSI
      4) ASoC: rsnd: remove rsnd_dma_detach()
      5) ASoC: rsnd: don't call unneeded of_node_put() on dma.c
      6) ASoC: rsnd: add nolock_start/stop callback
      7) ASoC: rsnd: Request/Release DMA channel each time
      8) ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU

 sound/soc/sh/Kconfig     |   1 +
 sound/soc/sh/rcar/core.c |  30 +++++++++++++-
 sound/soc/sh/rcar/dma.c  | 304 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------
 sound/soc/sh/rcar/rsnd.h |  18 ++++++--
 sound/soc/sh/rcar/src.c  |   2 +-
 sound/soc/sh/rcar/ssi.c  |  22 +++++-----
 6 files changed, 248 insertions(+), 129 deletions(-)



Best regards
---
Kuninori Morimoto

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/8] ASoC: rsnd: depends on OF
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
@ 2016-10-25  0:35 ` Kuninori Morimoto
  2016-10-25 13:28   ` Mark Brown
  2016-10-26 15:12   ` Applied "ASoC: rsnd: depends on OF" to the asoc tree Mark Brown
  2016-10-25  0:36 ` [PATCH 2/8] ASoC: rsnd: remove non DT support for DMA Kuninori Morimoto
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:35 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

Current Renesas sound driver is completely depends on CONFIG_OF

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 6db6405..610fa85 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
 	tristate "R-Car series SRU/SCU/SSIU/SSI support"
 	depends on COMMON_CLK
+	depends on OF
 	select SND_SIMPLE_CARD
 	select REGMAP_MMIO
 	help
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/8] ASoC: rsnd: remove non DT support for DMA
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
  2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
@ 2016-10-25  0:36 ` Kuninori Morimoto
  2016-10-25 19:24   ` Applied "ASoC: rsnd: remove non DT support for DMA" to the asoc tree Mark Brown
  2016-10-25  0:36 ` [PATCH 3/8] ASoC: rsnd: don't use devm_request_irq() for SSI Kuninori Morimoto
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

Current Renesas Sound driver is based on DeviceTree, and no one is
using this driver from non DT. Non-DT support is no longer needed.
Let's remove it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/dma.c  | 21 ++++++---------------
 sound/soc/sh/rcar/rsnd.h |  2 +-
 sound/soc/sh/rcar/src.c  |  2 +-
 sound/soc/sh/rcar/ssi.c  |  3 +--
 4 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index b3bdd36..e0761ca 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -191,7 +191,7 @@ static int rsnd_dmaen_remove(struct rsnd_mod *mod,
 }
 
 static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
-			   struct rsnd_dma *dma, int id,
+			   struct rsnd_dma *dma,
 			   struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
 {
 	struct rsnd_mod *mod = rsnd_mod_get(dma);
@@ -208,17 +208,8 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
 		return -EIO;
 	}
 
-	if (dev->of_node) {
-		dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
-	} else {
-		dma_cap_mask_t mask;
-
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
+	dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
 
-		dmaen->chan = dma_request_channel(mask, shdma_chan_filter,
-						  (void *)(uintptr_t)id);
-	}
 	if (IS_ERR_OR_NULL(dmaen->chan)) {
 		dmaen->chan = NULL;
 		dev_err(dev, "can't get dma channel\n");
@@ -394,7 +385,7 @@ static int rsnd_dmapp_start(struct rsnd_mod *mod,
 }
 
 static int rsnd_dmapp_attach(struct rsnd_dai_stream *io,
-			     struct rsnd_dma *dma, int id,
+			     struct rsnd_dma *dma,
 			     struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
 {
 	struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
@@ -627,7 +618,7 @@ static void rsnd_dma_of_path(struct rsnd_mod *this,
 }
 
 int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
-		    struct rsnd_mod **dma_mod, int id)
+		    struct rsnd_mod **dma_mod)
 {
 	struct rsnd_mod *mod_from = NULL;
 	struct rsnd_mod *mod_to = NULL;
@@ -636,7 +627,7 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_mod_ops *ops;
 	enum rsnd_mod_type type;
-	int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
+	int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma,
 		      struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
 	int is_play = rsnd_io_is_play(io);
 	int ret, dma_id;
@@ -695,7 +686,7 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 			rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
 			rsnd_mod_name(mod_to),   rsnd_mod_id(mod_to));
 
-		ret = attach(io, dma, id, mod_from, mod_to);
+		ret = attach(io, dma, mod_from, mod_to);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index b3b4d89..2460d1f 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -199,7 +199,7 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
  *	R-Car DMA
  */
 int rsnd_dma_attach(struct rsnd_dai_stream *io,
-		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod, int id);
+		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 int rsnd_dma_probe(struct rsnd_priv *priv);
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 969a516..e13d6d4 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -475,7 +475,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod,
 			return ret;
 	}
 
-	ret = rsnd_dma_attach(io, mod, &src->dma, 0);
+	ret = rsnd_dma_attach(io, mod, &src->dma);
 
 	return ret;
 }
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 94a19f9..59cd982 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -669,7 +669,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 			      struct rsnd_priv *priv)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	int dma_id = 0; /* not needed */
 	int ret;
 
 	/*
@@ -684,7 +683,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 		return ret;
 
 	/* SSI probe might be called many times in MUX multi path */
-	ret = rsnd_dma_attach(io, mod, &ssi->dma, dma_id);
+	ret = rsnd_dma_attach(io, mod, &ssi->dma);
 
 	return ret;
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/8] ASoC: rsnd: don't use devm_request_irq() for SSI
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
  2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
  2016-10-25  0:36 ` [PATCH 2/8] ASoC: rsnd: remove non DT support for DMA Kuninori Morimoto
@ 2016-10-25  0:36 ` Kuninori Morimoto
  2016-10-25 19:23   ` Applied "ASoC: rsnd: don't use devm_request_irq() for SSI" to the asoc tree Mark Brown
  2016-10-25  0:36 ` [PATCH 4/8] ASoC: rsnd: remove rsnd_dma_detach() Kuninori Morimoto
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

SSI will use DMA mode, and migh be fallback to PIO mode.
Using devm_request_irq() makes its operation more complex when
it fallbacks to PIO mode.
Let's use manual request_irq()/free_irq()

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/ssi.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 59cd982..b0338d0 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -644,10 +644,14 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
-	ret = devm_request_irq(dev, ssi->irq,
-			       rsnd_ssi_interrupt,
-			       IRQF_SHARED,
-			       dev_name(dev), mod);
+	/*
+	 * SSI might be called again as PIO fallback
+	 * It is easy to manual handling for IRQ request/free
+	 */
+	ret = request_irq(ssi->irq,
+			  rsnd_ssi_interrupt,
+			  IRQF_SHARED,
+			  dev_name(dev), mod);
 
 	return ret;
 }
@@ -693,12 +697,9 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
 			       struct rsnd_priv *priv)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	struct device *dev = rsnd_priv_to_dev(priv);
-	int irq = ssi->irq;
 
 	/* PIO will request IRQ again */
-	if (ssi->dma)
-		devm_free_irq(dev, irq, mod);
+	free_irq(ssi->irq, mod);
 
 	rsnd_dma_detach(mod, &ssi->dma);
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/8] ASoC: rsnd: remove rsnd_dma_detach()
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
                   ` (2 preceding siblings ...)
  2016-10-25  0:36 ` [PATCH 3/8] ASoC: rsnd: don't use devm_request_irq() for SSI Kuninori Morimoto
@ 2016-10-25  0:36 ` Kuninori Morimoto
  2016-10-25 19:23   ` Applied "ASoC: rsnd: remove rsnd_dma_detach()" to the asoc tree Mark Brown
  2016-10-25  0:37 ` [PATCH 5/8] ASoC: rsnd: don't call unneeded of_node_put() on dma.c Kuninori Morimoto
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:36 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

DMA mod is now connected to stream via rsnd_dai_connect().
This means DMA mod can use .remove for its clearance.
rsnd_dma_detach() is no longer needed.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/dma.c  | 11 -----------
 sound/soc/sh/rcar/rsnd.h |  1 -
 sound/soc/sh/rcar/ssi.c  |  2 --
 3 files changed, 14 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index e0761ca..c85a551 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -698,17 +698,6 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 	return 0;
 }
 
-void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod)
-{
-	if (*dma_mod) {
-		struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-		struct device *dev = rsnd_priv_to_dev(priv);
-
-		devm_kfree(dev, *dma_mod);
-		*dma_mod = NULL;
-	}
-}
-
 int rsnd_dma_probe(struct rsnd_priv *priv)
 {
 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 2460d1f..c1cee1a 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -200,7 +200,6 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod, enum rsnd_reg reg,
  */
 int rsnd_dma_attach(struct rsnd_dai_stream *io,
 		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
-void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 int rsnd_dma_probe(struct rsnd_priv *priv);
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
 					  struct rsnd_mod *mod, char *name);
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index b0338d0..e23e07b 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -701,8 +701,6 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
 	/* PIO will request IRQ again */
 	free_irq(ssi->irq, mod);
 
-	rsnd_dma_detach(mod, &ssi->dma);
-
 	return 0;
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 5/8] ASoC: rsnd: don't call unneeded of_node_put() on dma.c
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
                   ` (3 preceding siblings ...)
  2016-10-25  0:36 ` [PATCH 4/8] ASoC: rsnd: remove rsnd_dma_detach() Kuninori Morimoto
@ 2016-10-25  0:37 ` Kuninori Morimoto
  2016-10-25 19:23   ` Applied "ASoC: rsnd: don't call unneeded of_node_put() on dma.c" to the asoc tree Mark Brown
  2016-10-25  0:37 ` [PATCH 6/8] ASoC: rsnd: add nolock_start/stop callback Kuninori Morimoto
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:37 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

Current rsnd_dmaen_start() is calling of_node_put() for np,
but it is not needed if it goes through this loop.
This patch tidyup it

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/dma.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index c85a551..2f03277 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -143,19 +143,17 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
 					  struct rsnd_mod *mod, char *name)
 {
-	struct dma_chan *chan;
+	struct dma_chan *chan = NULL;
 	struct device_node *np;
 	int i = 0;
 
 	for_each_child_of_node(of_node, np) {
-		if (i == rsnd_mod_id(mod))
-			break;
+		if (i == rsnd_mod_id(mod) && (!chan))
+			chan = of_dma_request_slave_channel(np, name);
 		i++;
 	}
 
-	chan = of_dma_request_slave_channel(np, name);
-
-	of_node_put(np);
+	/* It should call of_node_put(), since, it is rsnd_xxx_of_node() */
 	of_node_put(of_node);
 
 	return chan;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 6/8] ASoC: rsnd: add nolock_start/stop callback
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
                   ` (4 preceding siblings ...)
  2016-10-25  0:37 ` [PATCH 5/8] ASoC: rsnd: don't call unneeded of_node_put() on dma.c Kuninori Morimoto
@ 2016-10-25  0:37 ` Kuninori Morimoto
  2016-10-25 19:23   ` Applied "ASoC: rsnd: add nolock_start/stop callback" to the asoc tree Mark Brown
  2016-10-25  0:37 ` [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time Kuninori Morimoto
  2016-10-25  0:38 ` [PATCH 8/8] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU Kuninori Morimoto
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:37 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

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>
---
 sound/soc/sh/rcar/core.c | 26 ++++++++++++++++++++++++++
 sound/soc/sh/rcar/rsnd.h | 15 ++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index ea14a14..9ffa299 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 c1cee1a..422b534 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)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
                   ` (5 preceding siblings ...)
  2016-10-25  0:37 ` [PATCH 6/8] ASoC: rsnd: add nolock_start/stop callback Kuninori Morimoto
@ 2016-10-25  0:37 ` Kuninori Morimoto
  2016-10-25 14:02   ` Mark Brown
  2016-10-25  0:38 ` [PATCH 8/8] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU Kuninori Morimoto
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:37 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

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.
This patch fixup to request/release DMA channel each time.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/dma.c | 182 ++++++++++++++++++++++++++++--------------------
 1 file changed, 105 insertions(+), 77 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 2f03277..27a5a2e 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -34,6 +34,8 @@ struct rsnd_dmapp {
 
 struct rsnd_dma {
 	struct rsnd_mod		mod;
+	struct rsnd_mod		*mod_from;
+	struct rsnd_mod		*mod_to;
 	dma_addr_t		src_addr;
 	dma_addr_t		dst_addr;
 	union {
@@ -92,6 +94,20 @@ static void rsnd_dmaen_complete(void *data)
 	rsnd_mod_interrupt(mod, __rsnd_dmaen_complete);
 }
 
+static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
+						   struct rsnd_mod *mod_from,
+						   struct rsnd_mod *mod_to)
+{
+	if ((!mod_from && !mod_to) ||
+	    (mod_from && mod_to))
+		return NULL;
+
+	if (mod_from)
+		return rsnd_mod_dma_req(io, mod_from);
+	else
+		return rsnd_mod_dma_req(io, mod_to);
+}
+
 static int rsnd_dmaen_stop(struct rsnd_mod *mod,
 			   struct rsnd_dai_stream *io,
 			   struct rsnd_priv *priv)
@@ -99,7 +115,59 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod,
 	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
 	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 
-	dmaengine_terminate_all(dmaen->chan);
+	if (dmaen->chan) {
+		dmaengine_terminate_all(dmaen->chan);
+	}
+
+	return 0;
+}
+
+static int rsnd_dmaen_nolock_stop(struct rsnd_mod *mod,
+				   struct rsnd_dai_stream *io,
+				   struct rsnd_priv *priv)
+{
+	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
+
+	/*
+	 * DMAEngine release uses mutex lock.
+	 * Thus, it shouldn't be called under spinlock.
+	 * Let's call it under nolock_start
+	 */
+	if (dmaen->chan)
+		dma_release_channel(dmaen->chan);
+
+	dmaen->chan = NULL;
+
+	return 0;
+}
+
+static int rsnd_dmaen_nolock_start(struct rsnd_mod *mod,
+			    struct rsnd_dai_stream *io,
+			    struct rsnd_priv *priv)
+{
+	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	if (dmaen->chan) {
+		dev_err(dev, "it already has dma channel\n");
+		return -EIO;
+	}
+
+	/*
+	 * DMAEngine request uses mutex lock.
+	 * Thus, it shouldn't be called under spinlock.
+	 * Let's call it under nolock_start
+	 */
+	dmaen->chan = rsnd_dmaen_request_channel(io,
+						 dma->mod_from,
+						 dma->mod_to);
+	if (IS_ERR_OR_NULL(dmaen->chan)) {
+		dmaen->chan = NULL;
+		dev_err(dev, "can't get dma channel\n");
+		return PTR_ERR(dmaen->chan);
+	}
 
 	return 0;
 }
@@ -113,7 +181,23 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	struct snd_pcm_substream *substream = io->substream;
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct dma_async_tx_descriptor *desc;
+	struct dma_slave_config cfg = {};
 	int is_play = rsnd_io_is_play(io);
+	int ret;
+
+	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+	cfg.src_addr	= dma->src_addr;
+	cfg.dst_addr	= dma->dst_addr;
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+
+	dev_dbg(dev, "%s[%d] %pad -> %pad\n",
+		rsnd_mod_name(mod), rsnd_mod_id(mod),
+		&cfg.src_addr, &cfg.dst_addr);
+
+	ret = dmaengine_slave_config(dmaen->chan, &cfg);
+	if (ret < 0)
+		return ret;
 
 	desc = dmaengine_prep_dma_cyclic(dmaen->chan,
 					 substream->runtime->dma_addr,
@@ -159,97 +243,39 @@ struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
 	return chan;
 }
 
-static struct dma_chan *rsnd_dmaen_request_channel(struct rsnd_dai_stream *io,
-						   struct rsnd_mod *mod_from,
-						   struct rsnd_mod *mod_to)
-{
-	if ((!mod_from && !mod_to) ||
-	    (mod_from && mod_to))
-		return NULL;
-
-	if (mod_from)
-		return rsnd_mod_dma_req(io, mod_from);
-	else
-		return rsnd_mod_dma_req(io, mod_to);
-}
-
-static int rsnd_dmaen_remove(struct rsnd_mod *mod,
-			      struct rsnd_dai_stream *io,
-			      struct rsnd_priv *priv)
-{
-	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
-	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
-
-	if (dmaen->chan)
-		dma_release_channel(dmaen->chan);
-
-	dmaen->chan = NULL;
-
-	return 0;
-}
-
 static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
 			   struct rsnd_dma *dma,
 			   struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
 {
-	struct rsnd_mod *mod = rsnd_mod_get(dma);
-	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 	struct rsnd_priv *priv = rsnd_io_to_priv(io);
 	struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
-	struct device *dev = rsnd_priv_to_dev(priv);
-	struct dma_slave_config cfg = {};
-	int is_play = rsnd_io_is_play(io);
-	int ret;
-
-	if (dmaen->chan) {
-		dev_err(dev, "it already has dma channel\n");
-		return -EIO;
-	}
-
-	dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
-
-	if (IS_ERR_OR_NULL(dmaen->chan)) {
-		dmaen->chan = NULL;
-		dev_err(dev, "can't get dma channel\n");
-		goto rsnd_dma_channel_err;
+	struct dma_chan *chan;
+
+	/* try to get DMAEngine channel */
+	chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
+	if (IS_ERR_OR_NULL(chan)) {
+		/*
+		 * DMA failed. try to PIO mode
+		 * see
+		 *	rsnd_ssi_fallback()
+		 *	rsnd_rdai_continuance_probe()
+		 */
+		return -EAGAIN;
 	}
 
-	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-	cfg.src_addr	= dma->src_addr;
-	cfg.dst_addr	= dma->dst_addr;
-	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-
-	dev_dbg(dev, "%s[%d] %pad -> %pad\n",
-		rsnd_mod_name(mod), rsnd_mod_id(mod),
-		&cfg.src_addr, &cfg.dst_addr);
-
-	ret = dmaengine_slave_config(dmaen->chan, &cfg);
-	if (ret < 0)
-		goto rsnd_dma_attach_err;
+	dma_release_channel(chan);
 
 	dmac->dmaen_num++;
 
 	return 0;
-
-rsnd_dma_attach_err:
-	rsnd_dmaen_remove(mod, io, priv);
-rsnd_dma_channel_err:
-
-	/*
-	 * DMA failed. try to PIO mode
-	 * see
-	 *	rsnd_ssi_fallback()
-	 *	rsnd_rdai_continuance_probe()
-	 */
-	return -EAGAIN;
 }
 
 static struct rsnd_mod_ops rsnd_dmaen_ops = {
 	.name	= "audmac",
+	.nolock_start = rsnd_dmaen_nolock_start,
+	.nolock_stop  = rsnd_dmaen_nolock_stop,
 	.start	= rsnd_dmaen_start,
 	.stop	= rsnd_dmaen_stop,
-	.remove	= rsnd_dmaen_remove,
 };
 
 /*
@@ -671,9 +697,6 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 
 		*dma_mod = rsnd_mod_get(dma);
 
-		dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
-		dma->dst_addr = rsnd_dma_addr(io, mod_to,   is_play, 0);
-
 		ret = rsnd_mod_init(priv, *dma_mod, ops, NULL,
 				    rsnd_mod_get_status, type, dma_id);
 		if (ret < 0)
@@ -687,6 +710,11 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 		ret = attach(io, dma, mod_from, mod_to);
 		if (ret < 0)
 			return ret;
+
+		dma->src_addr = rsnd_dma_addr(io, mod_from, is_play, 1);
+		dma->dst_addr = rsnd_dma_addr(io, mod_to,   is_play, 0);
+		dma->mod_from = mod_from;
+		dma->mod_to   = mod_to;
 	}
 
 	ret = rsnd_dai_connect(*dma_mod, io, type);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 8/8] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU
  2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
                   ` (6 preceding siblings ...)
  2016-10-25  0:37 ` [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time Kuninori Morimoto
@ 2016-10-25  0:38 ` Kuninori Morimoto
  2016-11-22 17:26   ` Applied "ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU" to the asoc tree Mark Brown
  7 siblings, 1 reply; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25  0:38 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

IOMMU needs DMA mapping function to use it. One solution is that
we can use DMA mapped dev on snd_pcm_lib_preallocate_pages_for_all()
for SNDRV_DMA_TYPE_DEV. But pcm_new and dma map timing are mismatched.
Thus, this patch uses SNDRV_DMA_TYPE_CONTINUOUS for pcm_new,
and use dma_sync_single_for_xxx() for each transfer.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 sound/soc/sh/rcar/core.c |  4 +--
 sound/soc/sh/rcar/dma.c  | 84 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 9ffa299..912dc62 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1126,8 +1126,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
 
 	return snd_pcm_lib_preallocate_pages_for_all(
 		rtd->pcm,
-		SNDRV_DMA_TYPE_DEV,
-		rtd->card->snd_card->dev,
+		SNDRV_DMA_TYPE_CONTINUOUS,
+		snd_dma_continuous_data(GFP_KERNEL),
 		PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
 }
 
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 27a5a2e..119aa8d 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -25,6 +25,10 @@
 
 struct rsnd_dmaen {
 	struct dma_chan		*chan;
+	dma_addr_t		dma_buf;
+	unsigned int		dma_len;
+	unsigned int		dma_period;
+	unsigned int		dma_cnt;
 };
 
 struct rsnd_dmapp {
@@ -58,10 +62,38 @@ struct rsnd_dma_ctrl {
 /*
  *		Audio DMAC
  */
+#define rsnd_dmaen_sync(dmaen, io, i)	__rsnd_dmaen_sync(dmaen, io, i, 1)
+#define rsnd_dmaen_unsync(dmaen, io, i)	__rsnd_dmaen_sync(dmaen, io, i, 0)
+static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io,
+			      int i, int sync)
+{
+	struct device *dev = dmaen->chan->device->dev;
+	enum dma_data_direction dir;
+	int is_play = rsnd_io_is_play(io);
+	dma_addr_t buf;
+	int len, max;
+	size_t period;
+
+	len	= dmaen->dma_len;
+	period	= dmaen->dma_period;
+	max	= len / period;
+	i	= i % max;
+	buf	= dmaen->dma_buf + (period * i);
+
+	dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	if (sync)
+		dma_sync_single_for_device(dev, buf, period, dir);
+	else
+		dma_sync_single_for_cpu(dev, buf, period, dir);
+}
+
 static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
 				  struct rsnd_dai_stream *io)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 	bool elapsed = false;
 	unsigned long flags;
 
@@ -78,9 +110,22 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (rsnd_io_is_working(io))
+	if (rsnd_io_is_working(io)) {
+		rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt);
+
+		/*
+		 * Next period is already started.
+		 * Let's sync Next Next period
+		 * see
+		 *	rsnd_dmaen_start()
+		 */
+		rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2);
+
 		elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
 
+		dmaen->dma_cnt++;
+	}
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (elapsed)
@@ -116,7 +161,12 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod,
 	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 
 	if (dmaen->chan) {
+		int is_play = rsnd_io_is_play(io);
+
 		dmaengine_terminate_all(dmaen->chan);
+		dma_unmap_single(dmaen->chan->device->dev,
+				 dmaen->dma_buf, dmaen->dma_len,
+				 is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	}
 
 	return 0;
@@ -182,7 +232,11 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct dma_async_tx_descriptor *desc;
 	struct dma_slave_config cfg = {};
+	dma_addr_t buf;
+	size_t len;
+	size_t period;
 	int is_play = rsnd_io_is_play(io);
+	int i;
 	int ret;
 
 	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
@@ -199,10 +253,19 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
+	len	= snd_pcm_lib_buffer_bytes(substream);
+	period	= snd_pcm_lib_period_bytes(substream);
+	buf	= dma_map_single(dmaen->chan->device->dev,
+				 substream->runtime->dma_area,
+				 len,
+				 is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	if (dma_mapping_error(dmaen->chan->device->dev, buf)) {
+		dev_err(dev, "dma map failed\n");
+		return -EIO;
+	}
+
 	desc = dmaengine_prep_dma_cyclic(dmaen->chan,
-					 substream->runtime->dma_addr,
-					 snd_pcm_lib_buffer_bytes(substream),
-					 snd_pcm_lib_period_bytes(substream),
+					 buf, len, period,
 					 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
 					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
@@ -214,6 +277,19 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	desc->callback		= rsnd_dmaen_complete;
 	desc->callback_param	= rsnd_mod_get(dma);
 
+	dmaen->dma_buf		= buf;
+	dmaen->dma_len		= len;
+	dmaen->dma_period	= period;
+	dmaen->dma_cnt		= 0;
+
+	/*
+	 * synchronize this and next period
+	 * see
+	 *	__rsnd_dmaen_complete()
+	 */
+	for (i = 0; i < 2; i++)
+		rsnd_dmaen_sync(dmaen, io, i);
+
 	if (dmaengine_submit(desc) < 0) {
 		dev_err(dev, "dmaengine_submit() fail\n");
 		return -EIO;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/8] ASoC: rsnd: depends on OF
  2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
@ 2016-10-25 13:28   ` Mark Brown
  2016-10-26  0:00     ` Kuninori Morimoto
  2016-10-26 15:12   ` Applied "ASoC: rsnd: depends on OF" to the asoc tree Mark Brown
  1 sibling, 1 reply; 20+ messages in thread
From: Mark Brown @ 2016-10-25 13:28 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Simon


[-- Attachment #1.1: Type: text/plain, Size: 398 bytes --]

On Tue, Oct 25, 2016 at 12:35:53AM +0000, Kuninori Morimoto wrote:

> @@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
>  config SND_SOC_RCAR
>  	tristate "R-Car series SRU/SCU/SSIU/SSI support"
>  	depends on COMMON_CLK
> +	depends on OF
>  	select SND_SIMPLE_CARD
>  	select REGMAP_MMIO
>  	help

Can we have an || COMPILE_TEST to help build coverage if there isn't a
build time dependency on DT please?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time
  2016-10-25  0:37 ` [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time Kuninori Morimoto
@ 2016-10-25 14:02   ` Mark Brown
  2016-10-25 23:55     ` Kuninori Morimoto
  0 siblings, 1 reply; 20+ messages in thread
From: Mark Brown @ 2016-10-25 14:02 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Simon


[-- Attachment #1.1: Type: text/plain, Size: 570 bytes --]

On Tue, Oct 25, 2016 at 12:37:59AM +0000, Kuninori Morimoto wrote:

> 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.
> This patch fixup to request/release DMA channel each time.

Isn't this something which should be handled by better power management
in the DMA driver rather than this?

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: add nolock_start/stop callback" to the asoc tree
  2016-10-25  0:37 ` [PATCH 6/8] ASoC: rsnd: add nolock_start/stop callback Kuninori Morimoto
@ 2016-10-25 19:23   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-25 19:23 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: add nolock_start/stop callback

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 10a9cca13220888c20a259abbd42ea117cddfdb0 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] 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>
---
 sound/soc/sh/rcar/core.c | 26 ++++++++++++++++++++++++++
 sound/soc/sh/rcar/rsnd.h | 15 ++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

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)
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: don't call unneeded of_node_put() on dma.c" to the asoc tree
  2016-10-25  0:37 ` [PATCH 5/8] ASoC: rsnd: don't call unneeded of_node_put() on dma.c Kuninori Morimoto
@ 2016-10-25 19:23   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-25 19:23 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: don't call unneeded of_node_put() on dma.c

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 161ba1f1a5c99c4525eb39cc71ec984e0a39e6d7 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Tue, 25 Oct 2016 00:37:18 +0000
Subject: [PATCH] ASoC: rsnd: don't call unneeded of_node_put() on dma.c

Current rsnd_dmaen_start() is calling of_node_put() for np,
but it is not needed if it goes through this loop.
This patch tidyup it

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/rcar/dma.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index c85a55111392..2f0327714625 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -143,19 +143,17 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
 					  struct rsnd_mod *mod, char *name)
 {
-	struct dma_chan *chan;
+	struct dma_chan *chan = NULL;
 	struct device_node *np;
 	int i = 0;
 
 	for_each_child_of_node(of_node, np) {
-		if (i == rsnd_mod_id(mod))
-			break;
+		if (i == rsnd_mod_id(mod) && (!chan))
+			chan = of_dma_request_slave_channel(np, name);
 		i++;
 	}
 
-	chan = of_dma_request_slave_channel(np, name);
-
-	of_node_put(np);
+	/* It should call of_node_put(), since, it is rsnd_xxx_of_node() */
 	of_node_put(of_node);
 
 	return chan;
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: remove rsnd_dma_detach()" to the asoc tree
  2016-10-25  0:36 ` [PATCH 4/8] ASoC: rsnd: remove rsnd_dma_detach() Kuninori Morimoto
@ 2016-10-25 19:23   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-25 19:23 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: remove rsnd_dma_detach()

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From dae4b83295ae50a86b5e3c60e7b6e2c597a1b69d Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Tue, 25 Oct 2016 00:36:56 +0000
Subject: [PATCH] ASoC: rsnd: remove rsnd_dma_detach()

DMA mod is now connected to stream via rsnd_dai_connect().
This means DMA mod can use .remove for its clearance.
rsnd_dma_detach() is no longer needed.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/rcar/dma.c  | 11 -----------
 sound/soc/sh/rcar/rsnd.h |  1 -
 sound/soc/sh/rcar/ssi.c  |  2 --
 3 files changed, 14 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index e0761cac0ab7..c85a55111392 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -698,17 +698,6 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 	return 0;
 }
 
-void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod)
-{
-	if (*dma_mod) {
-		struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-		struct device *dev = rsnd_priv_to_dev(priv);
-
-		devm_kfree(dev, *dma_mod);
-		*dma_mod = NULL;
-	}
-}
-
 int rsnd_dma_probe(struct rsnd_priv *priv)
 {
 	struct platform_device *pdev = rsnd_priv_to_pdev(priv);
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 2460d1fbf775..c1cee1ab3e62 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -200,7 +200,6 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
  */
 int rsnd_dma_attach(struct rsnd_dai_stream *io,
 		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
-void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 int rsnd_dma_probe(struct rsnd_priv *priv);
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
 					  struct rsnd_mod *mod, char *name);
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index b0338d0a4cde..e23e07b54d8c 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -701,8 +701,6 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
 	/* PIO will request IRQ again */
 	free_irq(ssi->irq, mod);
 
-	rsnd_dma_detach(mod, &ssi->dma);
-
 	return 0;
 }
 
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: don't use devm_request_irq() for SSI" to the asoc tree
  2016-10-25  0:36 ` [PATCH 3/8] ASoC: rsnd: don't use devm_request_irq() for SSI Kuninori Morimoto
@ 2016-10-25 19:23   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-25 19:23 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: don't use devm_request_irq() for SSI

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 701172dca15ba9860ba73d3e18082fbd2a78f2c9 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Tue, 25 Oct 2016 00:36:34 +0000
Subject: [PATCH] ASoC: rsnd: don't use devm_request_irq() for SSI

SSI will use DMA mode, and migh be fallback to PIO mode.
Using devm_request_irq() makes its operation more complex when
it fallbacks to PIO mode.
Let's use manual request_irq()/free_irq()

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/rcar/ssi.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 59cd9824d8a4..b0338d0a4cde 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -644,10 +644,14 @@ static int rsnd_ssi_common_probe(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
-	ret = devm_request_irq(dev, ssi->irq,
-			       rsnd_ssi_interrupt,
-			       IRQF_SHARED,
-			       dev_name(dev), mod);
+	/*
+	 * SSI might be called again as PIO fallback
+	 * It is easy to manual handling for IRQ request/free
+	 */
+	ret = request_irq(ssi->irq,
+			  rsnd_ssi_interrupt,
+			  IRQF_SHARED,
+			  dev_name(dev), mod);
 
 	return ret;
 }
@@ -693,12 +697,9 @@ static int rsnd_ssi_dma_remove(struct rsnd_mod *mod,
 			       struct rsnd_priv *priv)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	struct device *dev = rsnd_priv_to_dev(priv);
-	int irq = ssi->irq;
 
 	/* PIO will request IRQ again */
-	if (ssi->dma)
-		devm_free_irq(dev, irq, mod);
+	free_irq(ssi->irq, mod);
 
 	rsnd_dma_detach(mod, &ssi->dma);
 
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: remove non DT support for DMA" to the asoc tree
  2016-10-25  0:36 ` [PATCH 2/8] ASoC: rsnd: remove non DT support for DMA Kuninori Morimoto
@ 2016-10-25 19:24   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-25 19:24 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: remove non DT support for DMA

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From b99305d20122174c9fd0469bae036f0c401999b5 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Tue, 25 Oct 2016 00:36:13 +0000
Subject: [PATCH] ASoC: rsnd: remove non DT support for DMA

Current Renesas Sound driver is based on DeviceTree, and no one is
using this driver from non DT. Non-DT support is no longer needed.
Let's remove it.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/rcar/dma.c  | 21 ++++++---------------
 sound/soc/sh/rcar/rsnd.h |  2 +-
 sound/soc/sh/rcar/src.c  |  2 +-
 sound/soc/sh/rcar/ssi.c  |  3 +--
 4 files changed, 9 insertions(+), 19 deletions(-)

diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index b3bdd362a511..e0761cac0ab7 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -191,7 +191,7 @@ static int rsnd_dmaen_remove(struct rsnd_mod *mod,
 }
 
 static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
-			   struct rsnd_dma *dma, int id,
+			   struct rsnd_dma *dma,
 			   struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
 {
 	struct rsnd_mod *mod = rsnd_mod_get(dma);
@@ -208,17 +208,8 @@ static int rsnd_dmaen_attach(struct rsnd_dai_stream *io,
 		return -EIO;
 	}
 
-	if (dev->of_node) {
-		dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
-	} else {
-		dma_cap_mask_t mask;
-
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
+	dmaen->chan = rsnd_dmaen_request_channel(io, mod_from, mod_to);
 
-		dmaen->chan = dma_request_channel(mask, shdma_chan_filter,
-						  (void *)(uintptr_t)id);
-	}
 	if (IS_ERR_OR_NULL(dmaen->chan)) {
 		dmaen->chan = NULL;
 		dev_err(dev, "can't get dma channel\n");
@@ -394,7 +385,7 @@ static int rsnd_dmapp_start(struct rsnd_mod *mod,
 }
 
 static int rsnd_dmapp_attach(struct rsnd_dai_stream *io,
-			     struct rsnd_dma *dma, int id,
+			     struct rsnd_dma *dma,
 			     struct rsnd_mod *mod_from, struct rsnd_mod *mod_to)
 {
 	struct rsnd_dmapp *dmapp = rsnd_dma_to_dmapp(dma);
@@ -627,7 +618,7 @@ static void rsnd_dma_of_path(struct rsnd_mod *this,
 }
 
 int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
-		    struct rsnd_mod **dma_mod, int id)
+		    struct rsnd_mod **dma_mod)
 {
 	struct rsnd_mod *mod_from = NULL;
 	struct rsnd_mod *mod_to = NULL;
@@ -636,7 +627,7 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct rsnd_mod_ops *ops;
 	enum rsnd_mod_type type;
-	int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma, int id,
+	int (*attach)(struct rsnd_dai_stream *io, struct rsnd_dma *dma,
 		      struct rsnd_mod *mod_from, struct rsnd_mod *mod_to);
 	int is_play = rsnd_io_is_play(io);
 	int ret, dma_id;
@@ -695,7 +686,7 @@ int rsnd_dma_attach(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
 			rsnd_mod_name(mod_from), rsnd_mod_id(mod_from),
 			rsnd_mod_name(mod_to),   rsnd_mod_id(mod_to));
 
-		ret = attach(io, dma, id, mod_from, mod_to);
+		ret = attach(io, dma, mod_from, mod_to);
 		if (ret < 0)
 			return ret;
 	}
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index b3b4d89347be..2460d1fbf775 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -199,7 +199,7 @@ u32 rsnd_get_dalign(struct rsnd_mod *mod, struct rsnd_dai_stream *io);
  *	R-Car DMA
  */
 int rsnd_dma_attach(struct rsnd_dai_stream *io,
-		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod, int id);
+		    struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 void rsnd_dma_detach(struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
 int rsnd_dma_probe(struct rsnd_priv *priv);
 struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node,
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index 969a5169de25..e13d6d439b32 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -475,7 +475,7 @@ static int rsnd_src_probe_(struct rsnd_mod *mod,
 			return ret;
 	}
 
-	ret = rsnd_dma_attach(io, mod, &src->dma, 0);
+	ret = rsnd_dma_attach(io, mod, &src->dma);
 
 	return ret;
 }
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 94a19f975fa2..59cd9824d8a4 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -669,7 +669,6 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 			      struct rsnd_priv *priv)
 {
 	struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
-	int dma_id = 0; /* not needed */
 	int ret;
 
 	/*
@@ -684,7 +683,7 @@ static int rsnd_ssi_dma_probe(struct rsnd_mod *mod,
 		return ret;
 
 	/* SSI probe might be called many times in MUX multi path */
-	ret = rsnd_dma_attach(io, mod, &ssi->dma, dma_id);
+	ret = rsnd_dma_attach(io, mod, &ssi->dma);
 
 	return ret;
 }
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time
  2016-10-25 14:02   ` Mark Brown
@ 2016-10-25 23:55     ` Kuninori Morimoto
  0 siblings, 0 replies; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-25 23:55 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon, Laurent


Hi Mark
Cc: Laurent

Thank you for your feedback

> > 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.
> > This patch fixup to request/release DMA channel each time.
> 
> Isn't this something which should be handled by better power management
> in the DMA driver rather than this?

I discussed about this topic with Laurent.
Yes, the best choice is that DMAEngine side should care about it,
but, it can't on current DMAEngine design.

# We need to call pm_runtime_get_sync() to power the hardware on
# which can't be called in atomic context.
# And dma_async_issue_pending() needs to be callable in atomic context
# so to fix this we would likely need to extend the DMA engine API

So, current *better* choice is sound driver request/release DMA channel
each time.

I will post v2 patch with [1/8] update

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/8] ASoC: rsnd: depends on OF
  2016-10-25 13:28   ` Mark Brown
@ 2016-10-26  0:00     ` Kuninori Morimoto
  0 siblings, 0 replies; 20+ messages in thread
From: Kuninori Morimoto @ 2016-10-26  0:00 UTC (permalink / raw)
  To: Mark Brown; +Cc: Linux-ALSA, Simon


Hi Mark

> > @@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
> >  config SND_SOC_RCAR
> >  	tristate "R-Car series SRU/SCU/SSIU/SSI support"
> >  	depends on COMMON_CLK
> > +	depends on OF
> >  	select SND_SIMPLE_CARD
> >  	select REGMAP_MMIO
> >  	help
> 
> Can we have an || COMPILE_TEST to help build coverage if there isn't a
> build time dependency on DT please?

Thanks. 
will do in v2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: depends on OF" to the asoc tree
  2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
  2016-10-25 13:28   ` Mark Brown
@ 2016-10-26 15:12   ` Mark Brown
  1 sibling, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-10-26 15:12 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: depends on OF

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 609c94865adcef3dba070a2d3905e4b67b4e6919 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Wed, 26 Oct 2016 04:12:34 +0000
Subject: [PATCH] ASoC: rsnd: depends on OF

Current Renesas sound driver is completely depends on CONFIG_OF

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 6db6405d952f..610fa85b3acd 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -37,6 +37,7 @@ config SND_SOC_SH4_SIU
 config SND_SOC_RCAR
 	tristate "R-Car series SRU/SCU/SSIU/SSI support"
 	depends on COMMON_CLK
+	depends on OF
 	select SND_SIMPLE_CARD
 	select REGMAP_MMIO
 	help
-- 
2.8.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Applied "ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU" to the asoc tree
  2016-10-25  0:38 ` [PATCH 8/8] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU Kuninori Morimoto
@ 2016-11-22 17:26   ` Mark Brown
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Brown @ 2016-11-22 17:26 UTC (permalink / raw)
  To: Kuninori Morimoto; +Cc: Linux-ALSA, Mark Brown, Simon

The patch

   ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU

has been applied to the asoc tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 4821d914fe747a91453021675a74069776f0b819 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Date: Mon, 14 Nov 2016 04:20:56 +0000
Subject: [PATCH] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU

IOMMU needs DMA mapping function to use it. One solution is that
we can use DMA mapped dev on snd_pcm_lib_preallocate_pages_for_all()
for SNDRV_DMA_TYPE_DEV. But pcm_new and dma map timing are mismatched.
Thus, this patch uses SNDRV_DMA_TYPE_CONTINUOUS for pcm_new,
and use dma_sync_single_for_xxx() for each transfer.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
---
 sound/soc/sh/rcar/core.c |  4 +--
 sound/soc/sh/rcar/dma.c  | 84 +++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 82 insertions(+), 6 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 9ffa29941ceb..912dc62ff9c7 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1126,8 +1126,8 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
 
 	return snd_pcm_lib_preallocate_pages_for_all(
 		rtd->pcm,
-		SNDRV_DMA_TYPE_DEV,
-		rtd->card->snd_card->dev,
+		SNDRV_DMA_TYPE_CONTINUOUS,
+		snd_dma_continuous_data(GFP_KERNEL),
 		PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
 }
 
diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c
index 3c663a5cfe8b..1f405c833867 100644
--- a/sound/soc/sh/rcar/dma.c
+++ b/sound/soc/sh/rcar/dma.c
@@ -25,6 +25,10 @@
 
 struct rsnd_dmaen {
 	struct dma_chan		*chan;
+	dma_addr_t		dma_buf;
+	unsigned int		dma_len;
+	unsigned int		dma_period;
+	unsigned int		dma_cnt;
 };
 
 struct rsnd_dmapp {
@@ -58,10 +62,38 @@ struct rsnd_dma_ctrl {
 /*
  *		Audio DMAC
  */
+#define rsnd_dmaen_sync(dmaen, io, i)	__rsnd_dmaen_sync(dmaen, io, i, 1)
+#define rsnd_dmaen_unsync(dmaen, io, i)	__rsnd_dmaen_sync(dmaen, io, i, 0)
+static void __rsnd_dmaen_sync(struct rsnd_dmaen *dmaen, struct rsnd_dai_stream *io,
+			      int i, int sync)
+{
+	struct device *dev = dmaen->chan->device->dev;
+	enum dma_data_direction dir;
+	int is_play = rsnd_io_is_play(io);
+	dma_addr_t buf;
+	int len, max;
+	size_t period;
+
+	len	= dmaen->dma_len;
+	period	= dmaen->dma_period;
+	max	= len / period;
+	i	= i % max;
+	buf	= dmaen->dma_buf + (period * i);
+
+	dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+	if (sync)
+		dma_sync_single_for_device(dev, buf, period, dir);
+	else
+		dma_sync_single_for_cpu(dev, buf, period, dir);
+}
+
 static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
 				  struct rsnd_dai_stream *io)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
+	struct rsnd_dma *dma = rsnd_mod_to_dma(mod);
+	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 	bool elapsed = false;
 	unsigned long flags;
 
@@ -78,9 +110,22 @@ static void __rsnd_dmaen_complete(struct rsnd_mod *mod,
 	 */
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (rsnd_io_is_working(io))
+	if (rsnd_io_is_working(io)) {
+		rsnd_dmaen_unsync(dmaen, io, dmaen->dma_cnt);
+
+		/*
+		 * Next period is already started.
+		 * Let's sync Next Next period
+		 * see
+		 *	rsnd_dmaen_start()
+		 */
+		rsnd_dmaen_sync(dmaen, io, dmaen->dma_cnt + 2);
+
 		elapsed = rsnd_dai_pointer_update(io, io->byte_per_period);
 
+		dmaen->dma_cnt++;
+	}
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	if (elapsed)
@@ -116,7 +161,12 @@ static int rsnd_dmaen_stop(struct rsnd_mod *mod,
 	struct rsnd_dmaen *dmaen = rsnd_dma_to_dmaen(dma);
 
 	if (dmaen->chan) {
+		int is_play = rsnd_io_is_play(io);
+
 		dmaengine_terminate_all(dmaen->chan);
+		dma_unmap_single(dmaen->chan->device->dev,
+				 dmaen->dma_buf, dmaen->dma_len,
+				 is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 	}
 
 	return 0;
@@ -184,7 +234,11 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	struct device *dev = rsnd_priv_to_dev(priv);
 	struct dma_async_tx_descriptor *desc;
 	struct dma_slave_config cfg = {};
+	dma_addr_t buf;
+	size_t len;
+	size_t period;
 	int is_play = rsnd_io_is_play(io);
+	int i;
 	int ret;
 
 	cfg.direction	= is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
@@ -201,10 +255,19 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
+	len	= snd_pcm_lib_buffer_bytes(substream);
+	period	= snd_pcm_lib_period_bytes(substream);
+	buf	= dma_map_single(dmaen->chan->device->dev,
+				 substream->runtime->dma_area,
+				 len,
+				 is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+	if (dma_mapping_error(dmaen->chan->device->dev, buf)) {
+		dev_err(dev, "dma map failed\n");
+		return -EIO;
+	}
+
 	desc = dmaengine_prep_dma_cyclic(dmaen->chan,
-					 substream->runtime->dma_addr,
-					 snd_pcm_lib_buffer_bytes(substream),
-					 snd_pcm_lib_period_bytes(substream),
+					 buf, len, period,
 					 is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
 					 DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
@@ -216,6 +279,19 @@ static int rsnd_dmaen_start(struct rsnd_mod *mod,
 	desc->callback		= rsnd_dmaen_complete;
 	desc->callback_param	= rsnd_mod_get(dma);
 
+	dmaen->dma_buf		= buf;
+	dmaen->dma_len		= len;
+	dmaen->dma_period	= period;
+	dmaen->dma_cnt		= 0;
+
+	/*
+	 * synchronize this and next period
+	 * see
+	 *	__rsnd_dmaen_complete()
+	 */
+	for (i = 0; i < 2; i++)
+		rsnd_dmaen_sync(dmaen, io, i);
+
 	if (dmaengine_submit(desc) < 0) {
 		dev_err(dev, "dmaengine_submit() fail\n");
 		return -EIO;
-- 
2.10.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2016-11-22 17:26 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-25  0:35 [PATCH 0/8] ASoC: rsnd: DMA power fix and IOMMU support Kuninori Morimoto
2016-10-25  0:35 ` [PATCH 1/8] ASoC: rsnd: depends on OF Kuninori Morimoto
2016-10-25 13:28   ` Mark Brown
2016-10-26  0:00     ` Kuninori Morimoto
2016-10-26 15:12   ` Applied "ASoC: rsnd: depends on OF" to the asoc tree Mark Brown
2016-10-25  0:36 ` [PATCH 2/8] ASoC: rsnd: remove non DT support for DMA Kuninori Morimoto
2016-10-25 19:24   ` Applied "ASoC: rsnd: remove non DT support for DMA" to the asoc tree Mark Brown
2016-10-25  0:36 ` [PATCH 3/8] ASoC: rsnd: don't use devm_request_irq() for SSI Kuninori Morimoto
2016-10-25 19:23   ` Applied "ASoC: rsnd: don't use devm_request_irq() for SSI" to the asoc tree Mark Brown
2016-10-25  0:36 ` [PATCH 4/8] ASoC: rsnd: remove rsnd_dma_detach() Kuninori Morimoto
2016-10-25 19:23   ` Applied "ASoC: rsnd: remove rsnd_dma_detach()" to the asoc tree Mark Brown
2016-10-25  0:37 ` [PATCH 5/8] ASoC: rsnd: don't call unneeded of_node_put() on dma.c Kuninori Morimoto
2016-10-25 19:23   ` Applied "ASoC: rsnd: don't call unneeded of_node_put() on dma.c" to the asoc tree Mark Brown
2016-10-25  0:37 ` [PATCH 6/8] ASoC: rsnd: add nolock_start/stop callback Kuninori Morimoto
2016-10-25 19:23   ` Applied "ASoC: rsnd: add nolock_start/stop callback" to the asoc tree Mark Brown
2016-10-25  0:37 ` [PATCH 7/8] ASoC: rsnd: Request/Release DMA channel each time Kuninori Morimoto
2016-10-25 14:02   ` Mark Brown
2016-10-25 23:55     ` Kuninori Morimoto
2016-10-25  0:38 ` [PATCH 8/8] ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU Kuninori Morimoto
2016-11-22 17:26   ` Applied "ASoC: rsnd: use dma_sync_single_for_xxx() for IOMMU" to the asoc tree Mark Brown

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.