aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc-dapm.h4
-rw-r--r--include/sound/soc.h3
-rw-r--r--sound/soc/soc-dapm.c45
3 files changed, 33 insertions, 19 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 27a72d5d4b00..2037c45adfe6 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -286,6 +286,8 @@ struct device;
286 .info = snd_soc_info_volsw, \ 286 .info = snd_soc_info_volsw, \
287 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 287 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
288 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } 288 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
289#define SOC_DAPM_SINGLE_VIRT(xname, max) \
290 SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0)
289#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ 291#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
290{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 292{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
291 .info = snd_soc_info_volsw, \ 293 .info = snd_soc_info_volsw, \
@@ -300,6 +302,8 @@ struct device;
300 .tlv.p = (tlv_array), \ 302 .tlv.p = (tlv_array), \
301 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ 303 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
302 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } 304 .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
305#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \
306 SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array)
303#define SOC_DAPM_ENUM(xname, xenum) \ 307#define SOC_DAPM_ENUM(xname, xenum) \
304{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 308{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
305 .info = snd_soc_info_enum_double, \ 309 .info = snd_soc_info_enum_double, \
diff --git a/include/sound/soc.h b/include/sound/soc.h
index d22cb0a06feb..b429dba57bf6 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1088,7 +1088,8 @@ struct snd_soc_pcm_runtime {
1088/* mixer control */ 1088/* mixer control */
1089struct soc_mixer_control { 1089struct soc_mixer_control {
1090 int min, max, platform_max; 1090 int min, max, platform_max;
1091 unsigned int reg, rreg, shift, rshift; 1091 int reg, rreg;
1092 unsigned int shift, rshift;
1092 unsigned int invert:1; 1093 unsigned int invert:1;
1093 unsigned int autodisable:1; 1094 unsigned int autodisable:1;
1094}; 1095};
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