Lines Matching +full:adc +full:- +full:mux
1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * (C) Copyright 2010-2016
9 * Mylène Josserand <mylene.josserand@free-electrons.com>
23 #include <sound/soc-dapm.h>
181 regcache_cache_only(scodec->regmap, false); in sun8i_codec_runtime_resume()
183 ret = regcache_sync(scodec->regmap); in sun8i_codec_runtime_resume()
196 regcache_cache_only(scodec->regmap, true); in sun8i_codec_runtime_suspend()
197 regcache_mark_dirty(scodec->regmap); in sun8i_codec_runtime_suspend()
233 return -EINVAL; in sun8i_codec_get_hw_rate()
243 struct sun8i_codec_aif *aif = &scodec->aifs[i]; in sun8i_codec_update_sample_rate()
245 if (aif->active_streams) in sun8i_codec_update_sample_rate()
246 max_rate = max(max_rate, aif->sample_rate); in sun8i_codec_update_sample_rate()
249 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */ in sun8i_codec_update_sample_rate()
257 regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, in sun8i_codec_update_sample_rate()
278 return -EINVAL; in sun8i_codec_set_fmt()
281 if (dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_set_fmt()
284 return -EINVAL; in sun8i_codec_set_fmt()
287 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
291 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
316 return -EINVAL; in sun8i_codec_set_fmt()
319 if (dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_set_fmt()
322 return -EINVAL; in sun8i_codec_set_fmt()
324 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
344 return -EINVAL; in sun8i_codec_set_fmt()
350 return -EINVAL; in sun8i_codec_set_fmt()
365 invert ^= scodec->quirks->lrck_inversion; in sun8i_codec_set_fmt()
368 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_set_fmt()
380 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_set_tdm_slot()
383 return -EINVAL; in sun8i_codec_set_tdm_slot()
385 aif->slots = slots; in sun8i_codec_set_tdm_slot()
386 aif->slot_width = slot_width; in sun8i_codec_set_tdm_slot()
420 if (dai->id != SUN8I_CODEC_AIF1) in sun8i_codec_startup()
423 if (!scodec->sysclk_refcnt) in sun8i_codec_startup()
425 else if (scodec->sysclk_rate == 22579200) in sun8i_codec_startup()
427 else if (scodec->sysclk_rate == 24576000) in sun8i_codec_startup()
430 return -EINVAL; in sun8i_codec_startup()
432 return snd_pcm_hw_constraint_list(substream->runtime, 0, in sun8i_codec_startup()
468 if (bdiv->div == div) in sun8i_codec_get_bclk_div()
469 return bdiv->val; in sun8i_codec_get_bclk_div()
472 return -EINVAL; in sun8i_codec_get_bclk_div()
481 return -EINVAL; in sun8i_codec_get_lrck_div_order()
496 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_hw_params()
498 unsigned int slots = aif->slots ?: params_channels(params); in sun8i_codec_hw_params()
499 unsigned int slot_width = aif->slot_width ?: params_width(params); in sun8i_codec_hw_params()
519 return -EINVAL; in sun8i_codec_hw_params()
522 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), in sun8i_codec_hw_params()
531 if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) { in sun8i_codec_hw_params()
533 int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id; in sun8i_codec_hw_params()
534 const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner]; in sun8i_codec_hw_params()
537 if (partner_aif->open_streams && in sun8i_codec_hw_params()
538 (lrck_div_order != partner_aif->lrck_div_order || in sun8i_codec_hw_params()
539 sample_rate != partner_aif->sample_rate)) { in sun8i_codec_hw_params()
540 dev_err(dai->dev, in sun8i_codec_hw_params()
542 dai->name, partner_name); in sun8i_codec_hw_params()
543 return -EBUSY; in sun8i_codec_hw_params()
548 clk_reg = SUN8I_AIF_CLK_CTRL(dai->id); in sun8i_codec_hw_params()
551 regmap_update_bits(scodec->regmap, clk_reg, in sun8i_codec_hw_params()
553 (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV); in sun8i_codec_hw_params()
560 regmap_update_bits(scodec->regmap, clk_reg, in sun8i_codec_hw_params()
573 ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module, in sun8i_codec_hw_params()
575 if (ret == -EBUSY) in sun8i_codec_hw_params()
576 dev_err(dai->dev, in sun8i_codec_hw_params()
578 dai->name, sample_rate); in sun8i_codec_hw_params()
582 if (!aif->open_streams) in sun8i_codec_hw_params()
583 scodec->sysclk_refcnt++; in sun8i_codec_hw_params()
584 scodec->sysclk_rate = sysclk_rate; in sun8i_codec_hw_params()
586 aif->lrck_div_order = lrck_div_order; in sun8i_codec_hw_params()
587 aif->sample_rate = sample_rate; in sun8i_codec_hw_params()
588 aif->open_streams |= BIT(substream->stream); in sun8i_codec_hw_params()
597 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; in sun8i_codec_hw_free()
600 if (aif->open_streams != BIT(substream->stream)) in sun8i_codec_hw_free()
603 clk_rate_exclusive_put(scodec->clk_module); in sun8i_codec_hw_free()
604 scodec->sysclk_refcnt--; in sun8i_codec_hw_free()
605 aif->lrck_div_order = 0; in sun8i_codec_hw_free()
606 aif->sample_rate = 0; in sun8i_codec_hw_free()
609 aif->open_streams &= ~BIT(substream->stream); in sun8i_codec_hw_free()
623 .name = "sun8i-codec-aif1",
648 .name = "sun8i-codec-aif2",
673 .name = "sun8i-codec-aif3",
702 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); in sun8i_codec_aif_event()
704 struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1']; in sun8i_codec_aif_event()
705 int stream = w->id == snd_soc_dapm_aif_out; in sun8i_codec_aif_event()
708 aif->active_streams |= BIT(stream); in sun8i_codec_aif_event()
710 aif->active_streams &= ~BIT(stream); in sun8i_codec_aif_event()
736 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
749 SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",
753 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
757 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
761 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
765 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
772 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
776 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
780 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
784 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
835 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
864 SND_SOC_DAPM_SUPPLY("CLK ADC",
881 SND_SOC_DAPM_SUPPLY("RST ADC",
889 SND_SOC_DAPM_SUPPLY("ADC",
896 /* AIF "ADC" Outputs */
915 SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,
920 /* AIF "ADC" Mono/Stereo Muxes */
921 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,
923 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,
926 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,
928 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,
931 /* AIF "ADC" Output Muxes */
932 SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
935 /* AIF "ADC" Mixers */
953 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0,
955 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0,
958 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0,
960 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0,
987 /* ADC Inputs (connected to analog codec DAPM context) */
1027 { "AIF3 ADC", NULL, "RST AIF3" },
1030 { "CLK ADC", NULL, "SYSCLK" },
1031 { "RST ADC", NULL, "CLK ADC" },
1032 { "ADC", NULL, "RST ADC" },
1033 { "ADCL", NULL, "ADC" },
1034 { "ADCR", NULL, "ADC" },
1042 /* AIF "ADC" Output Routes */
1043 { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" },
1044 { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" },
1046 { "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" },
1047 { "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" },
1049 { "AIF3 ADC", NULL, "AIF3 ADC Source Capture Route" },
1051 /* AIF "ADC" Mono/Stereo Mux Routes */
1052 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" },
1053 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" },
1054 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1055 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1056 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1057 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1059 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" },
1060 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" },
1061 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" },
1062 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" },
1063 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" },
1064 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" },
1066 { "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" },
1067 { "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" },
1068 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1069 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1070 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1071 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1073 { "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" },
1074 { "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" },
1075 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" },
1076 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" },
1077 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" },
1078 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" },
1080 /* AIF "ADC" Output Mux Routes */
1081 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" },
1082 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" },
1084 /* AIF "ADC" Mixer Routes */
1085 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" },
1086 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" },
1087 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" },
1088 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" },
1090 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" },
1091 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" },
1092 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" },
1093 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" },
1095 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" },
1096 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" },
1097 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" },
1099 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" },
1100 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" },
1101 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" },
1103 /* AIF "DAC" Input Mux Routes */
1104 { "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" },
1106 { "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" },
1108 { "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" },
1109 { "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" },
1112 /* AIF "DAC" Mono/Stereo Mux Routes */
1113 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" },
1114 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" },
1115 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1116 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1117 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1118 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1120 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" },
1121 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" },
1122 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" },
1123 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" },
1124 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" },
1125 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" },
1127 { "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" },
1128 { "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" },
1129 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" },
1130 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" },
1131 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" },
1132 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" },
1134 { "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" },
1135 { "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" },
1136 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" },
1137 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" },
1138 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" },
1139 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" },
1146 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" },
1148 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" },
1150 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" },
1152 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" },
1156 /* Legacy ADC Inputs (connected to analog codec DAPM context) */
1157 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0),
1158 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0),
1166 /* Legacy ADC Routes */
1167 { "ADCL", NULL, "AIF1 Slot 0 Left ADC" },
1168 { "ADCR", NULL, "AIF1 Slot 0 Right ADC" },
1182 if (scodec->quirks->legacy_widgets) { in sun8i_codec_component_probe()
1200 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, in sun8i_codec_component_probe()
1207 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, in sun8i_codec_component_probe()
1243 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL); in sun8i_codec_probe()
1245 return -ENOMEM; in sun8i_codec_probe()
1247 scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); in sun8i_codec_probe()
1248 if (IS_ERR(scodec->clk_module)) { in sun8i_codec_probe()
1249 dev_err(&pdev->dev, "Failed to get the module clock\n"); in sun8i_codec_probe()
1250 return PTR_ERR(scodec->clk_module); in sun8i_codec_probe()
1255 dev_err(&pdev->dev, "Failed to map the registers\n"); in sun8i_codec_probe()
1259 scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, in sun8i_codec_probe()
1261 if (IS_ERR(scodec->regmap)) { in sun8i_codec_probe()
1262 dev_err(&pdev->dev, "Failed to create our regmap\n"); in sun8i_codec_probe()
1263 return PTR_ERR(scodec->regmap); in sun8i_codec_probe()
1266 scodec->quirks = of_device_get_match_data(&pdev->dev); in sun8i_codec_probe()
1270 pm_runtime_enable(&pdev->dev); in sun8i_codec_probe()
1271 if (!pm_runtime_enabled(&pdev->dev)) { in sun8i_codec_probe()
1272 ret = sun8i_codec_runtime_resume(&pdev->dev); in sun8i_codec_probe()
1277 ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component, in sun8i_codec_probe()
1281 dev_err(&pdev->dev, "Failed to register codec\n"); in sun8i_codec_probe()
1288 if (!pm_runtime_status_suspended(&pdev->dev)) in sun8i_codec_probe()
1289 sun8i_codec_runtime_suspend(&pdev->dev); in sun8i_codec_probe()
1292 pm_runtime_disable(&pdev->dev); in sun8i_codec_probe()
1299 pm_runtime_disable(&pdev->dev); in sun8i_codec_remove()
1300 if (!pm_runtime_status_suspended(&pdev->dev)) in sun8i_codec_remove()
1301 sun8i_codec_runtime_suspend(&pdev->dev); in sun8i_codec_remove()
1315 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },
1316 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },
1328 .name = "sun8i-codec",
1338 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
1340 MODULE_ALIAS("platform:sun8i-codec");