aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h23
-rw-r--r--sound/soc/soc-core.c30
2 files changed, 33 insertions, 20 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 8326fc3db1cf..697e7ffe39d7 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -30,10 +30,10 @@
30#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \ 30#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
31 ((unsigned long)&(struct soc_mixer_control) \ 31 ((unsigned long)&(struct soc_mixer_control) \
32 {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \ 32 {.reg = xreg, .shift = xshift, .rshift = xshift, .max = xmax, \
33 .invert = xinvert}) 33 .platform_max = xmax, .invert = xinvert})
34#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ 34#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
35 ((unsigned long)&(struct soc_mixer_control) \ 35 ((unsigned long)&(struct soc_mixer_control) \
36 {.reg = xreg, .max = xmax, .invert = xinvert}) 36 {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
37#define SOC_SINGLE(xname, reg, shift, max, invert) \ 37#define SOC_SINGLE(xname, reg, shift, max, invert) \
38{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 38{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
39 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ 39 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
@@ -53,14 +53,14 @@
53 .put = snd_soc_put_volsw, \ 53 .put = snd_soc_put_volsw, \
54 .private_value = (unsigned long)&(struct soc_mixer_control) \ 54 .private_value = (unsigned long)&(struct soc_mixer_control) \
55 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ 55 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
56 .max = xmax, .invert = xinvert} } 56 .max = xmax, .platform_max = xmax, .invert = xinvert} }
57#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ 57#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
58{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 58{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
59 .info = snd_soc_info_volsw_2r, \ 59 .info = snd_soc_info_volsw_2r, \
60 .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ 60 .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
61 .private_value = (unsigned long)&(struct soc_mixer_control) \ 61 .private_value = (unsigned long)&(struct soc_mixer_control) \
62 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ 62 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
63 .max = xmax, .invert = xinvert} } 63 .max = xmax, .platform_max = xmax, .invert = xinvert} }
64#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \ 64#define SOC_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert, tlv_array) \
65{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 65{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
66 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 66 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -70,7 +70,7 @@
70 .put = snd_soc_put_volsw, \ 70 .put = snd_soc_put_volsw, \
71 .private_value = (unsigned long)&(struct soc_mixer_control) \ 71 .private_value = (unsigned long)&(struct soc_mixer_control) \
72 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ 72 {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
73 .max = xmax, .invert = xinvert} } 73 .max = xmax, .platform_max = xmax, .invert = xinvert} }
74#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ 74#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
75{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ 75{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
76 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ 76 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -80,7 +80,7 @@
80 .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ 80 .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
81 .private_value = (unsigned long)&(struct soc_mixer_control) \ 81 .private_value = (unsigned long)&(struct soc_mixer_control) \
82 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ 82 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
83 .max = xmax, .invert = xinvert} } 83 .max = xmax, .platform_max = xmax, .invert = xinvert} }
84#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ 84#define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \
85{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 85{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
86 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ 86 .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
@@ -89,7 +89,8 @@
89 .info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \ 89 .info = snd_soc_info_volsw_s8, .get = snd_soc_get_volsw_s8, \
90 .put = snd_soc_put_volsw_s8, \ 90 .put = snd_soc_put_volsw_s8, \
91 .private_value = (unsigned long)&(struct soc_mixer_control) \ 91 .private_value = (unsigned long)&(struct soc_mixer_control) \
92 {.reg = xreg, .min = xmin, .max = xmax} } 92 {.reg = xreg, .min = xmin, .max = xmax, \
93 .platform_max = xmax} }
93#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ 94#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \
94{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ 95{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
95 .max = xmax, .texts = xtexts } 96 .max = xmax, .texts = xtexts }
@@ -126,7 +127,7 @@
126 .get = xhandler_get, .put = xhandler_put, \ 127 .get = xhandler_get, .put = xhandler_put, \
127 .private_value = (unsigned long)&(struct soc_mixer_control) \ 128 .private_value = (unsigned long)&(struct soc_mixer_control) \
128 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ 129 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
129 .max = xmax, .invert = xinvert} } 130 .max = xmax, .platform_max = xmax, .invert = xinvert} }
130#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ 131#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
131 xhandler_get, xhandler_put, tlv_array) \ 132 xhandler_get, xhandler_put, tlv_array) \
132{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 133{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -146,7 +147,7 @@
146 .get = xhandler_get, .put = xhandler_put, \ 147 .get = xhandler_get, .put = xhandler_put, \
147 .private_value = (unsigned long)&(struct soc_mixer_control) \ 148 .private_value = (unsigned long)&(struct soc_mixer_control) \
148 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ 149 {.reg = xreg, .shift = shift_left, .rshift = shift_right, \
149 .max = xmax, .invert = xinvert} } 150 .max = xmax, .platform_max = xmax, .invert = xinvert} }
150#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ 151#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
151 xhandler_get, xhandler_put, tlv_array) \ 152 xhandler_get, xhandler_put, tlv_array) \
152{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ 153{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -157,7 +158,7 @@
157 .get = xhandler_get, .put = xhandler_put, \ 158 .get = xhandler_get, .put = xhandler_put, \
158 .private_value = (unsigned long)&(struct soc_mixer_control) \ 159 .private_value = (unsigned long)&(struct soc_mixer_control) \
159 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ 160 {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
160 .max = xmax, .invert = xinvert} } 161 .max = xmax, .platform_max = xmax, .invert = xinvert} }
161#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ 162#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
162{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 163{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
163 .info = snd_soc_info_bool_ext, \ 164 .info = snd_soc_info_bool_ext, \
@@ -572,7 +573,7 @@ struct snd_soc_pcm_runtime {
572 573
573/* mixer control */ 574/* mixer control */
574struct soc_mixer_control { 575struct soc_mixer_control {
575 int min, max; 576 int min, max, platform_max;
576 unsigned int reg, rreg, shift, rshift, invert; 577 unsigned int reg, rreg, shift, rshift, invert;
577}; 578};
578 579
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}
2034EXPORT_SYMBOL_GPL(snd_soc_info_volsw); 2038EXPORT_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}
2141EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); 2149EXPORT_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}
2248EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); 2260EXPORT_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 }