aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/soc-dapm.c141
1 files changed, 112 insertions, 29 deletions
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 32e7af9b93d5..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 }
@@ -2186,7 +2210,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
2186 2210
2187/* 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 */
2188static int soc_dapm_mixer_update_power(struct snd_soc_card *card, 2212static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2189 struct snd_kcontrol *kcontrol, int connect) 2213 struct snd_kcontrol *kcontrol,
2214 int connect, int rconnect)
2190{ 2215{
2191 struct snd_soc_dapm_path *path; 2216 struct snd_soc_dapm_path *path;
2192 int found = 0; 2217 int found = 0;
@@ -2195,8 +2220,33 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card,
2195 2220
2196 /* find dapm widget path assoc with kcontrol */ 2221 /* find dapm widget path assoc with kcontrol */
2197 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");
2198 found = 1; 2249 found = 1;
2199 soc_dapm_connect_path(path, connect, "mixer update");
2200 } 2250 }
2201 2251
2202 if (found) 2252 if (found)
@@ -2214,7 +2264,7 @@ int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm,
2214 2264
2215 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 2265 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
2216 card->update = update; 2266 card->update = update;
2217 ret = soc_dapm_mixer_update_power(card, kcontrol, connect); 2267 ret = soc_dapm_mixer_update_power(card, kcontrol, connect, -1);
2218 card->update = NULL; 2268 card->update = NULL;
2219 mutex_unlock(&card->dapm_mutex); 2269 mutex_unlock(&card->dapm_mutex);
2220 if (ret > 0) 2270 if (ret > 0)
@@ -3039,22 +3089,28 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
3039 int reg = mc->reg; 3089 int reg = mc->reg;
3040 unsigned int shift = mc->shift; 3090 unsigned int shift = mc->shift;
3041 int max = mc->max; 3091 int max = mc->max;
3092 unsigned int width = fls(max);
3042 unsigned int mask = (1 << fls(max)) - 1; 3093 unsigned int mask = (1 << fls(max)) - 1;
3043 unsigned int invert = mc->invert; 3094 unsigned int invert = mc->invert;
3044 unsigned int val; 3095 unsigned int reg_val, val, rval = 0;
3045 int ret = 0; 3096 int ret = 0;
3046 3097
3047 if (snd_soc_volsw_is_stereo(mc))
3048 dev_warn(dapm->dev,
3049 "ASoC: Control '%s' is stereo, which is not supported\n",
3050 kcontrol->id.name);
3051
3052 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3098 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3053 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) { 3099 if (dapm_kcontrol_is_powered(kcontrol) && reg != SND_SOC_NOPM) {
3054 ret = soc_dapm_read(dapm, reg, &val); 3100 ret = soc_dapm_read(dapm, reg, &reg_val);
3055 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;
3056 } else { 3108 } else {
3057 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;
3058 } 3114 }
3059 mutex_unlock(&card->dapm_mutex); 3115 mutex_unlock(&card->dapm_mutex);
3060 3116
@@ -3066,6 +3122,13 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
3066 else 3122 else
3067 ucontrol->value.integer.value[0] = val; 3123 ucontrol->value.integer.value[0] = val;
3068 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
3069 return ret; 3132 return ret;
3070} 3133}
3071EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); 3134EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
@@ -3089,46 +3152,66 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
3089 int reg = mc->reg; 3152 int reg = mc->reg;
3090 unsigned int shift = mc->shift; 3153 unsigned int shift = mc->shift;
3091 int max = mc->max; 3154 int max = mc->max;
3092 unsigned int mask = (1 << fls(max)) - 1; 3155 unsigned int width = fls(max);
3156 unsigned int mask = (1 << width) - 1;
3093 unsigned int invert = mc->invert; 3157 unsigned int invert = mc->invert;
3094 unsigned int val; 3158 unsigned int val, rval = 0;
3095 int connect, change, reg_change = 0; 3159 int connect, rconnect = -1, change, reg_change = 0;
3096 struct snd_soc_dapm_update update = { NULL }; 3160 struct snd_soc_dapm_update update = { NULL };
3097 int ret = 0; 3161 int ret = 0;
3098 3162
3099 if (snd_soc_volsw_is_stereo(mc))
3100 dev_warn(dapm->dev,
3101 "ASoC: Control '%s' is stereo, which is not supported\n",
3102 kcontrol->id.name);
3103
3104 val = (ucontrol->value.integer.value[0] & mask); 3163 val = (ucontrol->value.integer.value[0] & mask);
3105 connect = !!val; 3164 connect = !!val;
3106 3165
3107 if (invert) 3166 if (invert)
3108 val = max - val; 3167 val = max - val;
3109 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
3110 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); 3176 mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
3111 3177
3112 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));
3113 3184
3114 if (reg != SND_SOC_NOPM) { 3185 if (reg != SND_SOC_NOPM) {
3115 mask = mask << shift;
3116 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);
3117 3190
3118 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);
3119 } 3195 }
3120 3196
3121 if (change || reg_change) { 3197 if (change || reg_change) {
3122 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 }
3123 update.kcontrol = kcontrol; 3205 update.kcontrol = kcontrol;
3124 update.reg = reg; 3206 update.reg = reg;
3125 update.mask = mask; 3207 update.mask = mask << shift;
3126 update.val = val; 3208 update.val = val;
3127 card->update = &update; 3209 card->update = &update;
3128 } 3210 }
3129 change |= reg_change; 3211 change |= reg_change;
3130 3212
3131 ret = soc_dapm_mixer_update_power(card, kcontrol, connect); 3213 ret = soc_dapm_mixer_update_power(card, kcontrol, connect,
3214 rconnect);
3132 3215
3133 card->update = NULL; 3216 card->update = NULL;
3134 } 3217 }