mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-16 05:50:19 +00:00
ASoC: core: Fix for the volume limiting when invert is in use
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>
This commit is contained in:
parent
896060c76b
commit
d11bb4a925
@ -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,\
|
||||
@ -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 |\
|
||||
@ -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 |\
|
||||
@ -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 | \
|
||||
@ -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 }
|
||||
@ -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, \
|
||||
@ -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), \
|
||||
@ -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, \
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user