aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h7
-rw-r--r--sound/soc/soc-core.c66
2 files changed, 22 insertions, 51 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index e5e424ef3f7d..1738c2b6b373 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -64,7 +64,7 @@
64#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ 64#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
65{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 65{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
66 .info = snd_soc_info_volsw, \ 66 .info = snd_soc_info_volsw, \
67 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ 67 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
68 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ 68 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
69 xmax, xinvert) } 69 xmax, xinvert) }
70#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ 70#define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \
@@ -82,7 +82,7 @@
82 SNDRV_CTL_ELEM_ACCESS_READWRITE,\ 82 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
83 .tlv.p = (tlv_array), \ 83 .tlv.p = (tlv_array), \
84 .info = snd_soc_info_volsw, \ 84 .info = snd_soc_info_volsw, \
85 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw_2r, \ 85 .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \
86 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ 86 .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \
87 xmax, xinvert) } 87 xmax, xinvert) }
88#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ 88#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
@@ -393,8 +393,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
393 struct snd_ctl_elem_value *ucontrol); 393 struct snd_ctl_elem_value *ucontrol);
394int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, 394int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
395 struct snd_ctl_elem_value *ucontrol); 395 struct snd_ctl_elem_value *ucontrol);
396int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, 396#define snd_soc_put_volsw_2r snd_soc_put_volsw
397 struct snd_ctl_elem_value *ucontrol);
398int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, 397int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
399 struct snd_ctl_elem_info *uinfo); 398 struct snd_ctl_elem_info *uinfo);
400int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, 399int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 1a13d530f053..2a2507627520 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2327,7 +2327,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
2327 * @kcontrol: mixer control 2327 * @kcontrol: mixer control
2328 * @ucontrol: control element information 2328 * @ucontrol: control element information
2329 * 2329 *
2330 * Callback to set the value of a single mixer control. 2330 * Callback to set the value of a single mixer control, or a double mixer
2331 * control that spans 2 registers.
2331 * 2332 *
2332 * Returns 0 for success. 2333 * Returns 0 for success.
2333 */ 2334 */
@@ -2338,73 +2339,44 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2338 (struct soc_mixer_control *)kcontrol->private_value; 2339 (struct soc_mixer_control *)kcontrol->private_value;
2339 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2340 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2340 unsigned int reg = mc->reg; 2341 unsigned int reg = mc->reg;
2342 unsigned int reg2 = mc->rreg;
2341 unsigned int shift = mc->shift; 2343 unsigned int shift = mc->shift;
2342 unsigned int rshift = mc->rshift; 2344 unsigned int rshift = mc->rshift;
2343 int max = mc->max; 2345 int max = mc->max;
2344 unsigned int mask = (1 << fls(max)) - 1; 2346 unsigned int mask = (1 << fls(max)) - 1;
2345 unsigned int invert = mc->invert; 2347 unsigned int invert = mc->invert;
2346 unsigned int val, val2, val_mask; 2348 int err;
2349 bool type_2r = 0;
2350 unsigned int val2 = 0;
2351 unsigned int val, val_mask;
2347 2352
2348 val = (ucontrol->value.integer.value[0] & mask); 2353 val = (ucontrol->value.integer.value[0] & mask);
2349 if (invert) 2354 if (invert)
2350 val = max - val; 2355 val = max - val;
2351 val_mask = mask << shift; 2356 val_mask = mask << shift;
2352 val = val << shift; 2357 val = val << shift;
2353 if (shift != rshift) { 2358 if (snd_soc_volsw_is_stereo(mc)) {
2354 val2 = (ucontrol->value.integer.value[1] & mask); 2359 val2 = (ucontrol->value.integer.value[1] & mask);
2355 if (invert) 2360 if (invert)
2356 val2 = max - val2; 2361 val2 = max - val2;
2357 val_mask |= mask << rshift; 2362 if (reg == reg2) {
2358 val |= val2 << rshift; 2363 val_mask |= mask << rshift;
2359 } 2364 val |= val2 << rshift;
2360 return snd_soc_update_bits_locked(codec, reg, val_mask, val); 2365 } else {
2361} 2366 val2 = val2 << shift;
2362EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 2367 type_2r = 1;
2363 2368 }
2364/**
2365 * snd_soc_put_volsw_2r - double mixer set callback
2366 * @kcontrol: mixer control
2367 * @ucontrol: control element information
2368 *
2369 * Callback to set the value of a double mixer control that spans 2 registers.
2370 *
2371 * Returns 0 for success.
2372 */
2373int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
2374 struct snd_ctl_elem_value *ucontrol)
2375{
2376 struct soc_mixer_control *mc =
2377 (struct soc_mixer_control *)kcontrol->private_value;
2378 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2379 unsigned int reg = mc->reg;
2380 unsigned int reg2 = mc->rreg;
2381 unsigned int shift = mc->shift;
2382 int max = mc->max;
2383 unsigned int mask = (1 << fls(max)) - 1;
2384 unsigned int invert = mc->invert;
2385 int err;
2386 unsigned int val, val2, val_mask;
2387
2388 val_mask = mask << shift;
2389 val = (ucontrol->value.integer.value[0] & mask);
2390 val2 = (ucontrol->value.integer.value[1] & mask);
2391
2392 if (invert) {
2393 val = max - val;
2394 val2 = max - val2;
2395 } 2369 }
2396
2397 val = val << shift;
2398 val2 = val2 << shift;
2399
2400 err = snd_soc_update_bits_locked(codec, reg, val_mask, val); 2370 err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
2401 if (err < 0) 2371 if (err < 0)
2402 return err; 2372 return err;
2403 2373
2404 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2); 2374 if (type_2r)
2375 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
2376
2405 return err; 2377 return err;
2406} 2378}
2407EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); 2379EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
2408 2380
2409/** 2381/**
2410 * snd_soc_info_volsw_s8 - signed mixer info callback 2382 * snd_soc_info_volsw_s8 - signed mixer info callback