diff options
| -rw-r--r-- | include/sound/soc.h | 23 | ||||
| -rw-r--r-- | sound/soc/soc-core.c | 30 |
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 */ |
| 574 | struct soc_mixer_control { | 575 | struct 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 | } |
| 2034 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 2038 | EXPORT_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 | } |
| 2141 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); | 2149 | EXPORT_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 | } |
| 2248 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_s8); | 2260 | EXPORT_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 | } |
