FILE
mt8189-dai-tdm.c
File preview with syntax highlighting.
linux-6.19.14/sound/soc/mediatek/mt8189/mt8189-dai-tdm.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * MediaTek ALSA SoC Audio DAI TDM Control 4 * 5 * Copyright (c) 2025 MediaTek Inc. 6 * Author: Darren Ye <darren.ye@mediatek.com> 7 */ 8 9#include <linux/regmap.h> 10 11#include <sound/pcm_params.h> 12 13#include "mt8189-afe-clk.h" 14#include "mt8189-afe-common.h" 15#include "mt8189-interconnection.h" 16 17#define DPTX_CH_EN_MASK_2CH (0x3) 18#define DPTX_CH_EN_MASK_4CH (0xf) 19#define DPTX_CH_EN_MASK_6CH (0x3f) 20#define DPTX_CH_EN_MASK_8CH (0xff) 21 22enum { 23 SUPPLY_SEQ_APLL, 24 SUPPLY_SEQ_TDM_MCK_EN, 25 SUPPLY_SEQ_TDM_BCK_EN, 26 SUPPLY_SEQ_TDM_DPTX_MCK_EN, 27 SUPPLY_SEQ_TDM_DPTX_BCK_EN, 28 SUPPLY_SEQ_TDM_CG_EN, 29}; 30 31enum { 32 TDM_WLEN_8_BIT, 33 TDM_WLEN_16_BIT, 34 TDM_WLEN_24_BIT, 35 TDM_WLEN_32_BIT, 36}; 37 38enum { 39 TDM_CHANNEL_BCK_16, 40 TDM_CHANNEL_BCK_24, 41 TDM_CHANNEL_BCK_32 42}; 43 44enum { 45 TDM_CHANNEL_NUM_2, 46 TDM_CHANNEL_NUM_4, 47 TDM_CHANNEL_NUM_8 48}; 49 50enum { 51 TDM_CH_START_O30_O31, 52 TDM_CH_START_O32_O33, 53 TDM_CH_START_O34_O35, 54 TDM_CH_START_O36_O37, 55 TDM_CH_ZERO, 56}; 57 58enum { 59 DPTX_CHANNEL_2, 60 DPTX_CHANNEL_8, 61}; 62 63enum { 64 DPTX_WLEN_24_BIT, 65 DPTX_WLEN_16_BIT, 66}; 67 68struct mtk_afe_tdm_priv { 69 int bck_id; 70 int bck_rate; 71 72 int mclk_id; 73 int mclk_multiple; /* according to sample rate */ 74 int mclk_rate; 75 int mclk_apll; 76}; 77 78static unsigned int get_tdm_wlen(snd_pcm_format_t format) 79{ 80 return snd_pcm_format_physical_width(format) <= 16 ? 81 TDM_WLEN_16_BIT : TDM_WLEN_32_BIT; 82} 83 84static unsigned int get_tdm_channel_bck(snd_pcm_format_t format) 85{ 86 return snd_pcm_format_physical_width(format) <= 16 ? 87 TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32; 88} 89 90static unsigned int get_tdm_lrck_width(snd_pcm_format_t format) 91{ 92 return snd_pcm_format_physical_width(format) - 1; 93} 94 95static unsigned int get_tdm_ch(unsigned int ch) 96{ 97 switch (ch) { 98 case 1: 99 case 2: 100 return TDM_CHANNEL_NUM_2; 101 case 3: 102 case 4: 103 return TDM_CHANNEL_NUM_4; 104 case 5: 105 case 6: 106 case 7: 107 case 8: 108 default: 109 return TDM_CHANNEL_NUM_8; 110 } 111} 112 113static unsigned int get_dptx_ch_enable_mask(unsigned int ch) 114{ 115 switch (ch) { 116 case 1: 117 case 2: 118 return DPTX_CH_EN_MASK_2CH; 119 case 3: 120 case 4: 121 return DPTX_CH_EN_MASK_4CH; 122 case 5: 123 case 6: 124 return DPTX_CH_EN_MASK_6CH; 125 case 7: 126 case 8: 127 return DPTX_CH_EN_MASK_8CH; 128 default: 129 return DPTX_CH_EN_MASK_2CH; 130 } 131} 132 133static unsigned int get_dptx_ch(unsigned int ch) 134{ 135 if (ch == 2) 136 return DPTX_CHANNEL_2; 137 138 return DPTX_CHANNEL_8; 139} 140 141static unsigned int get_dptx_wlen(snd_pcm_format_t format) 142{ 143 return snd_pcm_format_physical_width(format) <= 16 ? 144 DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT; 145} 146 147/* interconnection */ 148enum { 149 HDMI_CONN_CH0, 150 HDMI_CONN_CH1, 151 HDMI_CONN_CH2, 152 HDMI_CONN_CH3, 153 HDMI_CONN_CH4, 154 HDMI_CONN_CH5, 155 HDMI_CONN_CH6, 156 HDMI_CONN_CH7, 157}; 158 159static const char *const hdmi_conn_mux_map[] = { 160 "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7", 161}; 162 163static int hdmi_conn_mux_map_value[] = { 164 HDMI_CONN_CH0, HDMI_CONN_CH1, HDMI_CONN_CH2, HDMI_CONN_CH3, 165 HDMI_CONN_CH4, HDMI_CONN_CH5, HDMI_CONN_CH6, HDMI_CONN_CH7, 166}; 167 168static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum, 169 AFE_HDMI_CONN0, 170 HDMI_O_0_SFT, 171 HDMI_O_0_MASK, 172 hdmi_conn_mux_map, 173 hdmi_conn_mux_map_value); 174 175static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum, 176 AFE_HDMI_CONN0, 177 HDMI_O_1_SFT, 178 HDMI_O_1_MASK, 179 hdmi_conn_mux_map, 180 hdmi_conn_mux_map_value); 181 182static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum, 183 AFE_HDMI_CONN0, 184 HDMI_O_2_SFT, 185 HDMI_O_2_MASK, 186 hdmi_conn_mux_map, 187 hdmi_conn_mux_map_value); 188 189static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum, 190 AFE_HDMI_CONN0, 191 HDMI_O_3_SFT, 192 HDMI_O_3_MASK, 193 hdmi_conn_mux_map, 194 hdmi_conn_mux_map_value); 195 196static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum, 197 AFE_HDMI_CONN0, 198 HDMI_O_4_SFT, 199 HDMI_O_4_MASK, 200 hdmi_conn_mux_map, 201 hdmi_conn_mux_map_value); 202 203static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum, 204 AFE_HDMI_CONN0, 205 HDMI_O_5_SFT, 206 HDMI_O_5_MASK, 207 hdmi_conn_mux_map, 208 hdmi_conn_mux_map_value); 209 210static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum, 211 AFE_HDMI_CONN0, 212 HDMI_O_6_SFT, 213 HDMI_O_6_MASK, 214 hdmi_conn_mux_map, 215 hdmi_conn_mux_map_value); 216 217static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum, 218 AFE_HDMI_CONN0, 219 HDMI_O_7_SFT, 220 HDMI_O_7_MASK, 221 hdmi_conn_mux_map, 222 hdmi_conn_mux_map_value); 223 224static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = { 225 SOC_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum), 226 SOC_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum), 227 SOC_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum), 228 SOC_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum), 229 SOC_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum), 230 SOC_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum), 231 SOC_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum), 232 SOC_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum), 233}; 234 235static const char *const tdm_out_demux_texts[] = { 236 "NONE", "TDMOUT", "DPTXOUT", 237}; 238 239static SOC_ENUM_SINGLE_DECL(tdm_out_demux_enum, 240 SND_SOC_NOPM, 241 0, 242 tdm_out_demux_texts); 243 244static const struct snd_kcontrol_new tdm_out_demux_control = 245 SOC_DAPM_ENUM("TDM Playback Route", tdm_out_demux_enum); 246 247static int get_tdm_id_by_name(const char *name) 248{ 249 if (strstr(name, "DPTX")) 250 return MT8189_DAI_TDM_DPTX; 251 252 return MT8189_DAI_TDM; 253} 254 255static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w, 256 struct snd_kcontrol *kcontrol, 257 int event) 258{ 259 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 260 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 261 struct mt8189_afe_private *afe_priv = afe->platform_priv; 262 int dai_id = get_tdm_id_by_name(w->name); 263 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 264 265 dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, bck: %d\n", 266 w->name, event, dai_id, tdm_priv->bck_rate); 267 268 switch (event) { 269 case SND_SOC_DAPM_PRE_PMU: 270 mt8189_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate); 271 break; 272 case SND_SOC_DAPM_POST_PMD: 273 mt8189_mck_disable(afe, tdm_priv->bck_id); 274 break; 275 default: 276 break; 277 } 278 279 return 0; 280} 281 282static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, 283 struct snd_kcontrol *kcontrol, 284 int event) 285{ 286 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); 287 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 288 struct mt8189_afe_private *afe_priv = afe->platform_priv; 289 int dai_id = get_tdm_id_by_name(w->name); 290 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 291 292 dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d, mclk %d\n", 293 w->name, event, dai_id, tdm_priv->mclk_rate); 294 295 switch (event) { 296 case SND_SOC_DAPM_PRE_PMU: 297 mt8189_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate); 298 break; 299 case SND_SOC_DAPM_POST_PMD: 300 tdm_priv->mclk_rate = 0; 301 mt8189_mck_disable(afe, tdm_priv->mclk_id); 302 break; 303 default: 304 break; 305 } 306 307 return 0; 308} 309 310static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = { 311 SND_SOC_DAPM_DEMUX("TDM Playback Route", SND_SOC_NOPM, 0, 0, 312 &tdm_out_demux_control), 313 314 SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN, 315 SND_SOC_NOPM, 0, 0, 316 mtk_tdm_bck_en_event, 317 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 318 319 SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN, 320 SND_SOC_NOPM, 0, 0, 321 mtk_tdm_mck_en_event, 322 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 323 324 SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN, 325 SND_SOC_NOPM, 0, 0, 326 mtk_tdm_bck_en_event, 327 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 328 329 SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_MCK_EN, 330 SND_SOC_NOPM, 0, 0, 331 mtk_tdm_mck_en_event, 332 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 333 334 SND_SOC_DAPM_SUPPLY_S("TDM_CG", SUPPLY_SEQ_TDM_CG_EN, 335 AUDIO_TOP_CON2, PDN_TDM_OUT_SFT, 1, 336 NULL, 0), 337}; 338 339static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source, 340 struct snd_soc_dapm_widget *sink) 341{ 342 struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm); 343 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); 344 struct mt8189_afe_private *afe_priv = afe->platform_priv; 345 int dai_id = get_tdm_id_by_name(sink->name); 346 struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; 347 int cur_apll; 348 349 /* which apll */ 350 cur_apll = mt8189_get_apll_by_name(afe, source->name); 351 352 return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0; 353} 354 355static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = { 356 {"TDM Playback Route", NULL, "HDMI"}, 357 358 {"TDM", "TDMOUT", "TDM Playback Route"}, 359 {"TDM", NULL, "TDM_BCK"}, 360 {"TDM", NULL, "TDM_CG"}, 361 362 {"TDM_DPTX", "DPTXOUT", "TDM Playback Route"}, 363 {"TDM_DPTX", NULL, "TDM_DPTX_BCK"}, 364 {"TDM_DPTX", NULL, "TDM_CG"}, 365 366 {"TDM_BCK", NULL, "TDM_MCK"}, 367 {"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"}, 368 {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, 369 {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, 370 {"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, 371 {"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, 372}; 373 374/* dai ops */ 375static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe, 376 struct mtk_afe_tdm_priv *tdm_priv, 377 int freq) 378{ 379 int apll; 380 int apll_rate; 381 382 apll = mt8189_get_apll_by_rate(afe, freq); 383 apll_rate = mt8189_get_apll_rate(afe, apll); 384 385 if (freq > apll_rate) 386 return -EINVAL; 387 388 if (apll_rate % freq != 0) 389 return -EINVAL; 390 391 tdm_priv->mclk_rate = freq; 392 tdm_priv->mclk_apll = apll; 393 394 return 0; 395} 396 397static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, 398 struct snd_pcm_hw_params *params, 399 struct snd_soc_dai *dai) 400{ 401 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 402 struct mt8189_afe_private *afe_priv = afe->platform_priv; 403 int tdm_id = dai->id; 404 struct mtk_afe_tdm_priv *tdm_priv; 405 unsigned int rate = params_rate(params); 406 unsigned int channels = params_channels(params); 407 snd_pcm_format_t format = params_format(params); 408 unsigned int tdm_con; 409 410 if (tdm_id >= MT8189_DAI_NUM || tdm_id < 0) 411 return -EINVAL; 412 413 tdm_priv = afe_priv->dai_priv[tdm_id]; 414 415 /* calculate mclk_rate, if not set explicitly */ 416 if (!tdm_priv->mclk_rate) { 417 tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple; 418 mtk_dai_tdm_cal_mclk(afe, 419 tdm_priv, 420 tdm_priv->mclk_rate); 421 } 422 423 /* calculate bck */ 424 tdm_priv->bck_rate = rate * 425 channels * 426 snd_pcm_format_physical_width(format); 427 428 if (tdm_priv->bck_rate > tdm_priv->mclk_rate) 429 return -EINVAL; 430 431 if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0) 432 return -EINVAL; 433 434 dev_dbg(afe->dev, "id %d, rate %d, ch %d, fmt %d, mclk %d, bck %d\n", 435 tdm_id, rate, channels, format, 436 tdm_priv->mclk_rate, tdm_priv->bck_rate); 437 438 /* set tdm */ 439 tdm_con = 1 << LEFT_ALIGN_SFT; 440 tdm_con |= get_tdm_wlen(format) << WLEN_SFT; 441 tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT; 442 tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT; 443 tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT; 444 regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con); 445 446 /* set dptx */ 447 if (tdm_id == MT8189_DAI_TDM_DPTX) { 448 regmap_update_bits(afe->regmap, AFE_DPTX_CON, 449 DPTX_CHANNEL_ENABLE_MASK_SFT, 450 get_dptx_ch_enable_mask(channels) << 451 DPTX_CHANNEL_ENABLE_SFT); 452 regmap_update_bits(afe->regmap, AFE_DPTX_CON, 453 DPTX_CHANNEL_NUMBER_MASK_SFT, 454 get_dptx_ch(channels) << 455 DPTX_CHANNEL_NUMBER_SFT); 456 regmap_update_bits(afe->regmap, AFE_DPTX_CON, 457 DPTX_16BIT_MASK_SFT, 458 get_dptx_wlen(format) << DPTX_16BIT_SFT); 459 } 460 switch (channels) { 461 case 1: 462 case 2: 463 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 464 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT; 465 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; 466 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 467 break; 468 case 3: 469 case 4: 470 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 471 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 472 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT; 473 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 474 break; 475 case 5: 476 case 6: 477 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 478 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 479 tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; 480 tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT; 481 break; 482 case 7: 483 case 8: 484 tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT; 485 tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT; 486 tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT; 487 tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT; 488 break; 489 default: 490 tdm_con = 0; 491 } 492 regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con); 493 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 494 HDMI_CH_NUM_MASK_SFT, 495 channels << HDMI_CH_NUM_SFT); 496 497 return 0; 498} 499 500static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream, 501 int cmd, 502 struct snd_soc_dai *dai) 503{ 504 struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); 505 int tdm_id = dai->id; 506 507 dev_dbg(afe->dev, "%s(), cmd %d, tdm_id %d\n", __func__, cmd, tdm_id); 508 509 switch (cmd) { 510 case SNDRV_PCM_TRIGGER_START: 511 case SNDRV_PCM_TRIGGER_RESUME: 512 /* enable Out control */ 513 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 514 HDMI_OUT_ON_MASK_SFT, 515 0x1 << HDMI_OUT_ON_SFT); 516 517 /* enable dptx */ 518 if (tdm_id == MT8189_DAI_TDM_DPTX) { 519 regmap_update_bits(afe->regmap, AFE_DPTX_CON, 520 DPTX_ON_MASK_SFT, 0x1 << 521 DPTX_ON_SFT); 522 } 523 524 /* enable tdm */ 525 regmap_update_bits(afe->regmap, AFE_TDM_CON1, 526 TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT); 527 break; 528 case SNDRV_PCM_TRIGGER_STOP: 529 case SNDRV_PCM_TRIGGER_SUSPEND: 530 /* disable tdm */ 531 regmap_update_bits(afe->regmap, AFE_TDM_CON1, 532 TDM_EN_MASK_SFT, 0); 533 534 /* disable dptx */ 535 if (tdm_id == MT8189_DAI_TDM_DPTX) { 536 regmap_update_bits(afe->regmap, AFE_DPTX_CON, 537 DPTX_ON_MASK_SFT, 0); 538 } 539 540 /* disable Out control */ 541 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 542 HDMI_OUT_ON_MASK_SFT, 0); 543 break; 544 default: 545 return -EINVAL; 546 } 547 548 return 0; 549} 550 551static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, 552 int clk_id, unsigned int freq, int dir) 553{ 554 struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); 555 struct mt8189_afe_private *afe_priv = afe->platform_priv; 556 struct mtk_afe_tdm_priv *tdm_priv; 557 558 if (dai->id >= MT8189_DAI_NUM || dai->id < 0) 559 return -EINVAL; 560 561 tdm_priv = afe_priv->dai_priv[dai->id]; 562 563 if (!tdm_priv) 564 return -EINVAL; 565 566 if (dir != SND_SOC_CLOCK_OUT) 567 return -EINVAL; 568 569 dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); 570 571 return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); 572} 573 574static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { 575 .hw_params = mtk_dai_tdm_hw_params, 576 .trigger = mtk_dai_tdm_trigger, 577 .set_sysclk = mtk_dai_tdm_set_sysclk, 578}; 579 580/* dai driver */ 581#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ 582 SNDRV_PCM_RATE_88200 |\ 583 SNDRV_PCM_RATE_96000 |\ 584 SNDRV_PCM_RATE_176400 |\ 585 SNDRV_PCM_RATE_192000) 586 587#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 588 SNDRV_PCM_FMTBIT_S24_LE |\ 589 SNDRV_PCM_FMTBIT_S32_LE) 590 591static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = { 592 { 593 .name = "TDM", 594 .id = MT8189_DAI_TDM, 595 .playback = { 596 .stream_name = "TDM", 597 .channels_min = 2, 598 .channels_max = 8, 599 .rates = MTK_TDM_RATES, 600 .formats = MTK_TDM_FORMATS, 601 }, 602 .ops = &mtk_dai_tdm_ops, 603 }, 604 { 605 .name = "TDM_DPTX", 606 .id = MT8189_DAI_TDM_DPTX, 607 .playback = { 608 .stream_name = "TDM_DPTX", 609 .channels_min = 2, 610 .channels_max = 8, 611 .rates = MTK_TDM_RATES, 612 .formats = MTK_TDM_FORMATS, 613 }, 614 .ops = &mtk_dai_tdm_ops, 615 }, 616}; 617 618static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe, 619 int id) 620{ 621 struct mtk_afe_tdm_priv *tdm_priv; 622 623 tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv), 624 GFP_KERNEL); 625 if (!tdm_priv) 626 return NULL; 627 628 if (id == MT8189_DAI_TDM_DPTX) 629 tdm_priv->mclk_multiple = 256; 630 else 631 tdm_priv->mclk_multiple = 128; 632 633 tdm_priv->bck_id = MT8189_TDMOUT_BCK; 634 tdm_priv->mclk_id = MT8189_TDMOUT_MCK; 635 636 return tdm_priv; 637} 638 639int mt8189_dai_tdm_register(struct mtk_base_afe *afe) 640{ 641 struct mt8189_afe_private *afe_priv = afe->platform_priv; 642 struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv; 643 struct mtk_base_afe_dai *dai; 644 645 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); 646 if (!dai) 647 return -ENOMEM; 648 649 dai->dai_drivers = mtk_dai_tdm_driver; 650 dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver); 651 dai->controls = mtk_dai_tdm_controls; 652 dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls); 653 dai->dapm_widgets = mtk_dai_tdm_widgets; 654 dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets); 655 dai->dapm_routes = mtk_dai_tdm_routes; 656 dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes); 657 658 tdm_priv = init_tdm_priv_data(afe, MT8189_DAI_TDM); 659 if (!tdm_priv) 660 return -ENOMEM; 661 662 tdm_dptx_priv = init_tdm_priv_data(afe, MT8189_DAI_TDM_DPTX); 663 if (!tdm_dptx_priv) 664 return -ENOMEM; 665 666 list_add(&dai->list, &afe->sub_dais); 667 668 afe_priv->dai_priv[MT8189_DAI_TDM] = tdm_priv; 669 afe_priv->dai_priv[MT8189_DAI_TDM_DPTX] = tdm_dptx_priv; 670 671 return 0; 672}
~/
Read-only file preview.