Skip to content

Commit

Permalink
ASoC: dapm: Add support for virtual mixer controls
Browse files Browse the repository at this point in the history
This patch adds support for virtual DAPM mixer controls. They are similar to
virtual DAPM enums. There is no hardware register backing the control, so
changing the control's value wont have any direct effect on the hardware. But it
still influences the DAPM graph by causing the path it sits on to be connected
or disconnected. This in turn can cause power changes for some of the widgets on
the DAPM graph, which will then modify the hardware state.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Tested-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
  • Loading branch information
Lars-Peter Clausen authored and Mark Brown committed Oct 7, 2013
1 parent da83fea commit 249ce13
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 19 deletions.
4 changes: 4 additions & 0 deletions include/sound/soc-dapm.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ struct device;
.info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
#define SOC_DAPM_SINGLE_VIRT(xname, max) \
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
Expand All @@ -300,6 +302,8 @@ struct device;
.tlv.p = (tlv_array), \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
#define SOC_DAPM_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_enum_double, \
Expand Down
3 changes: 2 additions & 1 deletion include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,8 @@ struct snd_soc_pcm_runtime {
/* mixer control */
struct soc_mixer_control {
int min, max, platform_max;
unsigned int reg, rreg, shift, rshift;
int reg, rreg;
unsigned int shift, rshift;
unsigned int invert:1;
unsigned int autodisable:1;
};
Expand Down
45 changes: 27 additions & 18 deletions sound/soc/soc-dapm.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,18 +499,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
int val;
struct soc_mixer_control *mc = (struct soc_mixer_control *)
w->kcontrol_news[i].private_value;
unsigned int reg = mc->reg;
int reg = mc->reg;
unsigned int shift = mc->shift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;

val = soc_widget_read(w, reg);
val = (val >> shift) & mask;
if (invert)
val = max - val;
if (reg != SND_SOC_NOPM) {
val = soc_widget_read(w, reg);
val = (val >> shift) & mask;
if (invert)
val = max - val;
p->connect = !!val;
} else {
p->connect = 0;
}

p->connect = !!val;
}
break;
case snd_soc_dapm_mux: {
Expand Down Expand Up @@ -2792,7 +2796,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = codec->card;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int reg = mc->reg;
unsigned int shift = mc->shift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
Expand All @@ -2805,7 +2809,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
kcontrol->id.name);

mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
if (dapm_kcontrol_is_powered(kcontrol))
if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
val = (snd_soc_read(codec, reg) >> shift) & mask;
else
val = dapm_kcontrol_get_value(kcontrol);
Expand Down Expand Up @@ -2836,7 +2840,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
struct snd_soc_card *card = codec->card;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
unsigned int reg = mc->reg;
int reg = mc->reg;
unsigned int shift = mc->shift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
Expand All @@ -2858,19 +2862,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,

mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);

dapm_kcontrol_set_value(kcontrol, val);
change = dapm_kcontrol_set_value(kcontrol, val);

mask = mask << shift;
val = val << shift;
if (reg != SND_SOC_NOPM) {
mask = mask << shift;
val = val << shift;

change = snd_soc_test_bits(codec, reg, mask, val);
}

change = snd_soc_test_bits(codec, reg, mask, val);
if (change) {
update.kcontrol = kcontrol;
update.reg = reg;
update.mask = mask;
update.val = val;
if (reg != SND_SOC_NOPM) {
update.kcontrol = kcontrol;
update.reg = reg;
update.mask = mask;
update.val = val;

card->update = &update;
card->update = &update;
}

soc_dapm_mixer_update_power(card, kcontrol, connect);

Expand Down

0 comments on commit 249ce13

Please sign in to comment.