Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // MediaTek ALSA SoC Audio DAI I2S Control
0004 //
0005 // Copyright (c) 2020 MediaTek Inc.
0006 // Author: Shane Chien <shane.chien@mediatek.com>
0007 //
0008 
0009 #include <linux/regmap.h>
0010 #include <sound/pcm_params.h>
0011 
0012 #include "mt8192-afe-common.h"
0013 #include "mt8192-interconnection.h"
0014 
0015 enum AUD_TX_LCH_RPT {
0016     AUD_TX_LCH_RPT_NO_REPEAT = 0,
0017     AUD_TX_LCH_RPT_REPEAT = 1
0018 };
0019 
0020 enum AUD_VBT_16K_MODE {
0021     AUD_VBT_16K_MODE_DISABLE = 0,
0022     AUD_VBT_16K_MODE_ENABLE = 1
0023 };
0024 
0025 enum AUD_EXT_MODEM {
0026     AUD_EXT_MODEM_SELECT_INTERNAL = 0,
0027     AUD_EXT_MODEM_SELECT_EXTERNAL = 1
0028 };
0029 
0030 enum AUD_PCM_SYNC_TYPE {
0031     /* bck sync length = 1 */
0032     AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
0033     /* bck sync length = PCM_INTF_CON1[9:13] */
0034     AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1
0035 };
0036 
0037 enum AUD_BT_MODE {
0038     AUD_BT_MODE_DUAL_MIC_ON_TX = 0,
0039     AUD_BT_MODE_SINGLE_MIC_ON_TX = 1
0040 };
0041 
0042 enum AUD_PCM_AFIFO_SRC {
0043     /* slave mode & external modem uses different crystal */
0044     AUD_PCM_AFIFO_ASRC = 0,
0045     /* slave mode & external modem uses the same crystal */
0046     AUD_PCM_AFIFO_AFIFO = 1
0047 };
0048 
0049 enum AUD_PCM_CLOCK_SOURCE {
0050     AUD_PCM_CLOCK_MASTER_MODE = 0,
0051     AUD_PCM_CLOCK_SLAVE_MODE = 1
0052 };
0053 
0054 enum AUD_PCM_WLEN {
0055     AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0,
0056     AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1
0057 };
0058 
0059 enum AUD_PCM_MODE {
0060     AUD_PCM_MODE_PCM_MODE_8K = 0,
0061     AUD_PCM_MODE_PCM_MODE_16K = 1,
0062     AUD_PCM_MODE_PCM_MODE_32K = 2,
0063     AUD_PCM_MODE_PCM_MODE_48K = 3,
0064 };
0065 
0066 enum AUD_PCM_FMT {
0067     AUD_PCM_FMT_I2S = 0,
0068     AUD_PCM_FMT_EIAJ = 1,
0069     AUD_PCM_FMT_PCM_MODE_A = 2,
0070     AUD_PCM_FMT_PCM_MODE_B = 3
0071 };
0072 
0073 enum AUD_BCLK_OUT_INV {
0074     AUD_BCLK_OUT_INV_NO_INVERSE = 0,
0075     AUD_BCLK_OUT_INV_INVERSE = 1
0076 };
0077 
0078 enum AUD_PCM_EN {
0079     AUD_PCM_EN_DISABLE = 0,
0080     AUD_PCM_EN_ENABLE = 1
0081 };
0082 
0083 /* dai component */
0084 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = {
0085     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN7,
0086                     I_ADDA_UL_CH1, 1, 0),
0087     SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN7,
0088                     I_DL2_CH1, 1, 0),
0089     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN7_1,
0090                     I_DL4_CH1, 1, 0),
0091 };
0092 
0093 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = {
0094     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN8,
0095                     I_ADDA_UL_CH2, 1, 0),
0096     SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN8,
0097                     I_DL2_CH2, 1, 0),
0098     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN8_1,
0099                     I_DL4_CH2, 1, 0),
0100 };
0101 
0102 static const struct snd_kcontrol_new mtk_pcm_1_playback_ch4_mix[] = {
0103     SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN27,
0104                     I_I2S0_CH1, 1, 0),
0105     SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN27,
0106                     I_I2S0_CH2, 1, 0),
0107     SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN27,
0108                     I_DL1_CH1, 1, 0),
0109     SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN27,
0110                     I_I2S2_CH1, 1, 0),
0111     SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN27,
0112                     I_I2S2_CH2, 1, 0),
0113     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN27_1,
0114                     I_DL4_CH1, 1, 0),
0115 };
0116 
0117 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch1_mix[] = {
0118     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN17,
0119                     I_ADDA_UL_CH1, 1, 0),
0120     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN17,
0121                     I_ADDA_UL_CH2, 1, 0),
0122     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN17,
0123                     I_ADDA_UL_CH3, 1, 0),
0124     SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN17,
0125                     I_DL2_CH1, 1, 0),
0126     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN17_1,
0127                     I_DL4_CH1, 1, 0),
0128 };
0129 
0130 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch2_mix[] = {
0131     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN18,
0132                     I_ADDA_UL_CH1, 1, 0),
0133     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN18,
0134                     I_ADDA_UL_CH2, 1, 0),
0135     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN18,
0136                     I_ADDA_UL_CH3, 1, 0),
0137     SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN18,
0138                     I_DL2_CH2, 1, 0),
0139     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN18_1,
0140                     I_DL4_CH2, 1, 0),
0141 };
0142 
0143 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch3_mix[] = {
0144     SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN23,
0145                     I_ADDA_UL_CH3, 1, 0),
0146 };
0147 
0148 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch4_mix[] = {
0149     SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1", AFE_CONN24,
0150                     I_I2S0_CH1, 1, 0),
0151     SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN24,
0152                     I_I2S0_CH2, 1, 0),
0153     SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN24,
0154                     I_DL1_CH1, 1, 0),
0155     SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH1", AFE_CONN24,
0156                     I_I2S2_CH1, 1, 0),
0157     SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN24,
0158                     I_I2S2_CH2, 1, 0),
0159     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN24_1,
0160                     I_DL4_CH1, 1, 0),
0161 };
0162 
0163 static const struct snd_kcontrol_new mtk_pcm_2_playback_ch5_mix[] = {
0164     SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2", AFE_CONN25,
0165                     I_I2S0_CH2, 1, 0),
0166     SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN25,
0167                     I_DL1_CH2, 1, 0),
0168     SOC_DAPM_SINGLE_AUTODISABLE("I2S2_CH2", AFE_CONN25,
0169                     I_I2S2_CH2, 1, 0),
0170     SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN25_1,
0171                     I_DL4_CH2, 1, 0),
0172 };
0173 
0174 static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w,
0175                 struct snd_kcontrol *kcontrol,
0176                 int event)
0177 {
0178     struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0179     struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0180 
0181     dev_info(afe->dev, "%s(), name %s, event 0x%x\n",
0182          __func__, w->name, event);
0183     return 0;
0184 }
0185 
0186 static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = {
0187     /* inter-connections */
0188     SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0,
0189                mtk_pcm_1_playback_ch1_mix,
0190                ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)),
0191     SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0,
0192                mtk_pcm_1_playback_ch2_mix,
0193                ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)),
0194     SND_SOC_DAPM_MIXER("PCM_1_PB_CH4", SND_SOC_NOPM, 0, 0,
0195                mtk_pcm_1_playback_ch4_mix,
0196                ARRAY_SIZE(mtk_pcm_1_playback_ch4_mix)),
0197     SND_SOC_DAPM_MIXER("PCM_2_PB_CH1", SND_SOC_NOPM, 0, 0,
0198                mtk_pcm_2_playback_ch1_mix,
0199                ARRAY_SIZE(mtk_pcm_2_playback_ch1_mix)),
0200     SND_SOC_DAPM_MIXER("PCM_2_PB_CH2", SND_SOC_NOPM, 0, 0,
0201                mtk_pcm_2_playback_ch2_mix,
0202                ARRAY_SIZE(mtk_pcm_2_playback_ch2_mix)),
0203     SND_SOC_DAPM_MIXER("PCM_2_PB_CH3", SND_SOC_NOPM, 0, 0,
0204                mtk_pcm_2_playback_ch3_mix,
0205                ARRAY_SIZE(mtk_pcm_2_playback_ch3_mix)),
0206     SND_SOC_DAPM_MIXER("PCM_2_PB_CH4", SND_SOC_NOPM, 0, 0,
0207                mtk_pcm_2_playback_ch4_mix,
0208                ARRAY_SIZE(mtk_pcm_2_playback_ch4_mix)),
0209     SND_SOC_DAPM_MIXER("PCM_2_PB_CH5", SND_SOC_NOPM, 0, 0,
0210                mtk_pcm_2_playback_ch5_mix,
0211                ARRAY_SIZE(mtk_pcm_2_playback_ch5_mix)),
0212 
0213     SND_SOC_DAPM_SUPPLY("PCM_1_EN",
0214                 PCM_INTF_CON1, PCM_EN_SFT, 0,
0215                 mtk_pcm_en_event,
0216                 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0217 
0218     SND_SOC_DAPM_SUPPLY("PCM_2_EN",
0219                 PCM2_INTF_CON, PCM2_EN_SFT, 0,
0220                 mtk_pcm_en_event,
0221                 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0222 
0223     SND_SOC_DAPM_INPUT("MD1_TO_AFE"),
0224     SND_SOC_DAPM_INPUT("MD2_TO_AFE"),
0225     SND_SOC_DAPM_OUTPUT("AFE_TO_MD1"),
0226     SND_SOC_DAPM_OUTPUT("AFE_TO_MD2"),
0227 };
0228 
0229 static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = {
0230     {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"},
0231     {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"},
0232     {"PCM 1 Playback", NULL, "PCM_1_PB_CH4"},
0233     {"PCM 2 Playback", NULL, "PCM_2_PB_CH1"},
0234     {"PCM 2 Playback", NULL, "PCM_2_PB_CH2"},
0235     {"PCM 2 Playback", NULL, "PCM_2_PB_CH3"},
0236     {"PCM 2 Playback", NULL, "PCM_2_PB_CH4"},
0237     {"PCM 2 Playback", NULL, "PCM_2_PB_CH5"},
0238 
0239     {"PCM 1 Playback", NULL, "PCM_1_EN"},
0240     {"PCM 2 Playback", NULL, "PCM_2_EN"},
0241     {"PCM 1 Capture", NULL, "PCM_1_EN"},
0242     {"PCM 2 Capture", NULL, "PCM_2_EN"},
0243 
0244     {"AFE_TO_MD1", NULL, "PCM 2 Playback"},
0245     {"AFE_TO_MD2", NULL, "PCM 1 Playback"},
0246     {"PCM 2 Capture", NULL, "MD1_TO_AFE"},
0247     {"PCM 1 Capture", NULL, "MD2_TO_AFE"},
0248 
0249     {"PCM_1_PB_CH1", "DL2_CH1", "DL2"},
0250     {"PCM_1_PB_CH2", "DL2_CH2", "DL2"},
0251     {"PCM_1_PB_CH4", "DL1_CH1", "DL1"},
0252     {"PCM_2_PB_CH1", "DL2_CH1", "DL2"},
0253     {"PCM_2_PB_CH2", "DL2_CH2", "DL2"},
0254     {"PCM_2_PB_CH4", "DL1_CH1", "DL1"},
0255 
0256     {"PCM_1_PB_CH1", "DL4_CH1", "DL4"},
0257     {"PCM_1_PB_CH2", "DL4_CH2", "DL4"},
0258     {"PCM_1_PB_CH4", "DL4_CH1", "DL4"},
0259     {"PCM_2_PB_CH1", "DL4_CH1", "DL4"},
0260     {"PCM_2_PB_CH2", "DL4_CH2", "DL4"},
0261     {"PCM_2_PB_CH4", "DL4_CH1", "DL4"},
0262     {"PCM_1_PB_CH4", "I2S0_CH1", "I2S0"},
0263     {"PCM_2_PB_CH4", "I2S2_CH1", "I2S2"},
0264     {"PCM_2_PB_CH5", "DL1_CH2", "DL1"},
0265     {"PCM_2_PB_CH5", "DL4_CH2", "DL4"},
0266     {"PCM_2_PB_CH5", "I2S0_CH2", "I2S0"},
0267     {"PCM_2_PB_CH5", "I2S2_CH2", "I2S2"},
0268 };
0269 
0270 /* dai ops */
0271 static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream,
0272                  struct snd_pcm_hw_params *params,
0273                  struct snd_soc_dai *dai)
0274 {
0275     struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
0276     unsigned int rate = params_rate(params);
0277     unsigned int rate_reg = mt8192_rate_transform(afe->dev, rate, dai->id);
0278     unsigned int pcm_con = 0;
0279 
0280     dev_info(afe->dev, "%s(), id %d, stream %d, rate %d, rate_reg %d, widget active p %d, c %d\n",
0281          __func__,
0282          dai->id,
0283          substream->stream,
0284          rate,
0285          rate_reg,
0286          dai->playback_widget->active,
0287          dai->capture_widget->active);
0288 
0289     if (dai->playback_widget->active || dai->capture_widget->active)
0290         return 0;
0291 
0292     switch (dai->id) {
0293     case MT8192_DAI_PCM_1:
0294         pcm_con |= AUD_BCLK_OUT_INV_NO_INVERSE << PCM_BCLK_OUT_INV_SFT;
0295         pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT;
0296         pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT;
0297         pcm_con |= AUD_EXT_MODEM_SELECT_INTERNAL << PCM_EXT_MODEM_SFT;
0298         pcm_con |= 0 << PCM_SYNC_LENGTH_SFT;
0299         pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT;
0300         pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT;
0301         pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT;
0302         pcm_con |= AUD_PCM_CLOCK_SLAVE_MODE << PCM_SLAVE_SFT;
0303         pcm_con |= rate_reg << PCM_MODE_SFT;
0304         pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM_FMT_SFT;
0305 
0306         regmap_update_bits(afe->regmap, PCM_INTF_CON1,
0307                    0xfffffffe, pcm_con);
0308         break;
0309     case MT8192_DAI_PCM_2:
0310         pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM2_TX_LCH_RPT_SFT;
0311         pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM2_VBT_16K_MODE_SFT;
0312         pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM2_BT_MODE_SFT;
0313         pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM2_AFIFO_SFT;
0314         pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM2_WLEN_SFT;
0315         pcm_con |= rate_reg << PCM2_MODE_SFT;
0316         pcm_con |= AUD_PCM_FMT_PCM_MODE_B << PCM2_FMT_SFT;
0317 
0318         regmap_update_bits(afe->regmap, PCM2_INTF_CON,
0319                    0xfffffffe, pcm_con);
0320         break;
0321     default:
0322         dev_warn(afe->dev, "%s(), id %d not support\n",
0323              __func__, dai->id);
0324         return -EINVAL;
0325     }
0326 
0327     return 0;
0328 }
0329 
0330 static const struct snd_soc_dai_ops mtk_dai_pcm_ops = {
0331     .hw_params = mtk_dai_pcm_hw_params,
0332 };
0333 
0334 /* dai driver */
0335 #define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\
0336                SNDRV_PCM_RATE_16000 |\
0337                SNDRV_PCM_RATE_32000 |\
0338                SNDRV_PCM_RATE_48000)
0339 
0340 #define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
0341              SNDRV_PCM_FMTBIT_S24_LE |\
0342              SNDRV_PCM_FMTBIT_S32_LE)
0343 
0344 static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = {
0345     {
0346         .name = "PCM 1",
0347         .id = MT8192_DAI_PCM_1,
0348         .playback = {
0349             .stream_name = "PCM 1 Playback",
0350             .channels_min = 1,
0351             .channels_max = 2,
0352             .rates = MTK_PCM_RATES,
0353             .formats = MTK_PCM_FORMATS,
0354         },
0355         .capture = {
0356             .stream_name = "PCM 1 Capture",
0357             .channels_min = 1,
0358             .channels_max = 2,
0359             .rates = MTK_PCM_RATES,
0360             .formats = MTK_PCM_FORMATS,
0361         },
0362         .ops = &mtk_dai_pcm_ops,
0363         .symmetric_rate = 1,
0364         .symmetric_sample_bits = 1,
0365     },
0366     {
0367         .name = "PCM 2",
0368         .id = MT8192_DAI_PCM_2,
0369         .playback = {
0370             .stream_name = "PCM 2 Playback",
0371             .channels_min = 1,
0372             .channels_max = 2,
0373             .rates = MTK_PCM_RATES,
0374             .formats = MTK_PCM_FORMATS,
0375         },
0376         .capture = {
0377             .stream_name = "PCM 2 Capture",
0378             .channels_min = 1,
0379             .channels_max = 2,
0380             .rates = MTK_PCM_RATES,
0381             .formats = MTK_PCM_FORMATS,
0382         },
0383         .ops = &mtk_dai_pcm_ops,
0384         .symmetric_rate = 1,
0385         .symmetric_sample_bits = 1,
0386     },
0387 };
0388 
0389 int mt8192_dai_pcm_register(struct mtk_base_afe *afe)
0390 {
0391     struct mtk_base_afe_dai *dai;
0392 
0393     dev_info(afe->dev, "%s()\n", __func__);
0394 
0395     dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
0396     if (!dai)
0397         return -ENOMEM;
0398 
0399     list_add(&dai->list, &afe->sub_dais);
0400 
0401     dai->dai_drivers = mtk_dai_pcm_driver;
0402     dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver);
0403 
0404     dai->dapm_widgets = mtk_dai_pcm_widgets;
0405     dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets);
0406     dai->dapm_routes = mtk_dai_pcm_routes;
0407     dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes);
0408     return 0;
0409 }