diff options
author | Peter Ujfalusi <peter.ujfalusi@nokia.com> | 2010-05-10 07:39:24 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-11 04:34:11 -0400 |
commit | d11bb4a925613fa814ed4ae350440eb24ebff336 (patch) | |
tree | 45332b4ea11ef84f6f33a7eb5a7957453de379a7 /sound | |
parent | 896060c76bdfd8a45eb33b3dd1a8307fe37f6c04 (diff) |
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/soc-core.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 34f71bf60140..e1043f644730 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2017,18 +2017,22 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | |||
2017 | { | 2017 | { |
2018 | struct soc_mixer_control *mc = | 2018 | struct soc_mixer_control *mc = |
2019 | (struct soc_mixer_control *)kcontrol->private_value; | 2019 | (struct soc_mixer_control *)kcontrol->private_value; |
2020 | int max = mc->max; | 2020 | int platform_max; |
2021 | unsigned int shift = mc->shift; | 2021 | unsigned int shift = mc->shift; |
2022 | unsigned int rshift = mc->rshift; | 2022 | unsigned int rshift = mc->rshift; |
2023 | 2023 | ||
2024 | if (max == 1 && !strstr(kcontrol->id.name, " Volume")) | 2024 | if (!mc->platform_max) |
2025 | mc->platform_max = mc->max; | ||
2026 | platform_max = mc->platform_max; | ||
2027 | |||
2028 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
2025 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 2029 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
2026 | else | 2030 | else |
2027 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 2031 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2028 | 2032 | ||
2029 | uinfo->count = shift == rshift ? 1 : 2; | 2033 | uinfo->count = shift == rshift ? 1 : 2; |
2030 | uinfo->value.integer.min = 0; | 2034 | uinfo->value.integer.min = 0; |
2031 | uinfo->value.integer.max = max; | 2035 | uinfo->value.integer.max = platform_max; |
2032 | return 0; | 2036 | return 0; |
2033 | } | 2037 | } |
2034 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 2038 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); |
@@ -2126,16 +2130,20 @@ int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, | |||
2126 | { | 2130 | { |
2127 | struct soc_mixer_control *mc = | 2131 | struct soc_mixer_control *mc = |
2128 | (struct soc_mixer_control *)kcontrol->private_value; | 2132 | (struct soc_mixer_control *)kcontrol->private_value; |
2129 | int max = mc->max; | 2133 | int platform_max; |
2130 | 2134 | ||
2131 | if (max == 1 && !strstr(kcontrol->id.name, " Volume")) | 2135 | if (!mc->platform_max) |
2136 | mc->platform_max = mc->max; | ||
2137 | platform_max = mc->platform_max; | ||
2138 | |||
2139 | if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume")) | ||
2132 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 2140 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
2133 | else | 2141 | else |
2134 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 2142 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2135 | 2143 | ||
2136 | uinfo->count = 2; | 2144 | uinfo->count = 2; |
2137 | uinfo->value.integer.min = 0; | 2145 | uinfo->value.integer.min = 0; |
2138 | uinfo->value.integer.max = max; | 2146 | uinfo->value.integer.max = platform_max; |
2139 | return 0; | 2147 | return 0; |
2140 | } | 2148 | } |
2141 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); | 2149 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); |
@@ -2236,13 +2244,17 @@ int snd_soc_info_volsw_s8(struct snd_kcontrol *kcontrol, | |||
2236 | { | 2244 | { |
2237 | struct soc_mixer_control *mc = | 2245 | struct soc_mixer_control *mc = |
2238 | (struct soc_mixer_control *)kcontrol->private_value; | 2246 | (struct soc_mixer_control *)kcontrol->private_value; |
2239 | int max = mc->max; | 2247 | int platform_max; |
2240 | int min = mc->min; | 2248 | int min = mc->min; |
2241 | 2249 | ||
2250 | if (!mc->platform_max) | ||
2251 | mc->platform_max = mc->max; | ||
2252 | platform_max = mc->platform_max; | ||
2253 | |||
2242 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 2254 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2243 | uinfo->count = 2; | 2255 | uinfo->count = 2; |
2244 | uinfo->value.integer.min = 0; | 2256 | uinfo->value.integer.min = 0; |
2245 | uinfo->value.integer.max = max-min; | 2257 | uinfo->value.integer.max = platform_max - min; |
2246 | return 0; | 2258 | return 0; |
2247 | } | 2259 | } |
2248 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); | 2260 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); |
@@ -2331,7 +2343,7 @@ int snd_soc_limit_volume(struct snd_soc_codec *codec, | |||
2331 | if (found) { | 2343 | if (found) { |
2332 | mc = (struct soc_mixer_control *)kctl->private_value; | 2344 | mc = (struct soc_mixer_control *)kctl->private_value; |
2333 | if (max <= mc->max) { | 2345 | if (max <= mc->max) { |
2334 | mc->max = max; | 2346 | mc->platform_max = max; |
2335 | ret = 0; | 2347 | ret = 0; |
2336 | } | 2348 | } |
2337 | } | 2349 | } |