diff options
author | Icenowy Zheng <icenowy@aosc.io> | 2017-06-05 09:27:20 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2017-06-06 14:27:34 -0400 |
commit | 50aadc14cee74009c72e7d66954b15f27d45c02f (patch) | |
tree | b15b0bb9fb5e20e7e3ba380eff7bbf6b6199de42 | |
parent | b08a20f58d2efcd88bf5276e34cd4020028accb7 (diff) |
ASoC: sun8i-codec-analog: prepare a mixer control/widget/route set for V3s
Allwinner V3s has an analog codec without MIC2 and Line In, which will
need a special set of mixer controls/widgets/routes, otherwise meaningless
controls will be exported to userspace and confuse the user.
Add the special set, and use it when the SoC has no MIC2 and Line In.
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | sound/soc/sunxi/sun8i-codec-analog.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/sound/soc/sunxi/sun8i-codec-analog.c b/sound/soc/sunxi/sun8i-codec-analog.c index edcc3eb7cd9a..29c446068151 100644 --- a/sound/soc/sunxi/sun8i-codec-analog.c +++ b/sound/soc/sunxi/sun8i-codec-analog.c | |||
@@ -219,6 +219,22 @@ static const struct snd_kcontrol_new sun8i_codec_mixer_controls[] = { | |||
219 | SUN8I_ADDA_LOMIXSC_MIC2, 1, 0), | 219 | SUN8I_ADDA_LOMIXSC_MIC2, 1, 0), |
220 | }; | 220 | }; |
221 | 221 | ||
222 | /* mixer controls */ | ||
223 | static const struct snd_kcontrol_new sun8i_v3s_codec_mixer_controls[] = { | ||
224 | SOC_DAPM_DOUBLE_R("DAC Playback Switch", | ||
225 | SUN8I_ADDA_LOMIXSC, | ||
226 | SUN8I_ADDA_ROMIXSC, | ||
227 | SUN8I_ADDA_LOMIXSC_DACL, 1, 0), | ||
228 | SOC_DAPM_DOUBLE_R("DAC Reversed Playback Switch", | ||
229 | SUN8I_ADDA_LOMIXSC, | ||
230 | SUN8I_ADDA_ROMIXSC, | ||
231 | SUN8I_ADDA_LOMIXSC_DACR, 1, 0), | ||
232 | SOC_DAPM_DOUBLE_R("Mic1 Playback Switch", | ||
233 | SUN8I_ADDA_LOMIXSC, | ||
234 | SUN8I_ADDA_ROMIXSC, | ||
235 | SUN8I_ADDA_LOMIXSC_MIC1, 1, 0), | ||
236 | }; | ||
237 | |||
222 | /* ADC mixer controls */ | 238 | /* ADC mixer controls */ |
223 | static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { | 239 | static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { |
224 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", | 240 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", |
@@ -243,6 +259,22 @@ static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { | |||
243 | SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0), | 259 | SUN8I_ADDA_LADCMIXSC_MIC2, 1, 0), |
244 | }; | 260 | }; |
245 | 261 | ||
262 | /* ADC mixer controls */ | ||
263 | static const struct snd_kcontrol_new sun8i_v3s_codec_adc_mixer_controls[] = { | ||
264 | SOC_DAPM_DOUBLE_R("Mixer Capture Switch", | ||
265 | SUN8I_ADDA_LADCMIXSC, | ||
266 | SUN8I_ADDA_RADCMIXSC, | ||
267 | SUN8I_ADDA_LADCMIXSC_OMIXRL, 1, 0), | ||
268 | SOC_DAPM_DOUBLE_R("Mixer Reversed Capture Switch", | ||
269 | SUN8I_ADDA_LADCMIXSC, | ||
270 | SUN8I_ADDA_RADCMIXSC, | ||
271 | SUN8I_ADDA_LADCMIXSC_OMIXRR, 1, 0), | ||
272 | SOC_DAPM_DOUBLE_R("Mic1 Capture Switch", | ||
273 | SUN8I_ADDA_LADCMIXSC, | ||
274 | SUN8I_ADDA_RADCMIXSC, | ||
275 | SUN8I_ADDA_LADCMIXSC_MIC1, 1, 0), | ||
276 | }; | ||
277 | |||
246 | /* volume / mute controls */ | 278 | /* volume / mute controls */ |
247 | static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale, | 279 | static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale, |
248 | -450, 150, 0); | 280 | -450, 150, 0); |
@@ -292,8 +324,9 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = { | |||
292 | /* Mic input path */ | 324 | /* Mic input path */ |
293 | SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, | 325 | SND_SOC_DAPM_PGA("Mic1 Amplifier", SUN8I_ADDA_MIC1G_MICBIAS_CTRL, |
294 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0), | 326 | SUN8I_ADDA_MIC1G_MICBIAS_CTRL_MIC1AMPEN, 0, NULL, 0), |
327 | }; | ||
295 | 328 | ||
296 | /* Mixers */ | 329 | static const struct snd_soc_dapm_widget sun8i_codec_mixer_widgets[] = { |
297 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, | 330 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, |
298 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, | 331 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, |
299 | sun8i_codec_mixer_controls, | 332 | sun8i_codec_mixer_controls, |
@@ -312,10 +345,31 @@ static const struct snd_soc_dapm_widget sun8i_codec_common_widgets[] = { | |||
312 | ARRAY_SIZE(sun8i_codec_adc_mixer_controls)), | 345 | ARRAY_SIZE(sun8i_codec_adc_mixer_controls)), |
313 | }; | 346 | }; |
314 | 347 | ||
348 | static const struct snd_soc_dapm_widget sun8i_v3s_codec_mixer_widgets[] = { | ||
349 | SND_SOC_DAPM_MIXER("Left Mixer", SUN8I_ADDA_DAC_PA_SRC, | ||
350 | SUN8I_ADDA_DAC_PA_SRC_LMIXEN, 0, | ||
351 | sun8i_v3s_codec_mixer_controls, | ||
352 | ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)), | ||
353 | SND_SOC_DAPM_MIXER("Right Mixer", SUN8I_ADDA_DAC_PA_SRC, | ||
354 | SUN8I_ADDA_DAC_PA_SRC_RMIXEN, 0, | ||
355 | sun8i_v3s_codec_mixer_controls, | ||
356 | ARRAY_SIZE(sun8i_v3s_codec_mixer_controls)), | ||
357 | SND_SOC_DAPM_MIXER("Left ADC Mixer", SUN8I_ADDA_ADC_AP_EN, | ||
358 | SUN8I_ADDA_ADC_AP_EN_ADCLEN, 0, | ||
359 | sun8i_v3s_codec_adc_mixer_controls, | ||
360 | ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)), | ||
361 | SND_SOC_DAPM_MIXER("Right ADC Mixer", SUN8I_ADDA_ADC_AP_EN, | ||
362 | SUN8I_ADDA_ADC_AP_EN_ADCREN, 0, | ||
363 | sun8i_v3s_codec_adc_mixer_controls, | ||
364 | ARRAY_SIZE(sun8i_v3s_codec_adc_mixer_controls)), | ||
365 | }; | ||
366 | |||
315 | static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = { | 367 | static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = { |
316 | /* Microphone Routes */ | 368 | /* Microphone Routes */ |
317 | { "Mic1 Amplifier", NULL, "MIC1"}, | 369 | { "Mic1 Amplifier", NULL, "MIC1"}, |
370 | }; | ||
318 | 371 | ||
372 | static const struct snd_soc_dapm_route sun8i_codec_mixer_routes[] = { | ||
319 | /* Left Mixer Routes */ | 373 | /* Left Mixer Routes */ |
320 | { "Left Mixer", "DAC Playback Switch", "Left DAC" }, | 374 | { "Left Mixer", "DAC Playback Switch", "Left DAC" }, |
321 | { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, | 375 | { "Left Mixer", "DAC Reversed Playback Switch", "Right DAC" }, |
@@ -714,6 +768,48 @@ static const struct sun8i_codec_analog_quirks sun8i_h3_quirks = { | |||
714 | .has_mic2 = true, | 768 | .has_mic2 = true, |
715 | }; | 769 | }; |
716 | 770 | ||
771 | static int sun8i_codec_analog_add_mixer(struct snd_soc_component *cmpnt, | ||
772 | const struct sun8i_codec_analog_quirks *quirks) | ||
773 | { | ||
774 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(cmpnt); | ||
775 | struct device *dev = cmpnt->dev; | ||
776 | int ret; | ||
777 | |||
778 | if (!quirks->has_mic2 && !quirks->has_linein) { | ||
779 | /* | ||
780 | * Apply the special widget set which has uses a control | ||
781 | * without MIC2 and Line In, for SoCs without these. | ||
782 | * TODO: not all special cases are supported now, this case | ||
783 | * is present because it's the case of V3s. | ||
784 | */ | ||
785 | ret = snd_soc_dapm_new_controls(dapm, | ||
786 | sun8i_v3s_codec_mixer_widgets, | ||
787 | ARRAY_SIZE(sun8i_v3s_codec_mixer_widgets)); | ||
788 | if (ret) { | ||
789 | dev_err(dev, "Failed to add V3s Mixer DAPM widgets: %d\n", ret); | ||
790 | return ret; | ||
791 | } | ||
792 | } else { | ||
793 | /* Apply the generic mixer widget set. */ | ||
794 | ret = snd_soc_dapm_new_controls(dapm, | ||
795 | sun8i_codec_mixer_widgets, | ||
796 | ARRAY_SIZE(sun8i_codec_mixer_widgets)); | ||
797 | if (ret) { | ||
798 | dev_err(dev, "Failed to add Mixer DAPM widgets: %d\n", ret); | ||
799 | return ret; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_mixer_routes, | ||
804 | ARRAY_SIZE(sun8i_codec_mixer_routes)); | ||
805 | if (ret) { | ||
806 | dev_err(dev, "Failed to add Mixer DAPM routes: %d\n", ret); | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | return 0; | ||
811 | } | ||
812 | |||
717 | static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) | 813 | static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) |
718 | { | 814 | { |
719 | struct device *dev = cmpnt->dev; | 815 | struct device *dev = cmpnt->dev; |
@@ -728,6 +824,9 @@ static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) | |||
728 | quirks = of_device_get_match_data(dev); | 824 | quirks = of_device_get_match_data(dev); |
729 | 825 | ||
730 | /* Add controls, widgets, and routes for individual features */ | 826 | /* Add controls, widgets, and routes for individual features */ |
827 | ret = sun8i_codec_analog_add_mixer(cmpnt, quirks); | ||
828 | if (ret) | ||
829 | return ret; | ||
731 | 830 | ||
732 | if (quirks->has_headphone) { | 831 | if (quirks->has_headphone) { |
733 | ret = sun8i_codec_add_headphone(cmpnt); | 832 | ret = sun8i_codec_add_headphone(cmpnt); |