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 498 return ret; 499 } 500 501 static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) 502 { 503 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); 504 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 505 int ret = 0; 506 507 ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, 508 &priv->dp_jack, mt8188_dp_jack_pins, 509 ARRAY_SIZE(mt8188_dp_jack_pins)); 510 if (ret) { 511 dev_info(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); 512 return ret; 513 } 514 515 ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL); 516 if (ret) 517 dev_info(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", 518 __func__, component->name, ret); 519 520 return ret; 521 } 522 523 static int mt8188_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) 524 { 525 struct snd_soc_card *card = rtd->card; 526 int ret = 0; 527 528 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dumb_spk_widgets, 529 ARRAY_SIZE(mt8188_dumb_spk_widgets)); 530 if (ret) { 531 dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret); 532 return ret; 533 } 534 535 ret = snd_soc_add_card_controls(card, mt8188_dumb_spk_controls, 536 ARRAY_SIZE(mt8188_dumb_spk_controls)); 537 if (ret) { 538 dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret); 539 return ret; 540 } 541 542 return ret; 543 } 544 545 static int mt8188_max98390_hw_params(struct snd_pcm_substream *substream, 546 struct snd_pcm_hw_params *params) 547 { 548 struct snd_soc_pcm_runtime *rtd = substream->private_data; 549 unsigned int bit_width = params_width(params); 550 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 551 struct snd_soc_dai *codec_dai; 552 int i; 553 554 snd_soc_dai_set_tdm_slot(cpu_dai, 0xf, 0xf, 4, bit_width); 555 556 for_each_rtd_codec_dais(rtd, i, codec_dai) { 557 if (!strcmp(codec_dai->component->name, MAX98390_DEV0_NAME)) 558 snd_soc_dai_set_tdm_slot(codec_dai, 0x8, 0x3, 4, bit_width); 559 560 if (!strcmp(codec_dai->component->name, MAX98390_DEV1_NAME)) 561 snd_soc_dai_set_tdm_slot(codec_dai, 0x4, 0x3, 4, bit_width); 562 563 if (!strcmp(codec_dai->component->name, MAX98390_DEV2_NAME)) 564 snd_soc_dai_set_tdm_slot(codec_dai, 0x2, 0x3, 4, bit_width); 565 566 if (!strcmp(codec_dai->component->name, MAX98390_DEV3_NAME)) 567 snd_soc_dai_set_tdm_slot(codec_dai, 0x1, 0x3, 4, bit_width); 568 } 569 return 0; 570 } 571 572 static const struct snd_soc_ops mt8188_max98390_ops = { 573 .hw_params = mt8188_max98390_hw_params, 574 }; 575 576 static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd) 577 { 578 struct snd_soc_card *card = rtd->card; 579 int ret; 580 581 /* add regular speakers dapm route */ 582 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_dual_spk_widgets, 583 ARRAY_SIZE(mt8188_dual_spk_widgets)); 584 if (ret) { 585 dev_err(rtd->dev, "unable to add Left/Right Speaker widget, ret %d\n", ret); 586 return ret; 587 } 588 589 ret = snd_soc_add_card_controls(card, mt8188_dual_spk_controls, 590 ARRAY_SIZE(mt8188_dual_spk_controls)); 591 if (ret) { 592 dev_err(rtd->dev, "unable to add Left/Right card controls, ret %d\n", ret); 593 return ret; 594 } 595 596 if (rtd->dai_link->num_codecs <= 2) 597 return ret; 598 599 /* add widgets/controls/dapm for rear speakers */ 600 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_rear_spk_widgets, 601 ARRAY_SIZE(mt8188_rear_spk_widgets)); 602 if (ret) { 603 dev_err(rtd->dev, "unable to add Rear Speaker widget, ret %d\n", ret); 604 /* Don't need to add routes if widget addition failed */ 605 return ret; 606 } 607 608 ret = snd_soc_add_card_controls(card, mt8188_rear_spk_controls, 609 ARRAY_SIZE(mt8188_rear_spk_controls)); 610 if (ret) { 611 dev_err(rtd->dev, "unable to add Rear card controls, ret %d\n", ret); 612 return ret; 613 } 614 615 return ret; 616 } 617 618 static int mt8188_nau8825_codec_init(struct snd_soc_pcm_runtime *rtd) 619 { 620 struct snd_soc_card *card = rtd->card; 621 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 622 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 623 struct snd_soc_jack *jack = &priv->headset_jack; 624 int ret; 625 626 ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets, 627 ARRAY_SIZE(mt8188_nau8825_widgets)); 628 if (ret) { 629 dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret); 630 return ret; 631 } 632 633 ret = snd_soc_add_card_controls(card, mt8188_nau8825_controls, 634 ARRAY_SIZE(mt8188_nau8825_controls)); 635 if (ret) { 636 dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret); 637 return ret; 638 } 639 640 ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", 641 SND_JACK_HEADSET | SND_JACK_BTN_0 | 642 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 643 SND_JACK_BTN_3, 644 jack, 645 nau8825_jack_pins, 646 ARRAY_SIZE(nau8825_jack_pins)); 647 if (ret) { 648 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 649 return ret; 650 } 651 652 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 653 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 654 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 655 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 656 ret = snd_soc_component_set_jack(component, jack, NULL); 657 658 if (ret) { 659 dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); 660 return ret; 661 } 662 663 return ret; 664 }; 665 666 static void mt8188_nau8825_codec_exit(struct snd_soc_pcm_runtime *rtd) 667 { 668 struct snd_soc_component *component = asoc_rtd_to_codec(rtd, 0)->component; 669 670 snd_soc_component_set_jack(component, NULL, NULL); 671 } 672 673 static int mt8188_nau8825_hw_params(struct snd_pcm_substream *substream, 674 struct snd_pcm_hw_params *params) 675 { 676 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 677 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 678 unsigned int rate = params_rate(params); 679 unsigned int bit_width = params_width(params); 680 int clk_freq, ret; 681 682 clk_freq = rate * 2 * bit_width; 683 684 /* Configure clock for codec */ 685 ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0, 686 SND_SOC_CLOCK_IN); 687 if (ret < 0) { 688 dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret); 689 return ret; 690 } 691 692 /* Configure pll for codec */ 693 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq, 694 params_rate(params) * 256); 695 if (ret < 0) { 696 dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret); 697 return ret; 698 } 699 700 return ret; 701 } 702 703 static const struct snd_soc_ops mt8188_nau8825_ops = { 704 .hw_params = mt8188_nau8825_hw_params, 705 }; 706 static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { 707 /* FE */ 708 [DAI_LINK_DL2_FE] = { 709 .name = "DL2_FE", 710 .stream_name = "DL2 Playback", 711 .trigger = { 712 SND_SOC_DPCM_TRIGGER_POST, 713 SND_SOC_DPCM_TRIGGER_POST, 714 }, 715 .dynamic = 1, 716 .dpcm_playback = 1, 717 SND_SOC_DAILINK_REG(playback2), 718 }, 719 [DAI_LINK_DL3_FE] = { 720 .name = "DL3_FE", 721 .stream_name = "DL3 Playback", 722 .trigger = { 723 SND_SOC_DPCM_TRIGGER_POST, 724 SND_SOC_DPCM_TRIGGER_POST, 725 }, 726 .dynamic = 1, 727 .dpcm_playback = 1, 728 SND_SOC_DAILINK_REG(playback3), 729 }, 730 [DAI_LINK_DL6_FE] = { 731 .name = "DL6_FE", 732 .stream_name = "DL6 Playback", 733 .trigger = { 734 SND_SOC_DPCM_TRIGGER_POST, 735 SND_SOC_DPCM_TRIGGER_POST, 736 }, 737 .dynamic = 1, 738 .dpcm_playback = 1, 739 SND_SOC_DAILINK_REG(playback6), 740 }, 741 [DAI_LINK_DL7_FE] = { 742 .name = "DL7_FE", 743 .stream_name = "DL7 Playback", 744 .trigger = { 745 SND_SOC_DPCM_TRIGGER_PRE, 746 SND_SOC_DPCM_TRIGGER_PRE, 747 }, 748 .dynamic = 1, 749 .dpcm_playback = 1, 750 SND_SOC_DAILINK_REG(playback7), 751 }, 752 [DAI_LINK_DL8_FE] = { 753 .name = "DL8_FE", 754 .stream_name = "DL8 Playback", 755 .trigger = { 756 SND_SOC_DPCM_TRIGGER_POST, 757 SND_SOC_DPCM_TRIGGER_POST, 758 }, 759 .dynamic = 1, 760 .dpcm_playback = 1, 761 SND_SOC_DAILINK_REG(playback8), 762 }, 763 [DAI_LINK_DL10_FE] = { 764 .name = "DL10_FE", 765 .stream_name = "DL10 Playback", 766 .trigger = { 767 SND_SOC_DPCM_TRIGGER_POST, 768 SND_SOC_DPCM_TRIGGER_POST, 769 }, 770 .dynamic = 1, 771 .dpcm_playback = 1, 772 SND_SOC_DAILINK_REG(playback10), 773 }, 774 [DAI_LINK_DL11_FE] = { 775 .name = "DL11_FE", 776 .stream_name = "DL11 Playback", 777 .trigger = { 778 SND_SOC_DPCM_TRIGGER_POST, 779 SND_SOC_DPCM_TRIGGER_POST, 780 }, 781 .dynamic = 1, 782 .dpcm_playback = 1, 783 SND_SOC_DAILINK_REG(playback11), 784 }, 785 [DAI_LINK_UL1_FE] = { 786 .name = "UL1_FE", 787 .stream_name = "UL1 Capture", 788 .trigger = { 789 SND_SOC_DPCM_TRIGGER_PRE, 790 SND_SOC_DPCM_TRIGGER_PRE, 791 }, 792 .dynamic = 1, 793 .dpcm_capture = 1, 794 SND_SOC_DAILINK_REG(capture1), 795 }, 796 [DAI_LINK_UL2_FE] = { 797 .name = "UL2_FE", 798 .stream_name = "UL2 Capture", 799 .trigger = { 800 SND_SOC_DPCM_TRIGGER_POST, 801 SND_SOC_DPCM_TRIGGER_POST, 802 }, 803 .dynamic = 1, 804 .dpcm_capture = 1, 805 SND_SOC_DAILINK_REG(capture2), 806 }, 807 [DAI_LINK_UL3_FE] = { 808 .name = "UL3_FE", 809 .stream_name = "UL3 Capture", 810 .trigger = { 811 SND_SOC_DPCM_TRIGGER_POST, 812 SND_SOC_DPCM_TRIGGER_POST, 813 }, 814 .dynamic = 1, 815 .dpcm_capture = 1, 816 SND_SOC_DAILINK_REG(capture3), 817 }, 818 [DAI_LINK_UL4_FE] = { 819 .name = "UL4_FE", 820 .stream_name = "UL4 Capture", 821 .trigger = { 822 SND_SOC_DPCM_TRIGGER_POST, 823 SND_SOC_DPCM_TRIGGER_POST, 824 }, 825 .dynamic = 1, 826 .dpcm_capture = 1, 827 SND_SOC_DAILINK_REG(capture4), 828 }, 829 [DAI_LINK_UL5_FE] = { 830 .name = "UL5_FE", 831 .stream_name = "UL5 Capture", 832 .trigger = { 833 SND_SOC_DPCM_TRIGGER_POST, 834 SND_SOC_DPCM_TRIGGER_POST, 835 }, 836 .dynamic = 1, 837 .dpcm_capture = 1, 838 SND_SOC_DAILINK_REG(capture5), 839 }, 840 [DAI_LINK_UL6_FE] = { 841 .name = "UL6_FE", 842 .stream_name = "UL6 Capture", 843 .trigger = { 844 SND_SOC_DPCM_TRIGGER_PRE, 845 SND_SOC_DPCM_TRIGGER_PRE, 846 }, 847 .dynamic = 1, 848 .dpcm_capture = 1, 849 SND_SOC_DAILINK_REG(capture6), 850 }, 851 [DAI_LINK_UL8_FE] = { 852 .name = "UL8_FE", 853 .stream_name = "UL8 Capture", 854 .trigger = { 855 SND_SOC_DPCM_TRIGGER_POST, 856 SND_SOC_DPCM_TRIGGER_POST, 857 }, 858 .dynamic = 1, 859 .dpcm_capture = 1, 860 SND_SOC_DAILINK_REG(capture8), 861 }, 862 [DAI_LINK_UL9_FE] = { 863 .name = "UL9_FE", 864 .stream_name = "UL9 Capture", 865 .trigger = { 866 SND_SOC_DPCM_TRIGGER_POST, 867 SND_SOC_DPCM_TRIGGER_POST, 868 }, 869 .dynamic = 1, 870 .dpcm_capture = 1, 871 SND_SOC_DAILINK_REG(capture9), 872 }, 873 [DAI_LINK_UL10_FE] = { 874 .name = "UL10_FE", 875 .stream_name = "UL10 Capture", 876 .trigger = { 877 SND_SOC_DPCM_TRIGGER_POST, 878 SND_SOC_DPCM_TRIGGER_POST, 879 }, 880 .dynamic = 1, 881 .dpcm_capture = 1, 882 SND_SOC_DAILINK_REG(capture10), 883 }, 884 /* BE */ 885 [DAI_LINK_DL_SRC_BE] = { 886 .name = "DL_SRC_BE", 887 .no_pcm = 1, 888 .dpcm_playback = 1, 889 SND_SOC_DAILINK_REG(dl_src), 890 }, 891 [DAI_LINK_DPTX_BE] = { 892 .name = "DPTX_BE", 893 .ops = &mt8188_dptx_ops, 894 .be_hw_params_fixup = mt8188_dptx_hw_params_fixup, 895 .no_pcm = 1, 896 .dpcm_playback = 1, 897 SND_SOC_DAILINK_REG(dptx), 898 }, 899 [DAI_LINK_ETDM1_IN_BE] = { 900 .name = "ETDM1_IN_BE", 901 .no_pcm = 1, 902 .dai_fmt = SND_SOC_DAIFMT_I2S | 903 SND_SOC_DAIFMT_NB_NF | 904 SND_SOC_DAIFMT_CBP_CFP, 905 .dpcm_capture = 1, 906 .ignore_suspend = 1, 907 SND_SOC_DAILINK_REG(etdm1_in), 908 }, 909 [DAI_LINK_ETDM2_IN_BE] = { 910 .name = "ETDM2_IN_BE", 911 .no_pcm = 1, 912 .dai_fmt = SND_SOC_DAIFMT_I2S | 913 SND_SOC_DAIFMT_NB_NF | 914 SND_SOC_DAIFMT_CBP_CFP, 915 .dpcm_capture = 1, 916 SND_SOC_DAILINK_REG(etdm2_in), 917 }, 918 [DAI_LINK_ETDM1_OUT_BE] = { 919 .name = "ETDM1_OUT_BE", 920 .no_pcm = 1, 921 .dai_fmt = SND_SOC_DAIFMT_I2S | 922 SND_SOC_DAIFMT_NB_NF | 923 SND_SOC_DAIFMT_CBC_CFC, 924 .dpcm_playback = 1, 925 SND_SOC_DAILINK_REG(etdm1_out), 926 }, 927 [DAI_LINK_ETDM2_OUT_BE] = { 928 .name = "ETDM2_OUT_BE", 929 .no_pcm = 1, 930 .dai_fmt = SND_SOC_DAIFMT_I2S | 931 SND_SOC_DAIFMT_NB_NF | 932 SND_SOC_DAIFMT_CBC_CFC, 933 .dpcm_playback = 1, 934 SND_SOC_DAILINK_REG(etdm2_out), 935 }, 936 [DAI_LINK_ETDM3_OUT_BE] = { 937 .name = "ETDM3_OUT_BE", 938 .no_pcm = 1, 939 .dai_fmt = SND_SOC_DAIFMT_I2S | 940 SND_SOC_DAIFMT_NB_NF | 941 SND_SOC_DAIFMT_CBC_CFC, 942 .dpcm_playback = 1, 943 SND_SOC_DAILINK_REG(etdm3_out), 944 }, 945 [DAI_LINK_PCM1_BE] = { 946 .name = "PCM1_BE", 947 .no_pcm = 1, 948 .dai_fmt = SND_SOC_DAIFMT_I2S | 949 SND_SOC_DAIFMT_NB_NF | 950 SND_SOC_DAIFMT_CBC_CFC, 951 .dpcm_playback = 1, 952 .dpcm_capture = 1, 953 SND_SOC_DAILINK_REG(pcm1), 954 }, 955 [DAI_LINK_UL_SRC_BE] = { 956 .name = "UL_SRC_BE", 957 .no_pcm = 1, 958 .dpcm_capture = 1, 959 SND_SOC_DAILINK_REG(ul_src), 960 }, 961 }; 962 963 static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) 964 { 965 struct snd_ctl_elem_id sid; 966 967 memset(&sid, 0, sizeof(sid)); 968 strcpy(sid.name, name); 969 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 970 return snd_ctl_find_id(card, &sid); 971 } 972 973 static void mt8188_fixup_controls(struct snd_soc_card *card) 974 { 975 struct mt8188_mt6359_priv *priv = snd_soc_card_get_drvdata(card); 976 struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data; 977 struct snd_kcontrol *kctl; 978 979 if (card_data->quirk & NAU8825_HS_PRESENT) { 980 struct snd_soc_dapm_widget *w, *next_w; 981 982 for_each_card_widgets_safe(card, w, next_w) { 983 if (strcmp(w->name, "Headphone")) 984 continue; 985 986 snd_soc_dapm_free_widget(w); 987 } 988 989 kctl = ctl_find(card->snd_card, "Headphone Switch"); 990 if (kctl) 991 snd_ctl_remove(card->snd_card, kctl); 992 else 993 dev_warn(card->dev, "Cannot find ctl : Headphone Switch\n"); 994 } 995 } 996 997 static struct snd_soc_card mt8188_mt6359_soc_card = { 998 .owner = THIS_MODULE, 999 .dai_link = mt8188_mt6359_dai_links, 1000 .num_links = ARRAY_SIZE(mt8188_mt6359_dai_links), 1001 .dapm_widgets = mt8188_mt6359_widgets, 1002 .num_dapm_widgets = ARRAY_SIZE(mt8188_mt6359_widgets), 1003 .controls = mt8188_mt6359_controls, 1004 .num_controls = ARRAY_SIZE(mt8188_mt6359_controls), 1005 .fixup_controls = mt8188_fixup_controls, 1006 }; 1007 1008 static int mt8188_mt6359_dev_probe(struct platform_device *pdev) 1009 { 1010 struct snd_soc_card *card = &mt8188_mt6359_soc_card; 1011 struct device_node *platform_node; 1012 struct mt8188_mt6359_priv *priv; 1013 struct mt8188_card_data *card_data; 1014 struct snd_soc_dai_link *dai_link; 1015 bool init_mt6359 = false; 1016 bool init_nau8825 = false; 1017 bool init_max98390 = false; 1018 bool init_dumb = false; 1019 int ret, i; 1020 1021 card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev); 1022 card->dev = &pdev->dev; 1023 1024 ret = snd_soc_of_parse_card_name(card, "model"); 1025 if (ret) 1026 return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n", 1027 __func__); 1028 1029 if (!card->name) 1030 card->name = card_data->name; 1031 1032 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 1033 if (!priv) 1034 return -ENOMEM; 1035 1036 if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) { 1037 ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); 1038 if (ret) 1039 return ret; 1040 } 1041 1042 platform_node = of_parse_phandle(pdev->dev.of_node, 1043 "mediatek,platform", 0); 1044 if (!platform_node) { 1045 ret = -EINVAL; 1046 return dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); 1047 } 1048 1049 ret = parse_dai_link_info(card); 1050 if (ret) 1051 goto err; 1052 1053 for_each_card_prelinks(card, i, dai_link) { 1054 if (!dai_link->platforms->name) 1055 dai_link->platforms->of_node = platform_node; 1056 1057 if (strcmp(dai_link->name, "DPTX_BE") == 0) { 1058 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 1059 dai_link->init = mt8188_dptx_codec_init; 1060 } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { 1061 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) 1062 dai_link->init = mt8188_hdmi_codec_init; 1063 } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || 1064 strcmp(dai_link->name, "UL_SRC_BE") == 0) { 1065 if (!init_mt6359) { 1066 dai_link->init = mt8188_mt6359_init; 1067 init_mt6359 = true; 1068 } 1069 } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 || 1070 strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || 1071 strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || 1072 strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { 1073 if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { 1074 dai_link->ops = &mt8188_max98390_ops; 1075 if (!init_max98390) { 1076 dai_link->init = mt8188_max98390_codec_init; 1077 init_max98390 = true; 1078 } 1079 } else if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) { 1080 dai_link->ops = &mt8188_nau8825_ops; 1081 if (!init_nau8825) { 1082 dai_link->init = mt8188_nau8825_codec_init; 1083 dai_link->exit = mt8188_nau8825_codec_exit; 1084 init_nau8825 = true; 1085 } 1086 } else { 1087 if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { 1088 if (!init_dumb) { 1089 dai_link->init = mt8188_dumb_amp_init; 1090 init_dumb = true; 1091 } 1092 } 1093 } 1094 } 1095 } 1096 1097 priv->private_data = card_data; 1098 snd_soc_card_set_drvdata(card, priv); 1099 1100 ret = devm_snd_soc_register_card(&pdev->dev, card); 1101 if (ret) 1102 dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", 1103 __func__); 1104 err: 1105 of_node_put(platform_node); 1106 clean_card_reference(card); 1107 return ret; 1108 } 1109 1110 static struct mt8188_card_data mt8188_evb_card = { 1111 .name = "mt8188_mt6359", 1112 }; 1113 1114 static struct mt8188_card_data mt8188_nau8825_card = { 1115 .name = "mt8188_nau8825", 1116 .quirk = NAU8825_HS_PRESENT, 1117 }; 1118 1119 static const struct of_device_id mt8188_mt6359_dt_match[] = { 1120 { 1121 .compatible = "mediatek,mt8188-mt6359-evb", 1122 .data = &mt8188_evb_card, 1123 }, 1124 { 1125 .compatible = "mediatek,mt8188-nau8825", 1126 .data = &mt8188_nau8825_card, 1127 }, 1128 {}, 1129 }; 1130 MODULE_DEVICE_TABLE(of, mt8188_mt6359_dt_match); 1131 1132 static struct platform_driver mt8188_mt6359_driver = { 1133 .driver = { 1134 .name = "mt8188_mt6359", 1135 .of_match_table = mt8188_mt6359_dt_match, 1136 .pm = &snd_soc_pm_ops, 1137 }, 1138 .probe = mt8188_mt6359_dev_probe, 1139 }; 1140 1141 module_platform_driver(mt8188_mt6359_driver); 1142 1143 /* Module information */ 1144 MODULE_DESCRIPTION("MT8188-MT6359 ALSA SoC machine driver"); 1145 MODULE_AUTHOR("Trevor Wu <trevor.wu@mediatek.com>"); 1146 MODULE_LICENSE("GPL"); 1147 MODULE_ALIAS("mt8188 mt6359 soc card"); 1148