aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIcenowy Zheng <icenowy@aosc.io>2017-06-05 09:27:20 -0400
committerMark Brown <broonie@kernel.org>2017-06-06 14:27:34 -0400
commit50aadc14cee74009c72e7d66954b15f27d45c02f (patch)
treeb15b0bb9fb5e20e7e3ba380eff7bbf6b6199de42
parentb08a20f58d2efcd88bf5276e34cd4020028accb7 (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.c101
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 */
223static 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 */
223static const struct snd_kcontrol_new sun8i_codec_adc_mixer_controls[] = { 239static 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 */
263static 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 */
247static const DECLARE_TLV_DB_SCALE(sun8i_codec_out_mixer_pregain_scale, 279static 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 */ 329static 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
348static 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
315static const struct snd_soc_dapm_route sun8i_codec_common_routes[] = { 367static 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
372static 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
771static 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
717static int sun8i_codec_analog_cmpnt_probe(struct snd_soc_component *cmpnt) 813static 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);