Skip to content

Commit

Permalink
ASoC: Add info callback for SX_TLV controls
Browse files Browse the repository at this point in the history
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: 1d99f24 ("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
  • Loading branch information
Charles Keepax authored and Mark Brown committed Oct 16, 2015
1 parent 6ff33f3 commit 3419871
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
6 changes: 4 additions & 2 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array),\
.info = snd_soc_info_volsw, \
.info = snd_soc_info_volsw_sx, \
.get = snd_soc_get_volsw_sx,\
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
Expand Down Expand Up @@ -156,7 +156,7 @@
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
SNDRV_CTL_ELEM_ACCESS_READWRITE, \
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.info = snd_soc_info_volsw_sx, \
.get = snd_soc_get_volsw_sx, \
.put = snd_soc_put_volsw_sx, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
Expand Down Expand Up @@ -574,6 +574,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info
int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
Expand Down
28 changes: 28 additions & 0 deletions sound/soc/soc-ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,34 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw);

/**
* snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
* @kcontrol: mixer control
* @uinfo: control element information
*
* Callback to provide information about a single mixer control, or a double
* mixer control that spans 2 registers of the SX TLV type. SX TLV controls
* have a range that represents both positive and negative values either side
* of zero but without a sign bit.
*
* Returns 0 for success.
*/
int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;

snd_soc_info_volsw(kcontrol, uinfo);
/* Max represents the number of levels in an SX control not the
* maximum value, so add the minimum value back on
*/
uinfo->value.integer.max += mc->min;

return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx);

/**
* snd_soc_get_volsw - single mixer get callback
* @kcontrol: mixer control
Expand Down

0 comments on commit 3419871

Please sign in to comment.