1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * mt8188-mt6359.c -- MT8188-MT6359 ALSA SoC machine driver 4 * 5 * Copyright (c) 2022 MediaTek Inc. 6 * Author: Trevor Wu <trevor.wu@mediatek.com> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/of_device.h> 11 #include <linux/pm_runtime.h> 12 #include <sound/jack.h> 13 #include <sound/pcm_params.h> 14 #include <sound/soc.h> 15 #include "mt8188-afe-common.h" 16 #include "../../codecs/mt6359.h" 17 #include "../common/mtk-afe-platform-driver.h" 18 #include "../common/mtk-soundcard-driver.h" 19 20 /* FE */ 21 SND_SOC_DAILINK_DEFS(playback2, 22 DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 23 DAILINK_COMP_ARRAY(COMP_DUMMY()), 24 DAILINK_COMP_ARRAY(COMP_EMPTY())); 25 26 SND_SOC_DAILINK_DEFS(playback3, 27 DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 28 DAILINK_COMP_ARRAY(COMP_DUMMY()), 29 DAILINK_COMP_ARRAY(COMP_EMPTY())); 30 31 SND_SOC_DAILINK_DEFS(playback6, 32 DAILINK_COMP_ARRAY(COMP_CPU("DL6")), 33 DAILINK_COMP_ARRAY(COMP_DUMMY()), 34 DAILINK_COMP_ARRAY(COMP_EMPTY())); 35 36 SND_SOC_DAILINK_DEFS(playback7, 37 DAILINK_COMP_ARRAY(COMP_CPU("DL7")), 38 DAILINK_COMP_ARRAY(COMP_DUMMY()), 39 DAILINK_COMP_ARRAY(COMP_EMPTY())); 40 41 SND_SOC_DAILINK_DEFS(playback8, 42 DAILINK_COMP_ARRAY(COMP_CPU("DL8")), 43 DAILINK_COMP_ARRAY(COMP_DUMMY()), 44 DAILINK_COMP_ARRAY(COMP_EMPTY())); 45 46 SND_SOC_DAILINK_DEFS(playback10, 47 DAILINK_COMP_ARRAY(COMP_CPU("DL10")), 48 DAILINK_COMP_ARRAY(COMP_DUMMY()), 49 DAILINK_COMP_ARRAY(COMP_EMPTY())); 50 51 SND_SOC_DAILINK_DEFS(playback11, 52 DAILINK_COMP_ARRAY(COMP_CPU("DL11")), 53 DAILINK_COMP_ARRAY(COMP_DUMMY()), 54 DAILINK_COMP_ARRAY(COMP_EMPTY())); 55 56 SND_SOC_DAILINK_DEFS(capture1, 57 DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 58 DAILINK_COMP_ARRAY(COMP_DUMMY()), 59 DAILINK_COMP_ARRAY(COMP_EMPTY())); 60 61 SND_SOC_DAILINK_DEFS(capture2, 62 DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 63 DAILINK_COMP_ARRAY(COMP_DUMMY()), 64 DAILINK_COMP_ARRAY(COMP_EMPTY())); 65 66 SND_SOC_DAILINK_DEFS(capture3, 67 DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 68 DAILINK_COMP_ARRAY(COMP_DUMMY()), 69 DAILINK_COMP_ARRAY(COMP_EMPTY())); 70 71 SND_SOC_DAILINK_DEFS(capture4, 72 DAILINK_COMP_ARRAY(COMP_CPU("UL4")), 73 DAILINK_COMP_ARRAY(COMP_DUMMY()), 74 DAILINK_COMP_ARRAY(COMP_EMPTY())); 75 76 SND_SOC_DAILINK_DEFS(capture5, 77 DAILINK_COMP_ARRAY(COMP_CPU("UL5")), 78 DAILINK_COMP_ARRAY(COMP_DUMMY()), 79 DAILINK_COMP_ARRAY(COMP_EMPTY())); 80 81 SND_SOC_DAILINK_DEFS(capture6, 82 DAILINK_COMP_ARRAY(COMP_CPU("UL6")), 83 DAILINK_COMP_ARRAY(COMP_DUMMY()), 84 DAILINK_COMP_ARRAY(COMP_EMPTY())); 85 86 SND_SOC_DAILINK_DEFS(capture8, 87 DAILINK_COMP_ARRAY(COMP_CPU("UL8")), 88 DAILINK_COMP_ARRAY(COMP_DUMMY()), 89 DAILINK_COMP_ARRAY(COMP_EMPTY())); 90 91 SND_SOC_DAILINK_DEFS(capture9, 92 DAILINK_COMP_ARRAY(COMP_CPU("UL9")), 93 DAILINK_COMP_ARRAY(COMP_DUMMY()), 94 DAILINK_COMP_ARRAY(COMP_EMPTY())); 95 96 SND_SOC_DAILINK_DEFS(capture10, 97 DAILINK_COMP_ARRAY(COMP_CPU("UL10")), 98 DAILINK_COMP_ARRAY(COMP_DUMMY()), 99 DAILINK_COMP_ARRAY(COMP_EMPTY())); 100 101 /* BE */ 102 SND_SOC_DAILINK_DEFS(dl_src, 103 DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")), 104 DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 105 "mt6359-snd-codec-aif1")), 106 DAILINK_COMP_ARRAY(COMP_EMPTY())); 107 108 SND_SOC_DAILINK_DEFS(dptx, 109 DAILINK_COMP_ARRAY(COMP_CPU("DPTX")), 110 DAILINK_COMP_ARRAY(COMP_DUMMY()), 111 DAILINK_COMP_ARRAY(COMP_EMPTY())); 112 113 SND_SOC_DAILINK_DEFS(etdm1_in, 114 DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")), 115 DAILINK_COMP_ARRAY(COMP_DUMMY()), 116 DAILINK_COMP_ARRAY(COMP_EMPTY())); 117 118 SND_SOC_DAILINK_DEFS(etdm2_in, 119 DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")), 120 DAILINK_COMP_ARRAY(COMP_DUMMY()), 121 DAILINK_COMP_ARRAY(COMP_EMPTY())); 122 123 SND_SOC_DAILINK_DEFS(etdm1_out, 124 DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")), 125 DAILINK_COMP_ARRAY(COMP_DUMMY()), 126 DAILINK_COMP_ARRAY(COMP_EMPTY())); 127 128 SND_SOC_DAILINK_DEFS(etdm2_out, 129 DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")), 130 DAILINK_COMP_ARRAY(COMP_DUMMY()), 131 DAILINK_COMP_ARRAY(COMP_EMPTY())); 132 133 SND_SOC_DAILINK_DEFS(etdm3_out, 134 DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")), 135 DAILINK_COMP_ARRAY(COMP_DUMMY()), 136 DAILINK_COMP_ARRAY(COMP_EMPTY())); 137 138 SND_SOC_DAILINK_DEFS(pcm1, 139 DAILINK_COMP_ARRAY(COMP_CPU("PCM1")), 140 DAILINK_COMP_ARRAY(COMP_DUMMY()), 141 DAILINK_COMP_ARRAY(COMP_EMPTY())); 142 143 SND_SOC_DAILINK_DEFS(ul_src, 144 DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")), 145 DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 146 "mt6359-snd-codec-aif1")), 147 DAILINK_COMP_ARRAY(COMP_EMPTY())); 148 149 struct mt8188_mt6359_priv { 150 struct snd_soc_jack dp_jack; 151 struct snd_soc_jack hdmi_jack; 152 }; 153 154 static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = { 155 { 156 .pin = "HDMI", 157 .mask = SND_JACK_LINEOUT, 158 }, 159 }; 160 161 static struct snd_soc_jack_pin mt8188_dp_jack_pins[] = { 162 { 163 .pin = "DP", 164 .mask = SND_JACK_LINEOUT, 165 }, 166 }; 167 168 struct mt8188_card_data { 169 const char *name; 170 unsigned long quirk; 171 }; 172 173 static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = { 174 SND_SOC_DAPM_HP("Headphone", NULL), 175 SND_SOC_DAPM_MIC("Headset Mic", NULL), 176 SND_SOC_DAPM_SINK("HDMI"), 177 SND_SOC_DAPM_SINK("DP"), 178 }; 179 180 static const struct snd_kcontrol_new mt8188_mt6359_controls[] = { 181 SOC_DAPM_PIN_SWITCH("Headphone"), 182 SOC_DAPM_PIN_SWITCH("Headset Mic"), 183 }; 184 185 #define CKSYS_AUD_TOP_CFG 0x032c 186 #define CKSYS_AUD_TOP_MON 0x0330 187 188 static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) 189 { 190 struct snd_soc_component *cmpnt_afe = 191 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 192 struct snd_soc_component *cmpnt_codec = 193 asoc_rtd_to_codec(rtd, 0)->component; 194 struct mtk_base_afe *afe; 195 struct mt8188_afe_private *afe_priv; 196 struct mtkaif_param *param; 197 int chosen_phase_1, chosen_phase_2; 198 int prev_cycle_1, prev_cycle_2; 199 int test_done_1, test_done_2; 200 int cycle_1, cycle_2; 201 int mtkaif_chosen_phase[MT8188_MTKAIF_MISO_NUM]; 202 int mtkaif_phase_cycle[MT8188_MTKAIF_MISO_NUM]; 203 int mtkaif_calibration_num_phase; 204 bool mtkaif_calibration_ok; 205 unsigned int monitor = 0; 206 int counter; 207 int phase; 208 int i; 209 210 if (!cmpnt_afe) 211 return -EINVAL; 212 213 afe = snd_soc_component_get_drvdata(cmpnt_afe); 214 afe_priv = afe->platform_priv; 215 param = &afe_priv->mtkaif_params; 216 217 dev_dbg(afe->dev, "%s(), start\n", __func__); 218 219 param->mtkaif_calibration_ok = false; 220 for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++) { 221 param->mtkaif_chosen_phase[i] = -1; 222 param->mtkaif_phase_cycle[i] = 0; 223 mtkaif_chosen_phase[i] = -1; 224 mtkaif_phase_cycle[i] = 0; 225 } 226 227 if (IS_ERR(afe_priv->topckgen)) { 228 dev_info(afe->dev, "%s() Cannot find topckgen controller\n", 229 __func__); 230 return 0; 231 } 232 233 pm_runtime_get_sync(afe->dev); 234 mt6359_mtkaif_calibration_enable(cmpnt_codec); 235 236 /* set test type to synchronizer pulse */ 237 regmap_update_bits(afe_priv->topckgen, 238 CKSYS_AUD_TOP_CFG, 0xffff, 0x4); 239 mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */ 240 mtkaif_calibration_ok = true; 241 242 for (phase = 0; 243 phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok; 244 phase++) { 245 mt6359_set_mtkaif_calibration_phase(cmpnt_codec, 246 phase, phase, phase); 247 248 regmap_set_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1); 249 250 test_done_1 = 0; 251 test_done_2 = 0; 252 253 cycle_1 = -1; 254 cycle_2 = -1; 255 256 counter = 0; 257 while (!(test_done_1 & test_done_2)) { 258 regmap_read(afe_priv->topckgen, 259 CKSYS_AUD_TOP_MON, &monitor); 260 test_done_1 = (monitor >> 28) & 0x1; 261 test_done_2 = (monitor >> 29) & 0x1; 262 263 if (test_done_1 == 1) 264 cycle_1 = monitor & 0xf; 265 266 if (test_done_2 == 1) 267 cycle_2 = (monitor >> 4) & 0xf; 268 269 /* handle if never test done */ 270 if (++counter > 10000) { 271 dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, monitor 0x%x\n", 272 __func__, 273 cycle_1, cycle_2, monitor); 274 mtkaif_calibration_ok = false; 275 break; 276 } 277 } 278 279 if (phase == 0) { 280 prev_cycle_1 = cycle_1; 281 prev_cycle_2 = cycle_2; 282 } 283 284 if (cycle_1 != prev_cycle_1 && 285 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) { 286 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = phase - 1; 287 mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0] = prev_cycle_1; 288 } 289 290 if (cycle_2 != prev_cycle_2 && 291 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) { 292 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = phase - 1; 293 mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1] = prev_cycle_2; 294 } 295 296 regmap_clear_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1); 297 298 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] >= 0 && 299 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] >= 0) 300 break; 301 } 302 303 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) { 304 mtkaif_calibration_ok = false; 305 chosen_phase_1 = 0; 306 } else { 307 chosen_phase_1 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0]; 308 } 309 310 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) { 311 mtkaif_calibration_ok = false; 312 chosen_phase_2 = 0; 313 } else { 314 chosen_phase_2 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1]; 315 } 316 317 mt6359_set_mtkaif_calibration_phase(cmpnt_codec, 318 chosen_phase_1, 319 chosen_phase_2, 320 0); 321 322 mt6359_mtkaif_calibration_disable(cmpnt_codec); 323 pm_runtime_put(afe->dev); 324 325 param->mtkaif_calibration_ok = mtkaif_calibration_ok; 326 param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = chosen_phase_1; 327 param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = chosen_phase_2; 328 329 for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++) 330 param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i]; 331 332 dev_info(afe->dev, "%s(), end, calibration ok %d\n", 333 __func__, param->mtkaif_calibration_ok); 334 335 return 0; 336 } 337 338 static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd) 339 { 340 struct snd_soc_component *cmpnt_codec = 341 asoc_rtd_to_codec(rtd, 0)->component; 342 343 /* set mtkaif protocol */ 344 mt6359_set_mtkaif_protocol(cmpnt_codec, 345 MT6359_MTKAIF_PROTOCOL_2_CLK_P2); 346 347 /* mtkaif calibration */ 348 mt8188_mt6359_mtkaif_calibration(rtd); 349 350 return 0; 351 } 352 353 enum { 354 DAI_LINK_DL2_FE, 355 DAI_LINK_DL3_FE, 356 DAI_LINK_DL6_FE, 357 DAI_LINK_DL7_FE, 358 DAI_LINK_DL8_FE, 359 DAI_LINK_DL10_FE, 360 DAI_LINK_DL11_FE, 361 DAI_LINK_UL1_FE, 362 DAI_LINK_UL2_FE, 363 DAI_LINK_UL3_FE, 364 DAI_LINK_UL4_FE, 365 DAI_LINK_UL5_FE, 366 DAI_LINK_UL6_FE, 367 DAI_LINK_UL8_FE, 368 DAI_LINK_UL9_FE, 369 DAI_LINK_UL10_FE, 370 DAI_LINK_DL_SRC_BE, 371 DAI_LINK_DPTX_BE, 372 DAI_LINK_ETDM1_IN_BE, 373 DAI_LINK_ETDM2_IN_BE, 374 DAI_LINK_ETDM1_OUT_BE, 375 DAI_LINK_ETDM2_OUT_BE, 376 DAI_LINK_ETDM3_OUT_BE, 377 DAI_LINK_PCM1_BE, 378 DAI_LINK_UL_SRC_BE, 379 }; 380 381 static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream, 382 struct snd_pcm_hw_params *params) 383 { 384 struct snd_soc_pcm_runtime *rtd = substream->private_data; 385 unsigned int rate = params_rate(params); 386 unsigned int mclk_fs_ratio = 256; 387 unsigned int mclk_fs = rate * mclk_fs_ratio; 388 struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); 389 390 return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); 391 } 392 393 static const struct snd_soc_ops mt8188_dptx_ops = { 394 .hw_params = mt8188_dptx_hw_params, 395 }; 396 397 static int mt8188_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 398 struct snd_pcm_hw_params *params) 399 { 400 /* fix BE i2s format to 32bit, clean param mask first */ 401 snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 402 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); 403 404 params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 405 406 return 0; 407 } 408 409 static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) 410 { 411 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); 412 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 413 int ret = 0; 414 415 ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", 416 SND_JACK_LINEOUT, &priv->hdmi_jack, 417 mt8188_hdmi_jack_pins, 418 ARRAY_SIZE(mt8188_hdmi_jack_pins)); 419 if (ret) { 420 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 421 return ret; 422 } 423 424 ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL); 425 if (ret) 426 dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", 427 __func__, component->name, ret); 428 429 return ret; 430 } 431 432 static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) 433 { 434 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); 435 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 436 int ret = 0; 437 438 ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, 439 &priv->dp_jack, mt8188_dp_jack_pins, 440 ARRAY_SIZE(mt8188_dp_jack_pins)); 441 if (ret) { 442 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 443 return ret; 444 } 445 446 ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL); 447 if (ret) 448 dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", 449 __func__, component->name, ret); 450 451 return ret; 452 } 453 454 static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { 455 /* FE */ 456 [DAI_LINK_DL2_FE] = { 457 .name = "DL2_FE", 458 .stream_name = "DL2 Playback", 459 .trigger = { 460 SND_SOC_DPCM_TRIGGER_POST, 461 SND_SOC_DPCM_TRIGGER_POST, 462 }, 463 .dynamic = 1, 464 .dpcm_playback = 1, 465 SND_SOC_DAILINK_REG(playback2), 466 }, 467 [DAI_LINK_DL3_FE] = { 468 .name = "DL3_FE", 469 .stream_name = "DL3 Playback", 470 .trigger = { 471 SND_SOC_DPCM_TRIGGER_POST, 472 SND_SOC_DPCM_TRIGGER_POST, 473 }, 474 .dynamic = 1, 475 .dpcm_playback = 1, 476 SND_SOC_DAILINK_REG(playback3), 477 }, 478 [DAI_LINK_DL6_FE] = { 479 .name = "DL6_FE", 480 .stream_name = "DL6 Playback", 481 .trigger = { 482 SND_SOC_DPCM_TRIGGER_POST, 483 SND_SOC_DPCM_TRIGGER_POST, 484 }, 485 .dynamic = 1, 486 .dpcm_playback = 1, 487 SND_SOC_DAILINK_REG(playback6), 488 }, 489 [DAI_LINK_DL7_FE] = { 490 .name = "DL7_FE", 491 .stream_name = "DL7 Playback", 492 .trigger = { 493 SND_SOC_DPCM_TRIGGER_PRE, 494 SND_SOC_DPCM_TRIGGER_PRE, 495 }, 496 .dynamic = 1, 497 .dpcm_playback = 1, 498 SND_SOC_DAILINK_REG(playback7), 499 }, 500 [DAI_LINK_DL8_FE] = { 501 .name = "DL8_FE", 502 .stream_name = "DL8 Playback", 503 .trigger = { 504 SND_SOC_DPCM_TRIGGER_POST, 505 SND_SOC_DPCM_TRIGGER_POST, 506 }, 507 .dynamic = 1, 508 .dpcm_playback = 1, 509 SND_SOC_DAILINK_REG(playback8), 510 }, 511 [DAI_LINK_DL10_FE] = { 512 .name = "DL10_FE", 513 .stream_name = "DL10 Playback", 514 .trigger = { 515 SND_SOC_DPCM_TRIGGER_POST, 516 SND_SOC_DPCM_TRIGGER_POST, 517 }, 518 .dynamic = 1, 519 .dpcm_playback = 1, 520 SND_SOC_DAILINK_REG(playback10), 521 }, 522 [DAI_LINK_DL11_FE] = { 523 .name = "DL11_FE", 524 .stream_name = "DL11 Playback", 525 .trigger = { 526 SND_SOC_DPCM_TRIGGER_POST, 527 SND_SOC_DPCM_TRIGGER_POST, 528 }, 529 .dynamic = 1, 530 .dpcm_playback = 1, 531 SND_SOC_DAILINK_REG(playback11), 532 }, 533 [DAI_LINK_UL1_FE] = { 534 .name = "UL1_FE", 535 .stream_name = "UL1 Capture", 536 .trigger = { 537 SND_SOC_DPCM_TRIGGER_PRE, 538 SND_SOC_DPCM_TRIGGER_PRE, 539 }, 540 .dynamic = 1, 541 .dpcm_capture = 1, 542 SND_SOC_DAILINK_REG(capture1), 543 }, 544 [DAI_LINK_UL2_FE] = { 545 .name = "UL2_FE", 546 .stream_name = "UL2 Capture", 547 .trigger = { 548 SND_SOC_DPCM_TRIGGER_POST, 549 SND_SOC_DPCM_TRIGGER_POST, 550 }, 551 .dynamic = 1, 552 .dpcm_capture = 1, 553 SND_SOC_DAILINK_REG(capture2), 554 }, 555 [DAI_LINK_UL3_FE] = { 556 .name = "UL3_FE", 557 .stream_name = "UL3 Capture", 558 .trigger = { 559 SND_SOC_DPCM_TRIGGER_POST, 560 SND_SOC_DPCM_TRIGGER_POST, 561 }, 562 .dynamic = 1, 563 .dpcm_capture = 1, 564 SND_SOC_DAILINK_REG(capture3), 565 }, 566 [DAI_LINK_UL4_FE] = { 567 .name = "UL4_FE", 568 .stream_name = "UL4 Capture", 569 .trigger = { 570 SND_SOC_DPCM_TRIGGER_POST, 571 SND_SOC_DPCM_TRIGGER_POST, 572 }, 573 .dynamic = 1, 574 .dpcm_capture = 1, 575 SND_SOC_DAILINK_REG(capture4), 576 }, 577 [DAI_LINK_UL5_FE] = { 578 .name = "UL5_FE", 579 .stream_name = "UL5 Capture", 580 .trigger = { 581 SND_SOC_DPCM_TRIGGER_POST, 582 SND_SOC_DPCM_TRIGGER_POST, 583 }, 584 .dynamic = 1, 585 .dpcm_capture = 1, 586 SND_SOC_DAILINK_REG(capture5), 587 }, 588 [DAI_LINK_UL6_FE] = { 589 .name = "UL6_FE", 590 .stream_name = "UL6 Capture", 591 .trigger = { 592 SND_SOC_DPCM_TRIGGER_PRE, 593 SND_SOC_DPCM_TRIGGER_PRE, 594 }, 595 .dynamic = 1, 596 .dpcm_capture = 1, 597 SND_SOC_DAILINK_REG(capture6), 598 }, 599 [DAI_LINK_UL8_FE] = { 600 .name = "UL8_FE", 601 .stream_name = "UL8 Capture", 602 .trigger = { 603 SND_SOC_DPCM_TRIGGER_POST, 604 SND_SOC_DPCM_TRIGGER_POST, 605 }, 606 .dynamic = 1, 607 .dpcm_capture = 1, 608 SND_SOC_DAILINK_REG(capture8), 609 }, 610 [DAI_LINK_UL9_FE] = { 611 .name = "UL9_FE", 612 .stream_name = "UL9 Capture", 613 .trigger = { 614 SND_SOC_DPCM_TRIGGER_POST, 615 SND_SOC_DPCM_TRIGGER_POST, 616 }, 617 .dynamic = 1, 618 .dpcm_capture = 1, 619 SND_SOC_DAILINK_REG(capture9), 620 }, 621 [DAI_LINK_UL10_FE] = { 622 .name = "UL10_FE", 623 .stream_name = "UL10 Capture", 624 .trigger = { 625 SND_SOC_DPCM_TRIGGER_POST, 626 SND_SOC_DPCM_TRIGGER_POST, 627 }, 628 .dynamic = 1, 629 .dpcm_capture = 1, 630 SND_SOC_DAILINK_REG(capture10), 631 }, 632 /* BE */ 633 [DAI_LINK_DL_SRC_BE] = { 634 .name = "DL_SRC_BE", 635 .no_pcm = 1, 636 .dpcm_playback = 1, 637 SND_SOC_DAILINK_REG(dl_src), 638 }, 639 [DAI_LINK_DPTX_BE] = { 640 .name = "DPTX_BE", 641 .ops = &mt8188_dptx_ops, 642 .be_hw_params_fixup = mt8188_dptx_hw_params_fixup, 643 .no_pcm = 1, 644 .dpcm_playback = 1, 645 SND_SOC_DAILINK_REG(dptx), 646 }, 647 [DAI_LINK_ETDM1_IN_BE] = { 648 .name = "ETDM1_IN_BE", 649 .no_pcm = 1, 650 .dai_fmt = SND_SOC_DAIFMT_I2S | 651 SND_SOC_DAIFMT_NB_NF | 652 SND_SOC_DAIFMT_CBP_CFP, 653 .dpcm_capture = 1, 654 .ignore_suspend = 1, 655 SND_SOC_DAILINK_REG(etdm1_in), 656 }, 657 [DAI_LINK_ETDM2_IN_BE] = { 658 .name = "ETDM2_IN_BE", 659 .no_pcm = 1, 660 .dai_fmt = SND_SOC_DAIFMT_I2S | 661 SND_SOC_DAIFMT_NB_NF | 662 SND_SOC_DAIFMT_CBP_CFP, 663 .dpcm_capture = 1, 664 SND_SOC_DAILINK_REG(etdm2_in), 665 }, 666 [DAI_LINK_ETDM1_OUT_BE] = { 667 .name = "ETDM1_OUT_BE", 668 .no_pcm = 1, 669 .dai_fmt = SND_SOC_DAIFMT_I2S | 670 SND_SOC_DAIFMT_NB_NF | 671 SND_SOC_DAIFMT_CBC_CFC, 672 .dpcm_playback = 1, 673 SND_SOC_DAILINK_REG(etdm1_out), 674 }, 675 [DAI_LINK_ETDM2_OUT_BE] = { 676 .name = "ETDM2_OUT_BE", 677 .no_pcm = 1, 678 .dai_fmt = SND_SOC_DAIFMT_I2S | 679 SND_SOC_DAIFMT_NB_NF | 680 SND_SOC_DAIFMT_CBC_CFC, 681 .dpcm_playback = 1, 682 SND_SOC_DAILINK_REG(etdm2_out), 683 }, 684 [DAI_LINK_ETDM3_OUT_BE] = { 685 .name = "ETDM3_OUT_BE", 686 .no_pcm = 1, 687 .dai_fmt = SND_SOC_DAIFMT_I2S | 688 SND_SOC_DAIFMT_NB_NF | 689 SND_SOC_DAIFMT_CBC_CFC, 690 .dpcm_playback = 1, 691 SND_SOC_DAILINK_REG(etdm3_out), 692 }, 693 [DAI_LINK_PCM1_BE] = { 694 .name = "PCM1_BE", 695 .no_pcm = 1, 696 .dai_fmt = SND_SOC_DAIFMT_I2S | 697 SND_SOC_DAIFMT_NB_NF | 698 SND_SOC_DAIFMT_CBC_CFC, 699 .dpcm_playback = 1, 700 .dpcm_capture = 1, 701 SND_SOC_DAILINK_REG(pcm1), 702 }, 703 [DAI_LINK_UL_SRC_BE] = { 704 .name = "UL_SRC_BE", 705 .no_pcm = 1, 706 .dpcm_capture = 1, 707 SND_SOC_DAILINK_REG(ul_src), 708 }, 709 }; 710 711 static struct snd_soc_card mt8188_mt6359_soc_card = { 712 .owner = THIS_MODULE, 713 .dai_link = mt8188_mt6359_dai_links, 714 .num_links = ARRAY_SIZE(mt8188_mt6359_dai_links), 715 .dapm_widgets = mt8188_mt6359_widgets, 716 .num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets), 717 .controls = mt8188_mt6359_controls, 718 .num_controls = ARRAY_SIZE(mt8188_mt6359_controls), 719 }; 720 721 static int mt8188_mt6359_dev_probe(struct platform_device *pdev) 722 { 723 struct snd_soc_card *card = &mt8188_mt6359_soc_card; 724 struct device_node *platform_node; 725 struct mt8188_mt6359_priv *priv; 726 struct mt8188_card_data *card_data; 727 struct snd_soc_dai_link *dai_link; 728 bool init_mt6359 = false; 729 int ret, i; 730 731 card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev); 732 card->dev = &pdev->dev; 733 734 ret = snd_soc_of_parse_card_name(card, "model"); 735 if (ret) 736 return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n", 737 __func__); 738 739 if (!card->name) 740 card->name = card_data->name; 741 742 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 743 if (!priv) 744 return -ENOMEM; 745 746 if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) { 747 ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); 748 if (ret) 749 return ret; 750 } 751 752 platform_node = of_parse_phandle(pdev->dev.of_node, 753 "mediatek,platform", 0); 754 if (!platform_node) { 755 ret = -EINVAL; 756 return dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); 757 } 758 759 ret = parse_dai_link_info(card); 760 if (ret) 761 goto err; 762 763 for_each_card_prelinks(card, i, dai_link) { 764 if (!dai_link->platforms->name) 765 dai_link->platforms->of_node = platform_node; 766 767 if (strcmp(dai_link->name, "DPTX_BE") == 0) { 768 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 769 dai_link->init = mt8188_dptx_codec_init; 770 } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { 771 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 772 dai_link->init = mt8188_hdmi_codec_init; 773 } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || 774 strcmp(dai_link->name, "UL_SRC_BE") == 0) { 775 if (!init_mt6359) { 776 dai_link->init = mt8188_mt6359_init; 777 init_mt6359 = true; 778 } 779 } 780 } 781 782 snd_soc_card_set_drvdata(card, priv); 783 784 ret = devm_snd_soc_register_card(&pdev->dev, card); 785 if (ret) 786 dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", 787 __func__); 788 err: 789 of_node_put(platform_node); 790 clean_card_reference(card); 791 return ret; 792 } 793 794 static struct mt8188_card_data mt8188_evb_card = { 795 .name = "mt8188_mt6359", 796 }; 797 798 static const struct of_device_id mt8188_mt6359_dt_match[] = { 799 { 800 .compatible = "mediatek,mt8188-mt6359-evb", 801 .data = &mt8188_evb_card, 802 }, 803 {}, 804 }; 805 MODULE_DEVICE_TABLE(of, mt8188_mt6359_dt_match); 806 807 static struct platform_driver mt8188_mt6359_driver = { 808 .driver = { 809 .name = "mt8188_mt6359", 810 .of_match_table = mt8188_mt6359_dt_match, 811 .pm = &snd_soc_pm_ops, 812 }, 813 .probe = mt8188_mt6359_dev_probe, 814 }; 815 816 module_platform_driver(mt8188_mt6359_driver); 817 818 /* Module information */ 819 MODULE_DESCRIPTION("MT8188-MT6359 ALSA SoC machine driver"); 820 MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>"); 821 MODULE_LICENSE("GPL"); 822 MODULE_ALIAS("mt8188 mt6359 soc card"); 823