0001
0002
0003
0004
0005
0006
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
0032 AUD_PCM_ONE_BCK_CYCLE_SYNC = 0,
0033
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
0044 AUD_PCM_AFIFO_ASRC = 0,
0045
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
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
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
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
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 }