Commit 3539cacf authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: rsnd: Add Volume Ramp support



This patch adds Volume Ramp to Renesas sound driver.

amixer set "DVC Out" 100%
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" on
aplay xxx.wav &
amixer set "DVC Out"  80%  // Volume Down
amixer set "DVC Out" 100%  // Volume Up

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent d3a76823
Loading
Loading
Loading
Loading
+84 −3
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@ 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 */
};

#define rsnd_mod_to_dvc(_mod)	\
@@ -49,9 +52,37 @@ 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);
	u32 val[RSND_DVC_CHANNELS];
	u32 dvucr = 0;
	u32 mute = 0;
	int i;
@@ -62,10 +93,35 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
	/* Disable DVC Register access */
	rsnd_mod_write(mod, DVC_DVUER, 0);

	/* Enable Ramp */
	if (dvc->ren.val) {
		dvucr |= 0x10;

		/* Digital Volume Max */
		for (i = 0; i < RSND_DVC_CHANNELS; i++)
			val[i] = dvc->volume.cfg.max;

		rsnd_mod_write(mod, DVC_VRCTR, 0xff);
		rsnd_mod_write(mod, DVC_VRPDR, dvc->rup.val << 8 |
					       dvc->rdown.val);
		/*
		 * FIXME !!
		 * use scale-downed Digital Volume
		 * as Volume Ramp
		 * 7F FFFF -> 3FF
		 */
		rsnd_mod_write(mod, DVC_VRDBR,
			       0x3ff - (dvc->volume.val[0] >> 13));

	} else {
		for (i = 0; i < RSND_DVC_CHANNELS; i++)
			val[i] = dvc->volume.val[i];
	}

	/* Enable Digital Volume */
	dvucr = 0x100;
	rsnd_mod_write(mod, DVC_VOL0R, dvc->volume.val[0]);
	rsnd_mod_write(mod, DVC_VOL1R, dvc->volume.val[1]);
	dvucr |= 0x100;
	rsnd_mod_write(mod, DVC_VOL0R, val[0]);
	rsnd_mod_write(mod, DVC_VOL1R, val[1]);

	/*  Enable Mute */
	if (mute) {
@@ -324,6 +380,31 @@ 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;

	return 0;
}

+3 −0
Original line number Diff line number Diff line
@@ -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),
+6 −0
Original line number Diff line number Diff line
@@ -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;