diff options
-rw-r--r-- | include/sound/soc.h | 10 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 32 |
2 files changed, 36 insertions, 6 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 769e27c774a3..bc56738cb109 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -58,8 +58,9 @@ | |||
58 | .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ | 58 | .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ |
59 | .put = snd_soc_put_volsw_range, \ | 59 | .put = snd_soc_put_volsw_range, \ |
60 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | 60 | .private_value = (unsigned long)&(struct soc_mixer_control) \ |
61 | {.reg = xreg, .shift = xshift, .min = xmin,\ | 61 | {.reg = xreg, .rreg = xreg, .shift = xshift, \ |
62 | .max = xmax, .platform_max = xmax, .invert = xinvert} } | 62 | .rshift = xshift, .min = xmin, .max = xmax, \ |
63 | .platform_max = xmax, .invert = xinvert} } | ||
63 | #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ | 64 | #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ |
64 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 65 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
65 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 66 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ |
@@ -88,8 +89,9 @@ | |||
88 | .info = snd_soc_info_volsw_range, \ | 89 | .info = snd_soc_info_volsw_range, \ |
89 | .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ | 90 | .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ |
90 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | 91 | .private_value = (unsigned long)&(struct soc_mixer_control) \ |
91 | {.reg = xreg, .shift = xshift, .min = xmin,\ | 92 | {.reg = xreg, .rreg = xreg, .shift = xshift, \ |
92 | .max = xmax, .platform_max = xmax, .invert = xinvert} } | 93 | .rshift = xshift, .min = xmin, .max = xmax, \ |
94 | .platform_max = xmax, .invert = xinvert} } | ||
93 | #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ | 95 | #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ |
94 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | 96 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
95 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ | 97 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 91d592ff67b7..e0d4630bfb4f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2917,7 +2917,7 @@ int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | |||
2917 | platform_max = mc->platform_max; | 2917 | platform_max = mc->platform_max; |
2918 | 2918 | ||
2919 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | 2919 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
2920 | uinfo->count = 1; | 2920 | uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; |
2921 | uinfo->value.integer.min = 0; | 2921 | uinfo->value.integer.min = 0; |
2922 | uinfo->value.integer.max = platform_max - min; | 2922 | uinfo->value.integer.max = platform_max - min; |
2923 | 2923 | ||
@@ -2941,12 +2941,14 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | |||
2941 | (struct soc_mixer_control *)kcontrol->private_value; | 2941 | (struct soc_mixer_control *)kcontrol->private_value; |
2942 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2942 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2943 | unsigned int reg = mc->reg; | 2943 | unsigned int reg = mc->reg; |
2944 | unsigned int rreg = mc->rreg; | ||
2944 | unsigned int shift = mc->shift; | 2945 | unsigned int shift = mc->shift; |
2945 | int min = mc->min; | 2946 | int min = mc->min; |
2946 | int max = mc->max; | 2947 | int max = mc->max; |
2947 | unsigned int mask = (1 << fls(max)) - 1; | 2948 | unsigned int mask = (1 << fls(max)) - 1; |
2948 | unsigned int invert = mc->invert; | 2949 | unsigned int invert = mc->invert; |
2949 | unsigned int val, val_mask; | 2950 | unsigned int val, val_mask; |
2951 | int ret; | ||
2950 | 2952 | ||
2951 | val = ((ucontrol->value.integer.value[0] + min) & mask); | 2953 | val = ((ucontrol->value.integer.value[0] + min) & mask); |
2952 | if (invert) | 2954 | if (invert) |
@@ -2954,7 +2956,21 @@ int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | |||
2954 | val_mask = mask << shift; | 2956 | val_mask = mask << shift; |
2955 | val = val << shift; | 2957 | val = val << shift; |
2956 | 2958 | ||
2957 | return snd_soc_update_bits_locked(codec, reg, val_mask, val); | 2959 | ret = snd_soc_update_bits_locked(codec, reg, val_mask, val); |
2960 | if (ret != 0) | ||
2961 | return ret; | ||
2962 | |||
2963 | if (snd_soc_volsw_is_stereo(mc)) { | ||
2964 | val = ((ucontrol->value.integer.value[1] + min) & mask); | ||
2965 | if (invert) | ||
2966 | val = max - val; | ||
2967 | val_mask = mask << shift; | ||
2968 | val = val << shift; | ||
2969 | |||
2970 | ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val); | ||
2971 | } | ||
2972 | |||
2973 | return ret; | ||
2958 | } | 2974 | } |
2959 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | 2975 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); |
2960 | 2976 | ||
@@ -2974,11 +2990,13 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | |||
2974 | (struct soc_mixer_control *)kcontrol->private_value; | 2990 | (struct soc_mixer_control *)kcontrol->private_value; |
2975 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2991 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2976 | unsigned int reg = mc->reg; | 2992 | unsigned int reg = mc->reg; |
2993 | unsigned int rreg = mc->rreg; | ||
2977 | unsigned int shift = mc->shift; | 2994 | unsigned int shift = mc->shift; |
2978 | int min = mc->min; | 2995 | int min = mc->min; |
2979 | int max = mc->max; | 2996 | int max = mc->max; |
2980 | unsigned int mask = (1 << fls(max)) - 1; | 2997 | unsigned int mask = (1 << fls(max)) - 1; |
2981 | unsigned int invert = mc->invert; | 2998 | unsigned int invert = mc->invert; |
2999 | int ret; | ||
2982 | 3000 | ||
2983 | ucontrol->value.integer.value[0] = | 3001 | ucontrol->value.integer.value[0] = |
2984 | (snd_soc_read(codec, reg) >> shift) & mask; | 3002 | (snd_soc_read(codec, reg) >> shift) & mask; |
@@ -2988,6 +3006,16 @@ int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | |||
2988 | ucontrol->value.integer.value[0] = | 3006 | ucontrol->value.integer.value[0] = |
2989 | ucontrol->value.integer.value[0] - min; | 3007 | ucontrol->value.integer.value[0] - min; |
2990 | 3008 | ||
3009 | if (snd_soc_volsw_is_stereo(mc)) { | ||
3010 | ucontrol->value.integer.value[1] = | ||
3011 | (snd_soc_read(codec, rreg) >> shift) & mask; | ||
3012 | if (invert) | ||
3013 | ucontrol->value.integer.value[1] = | ||
3014 | max - ucontrol->value.integer.value[1]; | ||
3015 | ucontrol->value.integer.value[1] = | ||
3016 | ucontrol->value.integer.value[1] - min; | ||
3017 | } | ||
3018 | |||
2991 | return 0; | 3019 | return 0; |
2992 | } | 3020 | } |
2993 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | 3021 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); |