aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2015-10-14 08:31:24 -0400
committerMark Brown <broonie@kernel.org>2015-10-16 11:17:25 -0400
commit34198710f55b5f359f43e67d9a08fe5aadfbca1b (patch)
treed919662036a8a712283dc8246f1977988418bff8
parent6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff)
ASoC: Add info callback for SX_TLV controls
SX_TLV controls are intended for situations where the register behind the control has some non-zero value indicating the minimum gain and then gains increasing from there and eventually overflowing through zero. Currently every CODEC implementing these controls specifies the minimum as the non-zero value for the minimum and the maximum as the number of gain settings available. This means when the info callback subtracts the minimum value from the maximum value to calculate the number of gain levels available it is actually under reporting the available levels. This patch fixes this issue by adding a new snd_soc_info_volsw_sx callback that does not subtract the minimum value. Fixes: 1d99f2436d0d ("ASoC: core: Rework SOC_DOUBLE_R_SX_TLV add SOC_SINGLE_SX_TLV") Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Acked-by: Brian Austin <brian.austin@cirrus.com> Tested-by: Brian Austin <brian.austin@cirrus.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--include/sound/soc.h6
-rw-r--r--sound/soc/soc-ops.c28
2 files changed, 32 insertions, 2 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 884e728b09d9..26ede14597da 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -86,7 +86,7 @@
86 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 86 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
87 SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 87 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
88 .tlv.p = (tlv_array),\ 88 .tlv.p = (tlv_array),\
89 .info = snd_soc_info_volsw, \ 89 .info = snd_soc_info_volsw_sx, \
90 .get = snd_soc_get_volsw_sx,\ 90 .get = snd_soc_get_volsw_sx,\
91 .put = snd_soc_put_volsw_sx, \ 91 .put = snd_soc_put_volsw_sx, \
92 .private_value = (unsigned long)&(struct soc_mixer_control) \ 92 .private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -156,7 +156,7 @@
156 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 156 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
157 SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 157 SNDRV_CTL_ELEM_ACCESS_READWRITE, \
158 .tlv.p = (tlv_array), \ 158 .tlv.p = (tlv_array), \
159 .info = snd_soc_info_volsw, \ 159 .info = snd_soc_info_volsw_sx, \
160 .get = snd_soc_get_volsw_sx, \ 160 .get = snd_soc_get_volsw_sx, \
161 .put = snd_soc_put_volsw_sx, \ 161 .put = snd_soc_put_volsw_sx, \
162 .private_value = (unsigned long)&(struct soc_mixer_control) \ 162 .private_value = (unsigned long)&(struct soc_mixer_control) \
@@ -574,6 +574,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
574 struct snd_ctl_elem_value *ucontrol); 574 struct snd_ctl_elem_value *ucontrol);
575int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, 575int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
576 struct snd_ctl_elem_info *uinfo); 576 struct snd_ctl_elem_info *uinfo);
577int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
578 struct snd_ctl_elem_info *uinfo);
577#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info 579#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
578int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, 580int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
579 struct snd_ctl_elem_value *ucontrol); 581 struct snd_ctl_elem_value *ucontrol);
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index 100d92b5b77e..05977ae1ff2a 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -207,6 +207,34 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
207EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 207EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
208 208
209/** 209/**
210 * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
211 * @kcontrol: mixer control
212 * @uinfo: control element information
213 *
214 * Callback to provide information about a single mixer control, or a double
215 * mixer control that spans 2 registers of the SX TLV type. SX TLV controls
216 * have a range that represents both positive and negative values either side
217 * of zero but without a sign bit.
218 *
219 * Returns 0 for success.
220 */
221int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
222 struct snd_ctl_elem_info *uinfo)
223{
224 struct soc_mixer_control *mc =
225 (struct soc_mixer_control *)kcontrol->private_value;
226
227 snd_soc_info_volsw(kcontrol, uinfo);
228 /* Max represents the number of levels in an SX control not the
229 * maximum value, so add the minimum value back on
230 */
231 uinfo->value.integer.max += mc->min;
232
233 return 0;
234}
235EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);
236
237/**
210 * snd_soc_get_volsw - single mixer get callback 238 * snd_soc_get_volsw - single mixer get callback
211 * @kcontrol: mixer control 239 * @kcontrol: mixer control
212 * @ucontrol: control element information 240 * @ucontrol: control element information