aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2012-12-19 11:05:00 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-12-20 12:46:55 -0500
commit9bde4f0b1c83d1129a9fc8ec5b2611ba6dab1215 (patch)
treee93c78b38f234efd10b42a4c7576a7ceeb3112f1 /sound/soc
parent08b27848da620f206a8b6d80f26184485dd7aa40 (diff)
ASoC: core: Fix SOC_DOUBLE_RANGE() macros
Although we've had macros defining double _RANGE controls for a while now they've not actually been backed up properly by the implementation, it's treated everything as mono. Fix that by implementing the handling in the stereo controls, ensuring that the mono controls don't mistakenly get treated as stereo. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@ti.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/soc-core.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 91d592ff67b7..e0d4630bfb4f 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2917,7 +2917,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
2917 platform_max = mc->platform_max; 2917 platform_max = mc->platform_max;
2918 2918
2919 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 2919 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2920 uinfo->count = 1; 2920 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
2921 uinfo->value.integer.min = 0; 2921 uinfo->value.integer.min = 0;
2922 uinfo->value.integer.max = platform_max - min; 2922 uinfo->value.integer.max = platform_max - min;
2923 2923
@@ -2941,12 +2941,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
2941 (struct soc_mixer_control *)kcontrol->private_value; 2941 (struct soc_mixer_control *)kcontrol->private_value;
2942 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2942 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2943 unsigned int reg = mc->reg; 2943 unsigned int reg = mc->reg;
2944 unsigned int rreg = mc->rreg;
2944 unsigned int shift = mc->shift; 2945 unsigned int shift = mc->shift;
2945 int min = mc->min; 2946 int min = mc->min;
2946 int max = mc->max; 2947 int max = mc->max;
2947 unsigned int mask = (1 << fls(max)) - 1; 2948 unsigned int mask = (1 << fls(max)) - 1;
2948 unsigned int invert = mc->invert; 2949 unsigned int invert = mc->invert;
2949 unsigned int val, val_mask; 2950 unsigned int val, val_mask;
2951 int ret;
2950 2952
2951 val = ((ucontrol->value.integer.value[0] + min) & mask); 2953 val = ((ucontrol->value.integer.value[0] + min) & mask);
2952 if (invert) 2954 if (invert)
@@ -2954,7 +2956,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
2954 val_mask = mask << shift; 2956 val_mask = mask << shift;
2955 val = val << shift; 2957 val = val << shift;
2956 2958
2957 return snd_soc_update_bits_locked(codec, reg, val_mask, val); 2959 ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
2960 if (ret != 0)
2961 return ret;
2962
2963 if (snd_soc_volsw_is_stereo(mc)) {
2964 val = ((ucontrol->value.integer.value[1] + min) & mask);
2965 if (invert)
2966 val = max - val;
2967 val_mask = mask << shift;
2968 val = val << shift;
2969
2970 ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val);
2971 }
2972
2973 return ret;
2958} 2974}
2959EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); 2975EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
2960 2976
@@ -2974,11 +2990,13 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
2974 (struct soc_mixer_control *)kcontrol->private_value; 2990 (struct soc_mixer_control *)kcontrol->private_value;
2975 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2991 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2976 unsigned int reg = mc->reg; 2992 unsigned int reg = mc->reg;
2993 unsigned int rreg = mc->rreg;
2977 unsigned int shift = mc->shift; 2994 unsigned int shift = mc->shift;
2978 int min = mc->min; 2995 int min = mc->min;
2979 int max = mc->max; 2996 int max = mc->max;
2980 unsigned int mask = (1 << fls(max)) - 1; 2997 unsigned int mask = (1 << fls(max)) - 1;
2981 unsigned int invert = mc->invert; 2998 unsigned int invert = mc->invert;
2999 int ret;
2982 3000
2983 ucontrol->value.integer.value[0] = 3001 ucontrol->value.integer.value[0] =
2984 (snd_soc_read(codec, reg) >> shift) & mask; 3002 (snd_soc_read(codec, reg) >> shift) & mask;
@@ -2988,6 +3006,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
2988 ucontrol->value.integer.value[0] = 3006 ucontrol->value.integer.value[0] =
2989 ucontrol->value.integer.value[0] - min; 3007 ucontrol->value.integer.value[0] - min;
2990 3008
3009 if (snd_soc_volsw_is_stereo(mc)) {
3010 ucontrol->value.integer.value[1] =
3011 (snd_soc_read(codec, rreg) >> shift) & mask;
3012 if (invert)
3013 ucontrol->value.integer.value[1] =
3014 max - ucontrol->value.integer.value[1];
3015 ucontrol->value.integer.value[1] =
3016 ucontrol->value.integer.value[1] - min;
3017 }
3018
2991 return 0; 3019 return 0;
2992} 3020}
2993EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); 3021EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);