[alsa-devel] Applied "ASoC: rsnd: add CTU support" to the asoc tree

Mark Brown broonie at kernel.org
Sat Mar 5 13:24:47 CET 2016


The patch

   ASoC: rsnd: add CTU support

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 ec2ac01afe001360b911e27c915579fd003339e8 Mon Sep 17 00:00:00 2001
From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
Date: Thu, 25 Feb 2016 05:55:23 +0000
Subject: [PATCH] ASoC: rsnd: add CTU support

This patch adds CTU (= Channel Transfer Unit) support on
Renesas R-Car sound driver.
It can Down/Up mixing and splitter. You need to check R-Car datasheet
especially CTUn_CPMDR/CTUn_SV0xR/CTUn_SV1xR/CTUn_SV2xR/CTUn_SV3xR
for setting parameter.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
Signed-off-by: Mark Brown <broonie at kernel.org>
---
 sound/soc/sh/rcar/ctu.c | 234 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 197 insertions(+), 37 deletions(-)

diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
index b326966ea407..9dcc1f9db026 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/sh/rcar/ctu.c
@@ -12,8 +12,74 @@
 #define CTU_NAME_SIZE	16
 #define CTU_NAME "ctu"
 
+/*
+ * User needs to setup CTU by amixer, and its settings are
+ * based on below registers
+ *
+ * CTUn_CPMDR : amixser set "CTU Pass"
+ * CTUn_SV0xR : amixser set "CTU SV0"
+ * CTUn_SV1xR : amixser set "CTU SV1"
+ * CTUn_SV2xR : amixser set "CTU SV2"
+ * CTUn_SV3xR : amixser set "CTU SV3"
+ *
+ * [CTU Pass]
+ * 0000: default
+ * 0001: Connect input data of channel 0
+ * 0010: Connect input data of channel 1
+ * 0011: Connect input data of channel 2
+ * 0100: Connect input data of channel 3
+ * 0101: Connect input data of channel 4
+ * 0110: Connect input data of channel 5
+ * 0111: Connect input data of channel 6
+ * 1000: Connect input data of channel 7
+ * 1001: Connect calculated data by scale values of matrix row 0
+ * 1010: Connect calculated data by scale values of matrix row 1
+ * 1011: Connect calculated data by scale values of matrix row 2
+ * 1100: Connect calculated data by scale values of matrix row 3
+ *
+ * [CTU SVx]
+ * [Output0] = [SV00, SV01, SV02, SV03, SV04, SV05, SV06, SV07]
+ * [Output1] = [SV10, SV11, SV12, SV13, SV14, SV15, SV16, SV17]
+ * [Output2] = [SV20, SV21, SV22, SV23, SV24, SV25, SV26, SV27]
+ * [Output3] = [SV30, SV31, SV32, SV33, SV34, SV35, SV36, SV37]
+ * [Output4] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
+ * [Output5] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
+ * [Output6] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
+ * [Output7] = [ 0,   0,    0,    0,    0,    0,    0,    0   ]
+ *
+ * [SVxx]
+ * Plus					Minus
+ * value	time		dB	value		time		dB
+ * -----------------------------------------------------------------------
+ * H'7F_FFFF	2		6	H'80_0000	2		6
+ * ...
+ * H'40_0000	1		0	H'C0_0000	1		0
+ * ...
+ * H'00_0001	2.38 x 10^-7	-132
+ * H'00_0000	0		Mute	H'FF_FFFF	2.38 x 10^-7	-132
+ *
+ *
+ * Ex) Input ch -> Output ch
+ *	1ch     ->  0ch
+ *	0ch     ->  1ch
+ *
+ *	amixer set "CTU Reset" on
+ *	amixer set "CTU Pass" 9,10
+ *	amixer set "CTU SV0" 0,4194304
+ *	amixer set "CTU SV1" 4194304,0
+ * or
+ *	amixer set "CTU Reset" on
+ *	amixer set "CTU Pass" 2,1
+ */
+
 struct rsnd_ctu {
 	struct rsnd_mod mod;
+	struct rsnd_kctrl_cfg_m pass;
+	struct rsnd_kctrl_cfg_m sv0;
+	struct rsnd_kctrl_cfg_m sv1;
+	struct rsnd_kctrl_cfg_m sv2;
+	struct rsnd_kctrl_cfg_m sv3;
+	struct rsnd_kctrl_cfg_s reset;
 	int channels;
 };
 
@@ -58,51 +124,91 @@ static int rsnd_ctu_probe_(struct rsnd_mod *mod,
 static void rsnd_ctu_value_init(struct rsnd_dai_stream *io,
 			       struct rsnd_mod *mod)
 {
+	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
+	u32 cpmdr = 0;
+	u32 scmdr = 0;
+	int i;
+
+	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
+		u32 val = ctu->pass.val[i];
+
+		cpmdr |= val << (28 - (i * 4));
+
+		if ((val > 0x8) && (scmdr < (val - 0x8)))
+			scmdr = val - 0x8;
+	}
+
 	rsnd_mod_write(mod, CTU_CTUIR, 1);
 
 	rsnd_mod_write(mod, CTU_ADINR, rsnd_runtime_channel_original(io));
 
-	rsnd_mod_write(mod, CTU_CPMDR, 0);
-	rsnd_mod_write(mod, CTU_SCMDR, 0);
-	rsnd_mod_write(mod, CTU_SV00R, 0);
-	rsnd_mod_write(mod, CTU_SV01R, 0);
-	rsnd_mod_write(mod, CTU_SV02R, 0);
-	rsnd_mod_write(mod, CTU_SV03R, 0);
-	rsnd_mod_write(mod, CTU_SV04R, 0);
-	rsnd_mod_write(mod, CTU_SV05R, 0);
-	rsnd_mod_write(mod, CTU_SV06R, 0);
-	rsnd_mod_write(mod, CTU_SV07R, 0);
-
-	rsnd_mod_write(mod, CTU_SV10R, 0);
-	rsnd_mod_write(mod, CTU_SV11R, 0);
-	rsnd_mod_write(mod, CTU_SV12R, 0);
-	rsnd_mod_write(mod, CTU_SV13R, 0);
-	rsnd_mod_write(mod, CTU_SV14R, 0);
-	rsnd_mod_write(mod, CTU_SV15R, 0);
-	rsnd_mod_write(mod, CTU_SV16R, 0);
-	rsnd_mod_write(mod, CTU_SV17R, 0);
-
-	rsnd_mod_write(mod, CTU_SV20R, 0);
-	rsnd_mod_write(mod, CTU_SV21R, 0);
-	rsnd_mod_write(mod, CTU_SV22R, 0);
-	rsnd_mod_write(mod, CTU_SV23R, 0);
-	rsnd_mod_write(mod, CTU_SV24R, 0);
-	rsnd_mod_write(mod, CTU_SV25R, 0);
-	rsnd_mod_write(mod, CTU_SV26R, 0);
-	rsnd_mod_write(mod, CTU_SV27R, 0);
-
-	rsnd_mod_write(mod, CTU_SV30R, 0);
-	rsnd_mod_write(mod, CTU_SV31R, 0);
-	rsnd_mod_write(mod, CTU_SV32R, 0);
-	rsnd_mod_write(mod, CTU_SV33R, 0);
-	rsnd_mod_write(mod, CTU_SV34R, 0);
-	rsnd_mod_write(mod, CTU_SV35R, 0);
-	rsnd_mod_write(mod, CTU_SV36R, 0);
-	rsnd_mod_write(mod, CTU_SV37R, 0);
+	rsnd_mod_write(mod, CTU_CPMDR, cpmdr);
+
+	rsnd_mod_write(mod, CTU_SCMDR, scmdr);
+
+	if (scmdr > 0) {
+		rsnd_mod_write(mod, CTU_SV00R, ctu->sv0.val[0]);
+		rsnd_mod_write(mod, CTU_SV01R, ctu->sv0.val[1]);
+		rsnd_mod_write(mod, CTU_SV02R, ctu->sv0.val[2]);
+		rsnd_mod_write(mod, CTU_SV03R, ctu->sv0.val[3]);
+		rsnd_mod_write(mod, CTU_SV04R, ctu->sv0.val[4]);
+		rsnd_mod_write(mod, CTU_SV05R, ctu->sv0.val[5]);
+		rsnd_mod_write(mod, CTU_SV06R, ctu->sv0.val[6]);
+		rsnd_mod_write(mod, CTU_SV07R, ctu->sv0.val[7]);
+	}
+	if (scmdr > 1) {
+		rsnd_mod_write(mod, CTU_SV10R, ctu->sv1.val[0]);
+		rsnd_mod_write(mod, CTU_SV11R, ctu->sv1.val[1]);
+		rsnd_mod_write(mod, CTU_SV12R, ctu->sv1.val[2]);
+		rsnd_mod_write(mod, CTU_SV13R, ctu->sv1.val[3]);
+		rsnd_mod_write(mod, CTU_SV14R, ctu->sv1.val[4]);
+		rsnd_mod_write(mod, CTU_SV15R, ctu->sv1.val[5]);
+		rsnd_mod_write(mod, CTU_SV16R, ctu->sv1.val[6]);
+		rsnd_mod_write(mod, CTU_SV17R, ctu->sv1.val[7]);
+	}
+	if (scmdr > 2) {
+		rsnd_mod_write(mod, CTU_SV20R, ctu->sv2.val[0]);
+		rsnd_mod_write(mod, CTU_SV21R, ctu->sv2.val[1]);
+		rsnd_mod_write(mod, CTU_SV22R, ctu->sv2.val[2]);
+		rsnd_mod_write(mod, CTU_SV23R, ctu->sv2.val[3]);
+		rsnd_mod_write(mod, CTU_SV24R, ctu->sv2.val[4]);
+		rsnd_mod_write(mod, CTU_SV25R, ctu->sv2.val[5]);
+		rsnd_mod_write(mod, CTU_SV26R, ctu->sv2.val[6]);
+		rsnd_mod_write(mod, CTU_SV27R, ctu->sv2.val[7]);
+	}
+	if (scmdr > 3) {
+		rsnd_mod_write(mod, CTU_SV30R, ctu->sv3.val[0]);
+		rsnd_mod_write(mod, CTU_SV31R, ctu->sv3.val[1]);
+		rsnd_mod_write(mod, CTU_SV32R, ctu->sv3.val[2]);
+		rsnd_mod_write(mod, CTU_SV33R, ctu->sv3.val[3]);
+		rsnd_mod_write(mod, CTU_SV34R, ctu->sv3.val[4]);
+		rsnd_mod_write(mod, CTU_SV35R, ctu->sv3.val[5]);
+		rsnd_mod_write(mod, CTU_SV36R, ctu->sv3.val[6]);
+		rsnd_mod_write(mod, CTU_SV37R, ctu->sv3.val[7]);
+	}
 
 	rsnd_mod_write(mod, CTU_CTUIR, 0);
 }
 
+static void rsnd_ctu_value_reset(struct rsnd_dai_stream *io,
+				 struct rsnd_mod *mod)
+{
+	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
+	int i;
+
+	if (!ctu->reset.val)
+		return;
+
+	for (i = 0; i < RSND_MAX_CHANNELS; i++) {
+		ctu->pass.val[i] = 0;
+		ctu->sv0.val[i] = 0;
+		ctu->sv1.val[i] = 0;
+		ctu->sv2.val[i] = 0;
+		ctu->sv3.val[i] = 0;
+	}
+	ctu->reset.val = 0;
+}
+
 static int rsnd_ctu_init(struct rsnd_mod *mod,
 			 struct rsnd_dai_stream *io,
 			 struct rsnd_priv *priv)
@@ -164,12 +270,66 @@ static int rsnd_ctu_hw_params(struct rsnd_mod *mod,
 	return 0;
 }
 
+static int rsnd_ctu_pcm_new(struct rsnd_mod *mod,
+			    struct rsnd_dai_stream *io,
+			    struct snd_soc_pcm_runtime *rtd)
+{
+	struct rsnd_ctu *ctu = rsnd_mod_to_ctu(mod);
+	int ret;
+
+	/* CTU Pass */
+	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass",
+			       NULL,
+			       &ctu->pass, RSND_MAX_CHANNELS,
+			       0xC);
+
+	/* ROW0 */
+	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0",
+			       NULL,
+			       &ctu->sv0, RSND_MAX_CHANNELS,
+			       0x00FFFFFF);
+	if (ret < 0)
+		return ret;
+
+	/* ROW1 */
+	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV1",
+			       NULL,
+			       &ctu->sv1, RSND_MAX_CHANNELS,
+			       0x00FFFFFF);
+	if (ret < 0)
+		return ret;
+
+	/* ROW2 */
+	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV2",
+			       NULL,
+			       &ctu->sv2, RSND_MAX_CHANNELS,
+			       0x00FFFFFF);
+	if (ret < 0)
+		return ret;
+
+	/* ROW3 */
+	ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV3",
+			       NULL,
+			       &ctu->sv3, RSND_MAX_CHANNELS,
+			       0x00FFFFFF);
+	if (ret < 0)
+		return ret;
+
+	/* Reset */
+	ret = rsnd_kctrl_new_s(mod, io, rtd, "CTU Reset",
+			       rsnd_ctu_value_reset,
+			       &ctu->reset, 1);
+
+	return ret;
+}
+
 static struct rsnd_mod_ops rsnd_ctu_ops = {
 	.name		= CTU_NAME,
 	.probe		= rsnd_ctu_probe_,
 	.init		= rsnd_ctu_init,
 	.quit		= rsnd_ctu_quit,
 	.hw_params	= rsnd_ctu_hw_params,
+	.pcm_new	= rsnd_ctu_pcm_new,
 };
 
 struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id)
-- 
2.7.0



More information about the Alsa-devel mailing list