diff options
author | Adam Thomson <Adam.Thomson@diasemi.com> | 2012-05-31 10:18:01 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-06-03 08:06:41 -0400 |
commit | 6c9d8cf6372ed2995a3d982f5c1f966e842101cc (patch) | |
tree | 1a71ce7d37e0183e7e01968e64774711d444d10e /sound/soc/soc-core.c | |
parent | bc92657a11c0982783979bbb84ceaf58ba222124 (diff) |
ASoC: core: Add single controls with specified range of values
Control type added for cases where a specific range of values
within a register are required for control.
Added convenience macros:
SOC_SINGLE_RANGE
SOC_SINGLE_RANGE_TLV
Added accessor implementations:
snd_soc_info_volsw_range
snd_soc_put_volsw_range
snd_soc_get_volsw_range
Signed-off-by: Michal Hajduk <Michal.Hajduk@diasemi.com>
Signed-off-by: Adam Thomson <Adam.Thomson@diasemi.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index ec8350570346..3d803f3cd272 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2792,6 +2792,104 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, | |||
2792 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | 2792 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); |
2793 | 2793 | ||
2794 | /** | 2794 | /** |
2795 | * snd_soc_info_volsw_range - single mixer info callback with range. | ||
2796 | * @kcontrol: mixer control | ||
2797 | * @uinfo: control element information | ||
2798 | * | ||
2799 | * Callback to provide information, within a range, about a single | ||
2800 | * mixer control. | ||
2801 | * | ||
2802 | * returns 0 for success. | ||
2803 | */ | ||
2804 | int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, | ||
2805 | struct snd_ctl_elem_info *uinfo) | ||
2806 | { | ||
2807 | struct soc_mixer_control *mc = | ||
2808 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2809 | int platform_max; | ||
2810 | int min = mc->min; | ||
2811 | |||
2812 | if (!mc->platform_max) | ||
2813 | mc->platform_max = mc->max; | ||
2814 | platform_max = mc->platform_max; | ||
2815 | |||
2816 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
2817 | uinfo->count = 1; | ||
2818 | uinfo->value.integer.min = 0; | ||
2819 | uinfo->value.integer.max = platform_max - min; | ||
2820 | |||
2821 | return 0; | ||
2822 | } | ||
2823 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_range); | ||
2824 | |||
2825 | /** | ||
2826 | * snd_soc_put_volsw_range - single mixer put value callback with range. | ||
2827 | * @kcontrol: mixer control | ||
2828 | * @ucontrol: control element information | ||
2829 | * | ||
2830 | * Callback to set the value, within a range, for a single mixer control. | ||
2831 | * | ||
2832 | * Returns 0 for success. | ||
2833 | */ | ||
2834 | int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, | ||
2835 | struct snd_ctl_elem_value *ucontrol) | ||
2836 | { | ||
2837 | struct soc_mixer_control *mc = | ||
2838 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2839 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2840 | unsigned int reg = mc->reg; | ||
2841 | unsigned int shift = mc->shift; | ||
2842 | int min = mc->min; | ||
2843 | int max = mc->max; | ||
2844 | unsigned int mask = (1 << fls(max)) - 1; | ||
2845 | unsigned int invert = mc->invert; | ||
2846 | unsigned int val, val_mask; | ||
2847 | |||
2848 | val = ((ucontrol->value.integer.value[0] + min) & mask); | ||
2849 | if (invert) | ||
2850 | val = max - val; | ||
2851 | val_mask = mask << shift; | ||
2852 | val = val << shift; | ||
2853 | |||
2854 | return snd_soc_update_bits_locked(codec, reg, val_mask, val); | ||
2855 | } | ||
2856 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range); | ||
2857 | |||
2858 | /** | ||
2859 | * snd_soc_get_volsw_range - single mixer get callback with range | ||
2860 | * @kcontrol: mixer control | ||
2861 | * @ucontrol: control element information | ||
2862 | * | ||
2863 | * Callback to get the value, within a range, of a single mixer control. | ||
2864 | * | ||
2865 | * Returns 0 for success. | ||
2866 | */ | ||
2867 | int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, | ||
2868 | struct snd_ctl_elem_value *ucontrol) | ||
2869 | { | ||
2870 | struct soc_mixer_control *mc = | ||
2871 | (struct soc_mixer_control *)kcontrol->private_value; | ||
2872 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2873 | unsigned int reg = mc->reg; | ||
2874 | unsigned int shift = mc->shift; | ||
2875 | int min = mc->min; | ||
2876 | int max = mc->max; | ||
2877 | unsigned int mask = (1 << fls(max)) - 1; | ||
2878 | unsigned int invert = mc->invert; | ||
2879 | |||
2880 | ucontrol->value.integer.value[0] = | ||
2881 | (snd_soc_read(codec, reg) >> shift) & mask; | ||
2882 | if (invert) | ||
2883 | ucontrol->value.integer.value[0] = | ||
2884 | max - ucontrol->value.integer.value[0]; | ||
2885 | ucontrol->value.integer.value[0] = | ||
2886 | ucontrol->value.integer.value[0] - min; | ||
2887 | |||
2888 | return 0; | ||
2889 | } | ||
2890 | EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range); | ||
2891 | |||
2892 | /** | ||
2795 | * snd_soc_limit_volume - Set new limit to an existing volume control. | 2893 | * snd_soc_limit_volume - Set new limit to an existing volume control. |
2796 | * | 2894 | * |
2797 | * @codec: where to look for the control | 2895 | * @codec: where to look for the control |