diff mbox

[6/6,v3] ASoC: rsnd: Add Volume Ramp support

Message ID 8761eu46cz.wl%kuninori.morimoto.gx@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Kuninori Morimoto Nov. 5, 2014, 4:29 a.m. UTC
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

This patch adds Volume Ramp to Renesas sound driver.

Below sample indicates
Mute -> Volume 100% -> Mute.
Here,
 - Mute        (= Normal Volume x 0%)
 - Volume 100% (= Normal Volume x 100%)

amixer set "DVC Out" 100%      // = Normal Volume
amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
amixer set "DVC Out Ramp" 0%   // Mute = Normal Volume x 0%
amixer set "DVC Out Ramp" on   // Volume Ramp ON
aplay xxx.wav &
amixer set "DVC Out Ramp" 100% // Mute to Normal Volume x 100%
amixer set "DVC Out Ramp" 0%   // Normal Volume x 100% to Mute

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
v2 -> v3

 - use enumerated list
 - it is using datasheet words (= xxx dB / yy step)

 sound/soc/sh/rcar/dvc.c  |   74 ++++++++++++++++++++++++++++++++++++++++++++++
 sound/soc/sh/rcar/gen.c  |    3 ++
 sound/soc/sh/rcar/rsnd.h |    6 ++++
 3 files changed, 83 insertions(+)

Comments

Mark Brown Nov. 6, 2014, 4:58 p.m. UTC | #1
On Tue, Nov 04, 2014 at 08:29:53PM -0800, Kuninori Morimoto wrote:

> amixer set "DVC Out" 100%      // = Normal Volume
> amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
> amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
> amixer set "DVC Out Ramp" 0%   // Mute = Normal Volume x 0%
> amixer set "DVC Out Ramp" on   // Volume Ramp ON
> aplay xxx.wav &
> amixer set "DVC Out Ramp" 100% // Mute to Normal Volume x 100%
> amixer set "DVC Out Ramp" 0%   // Normal Volume x 100% to Mute

Correct me if I'm wrong but I think what's confusing me here is that
what I'd expect to happen is that setting the ramp rate would cause any
volume change done by the user to ramp to the target volume (or mute)
but it looks like what's actually happening is that the ramp control is
providing an additional layer of volume control on top of the normal
volume control.
Kuninori Morimoto Nov. 7, 2014, 12:11 a.m. UTC | #2
Hi Mark

Thank you for your review

> > amixer set "DVC Out" 100%      // = Normal Volume
> > amixer set "DVC Out Ramp Up Rate"   "0.125 dB/64 steps"
> > amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
> > amixer set "DVC Out Ramp" 0%   // Mute = Normal Volume x 0%
> > amixer set "DVC Out Ramp" on   // Volume Ramp ON
> > aplay xxx.wav &
> > amixer set "DVC Out Ramp" 100% // Mute to Normal Volume x 100%
> > amixer set "DVC Out Ramp" 0%   // Normal Volume x 100% to Mute
> 
> Correct me if I'm wrong but I think what's confusing me here is that
> what I'd expect to happen is that setting the ramp rate would cause any
> volume change done by the user to ramp to the target volume (or mute)
> but it looks like what's actually happening is that the ramp control is
> providing an additional layer of volume control on top of the normal
> volume control.

Sorry for my poor explanation.
Yes, you are correct.
Volume Ramp chenges [ramp layer] (0% - 100%)
[ramp layer] is always 100% if you don't use Volume Ramp.

         [Normal Volume] x [ramp layer] = output

Please let me better/understandable naming.
Mark Brown Nov. 7, 2014, 10:45 a.m. UTC | #3
On Thu, Nov 06, 2014 at 04:11:12PM -0800, Kuninori Morimoto wrote:

> > Correct me if I'm wrong but I think what's confusing me here is that
> > what I'd expect to happen is that setting the ramp rate would cause any
> > volume change done by the user to ramp to the target volume (or mute)
> > but it looks like what's actually happening is that the ramp control is
> > providing an additional layer of volume control on top of the normal
> > volume control.

> Sorry for my poor explanation.
> Yes, you are correct.
> Volume Ramp chenges [ramp layer] (0% - 100%)
> [ramp layer] is always 100% if you don't use Volume Ramp.

>          [Normal Volume] x [ramp layer] = output

> Please let me better/understandable naming.

OK, right.  In that case what I'd expect is that the only control the
user gets is of the ramp rate and then if that's configured any time the
volume is changed the driver will ensure that the change is implemented
with a ramp - that'd correspond to the normal implementation of this in
other devices (usually the hardware just does this so we don't have to
do anything special in software).
diff mbox

Patch

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 8504f6b..0b38f888 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -38,6 +38,10 @@  struct rsnd_dvc {
 	struct clk *clk;
 	struct rsnd_dvc_cfg_m volume;
 	struct rsnd_dvc_cfg_m mute;
+	struct rsnd_dvc_cfg_s ren;	/* Ramp Enable */
+	struct rsnd_dvc_cfg_s rup;	/* Ramp Rate Up */
+	struct rsnd_dvc_cfg_s rdown;	/* Ramp Rate Down */
+	struct rsnd_dvc_cfg_s rvol;	/* Ramp Volume */
 };
 
 #define rsnd_mod_to_dvc(_mod)	\
@@ -49,6 +53,33 @@  struct rsnd_dvc {
 	     ((pos) = (struct rsnd_dvc *)(priv)->dvc + i);	\
 	     i++)
 
+static const char const *dvc_ramp_rate[] = {
+	"128 dB/1 step",	 /* 00000 */
+	"64 dB/1 step",		 /* 00001 */
+	"32 dB/1 step",		 /* 00010 */
+	"16 dB/1 step",		 /* 00011 */
+	"8 dB/1 step",		 /* 00100 */
+	"4 dB/1 step",		 /* 00101 */
+	"2 dB/1 step",		 /* 00110 */
+	"1 dB/1 step",		 /* 00111 */
+	"0.5 dB/1 step",	 /* 01000 */
+	"0.25 dB/1 step",	 /* 01001 */
+	"0.125 dB/1 step",	 /* 01010 */
+	"0.125 dB/2 steps",	 /* 01011 */
+	"0.125 dB/4 steps",	 /* 01100 */
+	"0.125 dB/8 steps",	 /* 01101 */
+	"0.125 dB/16 steps",	 /* 01110 */
+	"0.125 dB/32 steps",	 /* 01111 */
+	"0.125 dB/64 steps",	 /* 10000 */
+	"0.125 dB/128 steps",	 /* 10001 */
+	"0.125 dB/256 steps",	 /* 10010 */
+	"0.125 dB/512 steps",	 /* 10011 */
+	"0.125 dB/1024 steps",	 /* 10100 */
+	"0.125 dB/2048 steps",	 /* 10101 */
+	"0.125 dB/4096 steps",	 /* 10110 */
+	"0.125 dB/8192 steps",	 /* 10111 */
+};
+
 static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
 {
 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
@@ -67,6 +98,17 @@  static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
 	rsnd_mod_write(mod, DVC_VOL0R, dvc->volume.val[0]);
 	rsnd_mod_write(mod, DVC_VOL1R, dvc->volume.val[1]);
 
+	/* Enable Ramp */
+	if (dvc->ren.val) {
+		dvucr |= 0x10;
+		rsnd_mod_write(mod, DVC_VRCTR, 0xff);
+		rsnd_mod_write(mod, DVC_VRPDR, dvc->rup.val << 8 |
+					       dvc->rdown.val);
+		/* use inverted value for user experience */
+		rsnd_mod_write(mod, DVC_VRDBR, dvc->rvol.cfg.max -
+					       dvc->rvol.val);
+	}
+
 	/*  Enable Mute */
 	if (mute) {
 		dvucr |= 0x1;
@@ -323,6 +365,38 @@  static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
 	if (ret < 0)
 		return ret;
 
+	/* Ramp */
+	ret = _rsnd_dvc_pcm_new_s(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Ramp Switch" : "DVC In Ramp Switch",
+			&dvc->ren, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = _rsnd_dvc_pcm_new_e(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
+			&dvc->rup,
+			dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
+	if (ret < 0)
+		return ret;
+
+	ret = _rsnd_dvc_pcm_new_e(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
+			&dvc->rdown,
+			dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
+
+	if (ret < 0)
+		return ret;
+
+	ret = _rsnd_dvc_pcm_new_s(mod, rdai, rtd,
+			rsnd_dai_is_play(rdai, io) ?
+			"DVC Out Ramp Volume" : "DVC In Ramp Volume",
+			&dvc->rvol, 0x3ff);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index 61dee68..4cb3202 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -324,6 +324,9 @@  static int rsnd_gen2_probe(struct platform_device *pdev,
 		RSND_GEN_M_REG(DVC_ADINR,	0xe08,	0x100),
 		RSND_GEN_M_REG(DVC_DVUCR,	0xe10,	0x100),
 		RSND_GEN_M_REG(DVC_ZCMCR,	0xe14,	0x100),
+		RSND_GEN_M_REG(DVC_VRCTR,	0xe18,	0x100),
+		RSND_GEN_M_REG(DVC_VRPDR,	0xe1c,	0x100),
+		RSND_GEN_M_REG(DVC_VRDBR,	0xe20,	0x100),
 		RSND_GEN_M_REG(DVC_VOL0R,	0xe28,	0x100),
 		RSND_GEN_M_REG(DVC_VOL1R,	0xe2c,	0x100),
 		RSND_GEN_M_REG(DVC_DVUER,	0xe48,	0x100),
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h
index d119adf..ed44ca8 100644
--- a/sound/soc/sh/rcar/rsnd.h
+++ b/sound/soc/sh/rcar/rsnd.h
@@ -91,6 +91,9 @@  enum rsnd_reg {
 	RSND_REG_SHARE20,
 	RSND_REG_SHARE21,
 	RSND_REG_SHARE22,
+	RSND_REG_SHARE23,
+	RSND_REG_SHARE24,
+	RSND_REG_SHARE25,
 
 	RSND_REG_MAX,
 };
@@ -129,6 +132,9 @@  enum rsnd_reg {
 #define RSND_REG_CMD_CTRL		RSND_REG_SHARE20
 #define RSND_REG_CMDOUT_TIMSEL		RSND_REG_SHARE21
 #define RSND_REG_BUSIF_DALIGN		RSND_REG_SHARE22
+#define RSND_REG_DVC_VRCTR		RSND_REG_SHARE23
+#define RSND_REG_DVC_VRPDR		RSND_REG_SHARE24
+#define RSND_REG_DVC_VRDBR		RSND_REG_SHARE25
 
 struct rsnd_of_data;
 struct rsnd_priv;