0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/regmap.h>
0009 #include <sound/pcm_params.h>
0010
0011 #include "mt8192-afe-clk.h"
0012 #include "mt8192-afe-common.h"
0013 #include "mt8192-afe-gpio.h"
0014 #include "mt8192-interconnection.h"
0015
0016 struct mtk_afe_tdm_priv {
0017 int id;
0018 int bck_id;
0019 int bck_rate;
0020 int tdm_out_mode;
0021 int bck_invert;
0022 int lck_invert;
0023 int mclk_id;
0024 int mclk_multiple;
0025 int mclk_rate;
0026 int mclk_apll;
0027 };
0028
0029 enum {
0030 TDM_OUT_I2S = 0,
0031 TDM_OUT_DSP_A = 1,
0032 TDM_OUT_DSP_B = 2,
0033 };
0034
0035 enum {
0036 TDM_BCK_NON_INV = 0,
0037 TDM_BCK_INV = 1,
0038 };
0039
0040 enum {
0041 TDM_LCK_NON_INV = 0,
0042 TDM_LCK_INV = 1,
0043 };
0044
0045 enum {
0046 TDM_WLEN_16_BIT = 1,
0047 TDM_WLEN_32_BIT = 2,
0048 };
0049
0050 enum {
0051 TDM_CHANNEL_BCK_16 = 0,
0052 TDM_CHANNEL_BCK_24 = 1,
0053 TDM_CHANNEL_BCK_32 = 2,
0054 };
0055
0056 enum {
0057 TDM_CHANNEL_NUM_2 = 0,
0058 TDM_CHANNEL_NUM_4 = 1,
0059 TDM_CHANNEL_NUM_8 = 2,
0060 };
0061
0062 enum {
0063 TDM_CH_START_O30_O31 = 0,
0064 TDM_CH_START_O32_O33,
0065 TDM_CH_START_O34_O35,
0066 TDM_CH_START_O36_O37,
0067 TDM_CH_ZERO,
0068 };
0069
0070 static unsigned int get_tdm_wlen(snd_pcm_format_t format)
0071 {
0072 return snd_pcm_format_physical_width(format) <= 16 ?
0073 TDM_WLEN_16_BIT : TDM_WLEN_32_BIT;
0074 }
0075
0076 static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
0077 {
0078 return snd_pcm_format_physical_width(format) <= 16 ?
0079 TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
0080 }
0081
0082 static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
0083 {
0084 return snd_pcm_format_physical_width(format) - 1;
0085 }
0086
0087 static unsigned int get_tdm_ch(unsigned int ch)
0088 {
0089 switch (ch) {
0090 case 1:
0091 case 2:
0092 return TDM_CHANNEL_NUM_2;
0093 case 3:
0094 case 4:
0095 return TDM_CHANNEL_NUM_4;
0096 case 5:
0097 case 6:
0098 case 7:
0099 case 8:
0100 default:
0101 return TDM_CHANNEL_NUM_8;
0102 }
0103 }
0104
0105 static unsigned int get_tdm_ch_fixup(unsigned int channels)
0106 {
0107 if (channels > 4)
0108 return 8;
0109 else if (channels > 2)
0110 return 4;
0111 else
0112 return 2;
0113 }
0114
0115 static unsigned int get_tdm_ch_per_sdata(unsigned int mode,
0116 unsigned int channels)
0117 {
0118 if (mode == TDM_OUT_DSP_A || mode == TDM_OUT_DSP_B)
0119 return get_tdm_ch_fixup(channels);
0120 else
0121 return 2;
0122 }
0123
0124
0125 enum {
0126 HDMI_CONN_CH0 = 0,
0127 HDMI_CONN_CH1,
0128 HDMI_CONN_CH2,
0129 HDMI_CONN_CH3,
0130 HDMI_CONN_CH4,
0131 HDMI_CONN_CH5,
0132 HDMI_CONN_CH6,
0133 HDMI_CONN_CH7,
0134 };
0135
0136 static const char *const hdmi_conn_mux_map[] = {
0137 "CH0", "CH1", "CH2", "CH3",
0138 "CH4", "CH5", "CH6", "CH7",
0139 };
0140
0141 static int hdmi_conn_mux_map_value[] = {
0142 HDMI_CONN_CH0,
0143 HDMI_CONN_CH1,
0144 HDMI_CONN_CH2,
0145 HDMI_CONN_CH3,
0146 HDMI_CONN_CH4,
0147 HDMI_CONN_CH5,
0148 HDMI_CONN_CH6,
0149 HDMI_CONN_CH7,
0150 };
0151
0152 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
0153 AFE_HDMI_CONN0,
0154 HDMI_O_0_SFT,
0155 HDMI_O_0_MASK,
0156 hdmi_conn_mux_map,
0157 hdmi_conn_mux_map_value);
0158
0159 static const struct snd_kcontrol_new hdmi_ch0_mux_control =
0160 SOC_DAPM_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum);
0161
0162 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
0163 AFE_HDMI_CONN0,
0164 HDMI_O_1_SFT,
0165 HDMI_O_1_MASK,
0166 hdmi_conn_mux_map,
0167 hdmi_conn_mux_map_value);
0168
0169 static const struct snd_kcontrol_new hdmi_ch1_mux_control =
0170 SOC_DAPM_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum);
0171
0172 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
0173 AFE_HDMI_CONN0,
0174 HDMI_O_2_SFT,
0175 HDMI_O_2_MASK,
0176 hdmi_conn_mux_map,
0177 hdmi_conn_mux_map_value);
0178
0179 static const struct snd_kcontrol_new hdmi_ch2_mux_control =
0180 SOC_DAPM_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum);
0181
0182 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
0183 AFE_HDMI_CONN0,
0184 HDMI_O_3_SFT,
0185 HDMI_O_3_MASK,
0186 hdmi_conn_mux_map,
0187 hdmi_conn_mux_map_value);
0188
0189 static const struct snd_kcontrol_new hdmi_ch3_mux_control =
0190 SOC_DAPM_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum);
0191
0192 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
0193 AFE_HDMI_CONN0,
0194 HDMI_O_4_SFT,
0195 HDMI_O_4_MASK,
0196 hdmi_conn_mux_map,
0197 hdmi_conn_mux_map_value);
0198
0199 static const struct snd_kcontrol_new hdmi_ch4_mux_control =
0200 SOC_DAPM_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum);
0201
0202 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
0203 AFE_HDMI_CONN0,
0204 HDMI_O_5_SFT,
0205 HDMI_O_5_MASK,
0206 hdmi_conn_mux_map,
0207 hdmi_conn_mux_map_value);
0208
0209 static const struct snd_kcontrol_new hdmi_ch5_mux_control =
0210 SOC_DAPM_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum);
0211
0212 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
0213 AFE_HDMI_CONN0,
0214 HDMI_O_6_SFT,
0215 HDMI_O_6_MASK,
0216 hdmi_conn_mux_map,
0217 hdmi_conn_mux_map_value);
0218
0219 static const struct snd_kcontrol_new hdmi_ch6_mux_control =
0220 SOC_DAPM_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum);
0221
0222 static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
0223 AFE_HDMI_CONN0,
0224 HDMI_O_7_SFT,
0225 HDMI_O_7_MASK,
0226 hdmi_conn_mux_map,
0227 hdmi_conn_mux_map_value);
0228
0229 static const struct snd_kcontrol_new hdmi_ch7_mux_control =
0230 SOC_DAPM_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum);
0231
0232 enum {
0233 SUPPLY_SEQ_APLL,
0234 SUPPLY_SEQ_TDM_MCK_EN,
0235 SUPPLY_SEQ_TDM_BCK_EN,
0236 SUPPLY_SEQ_TDM_EN,
0237 };
0238
0239 static int get_tdm_id_by_name(const char *name)
0240 {
0241 return MT8192_DAI_TDM;
0242 }
0243
0244 static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w,
0245 struct snd_kcontrol *kcontrol,
0246 int event)
0247 {
0248 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0249 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0250 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0251 int dai_id = get_tdm_id_by_name(w->name);
0252 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
0253
0254 if (!tdm_priv) {
0255 dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
0256 return -EINVAL;
0257 }
0258
0259 dev_info(cmpnt->dev, "%s(), name %s, event 0x%x\n",
0260 __func__, w->name, event);
0261
0262 switch (event) {
0263 case SND_SOC_DAPM_PRE_PMU:
0264 mt8192_afe_gpio_request(afe->dev, true, tdm_priv->id, 0);
0265 break;
0266 case SND_SOC_DAPM_POST_PMD:
0267 mt8192_afe_gpio_request(afe->dev, false, tdm_priv->id, 0);
0268 break;
0269 default:
0270 break;
0271 }
0272
0273 return 0;
0274 }
0275
0276 static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
0277 struct snd_kcontrol *kcontrol,
0278 int event)
0279 {
0280 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0281 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0282 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0283 int dai_id = get_tdm_id_by_name(w->name);
0284 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
0285
0286 if (!tdm_priv) {
0287 dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
0288 return -EINVAL;
0289 }
0290
0291 dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
0292 __func__, w->name, event, dai_id);
0293
0294 switch (event) {
0295 case SND_SOC_DAPM_PRE_PMU:
0296 mt8192_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
0297 break;
0298 case SND_SOC_DAPM_POST_PMD:
0299 mt8192_mck_disable(afe, tdm_priv->bck_id);
0300 break;
0301 default:
0302 break;
0303 }
0304
0305 return 0;
0306 }
0307
0308 static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
0309 struct snd_kcontrol *kcontrol,
0310 int event)
0311 {
0312 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0313 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0314 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0315 int dai_id = get_tdm_id_by_name(w->name);
0316 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
0317
0318 if (!tdm_priv) {
0319 dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
0320 return -EINVAL;
0321 }
0322
0323 dev_info(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n",
0324 __func__, w->name, event, dai_id);
0325
0326 switch (event) {
0327 case SND_SOC_DAPM_PRE_PMU:
0328 mt8192_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
0329 break;
0330 case SND_SOC_DAPM_POST_PMD:
0331 tdm_priv->mclk_rate = 0;
0332 mt8192_mck_disable(afe, tdm_priv->mclk_id);
0333 break;
0334 default:
0335 break;
0336 }
0337
0338 return 0;
0339 }
0340
0341 static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
0342 SND_SOC_DAPM_MUX("HDMI_CH0_MUX", SND_SOC_NOPM, 0, 0,
0343 &hdmi_ch0_mux_control),
0344 SND_SOC_DAPM_MUX("HDMI_CH1_MUX", SND_SOC_NOPM, 0, 0,
0345 &hdmi_ch1_mux_control),
0346 SND_SOC_DAPM_MUX("HDMI_CH2_MUX", SND_SOC_NOPM, 0, 0,
0347 &hdmi_ch2_mux_control),
0348 SND_SOC_DAPM_MUX("HDMI_CH3_MUX", SND_SOC_NOPM, 0, 0,
0349 &hdmi_ch3_mux_control),
0350 SND_SOC_DAPM_MUX("HDMI_CH4_MUX", SND_SOC_NOPM, 0, 0,
0351 &hdmi_ch4_mux_control),
0352 SND_SOC_DAPM_MUX("HDMI_CH5_MUX", SND_SOC_NOPM, 0, 0,
0353 &hdmi_ch5_mux_control),
0354 SND_SOC_DAPM_MUX("HDMI_CH6_MUX", SND_SOC_NOPM, 0, 0,
0355 &hdmi_ch6_mux_control),
0356 SND_SOC_DAPM_MUX("HDMI_CH7_MUX", SND_SOC_NOPM, 0, 0,
0357 &hdmi_ch7_mux_control),
0358
0359 SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"),
0360
0361 SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN,
0362 AFE_TDM_CON1, TDM_EN_SFT, 0,
0363 mtk_tdm_en_event,
0364 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0365
0366 SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
0367 SND_SOC_NOPM, 0, 0,
0368 mtk_tdm_bck_en_event,
0369 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0370
0371 SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
0372 SND_SOC_NOPM, 0, 0,
0373 mtk_tdm_mck_en_event,
0374 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0375 };
0376
0377 static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
0378 struct snd_soc_dapm_widget *sink)
0379 {
0380 struct snd_soc_dapm_widget *w = sink;
0381 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
0382 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
0383 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0384 int dai_id = get_tdm_id_by_name(w->name);
0385 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
0386 int cur_apll;
0387
0388
0389 cur_apll = mt8192_get_apll_by_name(afe, source->name);
0390
0391 return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
0392 }
0393
0394 static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
0395 {"HDMI_CH0_MUX", "CH0", "HDMI"},
0396 {"HDMI_CH0_MUX", "CH1", "HDMI"},
0397 {"HDMI_CH0_MUX", "CH2", "HDMI"},
0398 {"HDMI_CH0_MUX", "CH3", "HDMI"},
0399 {"HDMI_CH0_MUX", "CH4", "HDMI"},
0400 {"HDMI_CH0_MUX", "CH5", "HDMI"},
0401 {"HDMI_CH0_MUX", "CH6", "HDMI"},
0402 {"HDMI_CH0_MUX", "CH7", "HDMI"},
0403
0404 {"HDMI_CH1_MUX", "CH0", "HDMI"},
0405 {"HDMI_CH1_MUX", "CH1", "HDMI"},
0406 {"HDMI_CH1_MUX", "CH2", "HDMI"},
0407 {"HDMI_CH1_MUX", "CH3", "HDMI"},
0408 {"HDMI_CH1_MUX", "CH4", "HDMI"},
0409 {"HDMI_CH1_MUX", "CH5", "HDMI"},
0410 {"HDMI_CH1_MUX", "CH6", "HDMI"},
0411 {"HDMI_CH1_MUX", "CH7", "HDMI"},
0412
0413 {"HDMI_CH2_MUX", "CH0", "HDMI"},
0414 {"HDMI_CH2_MUX", "CH1", "HDMI"},
0415 {"HDMI_CH2_MUX", "CH2", "HDMI"},
0416 {"HDMI_CH2_MUX", "CH3", "HDMI"},
0417 {"HDMI_CH2_MUX", "CH4", "HDMI"},
0418 {"HDMI_CH2_MUX", "CH5", "HDMI"},
0419 {"HDMI_CH2_MUX", "CH6", "HDMI"},
0420 {"HDMI_CH2_MUX", "CH7", "HDMI"},
0421
0422 {"HDMI_CH3_MUX", "CH0", "HDMI"},
0423 {"HDMI_CH3_MUX", "CH1", "HDMI"},
0424 {"HDMI_CH3_MUX", "CH2", "HDMI"},
0425 {"HDMI_CH3_MUX", "CH3", "HDMI"},
0426 {"HDMI_CH3_MUX", "CH4", "HDMI"},
0427 {"HDMI_CH3_MUX", "CH5", "HDMI"},
0428 {"HDMI_CH3_MUX", "CH6", "HDMI"},
0429 {"HDMI_CH3_MUX", "CH7", "HDMI"},
0430
0431 {"HDMI_CH4_MUX", "CH0", "HDMI"},
0432 {"HDMI_CH4_MUX", "CH1", "HDMI"},
0433 {"HDMI_CH4_MUX", "CH2", "HDMI"},
0434 {"HDMI_CH4_MUX", "CH3", "HDMI"},
0435 {"HDMI_CH4_MUX", "CH4", "HDMI"},
0436 {"HDMI_CH4_MUX", "CH5", "HDMI"},
0437 {"HDMI_CH4_MUX", "CH6", "HDMI"},
0438 {"HDMI_CH4_MUX", "CH7", "HDMI"},
0439
0440 {"HDMI_CH5_MUX", "CH0", "HDMI"},
0441 {"HDMI_CH5_MUX", "CH1", "HDMI"},
0442 {"HDMI_CH5_MUX", "CH2", "HDMI"},
0443 {"HDMI_CH5_MUX", "CH3", "HDMI"},
0444 {"HDMI_CH5_MUX", "CH4", "HDMI"},
0445 {"HDMI_CH5_MUX", "CH5", "HDMI"},
0446 {"HDMI_CH5_MUX", "CH6", "HDMI"},
0447 {"HDMI_CH5_MUX", "CH7", "HDMI"},
0448
0449 {"HDMI_CH6_MUX", "CH0", "HDMI"},
0450 {"HDMI_CH6_MUX", "CH1", "HDMI"},
0451 {"HDMI_CH6_MUX", "CH2", "HDMI"},
0452 {"HDMI_CH6_MUX", "CH3", "HDMI"},
0453 {"HDMI_CH6_MUX", "CH4", "HDMI"},
0454 {"HDMI_CH6_MUX", "CH5", "HDMI"},
0455 {"HDMI_CH6_MUX", "CH6", "HDMI"},
0456 {"HDMI_CH6_MUX", "CH7", "HDMI"},
0457
0458 {"HDMI_CH7_MUX", "CH0", "HDMI"},
0459 {"HDMI_CH7_MUX", "CH1", "HDMI"},
0460 {"HDMI_CH7_MUX", "CH2", "HDMI"},
0461 {"HDMI_CH7_MUX", "CH3", "HDMI"},
0462 {"HDMI_CH7_MUX", "CH4", "HDMI"},
0463 {"HDMI_CH7_MUX", "CH5", "HDMI"},
0464 {"HDMI_CH7_MUX", "CH6", "HDMI"},
0465 {"HDMI_CH7_MUX", "CH7", "HDMI"},
0466
0467 {"TDM", NULL, "HDMI_CH0_MUX"},
0468 {"TDM", NULL, "HDMI_CH1_MUX"},
0469 {"TDM", NULL, "HDMI_CH2_MUX"},
0470 {"TDM", NULL, "HDMI_CH3_MUX"},
0471 {"TDM", NULL, "HDMI_CH4_MUX"},
0472 {"TDM", NULL, "HDMI_CH5_MUX"},
0473 {"TDM", NULL, "HDMI_CH6_MUX"},
0474 {"TDM", NULL, "HDMI_CH7_MUX"},
0475
0476 {"TDM", NULL, "aud_tdm_clk"},
0477 {"TDM", NULL, "TDM_BCK"},
0478 {"TDM", NULL, "TDM_EN"},
0479 {"TDM_BCK", NULL, "TDM_MCK"},
0480 {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
0481 {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
0482 };
0483
0484
0485 static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
0486 struct mtk_afe_tdm_priv *tdm_priv,
0487 int freq)
0488 {
0489 int apll;
0490 int apll_rate;
0491
0492 apll = mt8192_get_apll_by_rate(afe, freq);
0493 apll_rate = mt8192_get_apll_rate(afe, apll);
0494
0495 if (!freq || freq > apll_rate) {
0496 dev_warn(afe->dev,
0497 "%s(), freq(%d Hz) invalid\n", __func__, freq);
0498 return -EINVAL;
0499 }
0500
0501 if (apll_rate % freq != 0) {
0502 dev_warn(afe->dev,
0503 "%s(), APLL cannot generate %d Hz", __func__, freq);
0504 return -EINVAL;
0505 }
0506
0507 tdm_priv->mclk_rate = freq;
0508 tdm_priv->mclk_apll = apll;
0509
0510 return 0;
0511 }
0512
0513 static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
0514 struct snd_pcm_hw_params *params,
0515 struct snd_soc_dai *dai)
0516 {
0517 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
0518 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0519 int tdm_id = dai->id;
0520 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id];
0521 unsigned int tdm_out_mode = tdm_priv->tdm_out_mode;
0522 unsigned int rate = params_rate(params);
0523 unsigned int channels = params_channels(params);
0524 unsigned int out_channels_per_sdata =
0525 get_tdm_ch_per_sdata(tdm_out_mode, channels);
0526 snd_pcm_format_t format = params_format(params);
0527 unsigned int tdm_con = 0;
0528
0529
0530 if (!tdm_priv->mclk_rate) {
0531 tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
0532 mtk_dai_tdm_cal_mclk(afe,
0533 tdm_priv,
0534 tdm_priv->mclk_rate);
0535 }
0536
0537
0538 tdm_priv->bck_rate = rate *
0539 out_channels_per_sdata *
0540 snd_pcm_format_physical_width(format);
0541
0542 if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
0543 dev_warn(afe->dev, "%s(), bck_rate > mclk_rate rate", __func__);
0544
0545 if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
0546 dev_warn(afe->dev, "%s(), bck cannot generate", __func__);
0547
0548 dev_info(afe->dev, "%s(), id %d, rate %d, channels %d, format %d, mclk_rate %d, bck_rate %d\n",
0549 __func__,
0550 tdm_id, rate, channels, format,
0551 tdm_priv->mclk_rate, tdm_priv->bck_rate);
0552
0553 dev_info(afe->dev, "%s(), out_channels_per_sdata = %d\n",
0554 __func__, out_channels_per_sdata);
0555
0556
0557 if (tdm_priv->bck_invert)
0558 regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
0559 BCK_INVERSE_MASK_SFT,
0560 0x1 << BCK_INVERSE_SFT);
0561
0562 if (tdm_priv->lck_invert)
0563 tdm_con |= 1 << LRCK_INVERSE_SFT;
0564
0565 if (tdm_priv->tdm_out_mode == TDM_OUT_I2S) {
0566 tdm_con |= 1 << DELAY_DATA_SFT;
0567 tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
0568 } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_A) {
0569 tdm_con |= 0 << DELAY_DATA_SFT;
0570 tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
0571 } else if (tdm_priv->tdm_out_mode == TDM_OUT_DSP_B) {
0572 tdm_con |= 1 << DELAY_DATA_SFT;
0573 tdm_con |= 0 << LRCK_TDM_WIDTH_SFT;
0574 }
0575
0576 tdm_con |= 1 << LEFT_ALIGN_SFT;
0577 tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
0578 tdm_con |= get_tdm_ch(out_channels_per_sdata) << CHANNEL_NUM_SFT;
0579 tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
0580 regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
0581
0582 if (out_channels_per_sdata == 2) {
0583 switch (channels) {
0584 case 1:
0585 case 2:
0586 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
0587 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
0588 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
0589 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
0590 break;
0591 case 3:
0592 case 4:
0593 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
0594 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
0595 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
0596 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
0597 break;
0598 case 5:
0599 case 6:
0600 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
0601 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
0602 tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
0603 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
0604 break;
0605 case 7:
0606 case 8:
0607 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
0608 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
0609 tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
0610 tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
0611 break;
0612 default:
0613 tdm_con = 0;
0614 }
0615 } else {
0616 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
0617 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
0618 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
0619 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
0620 }
0621
0622 regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
0623
0624 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
0625 HDMI_CH_NUM_MASK_SFT,
0626 channels << HDMI_CH_NUM_SFT);
0627 return 0;
0628 }
0629
0630 static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
0631 int clk_id, unsigned int freq, int dir)
0632 {
0633 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
0634 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0635 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
0636
0637 if (!tdm_priv) {
0638 dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
0639 return -EINVAL;
0640 }
0641
0642 if (dir != SND_SOC_CLOCK_OUT) {
0643 dev_warn(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__);
0644 return -EINVAL;
0645 }
0646
0647 dev_info(afe->dev, "%s(), freq %d\n", __func__, freq);
0648
0649 return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
0650 }
0651
0652 static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0653 {
0654 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
0655 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0656 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id];
0657
0658 if (!tdm_priv) {
0659 dev_warn(afe->dev, "%s(), tdm_priv == NULL", __func__);
0660 return -EINVAL;
0661 }
0662
0663
0664 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0665 case SND_SOC_DAIFMT_I2S:
0666 tdm_priv->tdm_out_mode = TDM_OUT_I2S;
0667 break;
0668 case SND_SOC_DAIFMT_DSP_A:
0669 tdm_priv->tdm_out_mode = TDM_OUT_DSP_A;
0670 break;
0671 case SND_SOC_DAIFMT_DSP_B:
0672 tdm_priv->tdm_out_mode = TDM_OUT_DSP_B;
0673 break;
0674 default:
0675 tdm_priv->tdm_out_mode = TDM_OUT_I2S;
0676 }
0677
0678
0679 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0680 case SND_SOC_DAIFMT_NB_NF:
0681 tdm_priv->bck_invert = TDM_BCK_NON_INV;
0682 tdm_priv->lck_invert = TDM_LCK_NON_INV;
0683 break;
0684 case SND_SOC_DAIFMT_NB_IF:
0685 tdm_priv->bck_invert = TDM_BCK_NON_INV;
0686 tdm_priv->lck_invert = TDM_LCK_INV;
0687 break;
0688 case SND_SOC_DAIFMT_IB_NF:
0689 tdm_priv->bck_invert = TDM_BCK_INV;
0690 tdm_priv->lck_invert = TDM_LCK_NON_INV;
0691 break;
0692 case SND_SOC_DAIFMT_IB_IF:
0693 default:
0694 tdm_priv->bck_invert = TDM_BCK_INV;
0695 tdm_priv->lck_invert = TDM_LCK_INV;
0696 break;
0697 }
0698
0699 return 0;
0700 }
0701
0702 static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
0703 .hw_params = mtk_dai_tdm_hw_params,
0704 .set_sysclk = mtk_dai_tdm_set_sysclk,
0705 .set_fmt = mtk_dai_tdm_set_fmt,
0706 };
0707
0708
0709 #define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
0710 SNDRV_PCM_RATE_88200 |\
0711 SNDRV_PCM_RATE_96000 |\
0712 SNDRV_PCM_RATE_176400 |\
0713 SNDRV_PCM_RATE_192000)
0714
0715 #define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
0716 SNDRV_PCM_FMTBIT_S24_LE |\
0717 SNDRV_PCM_FMTBIT_S32_LE)
0718
0719 static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
0720 {
0721 .name = "TDM",
0722 .id = MT8192_DAI_TDM,
0723 .playback = {
0724 .stream_name = "TDM",
0725 .channels_min = 2,
0726 .channels_max = 8,
0727 .rates = MTK_TDM_RATES,
0728 .formats = MTK_TDM_FORMATS,
0729 },
0730 .ops = &mtk_dai_tdm_ops,
0731 },
0732 };
0733
0734 static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe)
0735 {
0736 struct mtk_afe_tdm_priv *tdm_priv;
0737
0738 tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
0739 GFP_KERNEL);
0740 if (!tdm_priv)
0741 return NULL;
0742
0743 tdm_priv->mclk_multiple = 512;
0744 tdm_priv->bck_id = MT8192_I2S4_BCK;
0745 tdm_priv->mclk_id = MT8192_I2S4_MCK;
0746 tdm_priv->id = MT8192_DAI_TDM;
0747
0748 return tdm_priv;
0749 }
0750
0751 int mt8192_dai_tdm_register(struct mtk_base_afe *afe)
0752 {
0753 struct mt8192_afe_private *afe_priv = afe->platform_priv;
0754 struct mtk_afe_tdm_priv *tdm_priv;
0755 struct mtk_base_afe_dai *dai;
0756
0757 dev_info(afe->dev, "%s()\n", __func__);
0758
0759 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
0760 if (!dai)
0761 return -ENOMEM;
0762
0763 list_add(&dai->list, &afe->sub_dais);
0764
0765 dai->dai_drivers = mtk_dai_tdm_driver;
0766 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
0767
0768 dai->dapm_widgets = mtk_dai_tdm_widgets;
0769 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
0770 dai->dapm_routes = mtk_dai_tdm_routes;
0771 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
0772
0773 tdm_priv = init_tdm_priv_data(afe);
0774 if (!tdm_priv)
0775 return -ENOMEM;
0776
0777 afe_priv->dai_priv[MT8192_DAI_TDM] = tdm_priv;
0778
0779 return 0;
0780 }