diff options
-rw-r--r-- | include/sound/soc.h | 7 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 66 |
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); |
394 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | 394 | int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, |
395 | struct snd_ctl_elem_value *ucontrol); | 395 | struct snd_ctl_elem_value *ucontrol); |
396 | int 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); | ||
398 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | 397 | int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, |
399 | struct snd_ctl_elem_info *uinfo); | 398 | struct snd_ctl_elem_info *uinfo); |
400 | int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol, | 399 | int 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; |
2362 | EXPORT_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 | */ | ||
2373 | int 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 | } |
2407 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); | 2379 | EXPORT_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 |