]>
Commit | Line | Data |
---|---|---|
af068d41 GKH |
1 | From 34198710f55b5f359f43e67d9a08fe5aadfbca1b Mon Sep 17 00:00:00 2001 |
2 | From: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | |
3 | Date: Wed, 14 Oct 2015 13:31:24 +0100 | |
4 | Subject: ASoC: Add info callback for SX_TLV controls | |
5 | ||
6 | From: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | |
7 | ||
8 | commit 34198710f55b5f359f43e67d9a08fe5aadfbca1b upstream. | |
9 | ||
10 | SX_TLV controls are intended for situations where the register behind | |
11 | the control has some non-zero value indicating the minimum gain | |
12 | and then gains increasing from there and eventually overflowing through | |
13 | zero. | |
14 | ||
15 | Currently every CODEC implementing these controls specifies the minimum | |
16 | as the non-zero value for the minimum and the maximum as the number of | |
17 | gain settings available. | |
18 | ||
19 | This means when the info callback subtracts the minimum value from the | |
20 | maximum value to calculate the number of gain levels available it is | |
21 | actually under reporting the available levels. This patch fixes this | |
22 | issue by adding a new snd_soc_info_volsw_sx callback that does not | |
23 | subtract the minimum value. | |
24 | ||
25 | Fixes: 1d99f2436d0d ("ASoC: core: Rework SOC_DOUBLE_R_SX_TLV add SOC_SINGLE_SX_TLV") | |
26 | Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | |
27 | Acked-by: Brian Austin <brian.austin@cirrus.com> | |
28 | Tested-by: Brian Austin <brian.austin@cirrus.com> | |
29 | Signed-off-by: Mark Brown <broonie@kernel.org> | |
30 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
31 | ||
32 | --- | |
33 | include/sound/soc.h | 6 ++++-- | |
34 | sound/soc/soc-ops.c | 28 ++++++++++++++++++++++++++++ | |
35 | 2 files changed, 32 insertions(+), 2 deletions(-) | |
36 | ||
37 | --- a/include/sound/soc.h | |
38 | +++ b/include/sound/soc.h | |
39 | @@ -85,7 +85,7 @@ | |
40 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | |
41 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | |
42 | .tlv.p = (tlv_array),\ | |
43 | - .info = snd_soc_info_volsw, \ | |
44 | + .info = snd_soc_info_volsw_sx, \ | |
45 | .get = snd_soc_get_volsw_sx,\ | |
46 | .put = snd_soc_put_volsw_sx, \ | |
47 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
48 | @@ -155,7 +155,7 @@ | |
49 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | |
50 | SNDRV_CTL_ELEM_ACCESS_READWRITE, \ | |
51 | .tlv.p = (tlv_array), \ | |
52 | - .info = snd_soc_info_volsw, \ | |
53 | + .info = snd_soc_info_volsw_sx, \ | |
54 | .get = snd_soc_get_volsw_sx, \ | |
55 | .put = snd_soc_put_volsw_sx, \ | |
56 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | |
57 | @@ -563,6 +563,8 @@ int snd_soc_put_enum_double(struct snd_k | |
58 | struct snd_ctl_elem_value *ucontrol); | |
59 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | |
60 | struct snd_ctl_elem_info *uinfo); | |
61 | +int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, | |
62 | + struct snd_ctl_elem_info *uinfo); | |
63 | #define snd_soc_info_bool_ext snd_ctl_boolean_mono_info | |
64 | int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |
65 | struct snd_ctl_elem_value *ucontrol); | |
66 | --- a/sound/soc/soc-ops.c | |
67 | +++ b/sound/soc/soc-ops.c | |
68 | @@ -207,6 +207,34 @@ int snd_soc_info_volsw(struct snd_kcontr | |
69 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | |
70 | ||
71 | /** | |
72 | + * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls | |
73 | + * @kcontrol: mixer control | |
74 | + * @uinfo: control element information | |
75 | + * | |
76 | + * Callback to provide information about a single mixer control, or a double | |
77 | + * mixer control that spans 2 registers of the SX TLV type. SX TLV controls | |
78 | + * have a range that represents both positive and negative values either side | |
79 | + * of zero but without a sign bit. | |
80 | + * | |
81 | + * Returns 0 for success. | |
82 | + */ | |
83 | +int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, | |
84 | + struct snd_ctl_elem_info *uinfo) | |
85 | +{ | |
86 | + struct soc_mixer_control *mc = | |
87 | + (struct soc_mixer_control *)kcontrol->private_value; | |
88 | + | |
89 | + snd_soc_info_volsw(kcontrol, uinfo); | |
90 | + /* Max represents the number of levels in an SX control not the | |
91 | + * maximum value, so add the minimum value back on | |
92 | + */ | |
93 | + uinfo->value.integer.max += mc->min; | |
94 | + | |
95 | + return 0; | |
96 | +} | |
97 | +EXPORT_SYMBOL_GPL(snd_soc_info_volsw_sx); | |
98 | + | |
99 | +/** | |
100 | * snd_soc_get_volsw - single mixer get callback | |
101 | * @kcontrol: mixer control | |
102 | * @ucontrol: control element information |