aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-12-12 10:52:44 -0500
committerMark Brown <broonie@kernel.org>2016-12-12 10:52:44 -0500
commitc0f2302a6ac310bcacccafbefe414a8026375b60 (patch)
treeac7e09e792cb5bf1b3f9e9aab47250e884ced2bb
parent3f1b86139e94289289b00f745cc483b1fef5fd46 (diff)
parent02866eab0f0d88c4b6a68de72022c2b26f0359b5 (diff)
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-next
-rw-r--r--include/sound/soc-dapm.h14
-rw-r--r--sound/soc/codecs/adau17x1.c2
-rw-r--r--sound/soc/codecs/tlv320aic3x.c2
-rw-r--r--sound/soc/codecs/wm9712.c2
-rw-r--r--sound/soc/codecs/wm9713.c2
-rw-r--r--sound/soc/soc-dapm.c154
6 files changed, 141 insertions, 35 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index f60d755f7ac6..a466f4bdc835 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -272,6 +272,16 @@ struct device;
272 272
273 273
274/* dapm kcontrol types */ 274/* dapm kcontrol types */
275#define SOC_DAPM_DOUBLE(xname, reg, lshift, rshift, max, invert) \
276{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
277 .info = snd_soc_info_volsw, \
278 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
279 .private_value = SOC_DOUBLE_VALUE(reg, lshift, rshift, max, invert, 0) }
280#define SOC_DAPM_DOUBLE_R(xname, lreg, rreg, shift, max, invert) \
281{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
282 .info = snd_soc_info_volsw, \
283 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
284 .private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) }
275#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ 285#define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \
276{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 286{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
277 .info = snd_soc_info_volsw, \ 287 .info = snd_soc_info_volsw, \
@@ -615,6 +625,10 @@ struct snd_soc_dapm_update {
615 int reg; 625 int reg;
616 int mask; 626 int mask;
617 int val; 627 int val;
628 int reg2;
629 int mask2;
630 int val2;
631 bool has_second_set;
618}; 632};
619 633
620struct snd_soc_dapm_wcache { 634struct snd_soc_dapm_wcache {
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 439aa3ff1f99..b36511d965c8 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -160,7 +160,7 @@ static int adau17x1_dsp_mux_enum_put(struct snd_kcontrol *kcontrol,
160 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); 160 struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
161 struct adau *adau = snd_soc_codec_get_drvdata(codec); 161 struct adau *adau = snd_soc_codec_get_drvdata(codec);
162 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 162 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
163 struct snd_soc_dapm_update update; 163 struct snd_soc_dapm_update update = { 0 };
164 unsigned int stream = e->shift_l; 164 unsigned int stream = e->shift_l;
165 unsigned int val, change; 165 unsigned int val, change;
166 int reg; 166 int reg;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 5a8d96ec058c..8877b74b0510 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -157,7 +157,7 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
157 unsigned int mask = (1 << fls(max)) - 1; 157 unsigned int mask = (1 << fls(max)) - 1;
158 unsigned int invert = mc->invert; 158 unsigned int invert = mc->invert;
159 unsigned short val; 159 unsigned short val;
160 struct snd_soc_dapm_update update; 160 struct snd_soc_dapm_update update = { 0 };
161 int connect, change; 161 int connect, change;
162 162
163 val = (ucontrol->value.integer.value[0] & mask); 163 val = (ucontrol->value.integer.value[0] & mask);
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 557709eac698..85f7c5bb8b82 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -187,7 +187,7 @@ static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol,
187 struct soc_mixer_control *mc = 187 struct soc_mixer_control *mc =
188 (struct soc_mixer_control *)kcontrol->private_value; 188 (struct soc_mixer_control *)kcontrol->private_value;
189 unsigned int mixer, mask, shift, old; 189 unsigned int mixer, mask, shift, old;
190 struct snd_soc_dapm_update update; 190 struct snd_soc_dapm_update update = { 0 };
191 bool change; 191 bool change;
192 192
193 mixer = mc->shift >> 8; 193 mixer = mc->shift >> 8;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index e4301ddb1b84..7e4822185feb 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -231,7 +231,7 @@ static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol,
231 struct soc_mixer_control *mc = 231 struct soc_mixer_control *mc =
232 (struct soc_mixer_control *)kcontrol->private_value; 232 (struct soc_mixer_control *)kcontrol->private_value;
233 unsigned int mixer, mask, shift, old; 233 unsigned int mixer, mask, shift, old;
234 struct snd_soc_dapm_update update; 234 struct snd_soc_dapm_update update = { 0 };
235 bool change; 235 bool change;
236 236
237 mixer = mc->shift >> 8; 237 mixer = mc->shift >> 8;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 3bbe32ee4630..27dd02e57b31 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -330,6 +330,11 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
330 case snd_soc_dapm_mixer_named_ctl: 330 case snd_soc_dapm_mixer_named_ctl:
331 mc = (struct soc_mixer_control *)kcontrol->private_value; 331 mc = (struct soc_mixer_control *)kcontrol->private_value;
332 332
333 if (mc->autodisable && snd_soc_volsw_is_stereo(mc))
334 dev_warn(widget->dapm->dev,
335 "ASoC: Unsupported stereo autodisable control '%s'\n",
336 ctrl_name);
337
333 if (mc->autodisable) { 338 if (mc->autodisable) {
334 struct snd_soc_dapm_widget template; 339 struct snd_soc_dapm_widget template;
335 340
@@ -723,7 +728,8 @@ static int dapm_connect_mux(struct snd_soc_dapm_context *dapm,
723} 728}
724 729
725/* set up initial codec paths */ 730/* set up initial codec paths */
726static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i) 731static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i,
732 int nth_path)
727{ 733{
728 struct soc_mixer_control *mc = (struct soc_mixer_control *) 734 struct soc_mixer_control *mc = (struct soc_mixer_control *)
729 p->sink->kcontrol_news[i].private_value; 735 p->sink->kcontrol_news[i].private_value;
@@ -736,7 +742,25 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i)
736 742
737 if (reg != SND_SOC_NOPM) { 743 if (reg != SND_SOC_NOPM) {
738 soc_dapm_read(p->sink->dapm, reg, &val); 744 soc_dapm_read(p->sink->dapm, reg, &val);
739 val = (val >> shift) & mask; 745 /*
746 * The nth_path argument allows this function to know
747 * which path of a kcontrol it is setting the initial
748 * status for. Ideally this would support any number
749 * of paths and channels. But since kcontrols only come
750 * in mono and stereo variants, we are limited to 2
751 * channels.
752 *
753 * The following code assumes for stereo controls the
754 * first path is the left channel, and all remaining
755 * paths are the right channel.
756 */
757 if (snd_soc_volsw_is_stereo(mc) && nth_path > 0) {
758 if (reg != mc->rreg)
759 soc_dapm_read(p->sink->dapm, mc->rreg, &val);
760 val = (val >> mc->rshift) & mask;
761 } else {
762 val = (val >> shift) & mask;
763 }
740 if (invert) 764 if (invert)
741 val = max - val; 765 val = max - val;
742 p->connect = !!val; 766 p->connect = !!val;
@@ -749,13 +773,13 @@ static void dapm_set_mixer_path_status(struct snd_soc_dapm_path *p, int i)
749static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm, 773static int dapm_connect_mixer(struct snd_soc_dapm_context *dapm,
750 struct snd_soc_dapm_path *path, const char *control_name) 774 struct snd_soc_dapm_path *path, const char *control_name)
751{ 775{
752 int i; 776 int i, nth_path = 0;
753 777
754 /* search for mixer kcontrol */ 778 /* search for mixer kcontrol */
755 for (i = 0; i < path->sink->num_kcontrols; i++) { 779 for (i = 0; i < path->sink->num_kcontrols; i++) {
756 if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) { 780 if (!strcmp(control_name, path->sink->kcontrol_news[i].name)) {
757 path->name = path->sink->kcontrol_news[i].name; 781 path->name = path->sink->kcontrol_news[i].name;
758 dapm_set_mixer_path_status(path, i); 782 dapm_set_mixer_path_status(path, i, nth_path++);
759 return 0; 783 return 0;
760 } 784 }
761 } 785 }
@@ -1626,6 +1650,15 @@ static void dapm_widget_update(struct snd_soc_card *card)
1626 dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n", 1650 dev_err(w->dapm->dev, "ASoC: %s DAPM update failed: %d\n",
1627 w->name, ret); 1651 w->name, ret);
1628 1652
1653 if (update->has_second_set) {
1654 ret = soc_dapm_update_bits(w->dapm, update->reg2,
1655 update->mask2, update->val2);
1656 if (ret < 0)
1657 dev_err(w->dapm->dev,
1658 "ASoC: %s DAPM update failed: %d\n",
1659 w->name, ret);
1660 }
1661
1629 for (wi = 0; wi < wlist->num_widgets; wi++) { 1662 for (wi = 0; wi < wlist->num_widgets; wi++) {
1630 w = wlist->widgets[wi]; 1663 w = wlist->widgets[wi];
1631 1664
@@ -2177,7 +2210,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
2177 2210
2178/* test and update the power status of a mixer or switch widget */ 2211/* test and update the power status of a mixer or switch widget */
2179static int soc_dapm_mixer_update_power(struct snd_soc_card *card, 2212static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2180 struct snd_kcontrol *kcontrol, int connect) 2213 struct snd_kcontrol *kcontrol,
2214 int connect, int rconnect)
2181{ 2215{
2182 struct snd_soc_dapm_path *path; 2216 struct snd_soc_dapm_path *path;
2183 int found = 0; 2217 int found = 0;
@@ -2186,8 +2220,33 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2186 2220
2187 /* find dapm widget path assoc with kcontrol */ 2221 /* find dapm widget path assoc with kcontrol */
2188 dapm_kcontrol_for_each_path(path, kcontrol) { 2222 dapm_kcontrol_for_each_path(path, kcontrol) {
2223 /*
2224 * Ideally this function should support any number of
2225 * paths and channels. But since kcontrols only come
2226 * in mono and stereo variants, we are limited to 2
2227 * channels.
2228 *
2229 * The following code assumes for stereo controls the
2230 * first path (when 'found == 0') is the left channel,
2231 * and all remaining paths (when 'found == 1') are the
2232 * right channel.
2233 *
2234 * A stereo control is signified by a valid 'rconnect'
2235 * value, either 0 for unconnected, or >= 0 for connected.
2236 * This is chosen instead of using snd_soc_volsw_is_stereo,
2237 * so that the behavior of snd_soc_dapm_mixer_update_power
2238 * doesn't change even when the kcontrol passed in is
2239 * stereo.
2240 *
2241 * It passes 'connect' as the path connect status for
2242 * the left channel, and 'rconnect' for the right
2243 * channel.
2244 */
2245 if (found && rconnect >= 0)
2246 soc_dapm_connect_path(path, rconnect, "mixer update");
2247 else
2248 soc_dapm_connect_path(path, connect, "mixer update");
2189 found = 1; 2249 found = 1;
2190 soc_dapm_connect_path(path, connect, "mixer update");
2191 } 2250 }
2192 2251
2193 if (found) 2252 if (found)
@@ -2205,7 +2264,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
2205 2264
2206 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2265 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2207 card->update = update; 2266 card->update = update;
2208 ret = soc_dapm_mixer_update_power(card, kcontrol, connect); 2267 ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1);
2209 card->update = NULL; 2268 card->update = NULL;
2210 mutex_unlock(&card->dapm_mutex); 2269 mutex_unlock(&card->dapm_mutex);
2211 if (ret > 0) 2270 if (ret > 0)
@@ -3030,22 +3089,28 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
3030 int reg = mc->reg; 3089 int reg = mc->reg;
3031 unsigned int shift = mc->shift; 3090 unsigned int shift = mc->shift;
3032 int max = mc->max; 3091 int max = mc->max;
3092 unsigned int width = fls(max);
3033 unsigned int mask = (1 << fls(max)) - 1; 3093 unsigned int mask = (1 << fls(max)) - 1;
3034 unsigned int invert = mc->invert; 3094 unsigned int invert = mc->invert;
3035 unsigned int val; 3095 unsigned int reg_val, val, rval = 0;
3036 int ret = 0; 3096 int ret = 0;
3037 3097
3038 if (snd_soc_volsw_is_stereo(mc))
3039 dev_warn(dapm->dev,
3040 "ASoC: Control '%s' is stereo, which is not supported\n",
3041 kcontrol->id.name);
3042
3043 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3098 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3044 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { 3099 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
3045 ret = soc_dapm_read(dapm, reg, &val); 3100 ret = soc_dapm_read(dapm, reg, &reg_val);
3046 val = (val >> shift) & mask; 3101 val = (reg_val >> shift) & mask;
3102
3103 if (ret == 0 && reg != mc->rreg)
3104 ret = soc_dapm_read(dapm, mc->rreg, &reg_val);
3105
3106 if (snd_soc_volsw_is_stereo(mc))
3107 rval = (reg_val >> mc->rshift) & mask;
3047 } else { 3108 } else {
3048 val = dapm_kcontrol_get_value(kcontrol); 3109 reg_val = dapm_kcontrol_get_value(kcontrol);
3110 val = reg_val & mask;
3111
3112 if (snd_soc_volsw_is_stereo(mc))
3113 rval = (reg_val >> width) & mask;
3049 } 3114 }
3050 mutex_unlock(&card->dapm_mutex); 3115 mutex_unlock(&card->dapm_mutex);
3051 3116
@@ -3057,6 +3122,13 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
3057 else 3122 else
3058 ucontrol->value.integer.value[0] = val; 3123 ucontrol->value.integer.value[0] = val;
3059 3124
3125 if (snd_soc_volsw_is_stereo(mc)) {
3126 if (invert)
3127 ucontrol->value.integer.value[1] = max - rval;
3128 else
3129 ucontrol->value.integer.value[1] = rval;
3130 }
3131
3060 return ret; 3132 return ret;
3061} 3133}
3062EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); 3134EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
@@ -3080,46 +3152,66 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
3080 int reg = mc->reg; 3152 int reg = mc->reg;
3081 unsigned int shift = mc->shift; 3153 unsigned int shift = mc->shift;
3082 int max = mc->max; 3154 int max = mc->max;
3083 unsigned int mask = (1 << fls(max)) - 1; 3155 unsigned int width = fls(max);
3156 unsigned int mask = (1 << width) - 1;
3084 unsigned int invert = mc->invert; 3157 unsigned int invert = mc->invert;
3085 unsigned int val; 3158 unsigned int val, rval = 0;
3086 int connect, change, reg_change = 0; 3159 int connect, rconnect = -1, change, reg_change = 0;
3087 struct snd_soc_dapm_update update; 3160 struct snd_soc_dapm_update update = { NULL };
3088 int ret = 0; 3161 int ret = 0;
3089 3162
3090 if (snd_soc_volsw_is_stereo(mc))
3091 dev_warn(dapm->dev,
3092 "ASoC: Control '%s' is stereo, which is not supported\n",
3093 kcontrol->id.name);
3094
3095 val = (ucontrol->value.integer.value[0] & mask); 3163 val = (ucontrol->value.integer.value[0] & mask);
3096 connect = !!val; 3164 connect = !!val;
3097 3165
3098 if (invert) 3166 if (invert)
3099 val = max - val; 3167 val = max - val;
3100 3168
3169 if (snd_soc_volsw_is_stereo(mc)) {
3170 rval = (ucontrol->value.integer.value[1] & mask);
3171 rconnect = !!rval;
3172 if (invert)
3173 rval = max - rval;
3174 }
3175
3101 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3176 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3102 3177
3103 change = dapm_kcontrol_set_value(kcontrol, val); 3178 /* This assumes field width < (bits in unsigned int / 2) */
3179 if (width > sizeof(unsigned int) * 8 / 2)
3180 dev_warn(dapm->dev,
3181 "ASoC: control %s field width limit exceeded\n",
3182 kcontrol->id.name);
3183 change = dapm_kcontrol_set_value(kcontrol, val | (rval << width));
3104 3184
3105 if (reg != SND_SOC_NOPM) { 3185 if (reg != SND_SOC_NOPM) {
3106 mask = mask << shift;
3107 val = val << shift; 3186 val = val << shift;
3187 rval = rval << mc->rshift;
3188
3189 reg_change = soc_dapm_test_bits(dapm, reg, mask << shift, val);
3108 3190
3109 reg_change = soc_dapm_test_bits(dapm, reg, mask, val); 3191 if (snd_soc_volsw_is_stereo(mc))
3192 reg_change |= soc_dapm_test_bits(dapm, mc->rreg,
3193 mask << mc->rshift,
3194 rval);
3110 } 3195 }
3111 3196
3112 if (change || reg_change) { 3197 if (change || reg_change) {
3113 if (reg_change) { 3198 if (reg_change) {
3199 if (snd_soc_volsw_is_stereo(mc)) {
3200 update.has_second_set = true;
3201 update.reg2 = mc->rreg;
3202 update.mask2 = mask << mc->rshift;
3203 update.val2 = rval;
3204 }
3114 update.kcontrol = kcontrol; 3205 update.kcontrol = kcontrol;
3115 update.reg = reg; 3206 update.reg = reg;
3116 update.mask = mask; 3207 update.mask = mask << shift;
3117 update.val = val; 3208 update.val = val;
3118 card->update = &update; 3209 card->update = &update;
3119 } 3210 }
3120 change |= reg_change; 3211 change |= reg_change;
3121 3212
3122 ret = soc_dapm_mixer_update_power(card, kcontrol, connect); 3213 ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
3214 rconnect);
3123 3215
3124 card->update = NULL; 3216 card->update = NULL;
3125 } 3217 }
@@ -3192,7 +3284,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
3192 unsigned int *item = ucontrol->value.enumerated.item; 3284 unsigned int *item = ucontrol->value.enumerated.item;
3193 unsigned int val, change, reg_change = 0; 3285 unsigned int val, change, reg_change = 0;
3194 unsigned int mask; 3286 unsigned int mask;
3195 struct snd_soc_dapm_update update; 3287 struct snd_soc_dapm_update update = { NULL };
3196 int ret = 0; 3288 int ret = 0;
3197 3289
3198 if (item[0] >= e->items) 3290 if (item[0] >= e->items)