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/input.h> 10 #include <linux/module.h> 11 #include <linux/of_device.h> 12 #include <linux/pm_runtime.h> 13 #include <sound/jack.h> 14 #include <sound/pcm_params.h> 15 #include <sound/soc.h> 16 #include "mt8188-afe-common.h" 17 #include "../../codecs/nau8825.h" 18 #include "../../codecs/mt6359.h" 19 #include "../common/mtk-afe-platform-driver.h" 20 #include "../common/mtk-soundcard-driver.h" 21 22 #define NAU8825_HS_PRESENT BIT(0) 23 24 /* 25 * Maxim MAX98390 26 */ 27 #define MAX98390_CODEC_DAI "max98390-aif1" 28 #define MAX98390_DEV0_NAME "max98390.0-0038" /* rear right */ 29 #define MAX98390_DEV1_NAME "max98390.0-0039" /* rear left */ 30 #define MAX98390_DEV2_NAME "max98390.0-003a" /* front right */ 31 #define MAX98390_DEV3_NAME "max98390.0-003b" /* front left */ 32 33 /* 34 * Nau88l25 35 */ 36 #define NAU8825_CODEC_DAI "nau8825-hifi" 37 38 /* FE */ 39 SND_SOC_DAILINK_DEFS(playback2, 40 DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 41 DAILINK_COMP_ARRAY(COMP_DUMMY()), 42 DAILINK_COMP_ARRAY(COMP_EMPTY())); 43 44 SND_SOC_DAILINK_DEFS(playback3, 45 DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 46 DAILINK_COMP_ARRAY(COMP_DUMMY()), 47 DAILINK_COMP_ARRAY(COMP_EMPTY())); 48 49 SND_SOC_DAILINK_DEFS(playback6, 50 DAILINK_COMP_ARRAY(COMP_CPU("DL6")), 51 DAILINK_COMP_ARRAY(COMP_DUMMY()), 52 DAILINK_COMP_ARRAY(COMP_EMPTY())); 53 54 SND_SOC_DAILINK_DEFS(playback7, 55 DAILINK_COMP_ARRAY(COMP_CPU("DL7")), 56 DAILINK_COMP_ARRAY(COMP_DUMMY()), 57 DAILINK_COMP_ARRAY(COMP_EMPTY())); 58 59 SND_SOC_DAILINK_DEFS(playback8, 60 DAILINK_COMP_ARRAY(COMP_CPU("DL8")), 61 DAILINK_COMP_ARRAY(COMP_DUMMY()), 62 DAILINK_COMP_ARRAY(COMP_EMPTY())); 63 64 SND_SOC_DAILINK_DEFS(playback10, 65 DAILINK_COMP_ARRAY(COMP_CPU("DL10")), 66 DAILINK_COMP_ARRAY(COMP_DUMMY()), 67 DAILINK_COMP_ARRAY(COMP_EMPTY())); 68 69 SND_SOC_DAILINK_DEFS(playback11, 70 DAILINK_COMP_ARRAY(COMP_CPU("DL11")), 71 DAILINK_COMP_ARRAY(COMP_DUMMY()), 72 DAILINK_COMP_ARRAY(COMP_EMPTY())); 73 74 SND_SOC_DAILINK_DEFS(capture1, 75 DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 76 DAILINK_COMP_ARRAY(COMP_DUMMY()), 77 DAILINK_COMP_ARRAY(COMP_EMPTY())); 78 79 SND_SOC_DAILINK_DEFS(capture2, 80 DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 81 DAILINK_COMP_ARRAY(COMP_DUMMY()), 82 DAILINK_COMP_ARRAY(COMP_EMPTY())); 83 84 SND_SOC_DAILINK_DEFS(capture3, 85 DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 86 DAILINK_COMP_ARRAY(COMP_DUMMY()), 87 DAILINK_COMP_ARRAY(COMP_EMPTY())); 88 89 SND_SOC_DAILINK_DEFS(capture4, 90 DAILINK_COMP_ARRAY(COMP_CPU("UL4")), 91 DAILINK_COMP_ARRAY(COMP_DUMMY()), 92 DAILINK_COMP_ARRAY(COMP_EMPTY())); 93 94 SND_SOC_DAILINK_DEFS(capture5, 95 DAILINK_COMP_ARRAY(COMP_CPU("UL5")), 96 DAILINK_COMP_ARRAY(COMP_DUMMY()), 97 DAILINK_COMP_ARRAY(COMP_EMPTY())); 98 99 SND_SOC_DAILINK_DEFS(capture6, 100 DAILINK_COMP_ARRAY(COMP_CPU("UL6")), 101 DAILINK_COMP_ARRAY(COMP_DUMMY()), 102 DAILINK_COMP_ARRAY(COMP_EMPTY())); 103 104 SND_SOC_DAILINK_DEFS(capture8, 105 DAILINK_COMP_ARRAY(COMP_CPU("UL8")), 106 DAILINK_COMP_ARRAY(COMP_DUMMY()), 107 DAILINK_COMP_ARRAY(COMP_EMPTY())); 108 109 SND_SOC_DAILINK_DEFS(capture9, 110 DAILINK_COMP_ARRAY(COMP_CPU("UL9")), 111 DAILINK_COMP_ARRAY(COMP_DUMMY()), 112 DAILINK_COMP_ARRAY(COMP_EMPTY())); 113 114 SND_SOC_DAILINK_DEFS(capture10, 115 DAILINK_COMP_ARRAY(COMP_CPU("UL10")), 116 DAILINK_COMP_ARRAY(COMP_DUMMY()), 117 DAILINK_COMP_ARRAY(COMP_EMPTY())); 118 119 /* BE */ 120 SND_SOC_DAILINK_DEFS(dl_src, 121 DAILINK_COMP_ARRAY(COMP_CPU("DL_SRC")), 122 DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 123 "mt6359-snd-codec-aif1")), 124 DAILINK_COMP_ARRAY(COMP_EMPTY())); 125 126 SND_SOC_DAILINK_DEFS(dptx, 127 DAILINK_COMP_ARRAY(COMP_CPU("DPTX")), 128 DAILINK_COMP_ARRAY(COMP_DUMMY()), 129 DAILINK_COMP_ARRAY(COMP_EMPTY())); 130 131 SND_SOC_DAILINK_DEFS(etdm1_in, 132 DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_IN")), 133 DAILINK_COMP_ARRAY(COMP_DUMMY()), 134 DAILINK_COMP_ARRAY(COMP_EMPTY())); 135 136 SND_SOC_DAILINK_DEFS(etdm2_in, 137 DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_IN")), 138 DAILINK_COMP_ARRAY(COMP_DUMMY()), 139 DAILINK_COMP_ARRAY(COMP_EMPTY())); 140 141 SND_SOC_DAILINK_DEFS(etdm1_out, 142 DAILINK_COMP_ARRAY(COMP_CPU("ETDM1_OUT")), 143 DAILINK_COMP_ARRAY(COMP_DUMMY()), 144 DAILINK_COMP_ARRAY(COMP_EMPTY())); 145 146 SND_SOC_DAILINK_DEFS(etdm2_out, 147 DAILINK_COMP_ARRAY(COMP_CPU("ETDM2_OUT")), 148 DAILINK_COMP_ARRAY(COMP_DUMMY()), 149 DAILINK_COMP_ARRAY(COMP_EMPTY())); 150 151 SND_SOC_DAILINK_DEFS(etdm3_out, 152 DAILINK_COMP_ARRAY(COMP_CPU("ETDM3_OUT")), 153 DAILINK_COMP_ARRAY(COMP_DUMMY()), 154 DAILINK_COMP_ARRAY(COMP_EMPTY())); 155 156 SND_SOC_DAILINK_DEFS(pcm1, 157 DAILINK_COMP_ARRAY(COMP_CPU("PCM1")), 158 DAILINK_COMP_ARRAY(COMP_DUMMY()), 159 DAILINK_COMP_ARRAY(COMP_EMPTY())); 160 161 SND_SOC_DAILINK_DEFS(ul_src, 162 DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")), 163 DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound", 164 "mt6359-snd-codec-aif1"), 165 COMP_CODEC("dmic-codec", 166 "dmic-hifi")), 167 DAILINK_COMP_ARRAY(COMP_EMPTY())); 168 169 struct mt8188_mt6359_priv { 170 struct snd_soc_jack dp_jack; 171 struct snd_soc_jack hdmi_jack; 172 struct snd_soc_jack headset_jack; 173 void *private_data; 174 }; 175 176 static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = { 177 { 178 .pin = "HDMI", 179 .mask = SND_JACK_LINEOUT, 180 }, 181 }; 182 183 static struct snd_soc_jack_pin mt8188_dp_jack_pins[] = { 184 { 185 .pin = "DP", 186 .mask = SND_JACK_LINEOUT, 187 }, 188 }; 189 190 static struct snd_soc_jack_pin nau8825_jack_pins[] = { 191 { 192 .pin = "Headphone Jack", 193 .mask = SND_JACK_HEADPHONE, 194 }, 195 { 196 .pin = "Headset Mic", 197 .mask = SND_JACK_MICROPHONE, 198 }, 199 }; 200 201 struct mt8188_card_data { 202 const char *name; 203 unsigned long quirk; 204 }; 205 206 static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = { 207 SOC_DAPM_PIN_SWITCH("Ext Spk"), 208 }; 209 210 static const struct snd_soc_dapm_widget mt8188_dumb_spk_widgets[] = { 211 SND_SOC_DAPM_SPK("Ext Spk", NULL), 212 }; 213 214 static const struct snd_kcontrol_new mt8188_dual_spk_controls[] = { 215 SOC_DAPM_PIN_SWITCH("Left Spk"), 216 SOC_DAPM_PIN_SWITCH("Right Spk"), 217 }; 218 219 static const struct snd_soc_dapm_widget mt8188_dual_spk_widgets[] = { 220 SND_SOC_DAPM_SPK("Left Spk", NULL), 221 SND_SOC_DAPM_SPK("Right Spk", NULL), 222 }; 223 224 static const struct snd_kcontrol_new mt8188_rear_spk_controls[] = { 225 SOC_DAPM_PIN_SWITCH("Rear Left Spk"), 226 SOC_DAPM_PIN_SWITCH("Rear Right Spk"), 227 }; 228 229 static const struct snd_soc_dapm_widget mt8188_rear_spk_widgets[] = { 230 SND_SOC_DAPM_SPK("Rear Left Spk", NULL), 231 SND_SOC_DAPM_SPK("Rear Right Spk", NULL), 232 }; 233 234 static const struct snd_soc_dapm_widget mt8188_mt6359_widgets[] = { 235 SND_SOC_DAPM_HP("Headphone", NULL), 236 SND_SOC_DAPM_MIC("Headset Mic", NULL), 237 SND_SOC_DAPM_SINK("HDMI"), 238 SND_SOC_DAPM_SINK("DP"), 239 }; 240 241 static const struct snd_kcontrol_new mt8188_mt6359_controls[] = { 242 SOC_DAPM_PIN_SWITCH("Headphone"), 243 SOC_DAPM_PIN_SWITCH("Headset Mic"), 244 }; 245 246 static const struct snd_soc_dapm_widget mt8188_nau8825_widgets[] = { 247 SND_SOC_DAPM_HP("Headphone Jack", NULL), 248 }; 249 250 static const struct snd_kcontrol_new mt8188_nau8825_controls[] = { 251 SOC_DAPM_PIN_SWITCH("Headphone Jack"), 252 }; 253 254 #define CKSYS_AUD_TOP_CFG 0x032c 255 #define CKSYS_AUD_TOP_MON 0x0330 256 257 static int mt8188_mt6359_mtkaif_calibration(struct snd_soc_pcm_runtime *rtd) 258 { 259 struct snd_soc_component *cmpnt_afe = 260 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); 261 struct snd_soc_component *cmpnt_codec = 262 asoc_rtd_to_codec(rtd, 0)->component; 263 struct mtk_base_afe *afe; 264 struct mt8188_afe_private *afe_priv; 265 struct mtkaif_param *param; 266 int chosen_phase_1, chosen_phase_2; 267 int prev_cycle_1, prev_cycle_2; 268 int test_done_1, test_done_2; 269 int cycle_1, cycle_2; 270 int mtkaif_chosen_phase[MT8188_MTKAIF_MISO_NUM]; 271 int mtkaif_phase_cycle[MT8188_MTKAIF_MISO_NUM]; 272 int mtkaif_calibration_num_phase; 273 bool mtkaif_calibration_ok; 274 unsigned int monitor = 0; 275 int counter; 276 int phase; 277 int i; 278 279 if (!cmpnt_afe) 280 return -EINVAL; 281 282 afe = snd_soc_component_get_drvdata(cmpnt_afe); 283 afe_priv = afe->platform_priv; 284 param = &afe_priv->mtkaif_params; 285 286 dev_dbg(afe->dev, "%s(), start\n", __func__); 287 288 param->mtkaif_calibration_ok = false; 289 for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++) { 290 param->mtkaif_chosen_phase[i] = -1; 291 param->mtkaif_phase_cycle[i] = 0; 292 mtkaif_chosen_phase[i] = -1; 293 mtkaif_phase_cycle[i] = 0; 294 } 295 296 if (IS_ERR(afe_priv->topckgen)) { 297 dev_info(afe->dev, "%s() Cannot find topckgen controller\n", 298 __func__); 299 return 0; 300 } 301 302 pm_runtime_get_sync(afe->dev); 303 mt6359_mtkaif_calibration_enable(cmpnt_codec); 304 305 /* set test type to synchronizer pulse */ 306 regmap_update_bits(afe_priv->topckgen, 307 CKSYS_AUD_TOP_CFG, 0xffff, 0x4); 308 mtkaif_calibration_num_phase = 42; /* mt6359: 0 ~ 42 */ 309 mtkaif_calibration_ok = true; 310 311 for (phase = 0; 312 phase <= mtkaif_calibration_num_phase && mtkaif_calibration_ok; 313 phase++) { 314 mt6359_set_mtkaif_calibration_phase(cmpnt_codec, 315 phase, phase, phase); 316 317 regmap_set_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1); 318 319 test_done_1 = 0; 320 test_done_2 = 0; 321 322 cycle_1 = -1; 323 cycle_2 = -1; 324 325 counter = 0; 326 while (!(test_done_1 & test_done_2)) { 327 regmap_read(afe_priv->topckgen, 328 CKSYS_AUD_TOP_MON, &monitor); 329 test_done_1 = (monitor >> 28) & 0x1; 330 test_done_2 = (monitor >> 29) & 0x1; 331 332 if (test_done_1 == 1) 333 cycle_1 = monitor & 0xf; 334 335 if (test_done_2 == 1) 336 cycle_2 = (monitor >> 4) & 0xf; 337 338 /* handle if never test done */ 339 if (++counter > 10000) { 340 dev_info(afe->dev, "%s(), test fail, cycle_1 %d, cycle_2 %d, monitor 0x%x\n", 341 __func__, 342 cycle_1, cycle_2, monitor); 343 mtkaif_calibration_ok = false; 344 break; 345 } 346 } 347 348 if (phase == 0) { 349 prev_cycle_1 = cycle_1; 350 prev_cycle_2 = cycle_2; 351 } 352 353 if (cycle_1 != prev_cycle_1 && 354 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) { 355 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = phase - 1; 356 mtkaif_phase_cycle[MT8188_MTKAIF_MISO_0] = prev_cycle_1; 357 } 358 359 if (cycle_2 != prev_cycle_2 && 360 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) { 361 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = phase - 1; 362 mtkaif_phase_cycle[MT8188_MTKAIF_MISO_1] = prev_cycle_2; 363 } 364 365 regmap_clear_bits(afe_priv->topckgen, CKSYS_AUD_TOP_CFG, 0x1); 366 367 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] >= 0 && 368 mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] >= 0) 369 break; 370 } 371 372 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] < 0) { 373 mtkaif_calibration_ok = false; 374 chosen_phase_1 = 0; 375 } else { 376 chosen_phase_1 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0]; 377 } 378 379 if (mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] < 0) { 380 mtkaif_calibration_ok = false; 381 chosen_phase_2 = 0; 382 } else { 383 chosen_phase_2 = mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1]; 384 } 385 386 mt6359_set_mtkaif_calibration_phase(cmpnt_codec, 387 chosen_phase_1, 388 chosen_phase_2, 389 0); 390 391 mt6359_mtkaif_calibration_disable(cmpnt_codec); 392 pm_runtime_put(afe->dev); 393 394 param->mtkaif_calibration_ok = mtkaif_calibration_ok; 395 param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_0] = chosen_phase_1; 396 param->mtkaif_chosen_phase[MT8188_MTKAIF_MISO_1] = chosen_phase_2; 397 398 for (i = 0; i < MT8188_MTKAIF_MISO_NUM; i++) 399 param->mtkaif_phase_cycle[i] = mtkaif_phase_cycle[i]; 400 401 dev_info(afe->dev, "%s(), end, calibration ok %d\n", 402 __func__, param->mtkaif_calibration_ok); 403 404 return 0; 405 } 406 407 static int mt8188_mt6359_init(struct snd_soc_pcm_runtime *rtd) 408 { 409 struct snd_soc_component *cmpnt_codec = 410 asoc_rtd_to_codec(rtd, 0)->component; 411 412 /* set mtkaif protocol */ 413 mt6359_set_mtkaif_protocol(cmpnt_codec, 414 MT6359_MTKAIF_PROTOCOL_2_CLK_P2); 415 416 /* mtkaif calibration */ 417 mt8188_mt6359_mtkaif_calibration(rtd); 418 419 return 0; 420 } 421 422 enum { 423 DAI_LINK_DL2_FE, 424 DAI_LINK_DL3_FE, 425 DAI_LINK_DL6_FE, 426 DAI_LINK_DL7_FE, 427 DAI_LINK_DL8_FE, 428 DAI_LINK_DL10_FE, 429 DAI_LINK_DL11_FE, 430 DAI_LINK_UL1_FE, 431 DAI_LINK_UL2_FE, 432 DAI_LINK_UL3_FE, 433 DAI_LINK_UL4_FE, 434 DAI_LINK_UL5_FE, 435 DAI_LINK_UL6_FE, 436 DAI_LINK_UL8_FE, 437 DAI_LINK_UL9_FE, 438 DAI_LINK_UL10_FE, 439 DAI_LINK_DL_SRC_BE, 440 DAI_LINK_DPTX_BE, 441 DAI_LINK_ETDM1_IN_BE, 442 DAI_LINK_ETDM2_IN_BE, 443 DAI_LINK_ETDM1_OUT_BE, 444 DAI_LINK_ETDM2_OUT_BE, 445 DAI_LINK_ETDM3_OUT_BE, 446 DAI_LINK_PCM1_BE, 447 DAI_LINK_UL_SRC_BE, 448 }; 449 450 static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream, 451 struct snd_pcm_hw_params *params) 452 { 453 struct snd_soc_pcm_runtime *rtd = substream->private_data; 454 unsigned int rate = params_rate(params); 455 unsigned int mclk_fs_ratio = 256; 456 unsigned int mclk_fs = rate * mclk_fs_ratio; 457 struct snd_soc_dai *dai = asoc_rtd_to_cpu(rtd, 0); 458 459 return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); 460 } 461 462 static const struct snd_soc_ops mt8188_dptx_ops = { 463 .hw_params = mt8188_dptx_hw_params, 464 }; 465 466 static int mt8188_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 467 struct snd_pcm_hw_params *params) 468 { 469 /* fix BE i2s format to 32bit, clean param mask first */ 470 snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 471 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); 472 473 params_set_format(params, SNDRV_PCM_FORMAT_S32_LE); 474 475 return 0; 476 } 477 478 static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) 479 { 480 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); 481 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 482 int ret = 0; 483 484 ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", 485 SND_JACK_LINEOUT, &priv->hdmi_jack, 486 mt8188_hdmi_jack_pins, 487 ARRAY_SIZE(mt8188_hdmi_jack_pins)); 488 if (ret) { 489 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 490 return ret; 491 } 492 493 ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL); 494 if (ret) { 495 dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", 496 __func__, component->name, ret); 497 return ret; 498 } 499 500 return 0; 501 } 502 503 static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) 504 { 505 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); 506 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 507 int ret = 0; 508 509 ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, 510 &priv->dp_jack, mt8188_dp_jack_pins, 511 ARRAY_SIZE(mt8188_dp_jack_pins)); 512 if (ret) { 513 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 514 return ret; 515 } 516 517 ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL); 518 if (ret) { 519 dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", 520 __func__, component->name, ret); 521 return ret; 522 } 523 524 return 0; 525 } 526 527 static int mt8188_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) 528 { 529 struct snd_soc_card *card = rtd->card; 530 int ret = 0; 531 532 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dumb_spk_widgets, 533 ARRAY_SIZE(mt8188_dumb_spk_widgets)); 534 if (ret) { 535 dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret); 536 return ret; 537 } 538 539 ret = snd_soc_add_card_controls(card, mt8188_dumb_spk_controls, 540 ARRAY_SIZE(mt8188_dumb_spk_controls)); 541 if (ret) { 542 dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret); 543 return ret; 544 } 545 546 return 0; 547 } 548 549 static int mt8188_max98390_hw_params(struct snd_pcm_substream *substream, 550 struct snd_pcm_hw_params *params) 551 { 552 struct snd_soc_pcm_runtime *rtd = substream->private_data; 553 unsigned int bit_width = params_width(params); 554 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 555 struct snd_soc_dai *codec_dai; 556 int i; 557 558 snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0xf, 4, bit_width); 559 560 for_each_rtd_codec_dais(rtd, i, codec_dai) { 561 if (!strcmp(codec_dai->component->name, MAX98390_DEV0_NAME)) 562 snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x3, 4, bit_width); 563 564 if (!strcmp(codec_dai->component->name, MAX98390_DEV1_NAME)) 565 snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x3, 4, bit_width); 566 567 if (!strcmp(codec_dai->component->name, MAX98390_DEV2_NAME)) 568 snd_soc_dai_set_tdm_slot(codec_dai, 0x2, 0x3, 4, bit_width); 569 570 if (!strcmp(codec_dai->component->name, MAX98390_DEV3_NAME)) 571 snd_soc_dai_set_tdm_slot(codec_dai, 0x1, 0x3, 4, bit_width); 572 } 573 return 0; 574 } 575 576 static const struct snd_soc_ops mt8188_max98390_ops = { 577 .hw_params = mt8188_max98390_hw_params, 578 }; 579 580 static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd) 581 { 582 struct snd_soc_card *card = rtd->card; 583 int ret; 584 585 /* add regular speakers dapm route */ 586 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dual_spk_widgets, 587 ARRAY_SIZE(mt8188_dual_spk_widgets)); 588 if (ret) { 589 dev_err(rtd->dev, "unable to add Left/Right Speaker widget, ret %d\n", ret); 590 return ret; 591 } 592 593 ret = snd_soc_add_card_controls(card, mt8188_dual_spk_controls, 594 ARRAY_SIZE(mt8188_dual_spk_controls)); 595 if (ret) { 596 dev_err(rtd->dev, "unable to add Left/Right card controls, ret %d\n", ret); 597 return ret; 598 } 599 600 if (rtd->dai_link->num_codecs <= 2) 601 return 0; 602 603 /* add widgets/controls/dapm for rear speakers */ 604 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_rear_spk_widgets, 605 ARRAY_SIZE(mt8188_rear_spk_widgets)); 606 if (ret) { 607 dev_err(rtd->dev, "unable to add Rear Speaker widget, ret %d\n", ret); 608 /* Don't need to add routes if widget addition failed */ 609 return ret; 610 } 611 612 ret = snd_soc_add_card_controls(card, mt8188_rear_spk_controls, 613 ARRAY_SIZE(mt8188_rear_spk_controls)); 614 if (ret) { 615 dev_err(rtd->dev, "unable to add Rear card controls, ret %d\n", ret); 616 return ret; 617 } 618 619 return 0; 620 } 621 622 static int mt8188_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 623 { 624 struct snd_soc_card *card = rtd->card; 625 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 626 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 627 struct snd_soc_jack *jack = &priv->headset_jack; 628 int ret; 629 630 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets, 631 ARRAY_SIZE(mt8188_nau8825_widgets)); 632 if (ret) { 633 dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret); 634 return ret; 635 } 636 637 ret = snd_soc_add_card_controls(card, mt8188_nau8825_controls, 638 ARRAY_SIZE(mt8188_nau8825_controls)); 639 if (ret) { 640 dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret); 641 return ret; 642 } 643 644 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 645 SND_JACK_HEADSET | SND_JACK_BTN_0 | 646 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 647 SND_JACK_BTN_3, 648 jack, 649 nau8825_jack_pins, 650 ARRAY_SIZE(nau8825_jack_pins)); 651 if (ret) { 652 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 653 return ret; 654 } 655 656 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 657 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 658 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 659 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 660 ret = snd_soc_component_set_jack(component, jack, NULL); 661 662 if (ret) { 663 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 664 return ret; 665 } 666 667 return 0; 668 }; 669 670 static void mt8188_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd) 671 { 672 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 673 674 snd_soc_component_set_jack(component, NULL, NULL); 675 } 676 677 static int mt8188_nau8825_hw_params(struct snd_pcm_substream *substream, 678 struct snd_pcm_hw_params *params) 679 { 680 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 681 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 682 unsigned int rate = params_rate(params); 683 unsigned int bit_width = params_width(params); 684 int clk_freq, ret; 685 686 clk_freq = rate * 2 * bit_width; 687 688 /* Configure clock for codec */ 689 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, 690 SND_SOC_CLOCK_IN); 691 if (ret < 0) { 692 dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); 693 return ret; 694 } 695 696 /* Configure pll for codec */ 697 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, 698 params_rate(params) * 256); 699 if (ret < 0) { 700 dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); 701 return ret; 702 } 703 704 return 0; 705 } 706 707 static const struct snd_soc_ops mt8188_nau8825_ops = { 708 .hw_params = mt8188_nau8825_hw_params, 709 }; 710 static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { 711 /* FE */ 712 [DAI_LINK_DL2_FE] = { 713 .name = "DL2_FE", 714 .stream_name = "DL2 Playback", 715 .trigger = { 716 SND_SOC_DPCM_TRIGGER_POST, 717 SND_SOC_DPCM_TRIGGER_POST, 718 }, 719 .dynamic = 1, 720 .dpcm_playback = 1, 721 SND_SOC_DAILINK_REG(playback2), 722 }, 723 [DAI_LINK_DL3_FE] = { 724 .name = "DL3_FE", 725 .stream_name = "DL3 Playback", 726 .trigger = { 727 SND_SOC_DPCM_TRIGGER_POST, 728 SND_SOC_DPCM_TRIGGER_POST, 729 }, 730 .dynamic = 1, 731 .dpcm_playback = 1, 732 SND_SOC_DAILINK_REG(playback3), 733 }, 734 [DAI_LINK_DL6_FE] = { 735 .name = "DL6_FE", 736 .stream_name = "DL6 Playback", 737 .trigger = { 738 SND_SOC_DPCM_TRIGGER_POST, 739 SND_SOC_DPCM_TRIGGER_POST, 740 }, 741 .dynamic = 1, 742 .dpcm_playback = 1, 743 SND_SOC_DAILINK_REG(playback6), 744 }, 745 [DAI_LINK_DL7_FE] = { 746 .name = "DL7_FE", 747 .stream_name = "DL7 Playback", 748 .trigger = { 749 SND_SOC_DPCM_TRIGGER_PRE, 750 SND_SOC_DPCM_TRIGGER_PRE, 751 }, 752 .dynamic = 1, 753 .dpcm_playback = 1, 754 SND_SOC_DAILINK_REG(playback7), 755 }, 756 [DAI_LINK_DL8_FE] = { 757 .name = "DL8_FE", 758 .stream_name = "DL8 Playback", 759 .trigger = { 760 SND_SOC_DPCM_TRIGGER_POST, 761 SND_SOC_DPCM_TRIGGER_POST, 762 }, 763 .dynamic = 1, 764 .dpcm_playback = 1, 765 SND_SOC_DAILINK_REG(playback8), 766 }, 767 [DAI_LINK_DL10_FE] = { 768 .name = "DL10_FE", 769 .stream_name = "DL10 Playback", 770 .trigger = { 771 SND_SOC_DPCM_TRIGGER_POST, 772 SND_SOC_DPCM_TRIGGER_POST, 773 }, 774 .dynamic = 1, 775 .dpcm_playback = 1, 776 SND_SOC_DAILINK_REG(playback10), 777 }, 778 [DAI_LINK_DL11_FE] = { 779 .name = "DL11_FE", 780 .stream_name = "DL11 Playback", 781 .trigger = { 782 SND_SOC_DPCM_TRIGGER_POST, 783 SND_SOC_DPCM_TRIGGER_POST, 784 }, 785 .dynamic = 1, 786 .dpcm_playback = 1, 787 SND_SOC_DAILINK_REG(playback11), 788 }, 789 [DAI_LINK_UL1_FE] = { 790 .name = "UL1_FE", 791 .stream_name = "UL1 Capture", 792 .trigger = { 793 SND_SOC_DPCM_TRIGGER_PRE, 794 SND_SOC_DPCM_TRIGGER_PRE, 795 }, 796 .dynamic = 1, 797 .dpcm_capture = 1, 798 SND_SOC_DAILINK_REG(capture1), 799 }, 800 [DAI_LINK_UL2_FE] = { 801 .name = "UL2_FE", 802 .stream_name = "UL2 Capture", 803 .trigger = { 804 SND_SOC_DPCM_TRIGGER_POST, 805 SND_SOC_DPCM_TRIGGER_POST, 806 }, 807 .dynamic = 1, 808 .dpcm_capture = 1, 809 SND_SOC_DAILINK_REG(capture2), 810 }, 811 [DAI_LINK_UL3_FE] = { 812 .name = "UL3_FE", 813 .stream_name = "UL3 Capture", 814 .trigger = { 815 SND_SOC_DPCM_TRIGGER_POST, 816 SND_SOC_DPCM_TRIGGER_POST, 817 }, 818 .dynamic = 1, 819 .dpcm_capture = 1, 820 SND_SOC_DAILINK_REG(capture3), 821 }, 822 [DAI_LINK_UL4_FE] = { 823 .name = "UL4_FE", 824 .stream_name = "UL4 Capture", 825 .trigger = { 826 SND_SOC_DPCM_TRIGGER_POST, 827 SND_SOC_DPCM_TRIGGER_POST, 828 }, 829 .dynamic = 1, 830 .dpcm_capture = 1, 831 SND_SOC_DAILINK_REG(capture4), 832 }, 833 [DAI_LINK_UL5_FE] = { 834 .name = "UL5_FE", 835 .stream_name = "UL5 Capture", 836 .trigger = { 837 SND_SOC_DPCM_TRIGGER_POST, 838 SND_SOC_DPCM_TRIGGER_POST, 839 }, 840 .dynamic = 1, 841 .dpcm_capture = 1, 842 SND_SOC_DAILINK_REG(capture5), 843 }, 844 [DAI_LINK_UL6_FE] = { 845 .name = "UL6_FE", 846 .stream_name = "UL6 Capture", 847 .trigger = { 848 SND_SOC_DPCM_TRIGGER_PRE, 849 SND_SOC_DPCM_TRIGGER_PRE, 850 }, 851 .dynamic = 1, 852 .dpcm_capture = 1, 853 SND_SOC_DAILINK_REG(capture6), 854 }, 855 [DAI_LINK_UL8_FE] = { 856 .name = "UL8_FE", 857 .stream_name = "UL8 Capture", 858 .trigger = { 859 SND_SOC_DPCM_TRIGGER_POST, 860 SND_SOC_DPCM_TRIGGER_POST, 861 }, 862 .dynamic = 1, 863 .dpcm_capture = 1, 864 SND_SOC_DAILINK_REG(capture8), 865 }, 866 [DAI_LINK_UL9_FE] = { 867 .name = "UL9_FE", 868 .stream_name = "UL9 Capture", 869 .trigger = { 870 SND_SOC_DPCM_TRIGGER_POST, 871 SND_SOC_DPCM_TRIGGER_POST, 872 }, 873 .dynamic = 1, 874 .dpcm_capture = 1, 875 SND_SOC_DAILINK_REG(capture9), 876 }, 877 [DAI_LINK_UL10_FE] = { 878 .name = "UL10_FE", 879 .stream_name = "UL10 Capture", 880 .trigger = { 881 SND_SOC_DPCM_TRIGGER_POST, 882 SND_SOC_DPCM_TRIGGER_POST, 883 }, 884 .dynamic = 1, 885 .dpcm_capture = 1, 886 SND_SOC_DAILINK_REG(capture10), 887 }, 888 /* BE */ 889 [DAI_LINK_DL_SRC_BE] = { 890 .name = "DL_SRC_BE", 891 .no_pcm = 1, 892 .dpcm_playback = 1, 893 SND_SOC_DAILINK_REG(dl_src), 894 }, 895 [DAI_LINK_DPTX_BE] = { 896 .name = "DPTX_BE", 897 .ops = &mt8188_dptx_ops, 898 .be_hw_params_fixup = mt8188_dptx_hw_params_fixup, 899 .no_pcm = 1, 900 .dpcm_playback = 1, 901 SND_SOC_DAILINK_REG(dptx), 902 }, 903 [DAI_LINK_ETDM1_IN_BE] = { 904 .name = "ETDM1_IN_BE", 905 .no_pcm = 1, 906 .dai_fmt = SND_SOC_DAIFMT_I2S | 907 SND_SOC_DAIFMT_NB_NF | 908 SND_SOC_DAIFMT_CBP_CFP, 909 .dpcm_capture = 1, 910 .ignore_suspend = 1, 911 SND_SOC_DAILINK_REG(etdm1_in), 912 }, 913 [DAI_LINK_ETDM2_IN_BE] = { 914 .name = "ETDM2_IN_BE", 915 .no_pcm = 1, 916 .dai_fmt = SND_SOC_DAIFMT_I2S | 917 SND_SOC_DAIFMT_NB_NF | 918 SND_SOC_DAIFMT_CBP_CFP, 919 .dpcm_capture = 1, 920 SND_SOC_DAILINK_REG(etdm2_in), 921 }, 922 [DAI_LINK_ETDM1_OUT_BE] = { 923 .name = "ETDM1_OUT_BE", 924 .no_pcm = 1, 925 .dai_fmt = SND_SOC_DAIFMT_I2S | 926 SND_SOC_DAIFMT_NB_NF | 927 SND_SOC_DAIFMT_CBC_CFC, 928 .dpcm_playback = 1, 929 SND_SOC_DAILINK_REG(etdm1_out), 930 }, 931 [DAI_LINK_ETDM2_OUT_BE] = { 932 .name = "ETDM2_OUT_BE", 933 .no_pcm = 1, 934 .dai_fmt = SND_SOC_DAIFMT_I2S | 935 SND_SOC_DAIFMT_NB_NF | 936 SND_SOC_DAIFMT_CBC_CFC, 937 .dpcm_playback = 1, 938 SND_SOC_DAILINK_REG(etdm2_out), 939 }, 940 [DAI_LINK_ETDM3_OUT_BE] = { 941 .name = "ETDM3_OUT_BE", 942 .no_pcm = 1, 943 .dai_fmt = SND_SOC_DAIFMT_I2S | 944 SND_SOC_DAIFMT_NB_NF | 945 SND_SOC_DAIFMT_CBC_CFC, 946 .dpcm_playback = 1, 947 SND_SOC_DAILINK_REG(etdm3_out), 948 }, 949 [DAI_LINK_PCM1_BE] = { 950 .name = "PCM1_BE", 951 .no_pcm = 1, 952 .dai_fmt = SND_SOC_DAIFMT_I2S | 953 SND_SOC_DAIFMT_NB_NF | 954 SND_SOC_DAIFMT_CBC_CFC, 955 .dpcm_playback = 1, 956 .dpcm_capture = 1, 957 SND_SOC_DAILINK_REG(pcm1), 958 }, 959 [DAI_LINK_UL_SRC_BE] = { 960 .name = "UL_SRC_BE", 961 .no_pcm = 1, 962 .dpcm_capture = 1, 963 SND_SOC_DAILINK_REG(ul_src), 964 }, 965 }; 966 967 static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) 968 { 969 struct snd_ctl_elem_id sid; 970 971 memset(&sid, 0, sizeof(sid)); 972 strcpy(sid.name, name); 973 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 974 return snd_ctl_find_id(card, &sid); 975 } 976 977 static void mt8188_fixup_controls(struct snd_soc_card *card) 978 { 979 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 980 struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data; 981 struct snd_kcontrol *kctl; 982 983 if (card_data->quirk & NAU8825_HS_PRESENT) { 984 struct snd_soc_dapm_widget *w, *next_w; 985 986 for_each_card_widgets_safe(card, w, next_w) { 987 if (strcmp(w->name, "Headphone")) 988 continue; 989 990 snd_soc_dapm_free_widget(w); 991 } 992 993 kctl = ctl_find(card->snd_card, "Headphone Switch"); 994 if (kctl) 995 snd_ctl_remove(card->snd_card, kctl); 996 else 997 dev_warn(card->dev, "Cannot find ctl : Headphone Switch\n"); 998 } 999 } 1000 1001 static struct snd_soc_card mt8188_mt6359_soc_card = { 1002 .owner = THIS_MODULE, 1003 .dai_link = mt8188_mt6359_dai_links, 1004 .num_links = ARRAY_SIZE(mt8188_mt6359_dai_links), 1005 .dapm_widgets = mt8188_mt6359_widgets, 1006 .num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets), 1007 .controls = mt8188_mt6359_controls, 1008 .num_controls = ARRAY_SIZE(mt8188_mt6359_controls), 1009 .fixup_controls = mt8188_fixup_controls, 1010 }; 1011 1012 static int mt8188_mt6359_dev_probe(struct platform_device *pdev) 1013 { 1014 struct snd_soc_card *card = &mt8188_mt6359_soc_card; 1015 struct device_node *platform_node; 1016 struct mt8188_mt6359_priv *priv; 1017 struct mt8188_card_data *card_data; 1018 struct snd_soc_dai_link *dai_link; 1019 bool init_mt6359 = false; 1020 bool init_nau8825 = false; 1021 bool init_max98390 = false; 1022 bool init_dumb = false; 1023 int ret, i; 1024 1025 card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev); 1026 card->dev = &pdev->dev; 1027 1028 ret = snd_soc_of_parse_card_name(card, "model"); 1029 if (ret) 1030 return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n", 1031 __func__); 1032 1033 if (!card->name) 1034 card->name = card_data->name; 1035 1036 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1037 if (!priv) 1038 return -ENOMEM; 1039 1040 if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) { 1041 ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); 1042 if (ret) 1043 return ret; 1044 } 1045 1046 platform_node = of_parse_phandle(pdev->dev.of_node, 1047 "mediatek,platform", 0); 1048 if (!platform_node) { 1049 ret = -EINVAL; 1050 return dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); 1051 } 1052 1053 ret = parse_dai_link_info(card); 1054 if (ret) 1055 goto err; 1056 1057 for_each_card_prelinks(card, i, dai_link) { 1058 if (!dai_link->platforms->name) 1059 dai_link->platforms->of_node = platform_node; 1060 1061 if (strcmp(dai_link->name, "DPTX_BE") == 0) { 1062 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 1063 dai_link->init = mt8188_dptx_codec_init; 1064 } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { 1065 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 1066 dai_link->init = mt8188_hdmi_codec_init; 1067 } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || 1068 strcmp(dai_link->name, "UL_SRC_BE") == 0) { 1069 if (!init_mt6359) { 1070 dai_link->init = mt8188_mt6359_init; 1071 init_mt6359 = true; 1072 } 1073 } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 || 1074 strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || 1075 strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || 1076 strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { 1077 if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { 1078 dai_link->ops = &mt8188_max98390_ops; 1079 if (!init_max98390) { 1080 dai_link->init = mt8188_max98390_codec_init; 1081 init_max98390 = true; 1082 } 1083 } else if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) { 1084 dai_link->ops = &mt8188_nau8825_ops; 1085 if (!init_nau8825) { 1086 dai_link->init = mt8188_nau8825_codec_init; 1087 dai_link->exit = mt8188_nau8825_codec_exit; 1088 init_nau8825 = true; 1089 } 1090 } else { 1091 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { 1092 if (!init_dumb) { 1093 dai_link->init = mt8188_dumb_amp_init; 1094 init_dumb = true; 1095 } 1096 } 1097 } 1098 } 1099 } 1100 1101 priv->private_data = card_data; 1102 snd_soc_card_set_drvdata(card, priv); 1103 1104 ret = devm_snd_soc_register_card(&pdev->dev, card); 1105 if (ret) 1106 dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", 1107 __func__); 1108 err: 1109 of_node_put(platform_node); 1110 clean_card_reference(card); 1111 return ret; 1112 } 1113 1114 static struct mt8188_card_data mt8188_evb_card = { 1115 .name = "mt8188_mt6359", 1116 }; 1117 1118 static struct mt8188_card_data mt8188_nau8825_card = { 1119 .name = "mt8188_nau8825", 1120 .quirk = NAU8825_HS_PRESENT, 1121 }; 1122 1123 static const struct of_device_id mt8188_mt6359_dt_match[] = { 1124 { .compatible = "mediatek,mt8188-mt6359-evb", .data = &mt8188_evb_card, }, 1125 { .compatible = "mediatek,mt8188-nau8825", .data = &mt8188_nau8825_card, }, 1126 { /* sentinel */ }, 1127 }; 1128 MODULE_DEVICE_TABLE(of, mt8188_mt6359_dt_match); 1129 1130 static struct platform_driver mt8188_mt6359_driver = { 1131 .driver = { 1132 .name = "mt8188_mt6359", 1133 .of_match_table = mt8188_mt6359_dt_match, 1134 .pm = &snd_soc_pm_ops, 1135 }, 1136 .probe = mt8188_mt6359_dev_probe, 1137 }; 1138 1139 module_platform_driver(mt8188_mt6359_driver); 1140 1141 /* Module information */ 1142 MODULE_DESCRIPTION("MT8188-MT6359 ALSA SoC machine driver"); 1143 MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>"); 1144 MODULE_LICENSE("GPL"); 1145 MODULE_ALIAS("mt8188 mt6359 soc card"); 1146