Discussion:
[PATCH 0/8] ASoC: rsnd: add Volume Ramp support
Kuninori Morimoto
2014-10-22 01:13:17 UTC
Permalink
Hi Mark

These patches add Volume Ramp support on Renesas R-Car sound driver.

Kuninori Morimoto (8):
ASoC: rsnd: tidyup debug information when read/write
ASoC: rsnd: tidyup RSND_DVC_VOLUME_NUM to RSND_DVC_CHANNELS
ASoC: rsnd: add struct rsnd_dvc_cfg and control DVC settings
ASoC: rsnd: control DVC_DVUCR under rsnd_dvc_volume_update()
ASoC: rsnd: move DVC_DVUER settings under rsnd_dvc_volume_update()
ASoC: rsnd: enable multiple DVC valume settings
ASoC: rsnd: enable single DVC valume settings
ASoC: rsnd: Add Volume Ramp support

sound/soc/sh/rcar/dvc.c | 155 ++++++++++++++++++++++++++++++++++------------
sound/soc/sh/rcar/gen.c | 30 ++++++---
sound/soc/sh/rcar/rsnd.h | 6 ++
3 files changed, 145 insertions(+), 46 deletions(-)


Best regards
---
Kuninori Morimoto
Kuninori Morimoto
2014-10-22 01:13:46 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

b8c637864a6904a9ba8e0df556d5bdf9f26b2c54
(ASoC: rsnd: use regmap_mmio instead of original regmap bus)
added regmap_mmio support on Renesas R-Car sound driver.
Then, debug information of register read/write
indicates regmap index, not register address.
This is a little bit confusable information.
This patch tidyup debug message, and added regmap debug hint
on comment area.

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/gen.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c
index f95e7ab..61dee68 100644
--- a/sound/soc/sh/rcar/gen.c
+++ b/sound/soc/sh/rcar/gen.c
@@ -8,6 +8,17 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+
+/*
+ * #define DEBUG
+ *
+ * you can also add below in
+ * ${LINUX}/drivers/base/regmap/regmap.c
+ * for regmap debug
+ *
+ * #define LOG_DEVICE "xxxx.rcar_sound"
+ */
+
#include "rsnd.h"

struct rsnd_gen {
@@ -67,9 +78,10 @@ u32 rsnd_read(struct rsnd_priv *priv,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return 0;

- regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);
+ dev_dbg(dev, "r %s(%d) - %4d : %08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod), reg, val);

- dev_dbg(dev, "r %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, val);
+ regmap_fields_read(gen->regs[reg], rsnd_mod_id(mod), &val);

return val;
}
@@ -84,9 +96,10 @@ void rsnd_write(struct rsnd_priv *priv,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;

- regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
+ dev_dbg(dev, "w %s(%d) - %4d : %08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data);

- dev_dbg(dev, "w %s - 0x%04d : %08x\n", rsnd_mod_name(mod), reg, data);
+ regmap_fields_write(gen->regs[reg], rsnd_mod_id(mod), data);
}

void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
@@ -98,11 +111,11 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
if (!rsnd_is_accessible_reg(priv, gen, reg))
return;

+ dev_dbg(dev, "b %s(%d) - %4d : %08x/%08x\n",
+ rsnd_mod_name(mod), rsnd_mod_id(mod), reg, data, mask);
+
regmap_fields_update_bits(gen->regs[reg], rsnd_mod_id(mod),
mask, data);
-
- dev_dbg(dev, "b %s - 0x%04d : %08x/%08x\n",
- rsnd_mod_name(mod), reg, data, mask);
}

#define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \
--
1.7.9.5
Mark Brown
2014-10-22 22:46:48 UTC
Permalink
Post by Kuninori Morimoto
b8c637864a6904a9ba8e0df556d5bdf9f26b2c54
(ASoC: rsnd: use regmap_mmio instead of original regmap bus)
added regmap_mmio support on Renesas R-Car sound driver.
Applied, thanks.
Kuninori Morimoto
2014-10-22 01:13:56 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

RSND_DVC_VOLUME_NUM means DVC channel number.
This patch tidyups this un-understandable naming

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 3f44393..b5f95ad4 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -12,7 +12,7 @@

#define RSND_DVC_NAME_SIZE 16
#define RSND_DVC_VOLUME_MAX 100
-#define RSND_DVC_VOLUME_NUM 2
+#define RSND_DVC_CHANNELS 2

#define DVC_NAME "dvc"

@@ -20,8 +20,8 @@ struct rsnd_dvc {
struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct clk *clk;
- u8 volume[RSND_DVC_VOLUME_NUM];
- u8 mute[RSND_DVC_VOLUME_NUM];
+ u8 volume[RSND_DVC_CHANNELS];
+ u8 mute[RSND_DVC_CHANNELS];
};

#define rsnd_mod_to_dvc(_mod) \
@@ -37,11 +37,11 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u32 max = (0x00800000 - 1);
- u32 vol[RSND_DVC_VOLUME_NUM];
+ u32 vol[RSND_DVC_CHANNELS];
u32 mute = 0;
int i;

- for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
+ for (i = 0; i < RSND_DVC_CHANNELS; i++) {
vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
mute |= (!!dvc->mute[i]) << i;
}
@@ -150,7 +150,7 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
u8 *val = (u8 *)kctrl->private_value;

- uinfo->count = RSND_DVC_VOLUME_NUM;
+ uinfo->count = RSND_DVC_CHANNELS;
uinfo->value.integer.min = 0;

if (val == dvc->volume) {
@@ -170,7 +170,7 @@ static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
u8 *val = (u8 *)kctrl->private_value;
int i;

- for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
+ for (i = 0; i < RSND_DVC_CHANNELS; i++)
ucontrol->value.integer.value[i] = val[i];

return 0;
@@ -183,7 +183,7 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
u8 *val = (u8 *)kctrl->private_value;
int i, change = 0;

- for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
+ for (i = 0; i < RSND_DVC_CHANNELS; i++) {
change |= (ucontrol->value.integer.value[i] != val[i]);
val[i] = ucontrol->value.integer.value[i];
}
--
1.7.9.5
Mark Brown
2014-10-22 22:46:55 UTC
Permalink
Post by Kuninori Morimoto
RSND_DVC_VOLUME_NUM means DVC channel number.
This patch tidyups this un-understandable naming
Applied, thanks.
Kuninori Morimoto
2014-10-22 01:14:14 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

DVC can control Digital Volume / Mute / Volume Ramp etc,
and these uses different max value.
Current driver is using fixed max value for each settings.
This patch adds new struct rsnd_dvc_cfg, and control these.

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 51 +++++++++++++++++++++++------------------------
1 file changed, 25 insertions(+), 26 deletions(-)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index b5f95ad4..deaf0fa 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -11,17 +11,21 @@
#include "rsnd.h"

#define RSND_DVC_NAME_SIZE 16
-#define RSND_DVC_VOLUME_MAX 100
#define RSND_DVC_CHANNELS 2

#define DVC_NAME "dvc"

+struct rsnd_dvc_cfg {
+ unsigned int max;
+ u32 val[RSND_DVC_CHANNELS];
+};
+
struct rsnd_dvc {
struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct clk *clk;
- u8 volume[RSND_DVC_CHANNELS];
- u8 mute[RSND_DVC_CHANNELS];
+ struct rsnd_dvc_cfg volume;
+ struct rsnd_dvc_cfg mute;
};

#define rsnd_mod_to_dvc(_mod) \
@@ -36,18 +40,15 @@ struct rsnd_dvc {
static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u32 max = (0x00800000 - 1);
- u32 vol[RSND_DVC_CHANNELS];
u32 mute = 0;
int i;

for (i = 0; i < RSND_DVC_CHANNELS; i++) {
- vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
- mute |= (!!dvc->mute[i]) << i;
+ mute |= (!!dvc->mute.val[i]) << i;
}

- rsnd_mod_write(mod, DVC_VOL0R, vol[0]);
- rsnd_mod_write(mod, DVC_VOL1R, vol[1]);
+ rsnd_mod_write(mod, DVC_VOL0R, dvc->volume.val[0]);
+ rsnd_mod_write(mod, DVC_VOL1R, dvc->volume.val[1]);

rsnd_mod_write(mod, DVC_ZCMCR, mute);
}
@@ -146,20 +147,16 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_info *uinfo)
{
- struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
- struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
- u8 *val = (u8 *)kctrl->private_value;
+ struct rsnd_dvc_cfg *cfg = (struct rsnd_dvc_cfg *)kctrl->private_value;

uinfo->count = RSND_DVC_CHANNELS;
uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = cfg->max;

- if (val == dvc->volume) {
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
- } else {
+ if (cfg->max == 1)
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->value.integer.max = 1;
- }
+ else
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;

return 0;
}
@@ -167,11 +164,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
- u8 *val = (u8 *)kctrl->private_value;
+ struct rsnd_dvc_cfg *cfg = (struct rsnd_dvc_cfg *)kctrl->private_value;
int i;

for (i = 0; i < RSND_DVC_CHANNELS; i++)
- ucontrol->value.integer.value[i] = val[i];
+ ucontrol->value.integer.value[i] = cfg->val[i];

return 0;
}
@@ -180,12 +177,12 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
struct snd_ctl_elem_value *ucontrol)
{
struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
- u8 *val = (u8 *)kctrl->private_value;
+ struct rsnd_dvc_cfg *cfg = (struct rsnd_dvc_cfg *)kctrl->private_value;
int i, change = 0;

for (i = 0; i < RSND_DVC_CHANNELS; i++) {
- change |= (ucontrol->value.integer.value[i] != val[i]);
- val[i] = ucontrol->value.integer.value[i];
+ change |= (ucontrol->value.integer.value[i] != cfg->val[i]);
+ cfg->val[i] = ucontrol->value.integer.value[i];
}

if (change)
@@ -198,7 +195,7 @@ static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd,
const unsigned char *name,
- u8 *private)
+ struct rsnd_dvc_cfg *private)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_kcontrol *kctrl;
@@ -232,18 +229,20 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
int ret;

/* Volume */
+ dvc->volume.max = 0x00800000 - 1;
ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
"DVC Out Playback Volume" : "DVC In Capture Volume",
- dvc->volume);
+ &dvc->volume);
if (ret < 0)
return ret;

/* Mute */
+ dvc->mute.max = 1;
ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
"DVC Out Mute Switch" : "DVC In Mute Switch",
- dvc->mute);
+ &dvc->mute);
if (ret < 0)
return ret;
--
1.7.9.5
Mark Brown
2014-10-22 22:47:03 UTC
Permalink
Post by Kuninori Morimoto
DVC can control Digital Volume / Mute / Volume Ramp etc,
and these uses different max value.
Applied, thanks.

Kuninori Morimoto
2014-10-22 01:14:23 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

rsnd_dvc_volume_update() is main function to control
DVC feature like Digital Volume / Mute / Ramp etc.
DVC_DVUCR should be controlled under this function.

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index deaf0fa..3952237 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -40,6 +40,7 @@ struct rsnd_dvc {
static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
{
struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
+ u32 dvucr = 0;
u32 mute = 0;
int i;

@@ -47,10 +48,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
mute |= (!!dvc->mute.val[i]) << 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]);

- rsnd_mod_write(mod, DVC_ZCMCR, mute);
+ /* Enable Mute */
+ if (mute) {
+ dvucr |= 0x1;
+ rsnd_mod_write(mod, DVC_ZCMCR, mute);
+ }
+
+ rsnd_mod_write(mod, DVC_DVUCR, dvucr);
}

static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
@@ -103,9 +112,6 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,

rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod));

- /* enable Volume / Mute */
- rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101);
-
/* ch0/ch1 Volume */
rsnd_dvc_volume_update(dvc_mod);
--
1.7.9.5
Kuninori Morimoto
2014-10-22 01:14:31 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

We need to Enable/Disable DVC_DVUER register if we set
DVCp_ZCMCR, DVCp_VRCTR, DVCp_VRPDR, DVCp_VRDBR,
DVCp_VOL0R, DVCp_VOL1R, DVCp_VOL2R, DVCp_VOL3R,
DVCp_VOL4R, DVCp_VOL5R, DVCp_VOL6R, DVCp_VOL7R
and, these are controlled under rsnd_dvc_volume_update().
This patch moves DVC_DVUER settings to it.

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 3952237..2fbaf27 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -48,6 +48,9 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
mute |= (!!dvc->mute.val[i]) << i;
}

+ /* Enable DVC Register access */
+ rsnd_mod_write(mod, DVC_DVUER, 1);
+
/* Enable Digital Volume */
dvucr = 0x100;
rsnd_mod_write(mod, DVC_VOL0R, dvc->volume.val[0]);
@@ -60,6 +63,9 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
}

rsnd_mod_write(mod, DVC_DVUCR, dvucr);
+
+ /* Disable DVC Register access */
+ rsnd_mod_write(mod, DVC_DVUER, 0);
}

static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
@@ -117,8 +123,6 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,

rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);

- rsnd_mod_write(dvc_mod, DVC_DVUER, 1);
-
rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io);

return 0;
--
1.7.9.5
Kuninori Morimoto
2014-10-22 01:14:39 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

DVC controls some digital volume features.
Some of them requests values for "each channels",
but, some of them requests values for "feature".
Current dvc.c is supporting Mute/Volume,
and these have "each channels" settings.
This patch adds rsnd_dvc_cfg_m and care about
multiple settings for each channels.

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 2fbaf27..e4dd1d8 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -17,6 +17,12 @@

struct rsnd_dvc_cfg {
unsigned int max;
+ unsigned int size;
+ u32 *val;
+};
+
+struct rsnd_dvc_cfg_m {
+ struct rsnd_dvc_cfg cfg;
u32 val[RSND_DVC_CHANNELS];
};

@@ -24,8 +30,8 @@ struct rsnd_dvc {
struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
struct clk *clk;
- struct rsnd_dvc_cfg volume;
- struct rsnd_dvc_cfg mute;
+ struct rsnd_dvc_cfg_m volume;
+ struct rsnd_dvc_cfg_m mute;
};

#define rsnd_mod_to_dvc(_mod) \
@@ -44,9 +50,8 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
u32 mute = 0;
int i;

- for (i = 0; i < RSND_DVC_CHANNELS; i++) {
- mute |= (!!dvc->mute.val[i]) << i;
- }
+ for (i = 0; i < dvc->mute.cfg.size; i++)
+ mute |= (!!dvc->mute.cfg.val[i]) << i;

/* Enable DVC Register access */
rsnd_mod_write(mod, DVC_DVUER, 1);
@@ -177,7 +182,7 @@ static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
struct rsnd_dvc_cfg *cfg = (struct rsnd_dvc_cfg *)kctrl->private_value;
int i;

- for (i = 0; i < RSND_DVC_CHANNELS; i++)
+ for (i = 0; i < cfg->size; i++)
ucontrol->value.integer.value[i] = cfg->val[i];

return 0;
@@ -190,7 +195,7 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
struct rsnd_dvc_cfg *cfg = (struct rsnd_dvc_cfg *)kctrl->private_value;
int i, change = 0;

- for (i = 0; i < RSND_DVC_CHANNELS; i++) {
+ for (i = 0; i < cfg->size; i++) {
change |= (ucontrol->value.integer.value[i] != cfg->val[i]);
cfg->val[i] = ucontrol->value.integer.value[i];
}
@@ -230,6 +235,19 @@ static int __rsnd_dvc_pcm_new(struct rsnd_mod *mod,
return 0;
}

+static int _rsnd_dvc_pcm_new_m(struct rsnd_mod *mod,
+ struct rsnd_dai *rdai,
+ struct snd_soc_pcm_runtime *rtd,
+ const unsigned char *name,
+ struct rsnd_dvc_cfg_m *private,
+ u32 max)
+{
+ private->cfg.max = max;
+ private->cfg.size = RSND_DVC_CHANNELS;
+ private->cfg.val = private->val;
+ return __rsnd_dvc_pcm_new(mod, rdai, rtd, name, &private->cfg);
+}
+
static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd)
@@ -239,20 +257,18 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
int ret;

/* Volume */
- dvc->volume.max = 0x00800000 - 1;
- ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
+ ret = _rsnd_dvc_pcm_new_m(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
"DVC Out Playback Volume" : "DVC In Capture Volume",
- &dvc->volume);
+ &dvc->volume, 0x00800000 - 1);
if (ret < 0)
return ret;

/* Mute */
- dvc->mute.max = 1;
- ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
+ ret = _rsnd_dvc_pcm_new_m(mod, rdai, rtd,
rsnd_dai_is_play(rdai, io) ?
"DVC Out Mute Switch" : "DVC In Mute Switch",
- &dvc->mute);
+ &dvc->mute, 1);
if (ret < 0)
return ret;
--
1.7.9.5
Kuninori Morimoto
2014-10-22 01:14:47 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

DVC controls some digital volume features.
Some of them requests values for "each channels",
but, some of them requests values for "feature".
And, Volume Ramp has "feature" settings.
This patch adds rsnd_dvc_cfg_s and care about
single settings.
Compiler will report like below at this point,
but, it will be removed if Volume Ramp was supported.
warning: '_rsnd_dvc_pcm_new_s' defined but not used

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index e4dd1d8..2654ab0 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -26,6 +26,11 @@ struct rsnd_dvc_cfg_m {
u32 val[RSND_DVC_CHANNELS];
};

+struct rsnd_dvc_cfg_s {
+ struct rsnd_dvc_cfg cfg;
+ u32 val;
+};
+
struct rsnd_dvc {
struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
struct rsnd_mod mod;
@@ -248,6 +253,19 @@ static int _rsnd_dvc_pcm_new_m(struct rsnd_mod *mod,
return __rsnd_dvc_pcm_new(mod, rdai, rtd, name, &private->cfg);
}

+static int _rsnd_dvc_pcm_new_s(struct rsnd_mod *mod,
+ struct rsnd_dai *rdai,
+ struct snd_soc_pcm_runtime *rtd,
+ const unsigned char *name,
+ struct rsnd_dvc_cfg_s *private,
+ u32 max)
+{
+ private->cfg.max = max;
+ private->cfg.size = 1;
+ private->cfg.val = &private->val;
+ return __rsnd_dvc_pcm_new(mod, rdai, rtd, name, &private->cfg);
+}
+
static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
struct rsnd_dai *rdai,
struct snd_soc_pcm_runtime *rtd)
--
1.7.9.5
Kuninori Morimoto
2014-10-22 01:14:55 UTC
Permalink
From: Kuninori Morimoto <***@renesas.com>

This patch adds Volume Ramp to
Renesas sound driver.

This sample indicates Mute -> Volume 100% -> Mute

amixer set "DVC Out Ramp" 100% // Mute as default
amixer set "DVC Out Ramp Period" 80%
amixer set "DVC Out Ramp Enable" on
aplay xxx.wav &
amixer set "DVC Out Ramp" 0% // to Volume 100%
amixer set "DVC Out Ramp" 100% // to Mute

Signed-off-by: Kuninori Morimoto <***@renesas.com>
---
sound/soc/sh/rcar/dvc.c | 34 ++++++++++++++++++++++++++++++++++
sound/soc/sh/rcar/gen.c | 3 +++
sound/soc/sh/rcar/rsnd.h | 6 ++++++
3 files changed, 43 insertions(+)

diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 2654ab0..f353f7d 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -37,6 +37,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 rperiod; /* Ramp Period */
+ struct rsnd_dvc_cfg_s rvol; /* Ramp Volume */
};

#define rsnd_mod_to_dvc(_mod) \
@@ -66,6 +69,15 @@ 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->rperiod.val << 8 |
+ dvc->rperiod.val);
+ rsnd_mod_write(mod, DVC_VRDBR, dvc->rvol.val);
+ }
+
/* Enable Mute */
if (mute) {
dvucr |= 0x1;
@@ -290,6 +302,28 @@ 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 Enable" : "DVC In Ramp Enable",
+ &dvc->ren, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = _rsnd_dvc_pcm_new_s(mod, rdai, rtd,
+ rsnd_dai_is_play(rdai, io) ?
+ "DVC Out Ramp Period" : "DVC In Ramp Period",
+ &dvc->rperiod, 0x17); /* 10111 */
+ 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;
--
1.7.9.5
Loading...