aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-dapm.c
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2013-10-06 07:43:49 -0400
committerMark Brown <broonie@linaro.org>2013-10-07 06:46:20 -0400
commit249ce1387b7739dbea2ac1a697e4bf1e37ec06b7 (patch)
tree04c94ebed2f16c4fcd730292557cfad6479ef4b4 /sound/soc/soc-dapm.c
parentda83fea6122ea637be5f960b95bb599561617319 (diff)
ASoC: dapm: Add support for virtual mixer controls
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>
Diffstat (limited to 'sound/soc/soc-dapm.c')
-rw-r--r--sound/soc/soc-dapm.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 177f8a1938da..9273216f22fc 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -499,18 +499,22 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
499 int val; 499 int val;
500 struct soc_mixer_control *mc = (struct soc_mixer_control *) 500 struct soc_mixer_control *mc = (struct soc_mixer_control *)
501 w->kcontrol_news[i].private_value; 501 w->kcontrol_news[i].private_value;
502 unsigned int reg = mc->reg; 502 int reg = mc->reg;
503 unsigned int shift = mc->shift; 503 unsigned int shift = mc->shift;
504 int max = mc->max; 504 int max = mc->max;
505 unsigned int mask = (1 << fls(max)) - 1; 505 unsigned int mask = (1 << fls(max)) - 1;
506 unsigned int invert = mc->invert; 506 unsigned int invert = mc->invert;
507 507
508 val = soc_widget_read(w, reg); 508 if (reg != SND_SOC_NOPM) {
509 val = (val >> shift) & mask; 509 val = soc_widget_read(w, reg);
510 if (invert) 510 val = (val >> shift) & mask;
511 val = max - val; 511 if (invert)
512 val = max - val;
513 p->connect = !!val;
514 } else {
515 p->connect = 0;
516 }
512 517
513 p->connect = !!val;
514 } 518 }
515 break; 519 break;
516 case snd_soc_dapm_mux: { 520 case snd_soc_dapm_mux: {
@@ -2792,7 +2796,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2792 struct snd_soc_card *card = codec->card; 2796 struct snd_soc_card *card = codec->card;
2793 struct soc_mixer_control *mc = 2797 struct soc_mixer_control *mc =
2794 (struct soc_mixer_control *)kcontrol->private_value; 2798 (struct soc_mixer_control *)kcontrol->private_value;
2795 unsigned int reg = mc->reg; 2799 int reg = mc->reg;
2796 unsigned int shift = mc->shift; 2800 unsigned int shift = mc->shift;
2797 int max = mc->max; 2801 int max = mc->max;
2798 unsigned int mask = (1 << fls(max)) - 1; 2802 unsigned int mask = (1 << fls(max)) - 1;
@@ -2805,7 +2809,7 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
2805 kcontrol->id.name); 2809 kcontrol->id.name);
2806 2810
2807 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2811 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2808 if (dapm_kcontrol_is_powered(kcontrol)) 2812 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM)
2809 val = (snd_soc_read(codec, reg) >> shift) & mask; 2813 val = (snd_soc_read(codec, reg) >> shift) & mask;
2810 else 2814 else
2811 val = dapm_kcontrol_get_value(kcontrol); 2815 val = dapm_kcontrol_get_value(kcontrol);
@@ -2836,7 +2840,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2836 struct snd_soc_card *card = codec->card; 2840 struct snd_soc_card *card = codec->card;
2837 struct soc_mixer_control *mc = 2841 struct soc_mixer_control *mc =
2838 (struct soc_mixer_control *)kcontrol->private_value; 2842 (struct soc_mixer_control *)kcontrol->private_value;
2839 unsigned int reg = mc->reg; 2843 int reg = mc->reg;
2840 unsigned int shift = mc->shift; 2844 unsigned int shift = mc->shift;
2841 int max = mc->max; 2845 int max = mc->max;
2842 unsigned int mask = (1 << fls(max)) - 1; 2846 unsigned int mask = (1 << fls(max)) - 1;
@@ -2858,19 +2862,24 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
2858 2862
2859 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2863 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2860 2864
2861 dapm_kcontrol_set_value(kcontrol, val); 2865 change = dapm_kcontrol_set_value(kcontrol, val);
2862 2866
2863 mask = mask << shift; 2867 if (reg != SND_SOC_NOPM) {
2864 val = val << shift; 2868 mask = mask << shift;
2869 val = val << shift;
2870
2871 change = snd_soc_test_bits(codec, reg, mask, val);
2872 }
2865 2873
2866 change = snd_soc_test_bits(codec, reg, mask, val);
2867 if (change) { 2874 if (change) {
2868 update.kcontrol = kcontrol; 2875 if (reg != SND_SOC_NOPM) {
2869 update.reg = reg; 2876 update.kcontrol = kcontrol;
2870 update.mask = mask; 2877 update.reg = reg;
2871 update.val = val; 2878 update.mask = mask;
2879 update.val = val;
2872 2880
2873 card->update = &update; 2881 card->update = &update;
2882 }
2874 2883
2875 soc_dapm_mixer_update_power(card, kcontrol, connect); 2884 soc_dapm_mixer_update_power(card, kcontrol, connect);
2876 2885