summaryrefslogtreecommitdiff
path: root/sound/soc/soc-ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-ops.c')
-rw-r--r--sound/soc/soc-ops.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index b27e89ff6a16..5be32c37bb8a 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -336,7 +336,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[0] < 0)
return -EINVAL;
val = ucontrol->value.integer.value[0];
- if (mc->platform_max && ((int)val + min) > mc->platform_max)
+ if (mc->platform_max && val > mc->platform_max)
return -EINVAL;
if (val > max - min)
return -EINVAL;
@@ -349,7 +349,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
if (ucontrol->value.integer.value[1] < 0)
return -EINVAL;
val2 = ucontrol->value.integer.value[1];
- if (mc->platform_max && ((int)val2 + min) > mc->platform_max)
+ if (mc->platform_max && val2 > mc->platform_max)
return -EINVAL;
if (val2 > max - min)
return -EINVAL;
@@ -502,17 +502,16 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol,
{
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- int platform_max;
- int min = mc->min;
+ int max;
- if (!mc->platform_max)
- mc->platform_max = mc->max;
- platform_max = mc->platform_max;
+ max = mc->max - mc->min;
+ if (mc->platform_max && mc->platform_max < max)
+ max = mc->platform_max;
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = platform_max - min;
+ uinfo->value.integer.max = max;
return 0;
}
@@ -639,6 +638,37 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
+static int snd_soc_clip_to_platform_max(struct snd_kcontrol *kctl)
+{
+ struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
+ struct snd_ctl_elem_value *uctl;
+ int ret;
+
+ if (!mc->platform_max)
+ return 0;
+
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return -ENOMEM;
+
+ ret = kctl->get(kctl, uctl);
+ if (ret < 0)
+ goto out;
+
+ if (uctl->value.integer.value[0] > mc->platform_max)
+ uctl->value.integer.value[0] = mc->platform_max;
+
+ if (snd_soc_volsw_is_stereo(mc) &&
+ uctl->value.integer.value[1] > mc->platform_max)
+ uctl->value.integer.value[1] = mc->platform_max;
+
+ ret = kctl->put(kctl, uctl);
+
+out:
+ kfree(uctl);
+ return ret;
+}
+
/**
* snd_soc_limit_volume - Set new limit to an existing volume control.
*
@@ -663,7 +693,7 @@ int snd_soc_limit_volume(struct snd_soc_card *card,
struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value;
if (max <= mc->max - mc->min) {
mc->platform_max = max;
- ret = 0;
+ ret = snd_soc_clip_to_platform_max(kctl);
}
}
return ret;