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