[alsa-devel] [PATCH 14/14] ASoC: rsnd: add TDM Extend Mode support

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Nov 30 09:54:03 CET 2015


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

Renesas R-Car can out TDM by
1) 6ch x 1 DAI as TDM Extend Mode
2) 2ch x 4 x 1 DAI as TDM split Mode
3) 2ch x 3 DAI or
   2ch x 4 DAI as TDM Multichannel Mode

This patch adds 1) TDM Extend Mode. Because of HW design,
this 6ch data will be outputed via 8ch data width.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 sound/soc/sh/rcar/core.c | 30 ++++++++++++++++++++++++++----
 sound/soc/sh/rcar/gen.c  |  1 +
 sound/soc/sh/rcar/rsnd.h |  1 +
 sound/soc/sh/rcar/ssi.c  | 18 +++++++++++++++++-
 sound/soc/sh/rcar/ssiu.c |  9 +++++++++
 5 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 7d364d7..b187a89 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -247,9 +247,9 @@ u32 rsnd_get_adinr_bit(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
 u32 rsnd_get_adinr_chan(struct rsnd_mod *mod, struct rsnd_dai_stream *io)
 {
 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
-	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	struct device *dev = rsnd_priv_to_dev(priv);
-	u32 chan = runtime->channels;
+	struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
+	u32 chan = rsnd_get_slot_rdai(rdai);
 
 	switch (chan) {
 	case 1:
@@ -569,9 +569,31 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	return 0;
 }
 
+static int rsnd_soc_set_dai_tdm_slot(struct snd_soc_dai *dai,
+				     u32 tx_mask, u32 rx_mask,
+				     int slots, int slot_width)
+{
+	struct rsnd_priv *priv = rsnd_dai_to_priv(dai);
+	struct rsnd_dai *rdai = rsnd_dai_to_rdai(dai);
+	struct device *dev = rsnd_priv_to_dev(priv);
+
+	switch (slots) {
+	case 6:
+		/* TDM Extend Mode */
+		rdai->slots = slots;
+		break;
+	default:
+		dev_err(dev, "unsupported TDM slots (%d)\n", slots);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct snd_soc_dai_ops rsnd_soc_dai_ops = {
 	.trigger	= rsnd_soc_dai_trigger,
 	.set_fmt	= rsnd_soc_dai_set_fmt,
+	.set_tdm_slot	= rsnd_soc_set_dai_tdm_slot,
 };
 
 static int rsnd_dai_probe(struct rsnd_priv *priv)
@@ -626,7 +648,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
 		drv->playback.rates		= RSND_RATES;
 		drv->playback.formats		= RSND_FMTS;
 		drv->playback.channels_min	= 2;
-		drv->playback.channels_max	= 2;
+		drv->playback.channels_max	= 6;
 		drv->playback.stream_name	= rdai->playback.name;
 
 		snprintf(rdai->capture.name, RSND_DAI_NAME_SIZE,
@@ -634,7 +656,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
 		drv->capture.rates		= RSND_RATES;
 		drv->capture.formats		= RSND_FMTS;
 		drv->capture.channels_min	= 2;
-		drv->capture.channels_max	= 2;
+		drv->capture.channels_max	= 6;
 		drv->capture.stream_name	= rdai->capture.name;
 
 		rdai->playback.rdai		= rdai;
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 2151aa5..50fc730 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -230,6 +230,7 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv)
 		RSND_GEN_M_REG(SSI_BUSIF_MODE,	0x0,	0x80),
 		RSND_GEN_M_REG(SSI_BUSIF_ADINR,	0x4,	0x80),
 		RSND_GEN_M_REG(SSI_BUSIF_DALIGN,0x8,	0x80),
+		RSND_GEN_M_REG(SSI_MODE,	0xc,	0x80),
 		RSND_GEN_M_REG(SSI_CTRL,	0x10,	0x80),
 		RSND_GEN_M_REG(SSI_INT_ENABLE,	0x18,	0x80),
 	};
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index 2111bf3..970e130 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -44,6 +44,7 @@
  */
 enum rsnd_reg {
 	/* SCU (SRC/SSIU/MIX/CTU/DVC) */
+	RSND_REG_SSI_MODE,		/* Gen2 only */
 	RSND_REG_SSI_MODE0,
 	RSND_REG_SSI_MODE1,
 	RSND_REG_SSI_CTRL,		/* Gen2 only */
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 44e9141..628739f 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -24,7 +24,9 @@
 #define	OIEN		(1 << 26)	/* Overflow Interrupt Enable */
 #define	IIEN		(1 << 25)	/* Idle Mode Interrupt Enable */
 #define	DIEN		(1 << 24)	/* Data Interrupt Enable */
-
+#define	CHNL_4		(1 << 22)	/* Channels */
+#define	CHNL_6		(2 << 22)	/* Channels */
+#define	CHNL_8		(3 << 22)	/* Channels */
 #define	DWL_8		(0 << 19)	/* Data Word Length */
 #define	DWL_16		(1 << 19)	/* Data Word Length */
 #define	DWL_18		(2 << 19)	/* Data Word Length */
@@ -57,6 +59,7 @@
  * SSIWSR
  */
 #define CONT		(1 << 8)	/* WS Continue Function */
+#define WS_MODE		(1 << 0)	/* WS Mode */
 
 #define SSI_NAME "ssi"
 
@@ -261,6 +264,7 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
 	struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io);
 	u32 cr_own;
 	u32 cr_mode;
+	u32 wsr;
 
 	/*
 	 * always use 32bit system word.
@@ -297,8 +301,20 @@ static int rsnd_ssi_config_init(struct rsnd_ssi *ssi,
 		cr_mode = DIEN;		/* PIO : enable Data interrupt */
 	}
 
+	/*
+	 * TDM Extend Mode
+	 * see
+	 *	rsnd_ssiu_init_gen2()
+	 */
+	wsr = ssi->wsr;
+	if (rsnd_get_slot_runtime(io) >= 6) {
+		wsr	|= WS_MODE;
+		cr_own	|= CHNL_8;
+	}
+
 	ssi->cr_own	= cr_own;
 	ssi->cr_mode	= cr_mode;
+	ssi->wsr	= wsr;
 
 	return 0;
 }
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index 6120b0a..3265501 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -78,6 +78,15 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
+	if (rsnd_get_slot_runtime(io) >= 6) {
+		/*
+		 * TDM Extend Mode
+		 * see
+		 *	rsnd_ssi_config_init()
+		 */
+		rsnd_mod_write(mod, SSI_MODE, 0x1);
+	}
+
 	if (rsnd_ssi_use_busif(io)) {
 		u32 val = rsnd_get_dalign(mod, io);
 
-- 
1.9.1



More information about the Alsa-devel mailing list