Skip to content

Commit

Permalink
ASoC: core: Fix for the volume limiting when invert is in use
Browse files Browse the repository at this point in the history
If the register for the volume needs invert, than the inversion
need to be done from the chip maximum, and not from the platform
dependent limit.
Introduce soc_mixer_control.platform_max value, which initially
equals to chip maximum.
The snd_soc_limit_volume function only modify the platform_max,
all volsw_info call returns this as well.
The .max value holds the chip default (maximum), and it is used
for the inversion, if it is needed.

Additional check in the volsw_info call has been added to check
the validity of the platform_max in case, when custom macros
used by codec drivers are not initializing it correctly.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
  • Loading branch information
Peter Ujfalusi authored and Mark Brown committed May 11, 2010
1 parent 896060c commit d11bb4a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 20 deletions.
23 changes: 12 additions & 11 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
.invert = xinvert})
.platform_max = xmax, .invert = xinvert})
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .max = xmax, .invert = xinvert})
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
#define SOC_SINGLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
Expand All @@ -53,14 +53,14 @@
.put = snd_soc_put_volsw, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw_2r, \
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
Expand All @@ -70,7 +70,7 @@
.put = snd_soc_put_volsw, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right,\
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
Expand All @@ -80,7 +80,7 @@
.get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
Expand All @@ -89,7 +89,8 @@
.info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
.put = snd_soc_put_volsw_s8, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .min = xmin, .max = xmax} }
{.reg = xreg, .min = xmin, .max = xmax, \
.platform_max = xmax} }
#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
.max = xmax, .texts = xtexts }
Expand Down Expand Up @@ -126,7 +127,7 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
Expand All @@ -146,7 +147,7 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .shift = shift_left, .rshift = shift_right, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
Expand All @@ -157,7 +158,7 @@
.get = xhandler_get, .put = xhandler_put, \
.private_value = (unsigned long)&(struct soc_mixer_control) \
{.reg = reg_left, .rreg = reg_right, .shift = xshift, \
.max = xmax, .invert = xinvert} }
.max = xmax, .platform_max = xmax, .invert = xinvert} }
#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_bool_ext, \
Expand Down Expand Up @@ -572,7 +573,7 @@ struct snd_soc_pcm_runtime {

/* mixer control */
struct soc_mixer_control {
int min, max;
int min, max, platform_max;
unsigned int reg, rreg, shift, rshift, invert;
};

Expand Down
30 changes: 21 additions & 9 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2017,18 +2017,22 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int max = mc->max;
int platform_max;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;

if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
if (!mc->platform_max)
mc->platform_max = mc->max;
platform_max = mc->platform_max;

if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;

uinfo->count = shift == rshift ? 1 : 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = max;
uinfo->value.integer.max = platform_max;
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
Expand Down Expand Up @@ -2126,16 +2130,20 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int max = mc->max;
int platform_max;

if (max == 1 && !strstr(kcontrol->id.name, " Volume"))
if (!mc->platform_max)
mc->platform_max = mc->max;
platform_max = mc->platform_max;

if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;

uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = max;
uinfo->value.integer.max = platform_max;
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
Expand Down Expand Up @@ -2236,13 +2244,17 @@ int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int max = mc->max;
int platform_max;
int min = mc->min;

if (!mc->platform_max)
mc->platform_max = mc->max;
platform_max = mc->platform_max;

uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = max-min;
uinfo->value.integer.max = platform_max - min;
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8);
Expand Down Expand Up @@ -2331,7 +2343,7 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec,
if (found) {
mc = (struct soc_mixer_control *)kctl->private_value;
if (max <= mc->max) {
mc->max = max;
mc->platform_max = max;
ret = 0;
}
}
Expand Down

0 comments on commit d11bb4a

Please sign in to comment.