1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // mt8186-mt6366-rt1019-rt5682s.c 4 // -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver 5 // 6 // Copyright (c) 2022 MediaTek Inc. 7 // Author: Jiaxin Yu <jiaxin.yu@mediatek.com> 8 // 9 10 #include <linux/input.h> 11 #include <linux/module.h> 12 #include <linux/of_device.h> 13 #include <linux/pm_runtime.h> 14 #include <sound/jack.h> 15 #include <sound/pcm_params.h> 16 #include <sound/rt5682.h> 17 #include <sound/soc.h> 18 19 #include "../../codecs/mt6358.h" 20 #include "../../codecs/rt5682.h" 21 #include "../common/mtk-afe-platform-driver.h" 22 #include "mt8186-afe-common.h" 23 #include "mt8186-afe-clk.h" 24 #include "mt8186-afe-gpio.h" 25 #include "mt8186-mt6366-common.h" 26 27 #define RT1019_CODEC_DAI "HiFi" 28 #define RT1019_DEV0_NAME "rt1019p" 29 30 #define RT5682S_CODEC_DAI "rt5682s-aif1" 31 #define RT5682S_DEV0_NAME "rt5682s.5-001a" 32 33 struct mt8186_mt6366_rt1019_rt5682s_priv { 34 struct snd_soc_jack headset_jack, hdmi_jack; 35 }; 36 37 static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = { 38 { 39 .dlc = COMP_CODEC_CONF("mt6358-sound"), 40 .name_prefix = "Mt6366", 41 }, 42 { 43 .dlc = COMP_CODEC_CONF("bt-sco"), 44 .name_prefix = "Mt8186 bt", 45 }, 46 { 47 .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), 48 .name_prefix = "Mt8186 hdmi", 49 }, 50 }; 51 52 static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd) 53 { 54 struct mt8186_mt6366_rt1019_rt5682s_priv *priv = 55 snd_soc_card_get_drvdata(rtd->card); 56 struct snd_soc_jack *jack = &priv->headset_jack; 57 struct snd_soc_component *cmpnt_codec = 58 asoc_rtd_to_codec(rtd, 0)->component; 59 int ret; 60 61 ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", 62 SND_JACK_HEADSET | SND_JACK_BTN_0 | 63 SND_JACK_BTN_1 | SND_JACK_BTN_2 | 64 SND_JACK_BTN_3, 65 jack); 66 if (ret) { 67 dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); 68 return ret; 69 } 70 71 snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); 72 snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); 73 snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); 74 snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); 75 76 return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); 77 } 78 79 static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, 80 struct snd_pcm_hw_params *params) 81 { 82 struct snd_soc_pcm_runtime *rtd = substream->private_data; 83 struct snd_soc_card *card = rtd->card; 84 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); 85 struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); 86 unsigned int rate = params_rate(params); 87 unsigned int mclk_fs_ratio = 128; 88 unsigned int mclk_fs = rate * mclk_fs_ratio; 89 int bitwidth; 90 int ret; 91 92 bitwidth = snd_pcm_format_width(params_format(params)); 93 if (bitwidth < 0) { 94 dev_err(card->dev, "invalid bit width: %d\n", bitwidth); 95 return bitwidth; 96 } 97 98 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); 99 if (ret) { 100 dev_err(card->dev, "failed to set tdm slot\n"); 101 return ret; 102 } 103 104 ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, 105 RT5682_PLL1_S_BCLK1, 106 params_rate(params) * 64, 107 params_rate(params) * 512); 108 if (ret) { 109 dev_err(card->dev, "failed to set pll\n"); 110 return ret; 111 } 112 113 ret = snd_soc_dai_set_sysclk(codec_dai, 114 RT5682_SCLK_S_PLL1, 115 params_rate(params) * 512, 116 SND_SOC_CLOCK_IN); 117 if (ret) { 118 dev_err(card->dev, "failed to set sysclk\n"); 119 return ret; 120 } 121 122 return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); 123 } 124 125 static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = { 126 .hw_params = mt8186_rt5682s_i2s_hw_params, 127 }; 128 129 static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd) 130 { 131 struct snd_soc_component *cmpnt_codec = 132 asoc_rtd_to_codec(rtd, 0)->component; 133 struct mt8186_mt6366_rt1019_rt5682s_priv *priv = 134 snd_soc_card_get_drvdata(rtd->card); 135 int ret; 136 137 ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack); 138 if (ret) { 139 dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); 140 return ret; 141 } 142 143 return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); 144 } 145 146 static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 147 struct snd_pcm_hw_params *params, 148 snd_pcm_format_t fmt) 149 { 150 struct snd_interval *channels = hw_param_interval(params, 151 SNDRV_PCM_HW_PARAM_CHANNELS); 152 153 dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); 154 155 /* fix BE i2s channel to 2 channel */ 156 channels->min = 2; 157 channels->max = 2; 158 159 /* clean param mask first */ 160 snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), 161 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); 162 163 params_set_format(params, fmt); 164 165 return 0; 166 } 167 168 static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 169 struct snd_pcm_hw_params *params) 170 { 171 return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); 172 } 173 174 static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 175 struct snd_pcm_hw_params *params) 176 { 177 return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); 178 } 179 180 static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream) 181 { 182 static const unsigned int rates[] = { 183 48000 184 }; 185 static const unsigned int channels[] = { 186 2 187 }; 188 static const struct snd_pcm_hw_constraint_list constraints_rates = { 189 .count = ARRAY_SIZE(rates), 190 .list = rates, 191 .mask = 0, 192 }; 193 static const struct snd_pcm_hw_constraint_list constraints_channels = { 194 .count = ARRAY_SIZE(channels), 195 .list = channels, 196 .mask = 0, 197 }; 198 199 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 200 struct snd_pcm_runtime *runtime = substream->runtime; 201 int ret; 202 203 ret = snd_pcm_hw_constraint_list(runtime, 0, 204 SNDRV_PCM_HW_PARAM_RATE, 205 &constraints_rates); 206 if (ret < 0) { 207 dev_err(rtd->dev, "hw_constraint_list rate failed\n"); 208 return ret; 209 } 210 211 ret = snd_pcm_hw_constraint_list(runtime, 0, 212 SNDRV_PCM_HW_PARAM_CHANNELS, 213 &constraints_channels); 214 if (ret < 0) { 215 dev_err(rtd->dev, "hw_constraint_list channel failed\n"); 216 return ret; 217 } 218 219 return 0; 220 } 221 222 static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = { 223 .startup = mt8186_mt6366_rt1019_rt5682s_playback_startup, 224 }; 225 226 static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream) 227 { 228 static const unsigned int rates[] = { 229 48000 230 }; 231 static const unsigned int channels[] = { 232 1, 2 233 }; 234 static const struct snd_pcm_hw_constraint_list constraints_rates = { 235 .count = ARRAY_SIZE(rates), 236 .list = rates, 237 .mask = 0, 238 }; 239 static const struct snd_pcm_hw_constraint_list constraints_channels = { 240 .count = ARRAY_SIZE(channels), 241 .list = channels, 242 .mask = 0, 243 }; 244 245 struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 246 struct snd_pcm_runtime *runtime = substream->runtime; 247 int ret; 248 249 ret = snd_pcm_hw_constraint_list(runtime, 0, 250 SNDRV_PCM_HW_PARAM_RATE, 251 &constraints_rates); 252 if (ret < 0) { 253 dev_err(rtd->dev, "hw_constraint_list rate failed\n"); 254 return ret; 255 } 256 257 ret = snd_pcm_hw_constraint_list(runtime, 0, 258 SNDRV_PCM_HW_PARAM_CHANNELS, 259 &constraints_channels); 260 if (ret < 0) { 261 dev_err(rtd->dev, "hw_constraint_list channel failed\n"); 262 return ret; 263 } 264 265 return 0; 266 } 267 268 static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = { 269 .startup = mt8186_mt6366_rt1019_rt5682s_capture_startup, 270 }; 271 272 /* FE */ 273 SND_SOC_DAILINK_DEFS(playback1, 274 DAILINK_COMP_ARRAY(COMP_CPU("DL1")), 275 DAILINK_COMP_ARRAY(COMP_DUMMY()), 276 DAILINK_COMP_ARRAY(COMP_EMPTY())); 277 278 SND_SOC_DAILINK_DEFS(playback12, 279 DAILINK_COMP_ARRAY(COMP_CPU("DL12")), 280 DAILINK_COMP_ARRAY(COMP_DUMMY()), 281 DAILINK_COMP_ARRAY(COMP_EMPTY())); 282 283 SND_SOC_DAILINK_DEFS(playback2, 284 DAILINK_COMP_ARRAY(COMP_CPU("DL2")), 285 DAILINK_COMP_ARRAY(COMP_DUMMY()), 286 DAILINK_COMP_ARRAY(COMP_EMPTY())); 287 288 SND_SOC_DAILINK_DEFS(playback3, 289 DAILINK_COMP_ARRAY(COMP_CPU("DL3")), 290 DAILINK_COMP_ARRAY(COMP_DUMMY()), 291 DAILINK_COMP_ARRAY(COMP_EMPTY())); 292 293 SND_SOC_DAILINK_DEFS(playback4, 294 DAILINK_COMP_ARRAY(COMP_CPU("DL4")), 295 DAILINK_COMP_ARRAY(COMP_DUMMY()), 296 DAILINK_COMP_ARRAY(COMP_EMPTY())); 297 298 SND_SOC_DAILINK_DEFS(playback5, 299 DAILINK_COMP_ARRAY(COMP_CPU("DL5")), 300 DAILINK_COMP_ARRAY(COMP_DUMMY()), 301 DAILINK_COMP_ARRAY(COMP_EMPTY())); 302 303 SND_SOC_DAILINK_DEFS(playback6, 304 DAILINK_COMP_ARRAY(COMP_CPU("DL6")), 305 DAILINK_COMP_ARRAY(COMP_DUMMY()), 306 DAILINK_COMP_ARRAY(COMP_EMPTY())); 307 308 SND_SOC_DAILINK_DEFS(playback7, 309 DAILINK_COMP_ARRAY(COMP_CPU("DL7")), 310 DAILINK_COMP_ARRAY(COMP_DUMMY()), 311 DAILINK_COMP_ARRAY(COMP_EMPTY())); 312 313 SND_SOC_DAILINK_DEFS(playback8, 314 DAILINK_COMP_ARRAY(COMP_CPU("DL8")), 315 DAILINK_COMP_ARRAY(COMP_DUMMY()), 316 DAILINK_COMP_ARRAY(COMP_EMPTY())); 317 318 SND_SOC_DAILINK_DEFS(capture1, 319 DAILINK_COMP_ARRAY(COMP_CPU("UL1")), 320 DAILINK_COMP_ARRAY(COMP_DUMMY()), 321 DAILINK_COMP_ARRAY(COMP_EMPTY())); 322 323 SND_SOC_DAILINK_DEFS(capture2, 324 DAILINK_COMP_ARRAY(COMP_CPU("UL2")), 325 DAILINK_COMP_ARRAY(COMP_DUMMY()), 326 DAILINK_COMP_ARRAY(COMP_EMPTY())); 327 328 SND_SOC_DAILINK_DEFS(capture3, 329 DAILINK_COMP_ARRAY(COMP_CPU("UL3")), 330 DAILINK_COMP_ARRAY(COMP_DUMMY()), 331 DAILINK_COMP_ARRAY(COMP_EMPTY())); 332 333 SND_SOC_DAILINK_DEFS(capture4, 334 DAILINK_COMP_ARRAY(COMP_CPU("UL4")), 335 DAILINK_COMP_ARRAY(COMP_DUMMY()), 336 DAILINK_COMP_ARRAY(COMP_EMPTY())); 337 338 SND_SOC_DAILINK_DEFS(capture5, 339 DAILINK_COMP_ARRAY(COMP_CPU("UL5")), 340 DAILINK_COMP_ARRAY(COMP_DUMMY()), 341 DAILINK_COMP_ARRAY(COMP_EMPTY())); 342 343 SND_SOC_DAILINK_DEFS(capture6, 344 DAILINK_COMP_ARRAY(COMP_CPU("UL6")), 345 DAILINK_COMP_ARRAY(COMP_DUMMY()), 346 DAILINK_COMP_ARRAY(COMP_EMPTY())); 347 348 SND_SOC_DAILINK_DEFS(capture7, 349 DAILINK_COMP_ARRAY(COMP_CPU("UL7")), 350 DAILINK_COMP_ARRAY(COMP_DUMMY()), 351 DAILINK_COMP_ARRAY(COMP_EMPTY())); 352 353 /* hostless */ 354 SND_SOC_DAILINK_DEFS(hostless_lpbk, 355 DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), 356 DAILINK_COMP_ARRAY(COMP_DUMMY()), 357 DAILINK_COMP_ARRAY(COMP_EMPTY())); 358 SND_SOC_DAILINK_DEFS(hostless_fm, 359 DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), 360 DAILINK_COMP_ARRAY(COMP_DUMMY()), 361 DAILINK_COMP_ARRAY(COMP_EMPTY())); 362 SND_SOC_DAILINK_DEFS(hostless_src1, 363 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), 364 DAILINK_COMP_ARRAY(COMP_DUMMY()), 365 DAILINK_COMP_ARRAY(COMP_EMPTY())); 366 SND_SOC_DAILINK_DEFS(hostless_src_bargein, 367 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), 368 DAILINK_COMP_ARRAY(COMP_DUMMY()), 369 DAILINK_COMP_ARRAY(COMP_EMPTY())); 370 371 /* BE */ 372 SND_SOC_DAILINK_DEFS(adda, 373 DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), 374 DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", 375 "mt6358-snd-codec-aif1"), 376 COMP_CODEC("dmic-codec", 377 "dmic-hifi")), 378 DAILINK_COMP_ARRAY(COMP_EMPTY())); 379 SND_SOC_DAILINK_DEFS(i2s0, 380 DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), 381 DAILINK_COMP_ARRAY(COMP_EMPTY()), 382 DAILINK_COMP_ARRAY(COMP_EMPTY())); 383 SND_SOC_DAILINK_DEFS(i2s1, 384 DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), 385 DAILINK_COMP_ARRAY(COMP_EMPTY()), 386 DAILINK_COMP_ARRAY(COMP_EMPTY())); 387 SND_SOC_DAILINK_DEFS(i2s2, 388 DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), 389 DAILINK_COMP_ARRAY(COMP_DUMMY()), 390 DAILINK_COMP_ARRAY(COMP_EMPTY())); 391 SND_SOC_DAILINK_DEFS(i2s3, 392 DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), 393 DAILINK_COMP_ARRAY(COMP_EMPTY()), 394 DAILINK_COMP_ARRAY(COMP_EMPTY())); 395 SND_SOC_DAILINK_DEFS(hw_gain1, 396 DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), 397 DAILINK_COMP_ARRAY(COMP_DUMMY()), 398 DAILINK_COMP_ARRAY(COMP_EMPTY())); 399 SND_SOC_DAILINK_DEFS(hw_gain2, 400 DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), 401 DAILINK_COMP_ARRAY(COMP_DUMMY()), 402 DAILINK_COMP_ARRAY(COMP_EMPTY())); 403 SND_SOC_DAILINK_DEFS(hw_src1, 404 DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), 405 DAILINK_COMP_ARRAY(COMP_DUMMY()), 406 DAILINK_COMP_ARRAY(COMP_EMPTY())); 407 SND_SOC_DAILINK_DEFS(hw_src2, 408 DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), 409 DAILINK_COMP_ARRAY(COMP_DUMMY()), 410 DAILINK_COMP_ARRAY(COMP_EMPTY())); 411 SND_SOC_DAILINK_DEFS(connsys_i2s, 412 DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), 413 DAILINK_COMP_ARRAY(COMP_DUMMY()), 414 DAILINK_COMP_ARRAY(COMP_EMPTY())); 415 SND_SOC_DAILINK_DEFS(pcm1, 416 DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), 417 DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), 418 DAILINK_COMP_ARRAY(COMP_EMPTY())); 419 SND_SOC_DAILINK_DEFS(tdm_in, 420 DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), 421 DAILINK_COMP_ARRAY(COMP_DUMMY()), 422 DAILINK_COMP_ARRAY(COMP_EMPTY())); 423 424 /* hostless */ 425 SND_SOC_DAILINK_DEFS(hostless_ul1, 426 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), 427 DAILINK_COMP_ARRAY(COMP_DUMMY()), 428 DAILINK_COMP_ARRAY(COMP_EMPTY())); 429 SND_SOC_DAILINK_DEFS(hostless_ul2, 430 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), 431 DAILINK_COMP_ARRAY(COMP_DUMMY()), 432 DAILINK_COMP_ARRAY(COMP_EMPTY())); 433 SND_SOC_DAILINK_DEFS(hostless_ul3, 434 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), 435 DAILINK_COMP_ARRAY(COMP_DUMMY()), 436 DAILINK_COMP_ARRAY(COMP_EMPTY())); 437 SND_SOC_DAILINK_DEFS(hostless_ul5, 438 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), 439 DAILINK_COMP_ARRAY(COMP_DUMMY()), 440 DAILINK_COMP_ARRAY(COMP_EMPTY())); 441 SND_SOC_DAILINK_DEFS(hostless_ul6, 442 DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), 443 DAILINK_COMP_ARRAY(COMP_DUMMY()), 444 DAILINK_COMP_ARRAY(COMP_EMPTY())); 445 SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, 446 DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), 447 DAILINK_COMP_ARRAY(COMP_DUMMY()), 448 DAILINK_COMP_ARRAY(COMP_EMPTY())); 449 SND_SOC_DAILINK_DEFS(hostless_src_aaudio, 450 DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), 451 DAILINK_COMP_ARRAY(COMP_DUMMY()), 452 DAILINK_COMP_ARRAY(COMP_EMPTY())); 453 static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { 454 /* Front End DAI links */ 455 { 456 .name = "Playback_1", 457 .stream_name = "Playback_1", 458 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 459 SND_SOC_DPCM_TRIGGER_PRE}, 460 .dynamic = 1, 461 .dpcm_playback = 1, 462 .dpcm_merged_format = 1, 463 .dpcm_merged_chan = 1, 464 .dpcm_merged_rate = 1, 465 .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, 466 SND_SOC_DAILINK_REG(playback1), 467 }, 468 { 469 .name = "Playback_12", 470 .stream_name = "Playback_12", 471 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 472 SND_SOC_DPCM_TRIGGER_PRE}, 473 .dynamic = 1, 474 .dpcm_playback = 1, 475 SND_SOC_DAILINK_REG(playback12), 476 }, 477 { 478 .name = "Playback_2", 479 .stream_name = "Playback_2", 480 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 481 SND_SOC_DPCM_TRIGGER_PRE}, 482 .dynamic = 1, 483 .dpcm_playback = 1, 484 .dpcm_merged_format = 1, 485 .dpcm_merged_chan = 1, 486 .dpcm_merged_rate = 1, 487 SND_SOC_DAILINK_REG(playback2), 488 }, 489 { 490 .name = "Playback_3", 491 .stream_name = "Playback_3", 492 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 493 SND_SOC_DPCM_TRIGGER_PRE}, 494 .dynamic = 1, 495 .dpcm_playback = 1, 496 .dpcm_merged_format = 1, 497 .dpcm_merged_chan = 1, 498 .dpcm_merged_rate = 1, 499 .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, 500 SND_SOC_DAILINK_REG(playback3), 501 }, 502 { 503 .name = "Playback_4", 504 .stream_name = "Playback_4", 505 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 506 SND_SOC_DPCM_TRIGGER_PRE}, 507 .dynamic = 1, 508 .dpcm_playback = 1, 509 SND_SOC_DAILINK_REG(playback4), 510 }, 511 { 512 .name = "Playback_5", 513 .stream_name = "Playback_5", 514 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 515 SND_SOC_DPCM_TRIGGER_PRE}, 516 .dynamic = 1, 517 .dpcm_playback = 1, 518 SND_SOC_DAILINK_REG(playback5), 519 }, 520 { 521 .name = "Playback_6", 522 .stream_name = "Playback_6", 523 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 524 SND_SOC_DPCM_TRIGGER_PRE}, 525 .dynamic = 1, 526 .dpcm_playback = 1, 527 SND_SOC_DAILINK_REG(playback6), 528 }, 529 { 530 .name = "Playback_7", 531 .stream_name = "Playback_7", 532 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 533 SND_SOC_DPCM_TRIGGER_PRE}, 534 .dynamic = 1, 535 .dpcm_playback = 1, 536 SND_SOC_DAILINK_REG(playback7), 537 }, 538 { 539 .name = "Playback_8", 540 .stream_name = "Playback_8", 541 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 542 SND_SOC_DPCM_TRIGGER_PRE}, 543 .dynamic = 1, 544 .dpcm_playback = 1, 545 SND_SOC_DAILINK_REG(playback8), 546 }, 547 { 548 .name = "Capture_1", 549 .stream_name = "Capture_1", 550 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 551 SND_SOC_DPCM_TRIGGER_PRE}, 552 .dynamic = 1, 553 .dpcm_capture = 1, 554 SND_SOC_DAILINK_REG(capture1), 555 }, 556 { 557 .name = "Capture_2", 558 .stream_name = "Capture_2", 559 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 560 SND_SOC_DPCM_TRIGGER_PRE}, 561 .dynamic = 1, 562 .dpcm_capture = 1, 563 .dpcm_merged_format = 1, 564 .dpcm_merged_chan = 1, 565 .dpcm_merged_rate = 1, 566 .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, 567 SND_SOC_DAILINK_REG(capture2), 568 }, 569 { 570 .name = "Capture_3", 571 .stream_name = "Capture_3", 572 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 573 SND_SOC_DPCM_TRIGGER_PRE}, 574 .dynamic = 1, 575 .dpcm_capture = 1, 576 SND_SOC_DAILINK_REG(capture3), 577 }, 578 { 579 .name = "Capture_4", 580 .stream_name = "Capture_4", 581 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 582 SND_SOC_DPCM_TRIGGER_PRE}, 583 .dynamic = 1, 584 .dpcm_capture = 1, 585 .dpcm_merged_format = 1, 586 .dpcm_merged_chan = 1, 587 .dpcm_merged_rate = 1, 588 .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, 589 SND_SOC_DAILINK_REG(capture4), 590 }, 591 { 592 .name = "Capture_5", 593 .stream_name = "Capture_5", 594 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 595 SND_SOC_DPCM_TRIGGER_PRE}, 596 .dynamic = 1, 597 .dpcm_capture = 1, 598 SND_SOC_DAILINK_REG(capture5), 599 }, 600 { 601 .name = "Capture_6", 602 .stream_name = "Capture_6", 603 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 604 SND_SOC_DPCM_TRIGGER_PRE}, 605 .dynamic = 1, 606 .dpcm_capture = 1, 607 .dpcm_merged_format = 1, 608 .dpcm_merged_chan = 1, 609 .dpcm_merged_rate = 1, 610 SND_SOC_DAILINK_REG(capture6), 611 }, 612 { 613 .name = "Capture_7", 614 .stream_name = "Capture_7", 615 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 616 SND_SOC_DPCM_TRIGGER_PRE}, 617 .dynamic = 1, 618 .dpcm_capture = 1, 619 SND_SOC_DAILINK_REG(capture7), 620 }, 621 { 622 .name = "Hostless_LPBK", 623 .stream_name = "Hostless_LPBK", 624 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 625 SND_SOC_DPCM_TRIGGER_PRE}, 626 .dynamic = 1, 627 .dpcm_playback = 1, 628 .dpcm_capture = 1, 629 .ignore_suspend = 1, 630 SND_SOC_DAILINK_REG(hostless_lpbk), 631 }, 632 { 633 .name = "Hostless_FM", 634 .stream_name = "Hostless_FM", 635 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 636 SND_SOC_DPCM_TRIGGER_PRE}, 637 .dynamic = 1, 638 .dpcm_playback = 1, 639 .dpcm_capture = 1, 640 .ignore_suspend = 1, 641 SND_SOC_DAILINK_REG(hostless_fm), 642 }, 643 { 644 .name = "Hostless_SRC_1", 645 .stream_name = "Hostless_SRC_1", 646 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 647 SND_SOC_DPCM_TRIGGER_PRE}, 648 .dynamic = 1, 649 .dpcm_playback = 1, 650 .dpcm_capture = 1, 651 .ignore_suspend = 1, 652 SND_SOC_DAILINK_REG(hostless_src1), 653 }, 654 { 655 .name = "Hostless_SRC_Bargein", 656 .stream_name = "Hostless_SRC_Bargein", 657 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 658 SND_SOC_DPCM_TRIGGER_PRE}, 659 .dynamic = 1, 660 .dpcm_playback = 1, 661 .dpcm_capture = 1, 662 .ignore_suspend = 1, 663 SND_SOC_DAILINK_REG(hostless_src_bargein), 664 }, 665 { 666 .name = "Hostless_HW_Gain_AAudio", 667 .stream_name = "Hostless_HW_Gain_AAudio", 668 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 669 SND_SOC_DPCM_TRIGGER_PRE}, 670 .dynamic = 1, 671 .dpcm_capture = 1, 672 .ignore_suspend = 1, 673 SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), 674 }, 675 { 676 .name = "Hostless_SRC_AAudio", 677 .stream_name = "Hostless_SRC_AAudio", 678 .trigger = {SND_SOC_DPCM_TRIGGER_PRE, 679 SND_SOC_DPCM_TRIGGER_PRE}, 680 .dynamic = 1, 681 .dpcm_playback = 1, 682 .dpcm_capture = 1, 683 .ignore_suspend = 1, 684 SND_SOC_DAILINK_REG(hostless_src_aaudio), 685 }, 686 /* Back End DAI links */ 687 { 688 .name = "Primary Codec", 689 .no_pcm = 1, 690 .dpcm_playback = 1, 691 .dpcm_capture = 1, 692 .ignore_suspend = 1, 693 .init = mt8186_mt6366_init, 694 SND_SOC_DAILINK_REG(adda), 695 }, 696 { 697 .name = "I2S3", 698 .no_pcm = 1, 699 .dai_fmt = SND_SOC_DAIFMT_I2S | 700 SND_SOC_DAIFMT_IB_IF | 701 SND_SOC_DAIFMT_CBM_CFM, 702 .dpcm_playback = 1, 703 .ignore_suspend = 1, 704 .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init, 705 .be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup, 706 SND_SOC_DAILINK_REG(i2s3), 707 }, 708 { 709 .name = "I2S0", 710 .no_pcm = 1, 711 .dpcm_capture = 1, 712 .ignore_suspend = 1, 713 .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, 714 .ops = &mt8186_rt5682s_i2s_ops, 715 SND_SOC_DAILINK_REG(i2s0), 716 }, 717 { 718 .name = "I2S1", 719 .no_pcm = 1, 720 .dpcm_playback = 1, 721 .ignore_suspend = 1, 722 .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, 723 .init = mt8186_rt5682s_init, 724 .ops = &mt8186_rt5682s_i2s_ops, 725 SND_SOC_DAILINK_REG(i2s1), 726 }, 727 { 728 .name = "I2S2", 729 .no_pcm = 1, 730 .dpcm_capture = 1, 731 .ignore_suspend = 1, 732 .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, 733 SND_SOC_DAILINK_REG(i2s2), 734 }, 735 { 736 .name = "HW Gain 1", 737 .no_pcm = 1, 738 .dpcm_playback = 1, 739 .dpcm_capture = 1, 740 .ignore_suspend = 1, 741 SND_SOC_DAILINK_REG(hw_gain1), 742 }, 743 { 744 .name = "HW Gain 2", 745 .no_pcm = 1, 746 .dpcm_playback = 1, 747 .dpcm_capture = 1, 748 .ignore_suspend = 1, 749 SND_SOC_DAILINK_REG(hw_gain2), 750 }, 751 { 752 .name = "HW_SRC_1", 753 .no_pcm = 1, 754 .dpcm_playback = 1, 755 .dpcm_capture = 1, 756 .ignore_suspend = 1, 757 SND_SOC_DAILINK_REG(hw_src1), 758 }, 759 { 760 .name = "HW_SRC_2", 761 .no_pcm = 1, 762 .dpcm_playback = 1, 763 .dpcm_capture = 1, 764 .ignore_suspend = 1, 765 SND_SOC_DAILINK_REG(hw_src2), 766 }, 767 { 768 .name = "CONNSYS_I2S", 769 .no_pcm = 1, 770 .dpcm_capture = 1, 771 .ignore_suspend = 1, 772 SND_SOC_DAILINK_REG(connsys_i2s), 773 }, 774 { 775 .name = "PCM 1", 776 .dai_fmt = SND_SOC_DAIFMT_I2S | 777 SND_SOC_DAIFMT_NB_IF, 778 .no_pcm = 1, 779 .dpcm_playback = 1, 780 .dpcm_capture = 1, 781 .ignore_suspend = 1, 782 SND_SOC_DAILINK_REG(pcm1), 783 }, 784 { 785 .name = "TDM IN", 786 .no_pcm = 1, 787 .dpcm_capture = 1, 788 .ignore_suspend = 1, 789 SND_SOC_DAILINK_REG(tdm_in), 790 }, 791 /* dummy BE for ul memif to record from dl memif */ 792 { 793 .name = "Hostless_UL1", 794 .no_pcm = 1, 795 .dpcm_capture = 1, 796 .ignore_suspend = 1, 797 SND_SOC_DAILINK_REG(hostless_ul1), 798 }, 799 { 800 .name = "Hostless_UL2", 801 .no_pcm = 1, 802 .dpcm_capture = 1, 803 .ignore_suspend = 1, 804 SND_SOC_DAILINK_REG(hostless_ul2), 805 }, 806 { 807 .name = "Hostless_UL3", 808 .no_pcm = 1, 809 .dpcm_capture = 1, 810 .ignore_suspend = 1, 811 SND_SOC_DAILINK_REG(hostless_ul3), 812 }, 813 { 814 .name = "Hostless_UL5", 815 .no_pcm = 1, 816 .dpcm_capture = 1, 817 .ignore_suspend = 1, 818 SND_SOC_DAILINK_REG(hostless_ul5), 819 }, 820 { 821 .name = "Hostless_UL6", 822 .no_pcm = 1, 823 .dpcm_capture = 1, 824 .ignore_suspend = 1, 825 SND_SOC_DAILINK_REG(hostless_ul6), 826 }, 827 }; 828 829 static const struct snd_soc_dapm_widget 830 mt8186_mt6366_rt1019_rt5682s_widgets[] = { 831 SND_SOC_DAPM_SPK("Speakers", NULL), 832 SND_SOC_DAPM_OUTPUT("HDMI1"), 833 }; 834 835 static const struct snd_soc_dapm_route 836 mt8186_mt6366_rt1019_rt5682s_routes[] = { 837 /* SPK */ 838 { "Speakers", NULL, "Speaker" }, 839 /* HDMI */ 840 { "HDMI1", NULL, "TX" }, 841 }; 842 843 static const struct snd_kcontrol_new 844 mt8186_mt6366_rt1019_rt5682s_controls[] = { 845 SOC_DAPM_PIN_SWITCH("Speakers"), 846 SOC_DAPM_PIN_SWITCH("HDMI1"), 847 }; 848 849 static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = { 850 .name = "mt8186_mt6366_rt1019_rt5682s", 851 .owner = THIS_MODULE, 852 .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, 853 .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), 854 .controls = mt8186_mt6366_rt1019_rt5682s_controls, 855 .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), 856 .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, 857 .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), 858 .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, 859 .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), 860 .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, 861 .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), 862 }; 863 864 static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) 865 { 866 struct snd_soc_card *card; 867 struct snd_soc_dai_link *dai_link; 868 struct mt8186_mt6366_rt1019_rt5682s_priv *priv; 869 struct device_node *platform_node, *headset_codec, *playback_codec; 870 int ret, i; 871 872 card = (struct snd_soc_card *)device_get_match_data(&pdev->dev); 873 if (!card) 874 return -EINVAL; 875 card->dev = &pdev->dev; 876 877 platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); 878 if (!platform_node) { 879 ret = -EINVAL; 880 dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); 881 return ret; 882 } 883 884 playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs"); 885 if (!playback_codec) { 886 ret = -EINVAL; 887 dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); 888 goto err_playback_codec; 889 } 890 891 headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); 892 if (!headset_codec) { 893 ret = -EINVAL; 894 dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); 895 goto err_headset_codec; 896 } 897 898 for_each_card_prelinks(card, i, dai_link) { 899 ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); 900 if (ret) { 901 dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", 902 dai_link->name); 903 goto err_probe; 904 } 905 906 ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); 907 if (ret) { 908 dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", 909 dai_link->name); 910 goto err_probe; 911 } 912 913 ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); 914 if (ret) { 915 dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", 916 dai_link->name); 917 goto err_probe; 918 } 919 920 if (!dai_link->platforms->name) 921 dai_link->platforms->of_node = platform_node; 922 } 923 924 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 925 if (!priv) { 926 ret = -ENOMEM; 927 goto err_probe; 928 } 929 930 snd_soc_card_set_drvdata(card, priv); 931 932 ret = mt8186_afe_gpio_init(&pdev->dev); 933 if (ret) { 934 dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); 935 goto err_probe; 936 } 937 938 ret = devm_snd_soc_register_card(&pdev->dev, card); 939 if (ret) 940 dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); 941 942 err_probe: 943 of_node_put(headset_codec); 944 err_headset_codec: 945 of_node_put(playback_codec); 946 err_playback_codec: 947 of_node_put(platform_node); 948 949 return ret; 950 } 951 952 #if IS_ENABLED(CONFIG_OF) 953 static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = { 954 { .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", 955 .data = &mt8186_mt6366_rt1019_rt5682s_soc_card, 956 }, 957 {} 958 }; 959 #endif 960 961 static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = { 962 .driver = { 963 .name = "mt8186_mt6366_rt1019_rt5682s", 964 #if IS_ENABLED(CONFIG_OF) 965 .of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match, 966 #endif 967 .pm = &snd_soc_pm_ops, 968 }, 969 .probe = mt8186_mt6366_rt1019_rt5682s_dev_probe, 970 }; 971 972 module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver); 973 974 /* Module information */ 975 MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver"); 976 MODULE_AUTHOR("Jiaxin Yu <jiaxin.yu@mediatek.com>"); 977 MODULE_LICENSE("GPL v2"); 978 MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card"); 979