aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-core.c
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2014-01-16 10:02:10 -0500
committerShengjiu Wang <b02247@freescale.com>2014-05-13 04:54:33 -0400
commit2dac3d5a08aa3e8f18610113264eb8dc7781b4ae (patch)
treec27684fa524b7ce49d651c36f6d62554cf675a2d /sound/soc/soc-core.c
parent7cb5ee809f648c51ae84b1e99e0167ed3a431610 (diff)
ASoC: core: Add signed register volume control logic
Some codecs use signed volume control representation with non standard register sizes, e.g. 6 or 7 bit signed integers. This patch adds generic signed register volume control logic to soc-core. Instead of a fixed width signed register control, this implementation uses a 'min' value and the signed bit location to translate it to an absolute volume. Using the 'sign_bit' we can calculate a correct mask for the register values and translate it back into signed integers of standard size. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org> (cherry picked from commit f227b88f0fce5f9b82aa934f8829a741c2e06d82)
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r--sound/soc/soc-core.c68
1 files changed, 61 insertions, 7 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index d56bbea6e75e..2192e69469b1 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2603,6 +2603,48 @@ int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
2603EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); 2603EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
2604 2604
2605/** 2605/**
2606 * snd_soc_read_signed - Read a codec register and interprete as signed value
2607 * @codec: codec
2608 * @reg: Register to read
2609 * @mask: Mask to use after shifting the register value
2610 * @shift: Right shift of register value
2611 * @sign_bit: Bit that describes if a number is negative or not.
2612 *
2613 * This functions reads a codec register. The register value is shifted right
2614 * by 'shift' bits and masked with the given 'mask'. Afterwards it translates
2615 * the given registervalue into a signed integer if sign_bit is non-zero.
2616 *
2617 * Returns the register value as signed int.
2618 */
2619static int snd_soc_read_signed(struct snd_soc_codec *codec, unsigned int reg,
2620 unsigned int mask, unsigned int shift, unsigned int sign_bit)
2621{
2622 int ret;
2623 unsigned int val;
2624
2625 val = (snd_soc_read(codec, reg) >> shift) & mask;
2626
2627 if (!sign_bit)
2628 return val;
2629
2630 /* non-negative number */
2631 if (!(val & BIT(sign_bit)))
2632 return val;
2633
2634 ret = val;
2635
2636 /*
2637 * The register most probably does not contain a full-sized int.
2638 * Instead we have an arbitrary number of bits in a signed
2639 * representation which has to be translated into a full-sized int.
2640 * This is done by filling up all bits above the sign-bit.
2641 */
2642 ret |= ~((int)(BIT(sign_bit) - 1));
2643
2644 return ret;
2645}
2646
2647/**
2606 * snd_soc_info_volsw - single mixer info callback 2648 * snd_soc_info_volsw - single mixer info callback
2607 * @kcontrol: mixer control 2649 * @kcontrol: mixer control
2608 * @uinfo: control element information 2650 * @uinfo: control element information
@@ -2630,7 +2672,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
2630 2672
2631 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; 2673 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
2632 uinfo->value.integer.min = 0; 2674 uinfo->value.integer.min = 0;
2633 uinfo->value.integer.max = platform_max; 2675 uinfo->value.integer.max = platform_max - mc->min;
2634 return 0; 2676 return 0;
2635} 2677}
2636EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 2678EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
@@ -2656,11 +2698,16 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2656 unsigned int shift = mc->shift; 2698 unsigned int shift = mc->shift;
2657 unsigned int rshift = mc->rshift; 2699 unsigned int rshift = mc->rshift;
2658 int max = mc->max; 2700 int max = mc->max;
2701 int min = mc->min;
2702 int sign_bit = mc->sign_bit;
2659 unsigned int mask = (1 << fls(max)) - 1; 2703 unsigned int mask = (1 << fls(max)) - 1;
2660 unsigned int invert = mc->invert; 2704 unsigned int invert = mc->invert;
2661 2705
2662 ucontrol->value.integer.value[0] = 2706 if (sign_bit)
2663 (snd_soc_read(codec, reg) >> shift) & mask; 2707 mask = BIT(sign_bit + 1) - 1;
2708
2709 ucontrol->value.integer.value[0] = snd_soc_read_signed(codec, reg, mask,
2710 shift, sign_bit) - min;
2664 if (invert) 2711 if (invert)
2665 ucontrol->value.integer.value[0] = 2712 ucontrol->value.integer.value[0] =
2666 max - ucontrol->value.integer.value[0]; 2713 max - ucontrol->value.integer.value[0];
@@ -2668,10 +2715,12 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
2668 if (snd_soc_volsw_is_stereo(mc)) { 2715 if (snd_soc_volsw_is_stereo(mc)) {
2669 if (reg == reg2) 2716 if (reg == reg2)
2670 ucontrol->value.integer.value[1] = 2717 ucontrol->value.integer.value[1] =
2671 (snd_soc_read(codec, reg) >> rshift) & mask; 2718 snd_soc_read_signed(codec, reg, mask, rshift,
2719 sign_bit) - min;
2672 else 2720 else
2673 ucontrol->value.integer.value[1] = 2721 ucontrol->value.integer.value[1] =
2674 (snd_soc_read(codec, reg2) >> shift) & mask; 2722 snd_soc_read_signed(codec, reg2, mask, shift,
2723 sign_bit) - min;
2675 if (invert) 2724 if (invert)
2676 ucontrol->value.integer.value[1] = 2725 ucontrol->value.integer.value[1] =
2677 max - ucontrol->value.integer.value[1]; 2726 max - ucontrol->value.integer.value[1];
@@ -2702,6 +2751,8 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2702 unsigned int shift = mc->shift; 2751 unsigned int shift = mc->shift;
2703 unsigned int rshift = mc->rshift; 2752 unsigned int rshift = mc->rshift;
2704 int max = mc->max; 2753 int max = mc->max;
2754 int min = mc->min;
2755 unsigned int sign_bit = mc->sign_bit;
2705 unsigned int mask = (1 << fls(max)) - 1; 2756 unsigned int mask = (1 << fls(max)) - 1;
2706 unsigned int invert = mc->invert; 2757 unsigned int invert = mc->invert;
2707 int err; 2758 int err;
@@ -2709,13 +2760,16 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
2709 unsigned int val2 = 0; 2760 unsigned int val2 = 0;
2710 unsigned int val, val_mask; 2761 unsigned int val, val_mask;
2711 2762
2712 val = (ucontrol->value.integer.value[0] & mask); 2763 if (sign_bit)
2764 mask = BIT(sign_bit + 1) - 1;
2765
2766 val = ((ucontrol->value.integer.value[0] + min) & mask);
2713 if (invert) 2767 if (invert)
2714 val = max - val; 2768 val = max - val;
2715 val_mask = mask << shift; 2769 val_mask = mask << shift;
2716 val = val << shift; 2770 val = val << shift;
2717 if (snd_soc_volsw_is_stereo(mc)) { 2771 if (snd_soc_volsw_is_stereo(mc)) {
2718 val2 = (ucontrol->value.integer.value[1] & mask); 2772 val2 = ((ucontrol->value.integer.value[1] + min) & mask);
2719 if (invert) 2773 if (invert)
2720 val2 = max - val2; 2774 val2 = max - val2;
2721 if (reg == reg2) { 2775 if (reg == reg2) {