提交 9bde4f0b 编写于 作者: M Mark Brown

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: NMark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: NLiam Girdwood <lrg@ti.com>
上级 08b27848
...@@ -58,8 +58,9 @@ ...@@ -58,8 +58,9 @@
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
.put = snd_soc_put_volsw_range, \ .put = snd_soc_put_volsw_range, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = xshift, .min = xmin,\ {.reg = xreg, .rreg = xreg, .shift = xshift, \
.max = xmax, .platform_max = xmax, .invert = xinvert} } .rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
...@@ -88,8 +89,9 @@ ...@@ -88,8 +89,9 @@
.info = snd_soc_info_volsw_range, \ .info = snd_soc_info_volsw_range, \
.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
.private_value = (unsigned long)&(struct soc_mixer_control) \ .private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = xshift, .min = xmin,\ {.reg = xreg, .rreg = xreg, .shift = xshift, \
.max = xmax, .platform_max = xmax, .invert = xinvert} } .rshift = xshift, .min = xmin, .max = xmax, \
.platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
......
...@@ -2917,7 +2917,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -2917,7 +2917,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
platform_max = mc->platform_max; platform_max = mc->platform_max;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1; uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = platform_max - min; uinfo->value.integer.max = platform_max - min;
...@@ -2941,12 +2941,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -2941,12 +2941,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int rreg = mc->rreg;
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
int min = mc->min; int min = mc->min;
int max = mc->max; int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1; unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
unsigned int val, val_mask; unsigned int val, val_mask;
int ret;
val = ((ucontrol->value.integer.value[0] + min) & mask); val = ((ucontrol->value.integer.value[0] + min) & mask);
if (invert) if (invert)
...@@ -2954,7 +2956,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -2954,7 +2956,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol,
val_mask = mask << shift; val_mask = mask << shift;
val = val << shift; val = val << shift;
return snd_soc_update_bits_locked(codec, reg, val_mask, val); ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
if (ret != 0)
return ret;
if (snd_soc_volsw_is_stereo(mc)) {
val = ((ucontrol->value.integer.value[1] + min) & mask);
if (invert)
val = max - val;
val_mask = mask << shift;
val = val << shift;
ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val);
}
return ret;
} }
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
...@@ -2974,11 +2990,13 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -2974,11 +2990,13 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value; (struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int reg = mc->reg; unsigned int reg = mc->reg;
unsigned int rreg = mc->rreg;
unsigned int shift = mc->shift; unsigned int shift = mc->shift;
int min = mc->min; int min = mc->min;
int max = mc->max; int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1; unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert; unsigned int invert = mc->invert;
int ret;
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
(snd_soc_read(codec, reg) >> shift) & mask; (snd_soc_read(codec, reg) >> shift) & mask;
...@@ -2988,6 +3006,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, ...@@ -2988,6 +3006,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = ucontrol->value.integer.value[0] =
ucontrol->value.integer.value[0] - min; ucontrol->value.integer.value[0] - min;
if (snd_soc_volsw_is_stereo(mc)) {
ucontrol->value.integer.value[1] =
(snd_soc_read(codec, rreg) >> shift) & mask;
if (invert)
ucontrol->value.integer.value[1] =
max - ucontrol->value.integer.value[1];
ucontrol->value.integer.value[1] =
ucontrol->value.integer.value[1] - min;
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册